Skip to content

Instantly share code, notes, and snippets.

@jordaniza
Created July 23, 2024 10:51
Show Gist options
  • Save jordaniza/47361db80383baf0ce27094a77581316 to your computer and use it in GitHub Desktop.
Save jordaniza/47361db80383baf0ce27094a77581316 to your computer and use it in GitHub Desktop.
RISC-0 Aragon

This working document aims to give a brief overview of how Aragon can architect a RISC-0 application for Zk voting.

Overview of a RISC-0 application

In this section we distill the elements of the RISC-0 toolchain relevant for our application.

CLICK TO OPEN IN A BROWSER

image

The steps we have are:

(These are not synced with the diagram)

  1. We write our rust application that will be compiled to an executable running on Bonsai.

We can use Steel as an abstraction for view functions and can query state up to 256 blocks in the past.

  1. Our compiled code can be saved somewhee, it should be available from a NextJS application as we will probably do a lot of the heavy lifting there. In Aragon's case we could do things like:
  • Run some pre-voting validations that will reject votes we know will not be valid
  • Run crosschain RPC calls to fetch balances across different networks
  • Determine a per-chain block number to query vote balances off, based on a proposal ID on a single chain
  • Locally aggregate votes in a DB so we can batch them for gas savings.
  • Aggregate totalSupply of a token across all chains
  1. When ready, we send the executable, the data and the ImageID (I think?) to Bonsai. This begins a proving session which could take some time (up to an hour). Bonsai will return us the receipt containting a SNARK or STARK (we want a SNARK but I Can see an additional step required for conversion)

  2. We take this proof + public data (journal) and submit to our custom solidity contract. We call the verifier to check the proof is valid and then we can update state accordingly in our governance contract. As aragon then, this contract could:

  • Serve as an oracle that allows a user to query if they've voted, which outcome they've voted on, which chain they voted on* etc etc
  • Serve as an aggregate oracle for the DAO when determining if a proposalId can be executed or not.
  • Once validated, the aggregate votes can be saved against the proposal.*

Questions

  • On 256 blockhashes

My understanding with Steel is that it uses blockhashes as part of the storage proof verification, so if the blockhash does not exist, we can't generate a proof for the view function. So am I right in saying that, for the time being, we need to have some sort of stateful contracts (such as ERC20 checkpointing) to query historical balances and delegation? Same for historical totalSupply of a token.

  • On aggregating proofs across multichains

What would be amazing is for a DAO to setup a proposal on the chain in which they want execution to happen (i.e. I want to do X on arbitrum, so create the proposal there), and then collect all votes, from all chains, and post them there. For that we need to generate proofs per chain. I'm wondering if that's possible with Steel or will we need to think of ways to aggregate votes by chain, generate proofs by chain, then do some sort of aggregation in the smart contract (we do this already with our ToucanReceiver contract).

  • On querying data and setting up offchain infra

I am assuming that we will need an offchain webservice to store vote data for each user and for applications. This is beacause our proofs only allow verification that the data is correct - you still need to find the data.

I'm curious how we might go about designing our contract to allow someone to query if they did vote on a proposal. I'm assuming, again, we can store the proofs somewhere, and have the user pass all the data to a view function that verifies it.

  • On aggregating vote data to determine if a vote has passed - diffs vs. aggregate

On our existing crosschain voting, we aggregate all votes and dispatch a new aggregate every time a cross chain vote happens. The previous tally is discarded and the new one set. The implications of this for Bonsai is that every time we run the prover, it must verify every existing vote, again, plus every new vote. My guess is that this bad design and we should try and limit the cycles of the prover, however this might add some complexity if someone changes their vote, and how we account for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment