2022 Nov 19
See all posts
Particular due to Balaji Srinivasan, and Coinbase, Kraken and Binance workers for dialogue.
Each time a serious centralized alternate blows up, a standard query that comes up is whether or not or not we will use cryptographic methods to unravel the issue. Relatively than relying solely on “fiat” strategies like authorities licenses, auditors and analyzing the company governance and the backgrounds of the people working the alternate, exchanges may create cryptographic proofs that present that the funds they maintain on-chain are sufficient to cowl their liabilities to their customers.
Much more ambitiously, an alternate may construct a system the place it could’t withdraw a depositor’s funds in any respect with out their consent. Doubtlessly, we may discover your complete spectrum between the “do not be evil” aspiring-good-guy CEX and the “cannot be evil”, however for-now inefficient and privacy-leaking, on-chain DEX. This submit will get into the historical past of makes an attempt to maneuver exchanges one or two steps nearer to trustlessness, the restrictions of those methods, and a few newer and extra highly effective concepts that depend on ZK-SNARKs and different superior applied sciences.
Steadiness lists and Merkle bushes: old-school proof-of-solvency
The earliest makes an attempt by exchanges to attempt to cryptographically show that they aren’t dishonest their customers return fairly far. In 2011, then-largest Bitcoin alternate MtGox proved that they’d funds by sending a transaction that moved 424242 BTC to a pre-announced deal with. In 2013, discussions started on the way to clear up the opposite aspect of the issue: proving the full measurement of shoppers’ deposits. If you happen to show that prospects’ deposits equal X (“proof of liabilities“), and show possession of the personal keys of X cash (“proof of belongings“), then you’ve gotten a proof of solvency: you’ve got confirmed the alternate has the funds to pay again all of its depositors.
The only strategy to show deposits is to easily publish an inventory of
(username, steadiness) pairs. Every consumer can verify that their steadiness is included within the checklist, and anybody can verify the total checklist to see that (i) each steadiness is non-negative, and (ii) the full sum is the claimed quantity. After all, this breaks privateness, so we will change the scheme somewhat bit: publish an inventory of
(hash(username, salt), steadiness) pairs, and ship every consumer privately their
salt worth. However even this leaks balances, and it leaks the sample of modifications in balances. The will to protect privateness brings us to the next invention: the Merkle tree method.
Inexperienced: Charlie’s node. Blue: nodes Charlie will obtain as a part of his proof. Yellow: root node, publicly proven to everybody.
The Merkle tree method consists of placing the desk of shoppers’ balances right into a Merkle sum tree. In a Merkle sum tree, every node is a
(steadiness, hash) pair. The underside-layer leaf nodes signify the balances and salted username hashes of particular person prospects. In every higher-layer node, the steadiness is the sum of the 2 balances beneath, and the hash is the hash of the 2 nodes beneath. A Merkle sum proof, like a Merkle proof, is a “department” of the tree, consisting of the sister nodes alongside the trail from a leaf to the basis.
The alternate would ship every consumer a Merkle sum proof of their steadiness. The consumer would then have a assure that their steadiness is appropriately included as a part of the full. A easy instance code implementation will be discovered here.
# The function for computing a parent node given two child nodes def combine_tree_nodes(L, R): = L L_hash, L_balance = R R_hash, R_balance assert L_balance >= 0 and R_balance >= 0 = hash( new_node_hash + L_balance.to_bytes(32, 'big') + L_hash + R_balance.to_bytes(32, 'big') R_hash )return (new_node_hash, L_balance + R_balance) # Builds a full Merkle tree. Stored in flattened form where # node i is the parent of nodes 2i and 2i+1 def build_merkle_sum_tree(user_table: "List[(username, salt, balance)]"): = get_next_power_of_2(len(user_table)) tree_size = ( tree None] * tree_size + [*user) for user in user_table] + [userdata_to_leaf(for _ in range(tree_size - len(user_table))] [EMPTY_LEAF )for i in range(tree_size - 1, 0, -1): = combine_tree_nodes(tree[i*2], tree[i*2+1]) tree[i] return tree # Root of a tree is stored at index 1 in the flattened form def get_root(tree): return tree # Gets a proof for a node at a particular index def get_proof(tree, index): = log2(len(tree)) - 1 branch_length # ^ = bitwise xor, x ^ 1 = sister node of x = index + len(tree) // 2 index_in_tree return [tree[(index_in_tree // 2**i) ^ 1] for i in range(branch_length)] # Verifies a proof (duh) def verify_proof(username, salt, balance, index, user_table_size, root, proof): = userdata_to_leaf(username, salt, balance) leaf = log2(get_next_power_of_2(user_table_size)) - 1 branch_length for i in range(branch_length): if index & (2**i): = combine_tree_nodes(proof[i], leaf) leaf else: = combine_tree_nodes(leaf, proof[i]) leaf return leaf == root
Privacy leakage in this design is much lower than with a fully public list, and it can be decreased further by shuffling the branches each time a root is published, but some privacy leakage is still there: Charlie learns that someone has a balance of 164 ETH, some two users have balances that add up to 70 ETH, etc. An attacker that controls many accounts could still potentially learn a significant amount about the exchange’s users.
One important subtlety of the scheme is the possibility of negative balances: what if an exchange that has 1390 ETH of customer balances but only 890 ETH in reserves tries to make up the difference by adding a -500 ETH balance under a fake account somewhere in the tree? It turns out that this possibility does not break the scheme, though this is the reason why we specifically need a Merkle sum tree and not a regular Merkle tree. Suppose that Henry is the fake account controlled by the exchange, and the exchange puts -500 ETH there:
Greta’s proof verification would fail: the exchange would have to give her Henry’s -500 ETH node, which she would reject as invalid. Eve and Fred’s proof verification would also fail, because the intermediate node above Henry has -230 total ETH, and so is also invalid! To get away with the theft, the exchange would have to hope that nobody in the entire right half of the tree checks their balance proof.
If the exchange can identify 500 ETH worth of users that they are confident will either not bother to check the proof, or will not be believed when they complain that they never received a proof, they could get away with the theft. But then the exchange could also just exclude those users from the tree and have the same effect. Hence, the Merkle tree technique is basically as good as a proof-of-liabilities scheme can be, if only achieving a proof of liabilities is the goal. But its privacy properties are still not ideal. You can go a little bit further by using Merkle trees in more clever ways, like making each satoshi or wei a separate leaf, however in the end with extra fashionable tech there are even higher methods to do it.
Enhancing privateness and robustness with ZK-SNARKs
ZK-SNARKs are a strong expertise. ZK-SNARKs could also be to cryptography what transformers are to AI: a general-purpose expertise that’s so highly effective that it’s going to fully steamroll a complete bunch of application-specific methods for a complete bunch of issues that had been developed within the a long time prior. And so, after all, we will use ZK-SNARKs to enormously simplify and enhance privateness in proof-of-liabilities protocols.
The only factor that we will do is put all customers’ deposits right into a Merkle tree (or, even less complicated, a KZG commitment), and use a ZK-SNARK to show that each one balances within the tree are non-negative and add as much as some claimed worth. If we add a layer of hashing for privateness, the Merkle department (or KZG proof) given to every consumer would reveal nothing in regards to the steadiness of another consumer.
Utilizing KZG commitments is one strategy to keep away from privateness leakage, as there isn’t a want to supply “sister nodes” as proofs, and a easy ZK-SNARK can be utilized to show the sum of the balances and that every steadiness is non-negative.
We will show the sum and non-negativity of balances within the above KZG with a special-purpose ZK-SNARK. Right here is one easy instance method to do that. We introduce an auxiliary polynomial (I(x)), which “builds up the bits” of every steadiness (we assume for the sake of instance that balances are beneath (2^15)) and the place each sixteenth place tracks a working complete with an offset in order that it sums to zero provided that the precise complete matches the declared complete. If (z) is an order-128 root of unity, we would show the equations:
(I(z^16x) = 0)
(I(z^16x + 14) = P(omega^2x+1))
(I(z^i) – 2*I(z^i-1) in , 1 if i mod 16 not in , 15)
(I(z^16*x + 15) = I(z^16*x-1) + I(z^16*x+14) – fracthe declared totaluser rely)
The primary values of a sound setting for (I(x)) can be
0 0 0 0
0 0 0 0
0 0 1 2
5 10 20 -165
0 0 0 0
0 0 0 0
0 1 3 6
12 25 50 -300 …
See right here and right here in my submit on ZK-SNARKs for additional rationalization of the way to convert equations like these right into a polynomial verify after which right into a ZK-SNARK. This is not an optimum protocol, but it surely does present how lately these sorts of cryptographic proofs aren’t that spooky!
With only some additional equations, constraint techniques like this may be tailored to extra advanced settings. For instance, in a leverage buying and selling system, a person customers having destructive balances is suitable however provided that they’ve sufficient different belongings to cowl the funds with some collateralization margin. A SNARK may very well be used to show this extra difficult constraint, reassuring customers that the alternate shouldn’t be risking their funds by secretly exempting other users from the principles.
Within the longer-term future, this type of ZK proof of liabilities may maybe be used not only for buyer deposits at exchanges, however for lending extra broadly. Anybody taking out a mortgage would put a report right into a polynomial or a tree containing that mortgage, and the basis of that construction would get revealed on-chain. This could let anybody looking for a mortgage ZK-prove to the lender that they haven’t but taken out too many different loans. Finally, authorized innovation may even make loans which were dedicated to on this method higher-priority than loans that haven’t. This leads us in precisely the identical path as one of many concepts that was mentioned within the “Decentralized Society: Finding Web3’s Soul” paper: a common notion of destructive status or encumberments on-chain via some type of “soulbound tokens”.
Proof of belongings
The only model of proof of belongings is the protocol that we noticed above: to show that you simply maintain X cash, you merely transfer X cash round at some pre-agreed time or in a transaction the place the information subject accommodates the phrases “these funds belong to Binance”. To keep away from paying transaction charges, you might signal an off-chain message as an alternative; each Bitcoin and Ethereum have requirements for off-chain signed messages.
There are two sensible issues with this easy proof-of-assets method:
- Coping with chilly storage
- Collateral dual-use
For security causes, most exchanges hold the good majority of buyer funds in “chilly storage”: on offline computer systems, the place transactions must be signed and carried over onto the web manually. Literal air-gapping is widespread: a chilly storage setup that I used to make use of for private funds concerned a completely offline pc producing a QR code containing the signed transaction, which I’d scan from my cellphone. Due to the excessive values at stake, the safety protocols utilized by exchanges are crazier nonetheless, and sometimes contain utilizing multi-party computation between a number of gadgets to additional scale back the prospect of a hack in opposition to a single machine compromising a key. Given this type of setup, making even a single additional message to show management of an deal with is an costly operation!
There are a number of paths that an alternate can take:
- Hold a number of public long-term-use addresses. The alternate would generate a number of addresses, publish a proof of every deal with as soon as to show possession, after which use these addresses repeatedly. That is by far the best possibility, although it does add some constraints in the way to protect safety and privateness.
- Have many addresses, show a number of randomly. The alternate would have many addresses, maybe even utilizing every deal with solely as soon as and retiring it after a single transaction. On this case, the alternate might have a protocol the place infrequently a number of addresses get randomly chosen and should be “opened” to show possession. Some exchanges already do one thing like this with an auditor, however in precept this method may very well be became a completely automated process.
- Extra difficult ZKP choices. For instance, an alternate may set all of its addresses to be 1-of-2 multisigs, the place one of many keys is totally different per deal with, and the opposite is a blinded model of some “grand” emergency backup key saved in some difficult however very high-security method, eg. a 12-of-16 multisig. To protect privateness and keep away from revealing your complete set of its addresses, the alternate may even run a zero information proof over the blockchain the place it proves the full steadiness of all addresses on chain which have this format.
The opposite main difficulty is guarding in opposition to collateral dual-use. Shuttling collateral backwards and forwards between one another to do proof of reserves is one thing that exchanges could easily do, and would enable them to faux to be solvent once they really aren’t. Ideally, proof of solvency can be performed in actual time, with a proof that updates after each block. If that is impractical, the following neatest thing can be to coordinate on a hard and fast schedule between the totally different exchanges, eg. proving reserves at 1400 UTC each Tuesday.
One closing difficulty is: are you able to do proof-of-assets on fiat? Exchanges do not simply maintain cryptocurrency, in addition they maintain fiat foreign money throughout the banking system. Right here, the reply is: sure, however such a process would inevitably depend on “fiat” belief fashions: the financial institution itself can attest to balances, auditors can attest to steadiness sheets, and so on. Provided that fiat shouldn’t be cryptographically verifiable, that is the most effective that may be performed inside that framework, but it surely’s nonetheless value doing.
An alternate method can be to cleanly separate between one entity that runs the alternate and offers with asset-backed stablecoins like USDC, and one other entity (USDC itself) that handles the cash-in and cash-out course of for transferring between crypto and conventional banking techniques. As a result of the “liabilities” of USDC are simply on-chain ERC20 tokens, proof of liabilities comes “without cost” and solely proof of belongings is required.
Plasma and validiums: can we make CEXes non-custodial?
Suppose that we need to go additional: we do not need to simply show that the alternate has the funds to pay again its customers. Relatively, we need to forestall the alternate from stealing customers’ funds fully.
The primary main try at this was Plasma, a scaling resolution that was common in Ethereum analysis circles in 2017 and 2018. Plasma works by splitting up the steadiness right into a set of particular person “cash”, the place every coin is assigned an index and lives in a selected place within the Merkle tree of a Plasma block. Making a sound switch of a coin requires placing a transaction into the right place of a tree whose root will get revealed on-chain.
Oversimplified diagram of 1 model of Plasma. Cash are held in a sensible contract that enforces the principles of the Plasma protocol at withdrawal time.
OmiseGo tried to make a decentralized alternate primarily based on this protocol, however since then they’ve pivoted to different concepts – as has, for that matter, Plasma Group itself, which is now the optimistic EVM rollup undertaking Optimism.
It is not value wanting on the technical limitations of Plasma as conceived in 2018 (eg. proving coin defragmentation) as some type of morality story about the entire idea. For the reason that peak of Plasma discourse in 2018, ZK-SNARKs have change into far more viable for scaling-related use instances, and as now we have mentioned above, ZK-SNARKs change all the things.
The extra fashionable model of the Plasma concept is what Starkware calls a validium: principally the identical as a ZK-rollup, besides the place knowledge is held off-chain. This development may very well be used for lots of use instances, conceivably something the place a centralized server must run some code and show that it is executing code appropriately. In a validium, the operator has no strategy to steal funds, although relying on the main points of the implementation some amount of consumer funds may get caught if the operator disappears.
That is all actually good: removed from CEX vs DEX being a binary, it seems that there’s a entire spectrum of choices, together with numerous types of hybrid centralization the place you achieve some advantages like effectivity however nonetheless have loads of cryptographic guardrails stopping the centralized operator from partaking in most types of abuses.
Nevertheless it’s value attending to the basic difficulty with the precise half of this design house: coping with consumer errors. By far crucial sort of error is: what if a consumer forgets their password, loses their gadgets, will get hacked, or in any other case loses entry to their account?
Exchanges can clear up this drawback: first e-mail restoration, and if even that fails, extra difficult types of restoration via KYC. However to have the ability to clear up such issues, the alternate wants to really have management over the cash. In an effort to have the power to recuperate consumer accounts’ funds for good causes, exchanges have to have energy that is also used to steal consumer accounts’ funds for dangerous causes. That is an unavoidable tradeoff.
The perfect long-term resolution is to depend on self-custody, in a future the place customers have quick access to applied sciences corresponding to multisig and social restoration wallets to assist cope with emergency conditions. However within the brief time period, there are two clear options which have clearly distinct prices and advantages:
|Custodial alternate (eg. Coinbase at present)||Consumer funds could also be misplaced if there’s a drawback on the alternate aspect||Alternate will help recuperate account|
|Non-custodial alternate (eg. Uniswap at present)||Consumer can withdraw even when alternate acts maliciously||Consumer funds could also be misplaced if consumer screws up|
One other vital difficulty is cross-chain assist: exchanges have to assist many various chains, and techniques like Plasma and validiums would wish to have code written in several languages to assist totally different platforms, and can’t be carried out in any respect on others (notably Bitcoin) of their present type. Within the long-term future, this will hopefully be fastened with technological upgrades and standardization; within the brief time period, nevertheless, it is one other argument in favor of custodial exchanges remaining custodial for now.
Conclusions: the way forward for higher exchanges
Within the brief time period, there are two clear “courses” of exchanges: custodial exchanges and non-custodial exchanges. At the moment, the latter class is simply DEXes corresponding to Uniswap, and sooner or later we might also see cryptographically “constrained” CEXes the place consumer funds are held in one thing like a validium good contract. We might also see half-custodial exchanges the place we belief them with fiat however not cryptocurrency.
Each forms of exchanges will live on, and the simplest backwards-compatible method to enhance the security of custodial exchanges is so as to add proof of reserve. This consists of a mixture of proof of belongings and proof of liabilities. There are technical challenges in making good protocols for each, however we will and may go so far as doable to make headway in each, and open-source the software program and processes as a lot as doable so that each one exchanges can profit.
Within the longer-term future, my hope is that we transfer nearer and nearer to all exchanges being non-custodial, not less than on the crypto aspect. Pockets restoration would exist, and there might must be extremely centralized restoration choices for brand new customers coping with small quantities, in addition to establishments that require such preparations for authorized causes, however this may be performed on the pockets layer reasonably than throughout the alternate itself. On the fiat aspect, motion between the standard banking system and the crypto ecosystem may very well be performed by way of money in / money out processes native to asset-backed stablecoins corresponding to USDC. Nonetheless, it would nonetheless take some time earlier than we will absolutely get there.