-
Notifications
You must be signed in to change notification settings - Fork 615
feat: Add root rollup circuit #3217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
ea15da4
add `assert_check_membership` this is check_membership in the cpp code
kevaundray 2306f9a
add hash module for computing hashes that are only relevant to the ro…
kevaundray 2e9cde4
add analogous code to "in-memory" merkle tree hashing
kevaundray 5ee3055
add code to `insert_subtree_to_snapshot_tree`
kevaundray c56ac3c
fill in `root_rollup_circuit`
kevaundray 0099445
commit cpp test vectors for computing the merkle tree
kevaundray de01802
Update yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/…
kevaundray ed5149e
Update yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/…
kevaundray bf76904
Update yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/…
kevaundray f9c853d
feat: add generic merkle tree
sirasistant cdd1cf5
style: use shorter initialization for arrays
sirasistant File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/hash.nr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| use crate::abis::global_variables::GlobalVariables; | ||
| use dep::aztec::constants_gen; | ||
|
|
||
| pub fn compute_block_hash_with_globals( | ||
| globals : GlobalVariables, | ||
| note_hash_tree_root : Field, | ||
| nullifier_tree_root : Field, | ||
| contract_tree_root : Field, | ||
| l1_to_l2_data_tree_root : Field, | ||
| public_data_tree_root : Field) -> Field { | ||
|
|
||
| let inputs = [globals.hash(), note_hash_tree_root, nullifier_tree_root, contract_tree_root, l1_to_l2_data_tree_root, public_data_tree_root]; | ||
|
|
||
| dep::std::hash::pedersen_hash_with_separator(inputs, constants_gen::GENERATOR_INDEX__BLOCK_HASH) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,3 +10,7 @@ mod merge; | |
| mod root; | ||
|
|
||
| mod components; | ||
|
|
||
| mod hash; | ||
|
|
||
| mod merkle_tree; | ||
164 changes: 164 additions & 0 deletions
164
yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/merkle_tree.nr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,164 @@ | ||
| // This is the naive way to do the merkle tree hashing given we know the height. | ||
| // Its janky but has the least complexity given that for loop bounds need to be constant. | ||
| // | ||
| // TODO: Check that in all cases the compiler is able to see that num_of_leaves | ||
| // is a constant, else this will be pretty expensive. | ||
| pub fn calculate_subtree<N>(leaves : [Field; N]) -> Field { | ||
| let num_of_leaves = leaves.len(); | ||
| if num_of_leaves == 128 { | ||
| calculate_subtree_128(leaves.as_slice()) | ||
| } else if num_of_leaves == 64 { | ||
| calculate_subtree_64(leaves.as_slice()) | ||
| } else if num_of_leaves == 32 { | ||
| calculate_subtree_32(leaves.as_slice()) | ||
| } else if num_of_leaves == 16 { | ||
| calculate_subtree_16(leaves.as_slice()) | ||
| } else if num_of_leaves == 8 { | ||
| calculate_subtree_8(leaves.as_slice()) | ||
| } else if num_of_leaves == 4 { | ||
| calculate_subtree_4(leaves.as_slice()) | ||
| } else if num_of_leaves == 2 { | ||
| calculate_subtree_2(leaves.as_slice()) | ||
| } else { | ||
| assert(false, "number of leaves should be 2, 4, 8, or 16"); | ||
|
kevaundray marked this conversation as resolved.
Outdated
|
||
| 0 | ||
| } | ||
| } | ||
|
|
||
| fn calculate_subtree_128(leaves : [Field]) -> Field { | ||
| assert(leaves.len() == 128, "number of leaves should be 128"); | ||
|
|
||
| let mut layer = [0; 64]; | ||
| for i in 0..layer.len() { | ||
| let combined = [leaves[2 * i], leaves[2 * i + 1]]; | ||
| layer[i] = dep::std::hash::pedersen_hash(combined); | ||
| } | ||
|
|
||
| calculate_subtree_64(layer.as_slice()) | ||
| } | ||
| fn calculate_subtree_64(leaves : [Field]) -> Field { | ||
| assert(leaves.len() == 64, "number of leaves should be 64"); | ||
|
|
||
| let mut layer = [0; 32]; | ||
| for i in 0..layer.len() { | ||
| let combined = [leaves[2 * i], leaves[2 * i + 1]]; | ||
| layer[i] = dep::std::hash::pedersen_hash(combined); | ||
| } | ||
|
|
||
| calculate_subtree_32(layer.as_slice()) | ||
| } | ||
| fn calculate_subtree_32(leaves : [Field]) -> Field { | ||
| assert(leaves.len() == 32, "number of leaves should be 32"); | ||
|
|
||
| let mut layer = [0; 16]; | ||
| for i in 0..layer.len() { | ||
| let combined = [leaves[2 * i], leaves[2 * i + 1]]; | ||
| layer[i] = dep::std::hash::pedersen_hash(combined); | ||
| } | ||
|
|
||
| calculate_subtree_16(layer.as_slice()) | ||
| } | ||
| fn calculate_subtree_16(leaves : [Field]) -> Field { | ||
| assert(leaves.len() == 16, "number of leaves should be 16"); | ||
|
|
||
| let mut layer = [0; 8]; | ||
| for i in 0..layer.len() { | ||
| let combined = [leaves[2 * i], leaves[2 * i + 1]]; | ||
| layer[i] = dep::std::hash::pedersen_hash(combined); | ||
| } | ||
|
|
||
| calculate_subtree_8(layer.as_slice()) | ||
| } | ||
| fn calculate_subtree_8(leaves : [Field]) -> Field { | ||
| assert(leaves.len() == 8, "number of leaves should be 8"); | ||
|
|
||
| let mut layer = [0; 4]; | ||
| for i in 0..layer.len() { | ||
| let combined = [leaves[2 * i], leaves[2 * i + 1]]; | ||
| layer[i] = dep::std::hash::pedersen_hash(combined); | ||
| } | ||
|
|
||
| calculate_subtree_4(layer) | ||
| } | ||
| fn calculate_subtree_4(leaves : [Field]) -> Field { | ||
| assert(leaves.len() == 4, "number of leaves should be 4"); | ||
|
|
||
| let mut layer = [0; 2]; | ||
| for i in 0..layer.len() { | ||
| let combined = [leaves[2 * i], leaves[2 * i + 1]]; | ||
| layer[i] = dep::std::hash::pedersen_hash(combined); | ||
| } | ||
|
|
||
| calculate_subtree_2(layer.as_slice()) | ||
| } | ||
| fn calculate_subtree_2(leaves : [Field]) -> Field { | ||
| dep::std::hash::pedersen_hash(leaves) | ||
| } | ||
|
|
||
| // These values are precomputed and we run tests to ensure that they | ||
| // are correct. The values themselves were computed from the cpp code. | ||
| // | ||
| // Would be good if we could use width since the compute_subtree | ||
| // algorithm uses depth. | ||
| fn calculate_empty_tree_root(depth : Field) -> Field { | ||
|
kevaundray marked this conversation as resolved.
Outdated
|
||
| if depth == 1 { | ||
| 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed | ||
| } else if depth == 2 { | ||
| 0x21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a71550 | ||
| } else if depth == 3{ | ||
| 0x0bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb | ||
| } else if depth == 4 { | ||
| 0x06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d | ||
| } else if depth == 5 { | ||
| 0x03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa0 | ||
| } else if depth == 6 { | ||
| 0x15d28cad4c0736decea8997cb324cf0a0e0602f4d74472cd977bce2c8dd9923f | ||
| } else if depth == 7 { | ||
| 0x268ed1e1c94c3a45a14db4108bc306613a1c23fab68e0466a002dfb0a3f8d2ab | ||
| } else if depth == 8 { | ||
| 0x0cd8d5695bc2dde99dd531671f76f1482f14ddba8eeca7cb9686d4a62359c257 | ||
| } else if depth == 9 { | ||
| 0x047fbb7eb974155702149e58ea6ad91f4c6e953e693db35e953e250d8ceac9a9 | ||
| } else if depth == 10 { | ||
| 0x00c5ae2526e665e2c7c698c11a06098b7159f720606d50e7660deb55758b0b02 | ||
| } else { | ||
| assert(false, "depth should be between 1 and 10"); | ||
| 0 | ||
| } | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_merkle_root_interop_test() { | ||
| // This is a test to ensure that we match the cpp implementation. | ||
| // You can grep for `TEST_F(root_rollup_tests, noir_interop_test)` | ||
| // to find the test that matches this. | ||
| let root = calculate_subtree([1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4]); | ||
| assert(0x17e8bb70a11d0c946345950879484d2f4f9fef397ff6adbfdec3baab2d41faab == root); | ||
|
|
||
| let empty_root = calculate_subtree([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); | ||
| assert(0x06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d == empty_root); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_empty_subroot() { | ||
| let expected_empty_root_2 = calculate_subtree([0,0]); | ||
| assert(calculate_empty_tree_root(1) == expected_empty_root_2); | ||
|
|
||
| let expected_empty_root_4 = calculate_subtree([0,0,0,0]); | ||
| assert(calculate_empty_tree_root(2) == expected_empty_root_4); | ||
|
|
||
| let expected_empty_root_8 = calculate_subtree([0,0,0,0,0,0,0,0]); | ||
| assert(calculate_empty_tree_root(3) == expected_empty_root_8); | ||
|
|
||
| let expected_empty_root_16 = calculate_subtree([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); | ||
| assert(calculate_empty_tree_root(4) == expected_empty_root_16); | ||
|
|
||
| let expected_empty_root_32 = calculate_subtree([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); | ||
| assert(calculate_empty_tree_root(5) == expected_empty_root_32); | ||
|
|
||
| let expected_empty_root_64 = calculate_subtree([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); | ||
| assert(calculate_empty_tree_root(6) == expected_empty_root_64); | ||
|
|
||
| let expected_empty_root_128 = calculate_subtree([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); | ||
| assert(calculate_empty_tree_root(7) == expected_empty_root_128); | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.