Skip to content

Commit

Permalink
feat: Enable merge and root rollup circuits in noir (#3248)
Browse files Browse the repository at this point in the history
Enables the noir version of the merge and root rollup circuits.

# Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if
the PR is ready to merge.
- [ ] If the pull request requires a cryptography review (e.g.
cryptographic algorithm implementations) I have added the 'crypto' tag.
- [x] I have reviewed my diff in github, line by line and removed
unexpected formatting changes, testing logs, or commented-out code.
- [x] Every change is related to the PR description.
- [ ] I have
[linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
this pull request to relevant issues (if any exist).

---------

Co-authored-by: ludamad <adam.domurad@gmail.com>
Co-authored-by: kevaundray <kevtheappdev@gmail.com>
  • Loading branch information
3 people authored Nov 9, 2023
1 parent 69dc616 commit 68555fc
Show file tree
Hide file tree
Showing 34 changed files with 1,168 additions and 159 deletions.
2 changes: 1 addition & 1 deletion yarn-project/end-to-end/src/benchmarks/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export async function sendTxs(
contract: BenchmarkingContract,
): Promise<SentTx[]> {
const calls = times(txCount, index => makeCall(index, context, contract));
calls.forEach(call => call.simulate({ skipPublicSimulation: true }));
await Promise.all(calls.map(call => call.simulate({ skipPublicSimulation: true })));
const sentTxs = calls.map(call => call.send());

// Awaiting txHash waits until the aztec node has received the tx into its p2p pool
Expand Down
1 change: 0 additions & 1 deletion yarn-project/noir-protocol-circuits/.prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
src/crates
src/target
src/types
2 changes: 1 addition & 1 deletion yarn-project/noir-protocol-circuits/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"formatting": "run -T prettier --check ./src && run -T eslint ./src",
"formatting:fix": "run -T prettier -w ./src",
"noir:build": "cd src && nargo compile --no-backend && rm -rf ./target/debug_*",
"noir:types": "yarn ts-node --esm src/scripts/generate_ts_from_abi.ts",
"noir:types": "yarn ts-node --esm src/scripts/generate_ts_from_abi.ts && yarn formatting:fix",
"noir:test": "cd src && nargo test",
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --passWithNoTests"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "rollup_merge"
name = "rollup_base"
type = "bin"
authors = [""]
compiler_version = ">=0.18.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod merge_rollup_inputs;
mod root_rollup_inputs;
mod previous_rollup_data;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::merge::merge_rollup_inputs::MergeRollupInputs;
use crate::abis::base_or_merge_rollup_public_inputs::BASE_ROLLUP_TYPE;
use crate::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot;
use crate::fixtures::previous_rollup_data::default_previous_rollup_data;

pub fn default_merge_rollup_inputs() -> MergeRollupInputs {
let mut inputs: MergeRollupInputs = dep::std::unsafe::zeroed();

inputs.previous_rollup_data = default_previous_rollup_data();

inputs
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use crate::abis::base_or_merge_rollup_public_inputs::BASE_ROLLUP_TYPE;
use crate::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot;
use crate::abis::previous_rollup_data::PreviousRollupData;

pub fn default_previous_rollup_data() -> [PreviousRollupData; 2] {
let mut previous_rollup_data: [PreviousRollupData; 2] = dep::std::unsafe::zeroed();

previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_note_hash_tree_snapshot = AppendOnlyTreeSnapshot {
root: 0,
next_available_leaf_index: 0
};
previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_note_hash_tree_snapshot = AppendOnlyTreeSnapshot {
root: 1,
next_available_leaf_index: 1
};
previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_note_hash_tree_snapshot = AppendOnlyTreeSnapshot {
root: 1,
next_available_leaf_index: 1
};
previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_note_hash_tree_snapshot = AppendOnlyTreeSnapshot {
root: 2,
next_available_leaf_index: 2
};

previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_nullifier_tree_snapshot = AppendOnlyTreeSnapshot {
root: 0,
next_available_leaf_index: 0
};
previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_nullifier_tree_snapshot = AppendOnlyTreeSnapshot {
root: 1,
next_available_leaf_index: 1
};
previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_nullifier_tree_snapshot = AppendOnlyTreeSnapshot {
root: 1,
next_available_leaf_index: 1
};
previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_nullifier_tree_snapshot = AppendOnlyTreeSnapshot {
root: 2,
next_available_leaf_index: 2
};

previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_contract_tree_snapshot = AppendOnlyTreeSnapshot {
root: 0,
next_available_leaf_index: 0
};
previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_contract_tree_snapshot = AppendOnlyTreeSnapshot {
root: 1,
next_available_leaf_index: 1
};
previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_contract_tree_snapshot = AppendOnlyTreeSnapshot {
root: 1,
next_available_leaf_index: 1
};
previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_contract_tree_snapshot = AppendOnlyTreeSnapshot {
root: 2,
next_available_leaf_index: 2
};

previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_public_data_tree_root = 3;
previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_public_data_tree_root = 3;

previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = BASE_ROLLUP_TYPE;
previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = BASE_ROLLUP_TYPE;

previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_subtree_height = 1;
previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_subtree_height = 1;

previous_rollup_data[0].base_or_merge_rollup_public_inputs.calldata_hash = [0, 1];
previous_rollup_data[1].base_or_merge_rollup_public_inputs.calldata_hash = [2, 3];

previous_rollup_data
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use crate::{
root::{
root_rollup_inputs::RootRollupInputs,
},
};
use dep::aztec::constants_gen::{
L1_TO_L2_MSG_TREE_HEIGHT,
L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
L1_TO_L2_MSG_SUBTREE_HEIGHT,
HISTORIC_BLOCKS_TREE_HEIGHT,
};
use crate::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot;
use crate::fixtures::previous_rollup_data::default_previous_rollup_data;

pub fn compute_zero_hashes<N>(mut hashes: [Field; N]) -> [Field; N] {
hashes[0] = dep::std::hash::pedersen_hash([0, 0]);

for i in 1..N {
hashes[i] = dep::std::hash::pedersen_hash([hashes[i-1], hashes[i-1]]);
}

hashes
}

pub fn compute_l1_l2_empty_snapshot() -> (AppendOnlyTreeSnapshot, [Field; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH]) {
let zero_hashes = compute_zero_hashes([0; L1_TO_L2_MSG_TREE_HEIGHT]);
let mut new_l1_to_l2_messages_tree_root_sibling_path = [0; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH];

for i in 0..L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH {
let index = L1_TO_L2_MSG_SUBTREE_HEIGHT + i - 1;
new_l1_to_l2_messages_tree_root_sibling_path[i] = zero_hashes[index];
}

(AppendOnlyTreeSnapshot{ root: zero_hashes[zero_hashes.len() - 1], next_available_leaf_index: 0 }, new_l1_to_l2_messages_tree_root_sibling_path)
}

pub fn compute_historic_blocks_tree_snapshot() -> (AppendOnlyTreeSnapshot, [Field; HISTORIC_BLOCKS_TREE_HEIGHT]) {
let zero_hashes = compute_zero_hashes([0; HISTORIC_BLOCKS_TREE_HEIGHT]);
let mut sibling_path = [0; HISTORIC_BLOCKS_TREE_HEIGHT];
for i in 1..HISTORIC_BLOCKS_TREE_HEIGHT {
sibling_path[i] = zero_hashes[i-1];
}
(AppendOnlyTreeSnapshot { root: zero_hashes[zero_hashes.len() - 1], next_available_leaf_index: 0 }, sibling_path)
}


pub fn default_root_rollup_inputs() -> RootRollupInputs {
let mut inputs: RootRollupInputs = dep::std::unsafe::zeroed();
let (l1_l2_empty_snapshot, l1_l2_empty_sibling_path) = compute_l1_l2_empty_snapshot();

inputs.new_l1_to_l2_messages_tree_root_sibling_path = l1_l2_empty_sibling_path;
inputs.start_l1_to_l2_messages_tree_snapshot = l1_l2_empty_snapshot;

let (historic_blocks_snapshot, historic_blocks_sibling_path) = compute_historic_blocks_tree_snapshot();

inputs.start_historic_blocks_tree_snapshot = historic_blocks_snapshot;
inputs.new_historic_blocks_tree_sibling_path = historic_blocks_sibling_path;

inputs.previous_rollup_data = default_previous_rollup_data();

inputs
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ mod components;

mod hash;

mod merkle_tree;
mod merkle_tree;

mod fixtures;
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,146 @@ impl MergeRollupInputs {

public_inputs
}
}

mod tests {
use crate::{
merge::merge_rollup_inputs::MergeRollupInputs,
fixtures::merge_rollup_inputs::default_merge_rollup_inputs,
};
use dep::types::hash::accumulate_sha256;
use dep::types::utils::uint128::U128;


#[test(should_fail_with="input proofs are of different rollup types")]
fn different_rollup_type_fails(){
let mut inputs = default_merge_rollup_inputs();
inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 0;
inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = 1;
let _output = inputs.merge_rollup_circuit();
}

#[test(should_fail_with="input proofs are of different rollup heights")]
fn different_height_fails(){
let mut inputs = default_merge_rollup_inputs();
inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_subtree_height = 0;
inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_subtree_height = 1;
let _output = inputs.merge_rollup_circuit();
}

#[test(should_fail_with="input proofs have different constants")]
fn constants_different_fails(){
let mut inputs = default_merge_rollup_inputs();
inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants.public_kernel_vk_tree_root = 1;
inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.public_kernel_vk_tree_root = 0;
let _output = inputs.merge_rollup_circuit();
}

#[test(should_fail_with="input proofs have different constants")]
fn constants_different_chain_id_fails(){
let mut inputs = default_merge_rollup_inputs();
inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants.global_variables.chain_id = 1;
inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.global_variables.chain_id = 0;
let _output = inputs.merge_rollup_circuit();
}

#[test(should_fail_with="input proofs have different note hash tree snapshots")]
fn previous_rollups_dont_follow_note_hash(){
let mut inputs = default_merge_rollup_inputs();
inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_note_hash_tree_snapshot.root = 0;
inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_note_hash_tree_snapshot.root = 1;
let _output = inputs.merge_rollup_circuit();
}

#[test(should_fail_with="input proofs have different nullifier tree snapshots")]
fn previous_rollups_dont_follow_nullifier(){
let mut inputs = default_merge_rollup_inputs();
inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_nullifier_tree_snapshot.root = 0;
inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_nullifier_tree_snapshot.root = 1;
let _output = inputs.merge_rollup_circuit();
}

#[test(should_fail_with="input proofs have different contract tree snapshots")]
fn previous_rollups_dont_follow_contracts(){
let mut inputs = default_merge_rollup_inputs();
inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.end_contract_tree_snapshot.root = 0;
inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.start_contract_tree_snapshot.root = 1;
let _output = inputs.merge_rollup_circuit();
}

#[test]
fn rollup_fields_are_set_correctly(){
let mut inputs = default_merge_rollup_inputs();
let mut outputs = inputs.merge_rollup_circuit();
assert_eq(outputs.rollup_type, 1);
assert_eq(outputs.rollup_subtree_height, inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_subtree_height + 1);

// set inputs to have a merge rollup type and set the rollup height and test again.
inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 1;
inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_subtree_height = 1;

inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = 1;
inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_subtree_height = 1;

outputs = inputs.merge_rollup_circuit();
assert_eq(outputs.rollup_type, 1);
assert_eq(outputs.rollup_subtree_height, 2);
}

#[test]
fn start_and_end_snapshots(){
let mut inputs = default_merge_rollup_inputs();
let outputs = inputs.merge_rollup_circuit();

assert(
outputs.start_note_hash_tree_snapshot.eq(inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_note_hash_tree_snapshot)
);
assert(
outputs.end_note_hash_tree_snapshot.eq(inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_note_hash_tree_snapshot)
);

assert(
outputs.start_nullifier_tree_snapshot.eq(inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_nullifier_tree_snapshot)
);
assert(
outputs.end_nullifier_tree_snapshot.eq(inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_nullifier_tree_snapshot)
);

assert(
outputs.start_contract_tree_snapshot.eq(inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_contract_tree_snapshot)
);
assert(
outputs.end_contract_tree_snapshot.eq(inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_contract_tree_snapshot)
);

assert_eq(
outputs.start_public_data_tree_root, inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_public_data_tree_root
);
assert_eq(
outputs.end_public_data_tree_root, inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end_public_data_tree_root
);
}

#[test]
fn calldata_hash(){
let mut inputs = default_merge_rollup_inputs();
let expected_calldata_hash = accumulate_sha256([
U128::from_field(0),
U128::from_field(1),
U128::from_field(2),
U128::from_field(3)
]);
let outputs = inputs.merge_rollup_circuit();

assert_eq(outputs.calldata_hash, expected_calldata_hash);
}

#[test]
fn constants_dont_change(){
let mut inputs = default_merge_rollup_inputs();
let outputs = inputs.merge_rollup_circuit();

assert(inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants.eq(outputs.constants));
assert(inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.eq(outputs.constants));
}
}
Loading

0 comments on commit 68555fc

Please sign in to comment.