Skip to content

An experimental progressive and fast zkRollup written in Rust, focused on performance, modularity, and applying cutting-edge Verifiable Computation proof systems.

License

Notifications You must be signed in to change notification settings

leonardoalt/fusion

Repository files navigation

Fusion zkRollup

Fusion is an experimental progressive Ethereum zkRollup written in Rust and focuses on performance, modularity, and applying cutting-edge Verifiable Computation proof systems.

Fusion is conceptually based on the original zkRollup. We use Zokrates for all circuits which provides high level abstractions for all algorithms and multiple backends. Currently the prover builds a Groth16 SNARK for each transaction in parallel, and there is no batching. Together with ZoKrates we are experimenting with Nova recursive proofs to enable incredibly fast transaction batching and compression.

See the end of this document for the full list of roadmap items, ideas, and concrete tasks.

Tool Suite

This repository contains the entire Fusion tool suite:

  • circuits: the SNARK state and signature verification ZoKrates code.
  • fusion-prover: the prover that takes a signed transaction and builds a SNARK of state changes and signature.
  • fusion-sequencer: the Fusion node. Receives L2 transactions via RPC, builds blocks, and sends them for verification on L1.
  • l1-verifier: the Fusion contracts deployed on L1. These contracts provide block verification and canonical state root updates for L2 nodes.
  • fusion-wallet: a simple CLI interface to sign/send Fusion transactions.

Cloning the repository

git clone --recurse-submodules https://github.com/leonardoalt/fusion.git

If you already cloned the repository without submodules, you can run the command below to initialize it:

git submodule update --init --recursive

Dependencies

Fusion requires the following installed:

Building the circuits

ZoKrates' latest release 0.8.7 is specifically required for this step.

cd circuits && make && make verifier

Note: the current circuits require at least 16GB of RAM to compile.

Building the L1 SNARK verifier

This step requires the circuit step above.

cd l1-verifier && make

Building the sequencer (has prover as dependency)

This step requires the L1 verifier step above.

cargo build --release --bin fusion-sequencer

Running

The easiest way to see everything running is via Rust tests with

cargo test --release -- --nocapture

For more details see the tests in fusion-sequencer. If you want to run it in production style, you may want to follow this list:

  1. Set eth_private_key in fusion.toml to the private key that will deploy the contract and submit L2 blocks.
  2. Set eth_rpc_url in fusion.toml to an Ethereum RPC endpoint. Since we are using anvil here, this is usually http://localhost:8545.
  3. Run source ./scripts/run_anvil_and_deploy_contract which starts anvil and deploys the contract.
  4. Set fusion_l1_contract in fusion.toml with the address of the deployed contract.
  5. Run ./scripts/run_node to start the node.
  6. You can run ./scripts/listen_to_node to check the ongoing output from the node.
  7. Now you can also run ./scripts/send_random_tx to send transactions.
  8. To stop everything, run ./scripts/kill_node and ./scripts/kill_anvil.

State

The state is a balanced Sparse Merkle Tree similar to this one. The tree has 256 levels besides the root. This implies that it has 2^256 leaves. Each leaf has an index, from 0 (left most) to 2^256 - 1 (right most). The path from the root to a leaf can be represented by the binary representation of the leaf's index: when walking down the tree, 0 means the path goes left, 1 means it goes right.

The tree also contains some optimizations, such as:

  • For the sparse branches of tree, we keep all nodes as 0, instead of hash(hash(...(0))) (such as in the Ethereum Beacon Chain Deposit Contract).
  • When merging two nodes, we apply:
    • merge(0, 0) = 0
    • merge(L, 0) = L, if L != 0
    • merge(0, R) = R, if R != 0
    • merge(L, R) = hash(L, R), if L != 0 and R != 0
  • The rules above may lead to collisions if the contents of two leaves are the same. To avoid that, we hash the leaf's contents together with its unique index.

The used hash is Poseidon in order to be SNARK friendly.

Signature and Addresses

Since we need to verify signatures inside zkSNARKs, we use EdDSA with the Baby Jubjub Elliptic Curve. A public key (PK) consists of a curve point where x and y are elements of the field used by Baby Jubjub. The PK can be compressed into 256 bits, which does not necessarily fit in the field. Given a public key (x, y), its Fusion address consists of poseidon(x, y). This means that Fusion accounts are not compatible with Ethereum accounts.

Execution

There are no VM and smart contracts at the moment.

Modularity

Fusion is designed to be highly modular and extensible. For example, here are a few things that can be modified quite easily:

  • the sequencer's block building strategy
  • the RPC node
  • the L2 state data structures
  • the proving backend (see branch nova)
  • the signature algorithm

This enables fast experimental iterations on all fronts which can quickly turn into progress.

Roadmap (and TODO items)

v1. Batch proofs - production after this!

Done

  • L2 RPC node
  • L2 sequencer
  • State verification circuit
  • State verification prover
  • Baby Jubjub signature verification circuit
  • Baby Jubjub signature verification prover
  • Transaction verification circuit
  • Transaction verification prover
  • L1 verifier
  • L2 block verification using L1 verifier
  • Baby Jubjub CLI wallet
  • L2 enter via L1 deposit
  • L2 exit via L1 withdraw

TODO

  • Transaction fees
  • Compress transaction proofs into a batch proof (in progress using Nova)
  • Separate mempool from sequencer
  • Reconstruct L2 state from scratch by re-playing block submissions to L1 verifier
  • Multi-key Merkle proofs
  • Forced transactions
  • Sequencer auction

v2. Execution

TODO

  • Integrate an extremely simple VM. Options:
    • High level VM in ZoKrates (similar to TinyZKEVM), using the SuperNova backend.
    • Low level VM in powdr, either using STARKs Nova (extension of Hermez) or Halo2 Nova (extension of PSE/Scroll).
    • Mix of the two above, using powdr as a backend in ZoKrates.
  • Subset of the EVM. Expand whatever idea is chosen from the previous item with EVM opcodes.
  • Full EVM. At this point I hope ZoKrates SuperNova has good performance so I can write everything in a high level.

About

An experimental progressive and fast zkRollup written in Rust, focused on performance, modularity, and applying cutting-edge Verifiable Computation proof systems.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published