Two weekends ago in Paris, we built the first POC of a zero knowledge DAO. Since January I had a fascination with the idea, and after meeting Zac from AZTEC at #EthCC, a key component of the solution crystalised. In this post, I'll explain the design considerations and potential implications.
One of my favourite thoughtpieces to explain blockchain is The DAO. The DAO in 2015 was a hallmark - a worldwide investment organisation that owned over $150M in ETH at the time, born independent of any nation and wasn't controlled by any single entity. Unfortunately, there was a bug in the code, and the experiment came to an end all too quickly. But the concept stood firmly into 2019, and now the theme of [blockchain] governance is as hot as scaling.
Since then, blockchain tech has evolved so rapidly, it's hard to keep up. Zero Knowledge Proofs have been of particular interest - a tool of mathematics whereby relationships are proven without revealing some information, which has great utility in privacy and scaling protocols. Ever since participating in Iden3's Zero Knowledge workshop at Web3 Summit, I knew that Zero Knowledge tech was even closer and more tangible than I thought was possible. When the AZTEC protocol for ZK ERC20's was announced and started gaining interest with their ZK-DAI token, I began reading deeper. AZTEC has received a large degree of funding to date because they are not just building for ZK transfers - they are building an engine (see their EIP).
Funnily enough, so were we, but for cross-chain token derivatives instead. And while we were pitching this idea to a friend, we were discussing cross-chain index funds and so on. You know, it would be crazy if the index fund was zero knowledge. You would invest money and the fund would allocate according to a portfolio, but you would never know the weightings. And so I got hooked on the concept of a ZK index fund. Further along the way, I realised that such a fund would take the structure of the original DAO anyways, and so we come to the ZKDAO.
A Zero Knowledge DAO
Recall a definition of what an organisation, decentralised or not, is in its simplest form:
a set of property, and a protocol for a set of individuals, [...] to interact with each other including rules for under what circumstances the individuals may use certain parts of the property 
In the case of an index fund, the property involved is capital to buy the assets, shares that are issued by the fund in exchange for such capital, and dividends that are distributed to shareholders. In contrast, a DAO investment fund is a lot simpler. The only property in question is its capital (ETH) and the protocol is a simple model of voting on proposals, based on the number of shares you possess.
I've highlighted previously that the core proposition of blockchain is trust for marginal cost -- you can setup a worldwide investment fund for the 30c it takes to deploy to mainnet. What happens when the protocol itself is anonymous?
Anonymous voting using AZTEC proofs
What is the simplest version of the protocol we are trying to implement?
- submitting a proposal
- voting on a proposal
- tallying votes and executing the proposal if they reach a threshold majority
Submitting the proposal would be easy, but how can we keep voter anonymity while retaining the ability to calculate if there's been a majority? Since we would like everyone's balances to remain private, how could we do this? Remember - the key of this exercise was not to produce a perfect design, but something better than what exists. And after researching into aggregating ZK proofs, I realised a more pragmatic approach would be to take a look at an existing ZK protocol - AZTEC. AZTEC
And then I met Zac, the founder, at EthCC, and from our conversation sprung the invaluable clarity - share balances can remain secret, and we know the fixed public
totalSupply of all shares, we could calculate this majority if shareholders revealed some proportion of their shares. The problem here is that some information is leaked as to the balance with every vote, however this isn't a completely unbeatable issue. Obfuscating the balances by shuffling coins around, a mixer/tumbler scheme, a dual-key stealth address protocol (see the AZTEC paper appendix A) are all possible approaches. ZK Merkle Sum Trees (as used in Plasma) are probably an interesting tool to explore in this case .
And so we (mis)used the AZTEC public dividend proof to prove a percentage of someone's shares were used to vote. At the hackathon, we spent the time reverse-engineering how it worked (since it's all quite undocumented for now). There were two additional constraints that arose during this design:
- votes can not be double-cast - ie. by transferring shares, and voting again.
- votes can be submitted on multiple proposals
Brief primer on AZTEC
AZTEC uses homeomorphic cryptography (meaning computation on encrypted data) and range proofs to build a primitive of a zero-knowledge note. The note is a representation of value that is only created and destroyed from transacting them - it is akin to the UXTO model of Bitcoin, with input value and output value, as opposed to Ethereum's account-based ledger.
A note is always associated with a public key, which is used to prove ownership of the tokens.
AZTEC's Cryptography Engine (ACE) specifies a set of zero knowledge proofs that it can validate. The proofs use notes as their base data type, however they are not tightly coupled to a ZK ERC-20 token - the NoteRegistry handles the conversion of ERC20 into new ZK notes by validating a proof supplied with it (see publicValue).
A dividend proof is for proving that an issued dividend note is a certain % of another note. In terms of its proof, it has one input and two outputs - the input note A, the output/dividend X and the residual value B. At ETHParis, we reverse-engineered how this very newly-written proof worked. Basically, you are satisfying this relationship:
$$ k_3 = k_1(z_b) - k_2(z_a) $$
Where \(k_i\) is the private values of a set of 3 notes (totalSupply, no. votes, zkShares), and \(z_a,z_b\) are the public factors of the dividend logic.
We use a dividend proof to reveal the number of votes cast by a shareholder, whilst hiding their balances (principles of the proof relationship). Again - the ACE engine defines proofs, which typically relate to notes, but the value we're using here in terms of number of votes doesn't relate to an existing note in the note registry.
ZKDAO Anonymous Voting Mechanism
We represent shares as ZK notes. Such notes can be the ERC20 tokens of a preexisting DAO, converted into zkshares by AZTEC's NoteRegistry (plug-n-play anonymity). The shares can be transferred in zero knowledge, meaning you can buy/sell without people knowing how much is transacted.
We represent votes using dividend proofs, wherein the input note is the totalSupply, the output notes are your zkShare and a fictitious note representing the votes you are casting. In this process, you are revealing the % of your voting power you are casting as a vote, as a % of the total supply of shares in existence. However, this is without revealing how many shares you own.
We can cast votes, but how do we mitigate people transferring their shares and thus casting two votes? Recall that if the number of the shares is unknown, then we can't do the simple accounting as a regular DAO does. To solve this, we designed a simple commit-reveal voting scheme. Users commit to their voting positions, and then only during the reveal phase can votes be tallied. The commit requires that the zk-note already exists, and such at the reveal stage you cannot double-vote as described above.
Maintaining perfect anonymity in the midst of voting on multiple proposals is difficult, since overlapping committal periods requires you keep the note in the same hands.
Implications and further ideas.
Again, blockchain tech moves and changes quicker than a plastic bag in a hurricane. Just in this past month, two new Ethereum smart-contract privacy technologies have been described - Zether and ZEXE (take a read from the fantastic Blockchain Research Newsletter for a good overview). They anonymise dApps at the blockchain's transaction level, which is clearly a big deal. I predict that it is highly likely we will see privacy-enabling tech like this at scale within 5 years, and not just specific to financial transfers.
In my mind, the most pertinent question is of the possibility of meritocracy - once you remove identity from the equation, what do people/agents base their decisions on?
The second implication is - can we prevent vote buying / collusion / bribery? In the current model, it is still possible to prove after-the-fact whether an address voted for a value. So while the actual addresses carry no identifying information in of themselves, if someone chooses to, they can still prove their ownership and thus be paid from it.
I was initially skeptical to work on this problem, because I'm not a studied cryptographer. Even writing this post, I was a bit hesitant to make certain claims. A week before I went to the hackathon with this idea, I shared my other research on decentralised reputation on EthResearch, which led to some really interesting conversations. From that, and continuing forth with ZKDAO, I'm learning it's good to get things out there. Even if they are imperfect, they exist, which is substantial on its own.
Reflecting on ETHParis, I couldn't have done it without my awesome teammates Simon Dosch and Max Niemzik - hacking with them was an absolute blast. Bizzarely but absolutely serendipitously, we gelled really well and progressed a series of small wins in an area we are hugely inexperienced in, and built the thing we set out to build - ZKDAO.
tired out of our minds, 5am, Paris
Take a look at our Github repo for the code. A massive shoutout and thank you to the AZTEC team who were there too, particularly Tom, whose brains we racked on Friday and was quite the help, and of course Zac, the man behind the magic. Lastly, thank you to the ETHParis organisers, it was a really enjoyable hackathon and fantastic venue at 42.
The development of authenticated data structures is fascinating. We've gone from the Merkle tree, to Merkle-Patricia for key-value storage, to Sparse Merkle Trees which are an amazing simplification of the KV design. Merkle Mountain Ranges (used in Grin) are effectively an optimization of recomputation of Merkle trees.
Plasma has popularised Merkle Sum Trees as an authenticated data structure for representing token value on a number line, where the leaves represent spans of 'balances'. It's not far fetched to imagine this implemented as a ZK circuit. I actually experimented with this using Circom Merkle circuits - you could use these to prove an update to the vote tally, without revealing which account/note was used in the update. The only unsolved issue then is how to prevent double-voting (I learned it's called a bijective mapping). ↩︎
The "small wins" I'm describing here are closest to what I imagine is the iterative / lean canvas idea of development. I'm currently doing some meta-analysis on this style of dev - during the hack, we basically wrote unit tests on generaing and validating dividend proofs in JS, our custom hook-in to the ACE in the ZKDAO contract, extracting the z_b and z_a parameters from the ACE ABI call (yay wrote our first Soli-dirty assembly). Max even wrote a Solidity function to leak the full balance of an AZTEC note from the spending key, which is crazy. All of our wins roughly were 1-2h apart, which was really motivating. I guess the attitude of "maybe we can do this but surely not in a weekend" meant we weren't prematurely optimizing or worrying about design. ↩︎