diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index ffe93c8dfd0..bbc11756c56 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -57,7 +57,7 @@ impl PublicKernelTailCircuitPrivateInputs { hint.leaf_slot, exists_in_tree, hint.leaf_preimage, - MembershipWitness { leaf_index: hint.membership_witness.leaf_index, sibling_path: hint.membership_witness.sibling_path }, + hint.membership_witness, public_data_tree_root ); } @@ -115,19 +115,20 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, kernel_data::PublicKernelData, - nullifier_leaf_preimage::NullifierLeafPreimage, membership_witness::PublicDataMembershipWitness + nullifier_leaf_preimage::NullifierLeafPreimage }, constants::{ MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX }, hash::{silo_nullifier, sha256_to_field}, public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, tests::{fixture_builder::FixtureBuilder, merkle_tree_utils::NonEmptyMerkleTree}, - partial_state_reference::PartialStateReference, utils::arrays::array_merge + partial_state_reference::PartialStateReference, utils::arrays::array_merge, + merkle_tree::MembershipWitness }; fn build_nullifier_tree() -> NonEmptyMerkleTree { @@ -264,7 +265,7 @@ mod tests { pub fn add_public_data_hint_for_settled_public_data(&mut self, leaf_index: u64) { let leaf_preimage = get_settled_public_data_leaves()[leaf_index]; - let membership_witness = PublicDataMembershipWitness { leaf_index: leaf_index as Field, sibling_path: self.public_data_tree.get_sibling_path(leaf_index) }; + let membership_witness = MembershipWitness { leaf_index: leaf_index as Field, sibling_path: self.public_data_tree.get_sibling_path(leaf_index) }; let hint = PublicDataHint { leaf_slot: leaf_preimage.slot, value: leaf_preimage.value, @@ -277,7 +278,7 @@ mod tests { pub fn add_public_data_hint_for_non_existent_public_data(&mut self, leaf_slot: Field, low_leaf_index: u64) { let leaf_preimage = get_settled_public_data_leaves()[low_leaf_index]; - let membership_witness = PublicDataMembershipWitness { + let membership_witness = MembershipWitness { leaf_index: low_leaf_index as Field, sibling_path: self.public_data_tree.get_sibling_path(low_leaf_index) }; @@ -360,18 +361,11 @@ mod tests { public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length ); - let hash_bytes: [u8; MAX_ENCRYPTED_LOGS_PER_TX * 32] = prev_encrypted_logs_hash - .to_be_bytes(32) - .append(&[0; MAX_ENCRYPTED_LOGS_PER_TX * 32 - 32]) - .as_array(); + let hash_bytes: [u8; MAX_ENCRYPTED_LOGS_PER_TX * 32] = prev_encrypted_logs_hash.to_be_bytes(32).append(&[0; MAX_ENCRYPTED_LOGS_PER_TX * 32 - 32]).as_array(); let expected_encrypted_logs_hash = sha256_to_field(hash_bytes); assert_eq(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); - let hash_bytes: [u8; MAX_UNENCRYPTED_LOGS_PER_TX * 32] = prev_unencrypted_logs_hash - .to_be_bytes(32) - .append(unencrypted_logs_hash.to_be_bytes(32)) - .append(&[0; MAX_UNENCRYPTED_LOGS_PER_TX * 32 - 64]) - .as_array(); + let hash_bytes: [u8; MAX_UNENCRYPTED_LOGS_PER_TX * 32] = prev_unencrypted_logs_hash.to_be_bytes(32).append(unencrypted_logs_hash.to_be_bytes(32)).append(&[0; MAX_UNENCRYPTED_LOGS_PER_TX * 32 - 64]).as_array(); let expected_unencrypted_logs_hash = sha256_to_field(hash_bytes); assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr index 8c40d7c2cf3..8bb008c5421 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr @@ -1,14 +1,14 @@ // This will be moved to a separate Read Request Reset Circuit. use crate::reset::read_request::{PendingReadHint, ReadRequestStatus, ReadValueHint, SettledReadHint}; use dep::types::{ - abis::{membership_witness::NoteHashMembershipWitness, note_hash_leaf_preimage::NoteHashLeafPreimage}, + abis::{note_hash_leaf_preimage::NoteHashLeafPreimage}, constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_TX, NOTE_HASH_TREE_HEIGHT}, merkle_tree::MembershipWitness }; struct NoteHashSettledReadHint { read_request_index: u64, - membership_witness: NoteHashMembershipWitness, // Should be MembershipWitness when we can handle generics when converting to ts types. + membership_witness: MembershipWitness, leaf_preimage: NoteHashLeafPreimage, } @@ -20,7 +20,7 @@ impl ReadValueHint for NoteHashSettledReadHint { impl SettledReadHint for NoteHashSettledReadHint { fn membership_witness(self) -> MembershipWitness { - MembershipWitness { leaf_index: self.membership_witness.leaf_index, sibling_path: self.membership_witness.sibling_path } + self.membership_witness } fn leaf_preimage(self) -> NoteHashLeafPreimage { @@ -30,7 +30,7 @@ impl SettledReadHint for NoteHashSe fn nada(read_request_len: u64) -> Self { NoteHashSettledReadHint { read_request_index: read_request_len, - membership_witness: NoteHashMembershipWitness::empty(), + membership_witness: MembershipWitness::empty(), leaf_preimage: NoteHashLeafPreimage::empty() } } @@ -46,10 +46,10 @@ mod tests { use crate::note_hash_read_request_reset::NoteHashSettledReadHint; use crate::reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus, reset_read_requests}; use dep::types::{ - address::AztecAddress, + address::AztecAddress, merkle_tree::MembershipWitness, abis::{ - membership_witness::NoteHashMembershipWitness, note_hash::NoteHashContext, - note_hash_leaf_preimage::NoteHashLeafPreimage, read_request::ReadRequestContext + note_hash::NoteHashContext, note_hash_leaf_preimage::NoteHashLeafPreimage, + read_request::ReadRequestContext }, constants::NOTE_HASH_TREE_HEIGHT, hash::silo_note_hash, tests::merkle_tree_utils::NonEmptyMerkleTree @@ -108,12 +108,12 @@ mod tests { let hints = [ NoteHashSettledReadHint { read_request_index: 0, - membership_witness: NoteHashMembershipWitness { leaf_index: 1, sibling_path: tree.get_sibling_path(1) }, + membership_witness: MembershipWitness { leaf_index: 1, sibling_path: tree.get_sibling_path(1) }, leaf_preimage: leaf_preimages[1] }, NoteHashSettledReadHint { read_request_index: 3, - membership_witness: NoteHashMembershipWitness { leaf_index: 0, sibling_path: tree.get_sibling_path(0) }, + membership_witness: MembershipWitness { leaf_index: 0, sibling_path: tree.get_sibling_path(0) }, leaf_preimage: leaf_preimages[0] } ]; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types/public_data_hint.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types/public_data_hint.nr index 28a3eb74cb0..2bd7316a9a9 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types/public_data_hint.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types/public_data_hint.nr @@ -1,14 +1,14 @@ use crate::reset::{mutable_data_read_request::LeafDataHint}; use dep::types::{ - abis::membership_witness::PublicDataMembershipWitness, - public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage + public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, merkle_tree::MembershipWitness, + constants::PUBLIC_DATA_TREE_HEIGHT }; struct PublicDataHint { leaf_slot: Field, value: Field, override_counter: u32, - membership_witness: PublicDataMembershipWitness, // Should be MembershipWitness when we can handle generics when converting to ts types. + membership_witness: MembershipWitness, // Should be MembershipWitness when we can handle generics when converting to ts types. leaf_preimage: PublicDataTreeLeafPreimage, } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr index aecee269f9e..07abf8e362c 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr @@ -1,9 +1,7 @@ use crate::abis::base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs; use dep::types::{ - abis::membership_witness::VKMembershipWitness, - constants::ROLLUP_VK_TREE_HEIGHT, - mocked::{Proof, VerificationKey}, - traits::Empty + constants::ROLLUP_VK_TREE_HEIGHT, mocked::{Proof, VerificationKey}, traits::Empty, + merkle_tree::MembershipWitness }; struct PreviousRollupData{ @@ -11,7 +9,7 @@ struct PreviousRollupData{ proof : Proof, vk : VerificationKey, vk_index : u32, - vk_sibling_path : VKMembershipWitness, + vk_sibling_path : MembershipWitness, } impl Empty for PreviousRollupData { @@ -21,7 +19,7 @@ impl Empty for PreviousRollupData { proof : Proof::empty(), vk : VerificationKey::empty(), vk_index : 0 as u32, - vk_sibling_path : VKMembershipWitness::empty(), + vk_sibling_path : MembershipWitness::empty(), } } -} \ No newline at end of file +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index 3df978857ad..238cc1dbd13 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -9,10 +9,9 @@ use crate::{ use dep::types::{ hash::sha256_to_field, abis::{ - append_only_tree_snapshot::AppendOnlyTreeSnapshot, - membership_witness::{ArchiveRootMembershipWitness, NullifierMembershipWitness, PublicDataMembershipWitness}, - nullifier_leaf_preimage::NullifierLeafPreimage, public_data_update_request::PublicDataUpdateRequest, - public_data_read::PublicDataRead, kernel_data::KernelData + append_only_tree_snapshot::AppendOnlyTreeSnapshot, nullifier_leaf_preimage::NullifierLeafPreimage, + public_data_update_request::PublicDataUpdateRequest, public_data_read::PublicDataRead, + kernel_data::KernelData }, constants::{ NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, @@ -20,7 +19,7 @@ use dep::types::{ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, NUM_ENCRYPTED_LOGS_HASHES_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, NUM_UNENCRYPTED_LOGS_HASHES_PER_TX, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, - PUBLIC_DATA_SUBTREE_HEIGHT + PUBLIC_DATA_SUBTREE_HEIGHT, ARCHIVE_HEIGHT }, merkle_tree::{ append_only_tree, assert_check_membership, calculate_empty_tree_root, calculate_subtree_root, @@ -43,9 +42,9 @@ struct BaseRollupInputs { sorted_public_data_writes: [PublicDataTreeLeaf; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], sorted_public_data_writes_indexes: [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], low_public_data_writes_preimages: [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - low_public_data_writes_witnesses: [PublicDataMembershipWitness; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + low_public_data_writes_witnesses: [MembershipWitness; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - archive_root_membership_witness: ArchiveRootMembershipWitness, + archive_root_membership_witness: MembershipWitness, constants: ConstantRollupData, } @@ -148,7 +147,7 @@ impl BaseRollupInputs { self.state_diff_hints.nullifier_subtree_sibling_path, self.state_diff_hints.nullifier_predecessor_preimages, self.state_diff_hints.nullifier_predecessor_membership_witnesses.map( - |witness: NullifierMembershipWitness| { + |witness: MembershipWitness| { MembershipWitness { leaf_index: witness.leaf_index, sibling_path: witness.sibling_path, @@ -266,7 +265,7 @@ fn insert_public_data_update_requests( sorted_public_data_writes: [PublicDataTreeLeaf; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], sorted_public_data_writes_indexes: [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], low_public_data_writes_preimages: [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - low_public_data_writes_witnesses: [PublicDataMembershipWitness; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + low_public_data_writes_witnesses: [MembershipWitness; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], public_data_writes_subtree_sibling_path: [Field; PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH] ) -> AppendOnlyTreeSnapshot { indexed_tree::batch_insert( @@ -277,7 +276,7 @@ fn insert_public_data_update_requests( public_data_writes_subtree_sibling_path, low_public_data_writes_preimages, low_public_data_writes_witnesses.map( - |witness: PublicDataMembershipWitness| { + |witness: MembershipWitness| { MembershipWitness { leaf_index: witness.leaf_index, sibling_path: witness.sibling_path, @@ -369,12 +368,11 @@ mod tests { use dep::types::{ abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, - membership_witness::{ArchiveRootMembershipWitness, NullifierMembershipWitness, PublicDataMembershipWitness}, nullifier_leaf_preimage::NullifierLeafPreimage, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, kernel_data::KernelData, side_effect::SideEffect, accumulated_data::CombinedAccumulatedData }, - address::{AztecAddress, EthAddress}, + merkle_tree::MembershipWitness, address::{AztecAddress, EthAddress}, constants::{ ARCHIVE_HEIGHT, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, @@ -409,12 +407,12 @@ mod tests { snapshot: AppendOnlyTreeSnapshot, public_data_writes: BoundedVec<(u64, PublicDataTreeLeaf), 2>, mut pre_existing_public_data: [PublicDataTreeLeafPreimage; EXISTING_LEAVES] - ) -> ([Field; 35], [PublicDataTreeLeaf; 32], [u64; 32], [PublicDataTreeLeafPreimage; 32], [PublicDataMembershipWitness; 32], [PublicDataTreeLeafPreimage; EXISTING_LEAVES]) { + ) -> ([Field; 35], [PublicDataTreeLeaf; 32], [u64; 32], [PublicDataTreeLeafPreimage; 32], [MembershipWitness; 32], [PublicDataTreeLeafPreimage; EXISTING_LEAVES]) { let mut subtree_path = [0; PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH]; let mut sorted_public_data_writes = [PublicDataTreeLeaf::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; let mut sorted_public_data_writes_indexes = [0 as u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; let mut low_public_data_writes_preimages = [PublicDataTreeLeafPreimage::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; - let mut low_public_data_writes_witnesses = [PublicDataMembershipWitness::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; + let mut low_public_data_writes_witnesses = [MembershipWitness::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; let mut new_subtree = [PublicDataTreeLeafPreimage::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; for i in 0..MAX_PUBLIC_DATA_WRITES_PER_TEST { @@ -458,7 +456,7 @@ mod tests { }; } low_public_data_writes_preimages[i] = low_leaf; - low_public_data_writes_witnesses[i] = PublicDataMembershipWitness { + low_public_data_writes_witnesses[i] = MembershipWitness { leaf_index: low_leaf_index as Field, sibling_path: public_data_tree.get_sibling_path(low_leaf_index) }; @@ -526,9 +524,9 @@ mod tests { nullifier_tree: &mut NonEmptyMerkleTree, kernel_data: &mut KernelData, start_nullifier_tree_snapshot: AppendOnlyTreeSnapshot - ) -> ([NullifierLeafPreimage; MAX_NEW_NULLIFIERS_PER_TX], [NullifierMembershipWitness; MAX_NEW_NULLIFIERS_PER_TX], [Field; MAX_NEW_NULLIFIERS_PER_TX], [u64; MAX_NEW_NULLIFIERS_PER_TX]) { + ) -> ([NullifierLeafPreimage; MAX_NEW_NULLIFIERS_PER_TX], [MembershipWitness; MAX_NEW_NULLIFIERS_PER_TX], [Field; MAX_NEW_NULLIFIERS_PER_TX], [u64; MAX_NEW_NULLIFIERS_PER_TX]) { let mut nullifier_predecessor_preimages = [NullifierLeafPreimage::empty(); MAX_NEW_NULLIFIERS_PER_TX]; - let mut low_nullifier_membership_witness = [NullifierMembershipWitness::empty(); MAX_NEW_NULLIFIERS_PER_TX]; + let mut low_nullifier_membership_witness = [MembershipWitness::empty(); MAX_NEW_NULLIFIERS_PER_TX]; let sorted_new_nullifier_tuples = sort_high_to_low( self.new_nullifiers.storage.map(|insertion: NullifierInsertion| insertion.value), @@ -562,7 +560,7 @@ mod tests { let mut low_preimage = pre_existing_nullifiers[low_index]; nullifier_predecessor_preimages[i] = low_preimage; - low_nullifier_membership_witness[i] = NullifierMembershipWitness { + low_nullifier_membership_witness[i] = MembershipWitness { leaf_index: low_index as Field, sibling_path: nullifier_tree.get_sibling_path(low_index) }; @@ -687,7 +685,7 @@ mod tests { sorted_public_data_writes_indexes, low_public_data_writes_preimages, low_public_data_writes_witnesses, - archive_root_membership_witness: ArchiveRootMembershipWitness { leaf_index: 0, sibling_path: start_archive.get_sibling_path(0) }, + archive_root_membership_witness: MembershipWitness { leaf_index: 0, sibling_path: start_archive.get_sibling_path(0) }, constants: self.constants } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr index 9c7dd03d70d..6af5eb698af 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr @@ -1,14 +1,16 @@ use dep::types::{ - abis::{membership_witness::NullifierMembershipWitness, nullifier_leaf_preimage::NullifierLeafPreimage}, + abis::{nullifier_leaf_preimage::NullifierLeafPreimage}, constants::{ MAX_NEW_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, - NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH -} + NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, + NULLIFIER_TREE_HEIGHT +}, + merkle_tree::MembershipWitness }; struct StateDiffHints { nullifier_predecessor_preimages: [NullifierLeafPreimage; MAX_NEW_NULLIFIERS_PER_TX], - nullifier_predecessor_membership_witnesses: [NullifierMembershipWitness; MAX_NEW_NULLIFIERS_PER_TX], + nullifier_predecessor_membership_witnesses: [MembershipWitness; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers: [Field; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifier_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr index 2d0566b9c0d..2c2a9325bcb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr @@ -6,9 +6,6 @@ mod function_selector; mod function_data; mod global_variables; - -mod membership_witness; - mod note_hash_leaf_preimage; mod nullifier_leaf_preimage; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/membership_witness.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/membership_witness.nr deleted file mode 100644 index e0dfc960f08..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/membership_witness.nr +++ /dev/null @@ -1,77 +0,0 @@ -use crate::{ - constants::{ - FUNCTION_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, ROLLUP_VK_TREE_HEIGHT, - ARCHIVE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT -}, - traits::Empty -}; - -// TODO(Kev): Instead of doing `MembershipWitness` we are forced -// to do this new struct because the typescript bindings generator -// does not have logic to monomorphize these properly. See the file named -// `typechain-type-alias` in the folder `bug-collecting-crate` -struct FunctionLeafMembershipWitness{ - leaf_index: Field, - sibling_path: [Field; FUNCTION_TREE_HEIGHT] -} - -struct VKMembershipWitness{ - leaf_index: Field, - sibling_path: [Field; ROLLUP_VK_TREE_HEIGHT] -} - -struct NullifierMembershipWitness{ - leaf_index: Field, - sibling_path: [Field; NULLIFIER_TREE_HEIGHT] -} - -struct PublicDataMembershipWitness{ - leaf_index: Field, - sibling_path: [Field; PUBLIC_DATA_TREE_HEIGHT] -} - -struct ArchiveRootMembershipWitness{ - leaf_index: Field, - sibling_path: [Field; ARCHIVE_HEIGHT] -} - -struct NoteHashMembershipWitness { - leaf_index: Field, - sibling_path: [Field; NOTE_HASH_TREE_HEIGHT], -} - -impl Empty for VKMembershipWitness { - fn empty() -> Self { - VKMembershipWitness { - leaf_index: 0, - sibling_path: [0; ROLLUP_VK_TREE_HEIGHT] - } - } -} - -impl Empty for NullifierMembershipWitness { - fn empty() -> Self { - NullifierMembershipWitness { - leaf_index: 0, - sibling_path: [0; NULLIFIER_TREE_HEIGHT] - } - } -} - -impl Empty for PublicDataMembershipWitness { - fn empty() -> Self { - PublicDataMembershipWitness { - leaf_index: 0, - sibling_path: [0; PUBLIC_DATA_TREE_HEIGHT] - } - } -} - -impl Empty for NoteHashMembershipWitness { - fn empty() -> Self { - NoteHashMembershipWitness { - leaf_index: 0, - sibling_path: [0; NOTE_HASH_TREE_HEIGHT] - } - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index e00c6c79a47..760189375dd 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -1,11 +1,9 @@ -use crate::abis::{ - call_request::CallRequest, private_call_stack_item::PrivateCallStackItem, - membership_witness::FunctionLeafMembershipWitness -}; +use crate::abis::{call_request::CallRequest, private_call_stack_item::PrivateCallStackItem}; use crate::address::{SaltedInitializationHash, PublicKeysHash, EthAddress}; use crate::contract_class_id::ContractClassId; use crate::mocked::{Proof, VerificationKey}; -use crate::constants::{MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL}; +use crate::constants::{MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, FUNCTION_TREE_HEIGHT}; +use crate::merkle_tree::membership::MembershipWitness; struct PrivateCallData { call_stack_item: PrivateCallStackItem, @@ -20,7 +18,7 @@ struct PrivateCallData { public_keys_hash: PublicKeysHash, contract_class_artifact_hash: Field, contract_class_public_bytecode_commitment: Field, - function_leaf_membership_witness: FunctionLeafMembershipWitness, + function_leaf_membership_witness: MembershipWitness, acir_hash: Field, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr index a5f7642811a..836e673b5e1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr @@ -1,13 +1,12 @@ -use crate::abis::{ - function_data::FunctionData, function_selector::FunctionSelector, - membership_witness::FunctionLeafMembershipWitness -}; +use crate::abis::{function_data::FunctionData, function_selector::FunctionSelector}; +use crate::merkle_tree::membership::MembershipWitness; +use crate::constants::FUNCTION_TREE_HEIGHT; struct ContractFunction { data: FunctionData, vk_hash: Field, acir_hash: Field, - membership_witness: FunctionLeafMembershipWitness, + membership_witness: MembershipWitness, } // sibling_path taken from __snapshots__/noir_test_gen.test.ts.snap @@ -18,7 +17,7 @@ global default_private_function = ContractFunction { }, vk_hash: 0, acir_hash: 1111, - membership_witness: FunctionLeafMembershipWitness { + membership_witness: MembershipWitness { leaf_index: 0, sibling_path: [ 0x1e5cebe7a50c5c8fd1ebe19ed6bbf80f77819b12a2a28f334e895501e1cda574, @@ -37,7 +36,7 @@ global default_public_function = ContractFunction { }, vk_hash: 0, acir_hash: 3333, - membership_witness: FunctionLeafMembershipWitness { + membership_witness: MembershipWitness { leaf_index: 2, sibling_path: [ 0x2d72ef5ebb7c974e1f5a8bed092f1cf1bf0a0cb1eda28516221ca7e5811ecf15, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr index c1b266fd6a0..a4c6a52930e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr @@ -2,16 +2,16 @@ use crate::{ abis::{ gas_settings::GasSettings, call_request::{CallerContext, CallRequest}, private_call_stack_item::PrivateCallStackItem, function_data::FunctionData, - max_block_number::MaxBlockNumber, membership_witness::FunctionLeafMembershipWitness, - private_circuit_public_inputs::PrivateCircuitPublicInputs, + max_block_number::MaxBlockNumber, private_circuit_public_inputs::PrivateCircuitPublicInputs, private_kernel::private_call_data::PrivateCallData, side_effect::SideEffect }, + merkle_tree::membership::MembershipWitness, address::{AztecAddress, EthAddress, SaltedInitializationHash, PublicKeysHash}, mocked::{Proof, VerificationKey}, tests::{fixtures, private_circuit_public_inputs_builder::PrivateCircuitPublicInputsBuilder}, transaction::{tx_request::TxRequest, tx_context::TxContext} }; -use crate::constants::{MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL}; +use crate::constants::{MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, FUNCTION_TREE_HEIGHT}; struct PrivateCallDataBuilder { // Values of PrivateCallStackItem. @@ -28,7 +28,7 @@ struct PrivateCallDataBuilder { public_keys_hash: PublicKeysHash, contract_class_artifact_hash: Field, contract_class_public_bytecode_commitment: Field, - function_leaf_membership_witness: FunctionLeafMembershipWitness, + function_leaf_membership_witness: MembershipWitness, acir_hash: Field, gas_settings: GasSettings, } diff --git a/yarn-project/noir-protocol-circuits-types/package.json b/yarn-project/noir-protocol-circuits-types/package.json index c8bcbff9171..83f918856b4 100644 --- a/yarn-project/noir-protocol-circuits-types/package.json +++ b/yarn-project/noir-protocol-circuits-types/package.json @@ -52,6 +52,7 @@ "@noir-lang/acvm_js": "portal:../../noir/packages/acvm_js", "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi", "@noir-lang/types": "portal:../../noir/packages/types", + "change-case": "^5.4.4", "tslib": "^2.4.0" }, "devDependencies": { diff --git a/yarn-project/noir-protocol-circuits-types/src/index.ts b/yarn-project/noir-protocol-circuits-types/src/index.ts index 6e48dddc7a3..5a0feac0424 100644 --- a/yarn-project/noir-protocol-circuits-types/src/index.ts +++ b/yarn-project/noir-protocol-circuits-types/src/index.ts @@ -71,26 +71,22 @@ import { mapRootRollupInputsToNoir, mapRootRollupPublicInputsFromNoir, } from './type_conversion.js'; -import { type ReturnType as BaseParityReturnType } from './types/parity_base_types.js'; -import { type ReturnType as RootParityReturnType } from './types/parity_root_types.js'; import { - type InputType as InitInputType, - type ReturnType as InitReturnType, -} from './types/private_kernel_init_types.js'; -import { - type InputType as InnerInputType, - type ReturnType as InnerReturnType, -} from './types/private_kernel_inner_types.js'; -import { type InputType as TailToPublicInputType } from './types/private_kernel_tail_to_public_types.js'; -import { - type InputType as TailInputType, - type ReturnType as TailReturnType, -} from './types/private_kernel_tail_types.js'; -import { type ReturnType as PublicPublicPreviousReturnType } from './types/public_kernel_app_logic_types.js'; -import { type ReturnType as PublicSetupReturnType } from './types/public_kernel_setup_types.js'; -import { type ReturnType as BaseRollupReturnType } from './types/rollup_base_types.js'; -import { type ReturnType as MergeRollupReturnType } from './types/rollup_merge_types.js'; -import { type ReturnType as RootRollupReturnType } from './types/rollup_root_types.js'; + type ParityBaseReturnType as BaseParityReturnType, + type RollupBaseReturnType as BaseRollupReturnType, + type PrivateKernelInitInputType as InitInputType, + type PrivateKernelInitReturnType as InitReturnType, + type PrivateKernelInnerInputType as InnerInputType, + type PrivateKernelInnerReturnType as InnerReturnType, + type RollupMergeReturnType as MergeRollupReturnType, + type PublicKernelAppLogicReturnType as PublicPublicPreviousReturnType, + type PublicKernelSetupReturnType as PublicSetupReturnType, + type ParityRootReturnType as RootParityReturnType, + type RollupRootReturnType as RootRollupReturnType, + type PrivateKernelTailInputType as TailInputType, + type PrivateKernelTailReturnType as TailReturnType, + type PrivateKernelTailToPublicInputType as TailToPublicInputType, +} from './types/index.js'; // TODO(Tom): This should be exported from noirc_abi /** diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/abi_type_with_generics.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/abi_type_with_generics.ts new file mode 100644 index 00000000000..c03dbb62a65 --- /dev/null +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/abi_type_with_generics.ts @@ -0,0 +1,127 @@ +import { type AbiType } from '@aztec/foundation/abi'; + +/** + * Represents a binding to a generic. + */ +export class BindingId { + constructor(public id: number, public isNumeric: boolean) {} +} + +export type StructType = { + path: string; + fields: { name: string; type: AbiTypeWithGenerics }[]; + /** The generics of the struct, bound to the fields */ + generics: BindingId[]; +}; + +export type StringType = { + kind: 'string'; + length: number | BindingId; +}; + +export type Constant = { + kind: 'constant'; + value: number; +}; + +export type ArrayType = { + kind: 'array'; + length: number | BindingId; + type: AbiTypeWithGenerics; +}; + +export type Tuple = { + kind: 'tuple'; + fields: AbiTypeWithGenerics[]; +}; + +export type Struct = { + kind: 'struct'; + structType: StructType; + /** The arguments are the concrete instantiation of the generics in the struct type. */ + args: AbiTypeWithGenerics[]; +}; + +export type AbiTypeWithGenerics = + | { kind: 'field' } + | { kind: 'boolean' } + | { kind: 'integer'; sign: string; width: number } + | { kind: 'binding'; id: BindingId } + | { kind: 'constant'; value: number } + | StringType + | ArrayType + | Tuple + | Struct; + +/** + * Maps an ABI type to an ABI type with generics. + * This performs pure type conversion, and does not generate any bindings. + */ +export function mapAbiTypeToAbiTypeWithGenerics(abiType: AbiType): AbiTypeWithGenerics { + switch (abiType.kind) { + case 'field': + case 'boolean': + case 'string': + case 'integer': + return abiType; + case 'array': + return { + kind: 'array', + length: abiType.length, + type: mapAbiTypeToAbiTypeWithGenerics(abiType.type), + }; + case 'struct': { + const structType = { + path: abiType.path, + fields: abiType.fields.map(field => ({ + name: field.name, + type: mapAbiTypeToAbiTypeWithGenerics(field.type), + })), + generics: [], + }; + return { + kind: 'struct', + structType, + args: [], + }; + } + } +} + +/** + * Finds the structs in an ABI type. + * This won't explore nested structs. + */ +export function findStructsInType(abiType: AbiTypeWithGenerics): Struct[] { + switch (abiType.kind) { + case 'field': + case 'boolean': + case 'string': + case 'integer': + return []; + case 'array': + return findStructsInType(abiType.type); + case 'tuple': + return abiType.fields.flatMap(findStructsInType); + case 'struct': + return [abiType]; + default: { + return []; + } + } +} + +/** + * Finds all the structs in an ABI type, including nested structs. + */ +export function findAllStructsInType(abiType: AbiTypeWithGenerics): Struct[] { + let allStructs: Struct[] = []; + let lastStructs = findStructsInType(abiType); + while (lastStructs.length > 0) { + allStructs = allStructs.concat(lastStructs); + lastStructs = lastStructs.flatMap(struct => + struct.structType.fields.flatMap(field => findStructsInType(field.type)), + ); + } + return allStructs; +} diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/demonomorphizer.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/demonomorphizer.ts new file mode 100644 index 00000000000..f2c513a329c --- /dev/null +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/demonomorphizer.ts @@ -0,0 +1,274 @@ +import { + type AbiTypeWithGenerics, + type ArrayType, + BindingId, + type Constant, + type StringType, + type Struct, + type StructType, + type Tuple, + findAllStructsInType, + findStructsInType, +} from './abi_type_with_generics.js'; + +/** + * Demonomorphizes a list of ABI types adding generics to structs. + * Since monomorphization of the generics destroys information, this process is not guaranteed to return the original structure. + * However, it should succesfully unify all struct types that share the same name and field names. + */ +export class Demonomorphizer { + private variantsMap: Map; + private visitedStructs: Map; + private lastBindingId = 0; + + /** + * Demonomorphizes the passed in ABI types, mutating them. + */ + public static demonomorphize(abiTypes: AbiTypeWithGenerics[]) { + new Demonomorphizer(abiTypes); + } + + private constructor(private types: AbiTypeWithGenerics[]) { + this.variantsMap = new Map(); + this.fillVariantsMap(); + + this.visitedStructs = new Map(); + this.demonomorphizeStructs(); + } + + /** + * Finds all the variants of the structs in the types. + * A variant is every use of a struct with the same name and fields. + */ + private fillVariantsMap() { + const allStructs = this.types.flatMap(findAllStructsInType); + for (const struct of allStructs) { + const id = Demonomorphizer.buildIdForStruct(struct.structType); + const variants = this.variantsMap.get(id) ?? []; + variants.push(struct); + this.variantsMap.set(id, variants); + } + } + + private demonomorphizeStructs() { + for (const type of this.types) { + const topLevelStructs = findStructsInType(type); + for (const struct of topLevelStructs) { + this.demonomorphizeStruct(struct); + } + } + } + + /** + * Demononomorphizes a struct, by demonomorphizing its dependencies first. + * Then it'll unify the types of the variants generating a unique generic type. + * It'll also generate args that instantiate the generic type with the concrete arguments for each variant. + */ + private demonomorphizeStruct(struct: Struct) { + const id = Demonomorphizer.buildIdForStruct(struct.structType); + if (this.visitedStructs.has(id)) { + return; + } + const dependencies = struct.structType.fields.flatMap(field => findStructsInType(field.type)); + for (const dependency of dependencies) { + this.demonomorphizeStruct(dependency); + } + if (this.visitedStructs.has(id)) { + throw new Error('Circular dependency detected'); + } + + const variants = this.variantsMap.get(id)!; + const mappedStructType = struct.structType; + + for (let i = 0; i < struct.structType.fields.length; i++) { + const variantTypes = variants.map(variant => variant.structType.fields[i].type); + const mappedType = this.unifyTypes(variantTypes, mappedStructType.generics, variants); + mappedStructType.fields[i].type = mappedType; + } + + // Mutate variants setting the new struct type + variants.forEach(variant => (variant.structType = mappedStructType)); + + this.visitedStructs.set(id, mappedStructType); + } + + /** + * Tries to unify the types of a set of variants recursively. + * Unification will imply replacing some properties with bindings and pushing bindings to the generics of the struct. + */ + private unifyTypes( + types: AbiTypeWithGenerics[], + generics: BindingId[], // Mutates generics adding new bindings + variants: Struct[], // mutates variants adding different args to the variants + ): AbiTypeWithGenerics { + const kinds = new Set(types.map(type => type.kind)); + if (kinds.size > 1) { + return this.buildBindingAndPushToVariants(types, generics, variants); + } + switch (types[0].kind) { + case 'field': + case 'boolean': + case 'binding': + return types[0]; + case 'integer': { + if (allDeepEqual(types)) { + return types[0]; + } else { + return this.buildBindingAndPushToVariants(types, generics, variants); + } + } + case 'string': { + const strings = types as StringType[]; + const unifiedString = strings[0]; + if (strings.every(string => string.length === unifiedString.length)) { + return unifiedString; + } else { + const unifiedStringType: StringType = unifiedString; + unifiedStringType.length = this.buildNumericBindingAndPushToVariants( + strings.map(string => { + if (typeof string.length !== 'number') { + throw new Error('Trying to unify strings with bindings'); + } + return string.length; + }), + generics, + variants, + ); + return unifiedStringType; + } + } + case 'array': { + const arrays = types as ArrayType[]; + const unifiedArrayType: ArrayType = arrays[0]; + if ( + !arrays.every(array => { + return array.length === unifiedArrayType.length; + }) + ) { + unifiedArrayType.length = this.buildNumericBindingAndPushToVariants( + arrays.map(array => { + if (typeof array.length !== 'number') { + throw new Error('Trying to unify arrays with bindings'); + } + return array.length; + }), + generics, + variants, + ); + } + + unifiedArrayType.type = this.unifyTypes( + arrays.map(array => array.type), + generics, + variants, + ); + return unifiedArrayType; + } + case 'tuple': { + const tuples = types as Tuple[]; + const unifiedTupleType: Tuple = tuples[0]; + for (let i = 0; i < unifiedTupleType.fields.length; i++) { + unifiedTupleType.fields[i] = this.unifyTypes( + tuples.map(tuple => tuple.fields[i]), + generics, + variants, + ); + } + return unifiedTupleType; + } + case 'struct': { + const structs = types as Struct[]; + const ids = new Set(structs.map(struct => Demonomorphizer.buildIdForStruct(struct.structType))); + if (ids.size > 1) { + // If the types are different structs, we can only unify them by creating a new binding. + // For example, if we have a struct A { x: u32 } and a struct A { x: Field }, the only possible unification is A { x: T } + return this.buildBindingAndPushToVariants(types, generics, variants); + } else { + // If the types are the same struct, we must unify the arguments to the struct. + // For example, if we have A and A, we need to unify to A and push T to the generics of the struct type. + const unifiedStruct = structs[0]; + + if (!structs.every(struct => struct.args.length === unifiedStruct.args.length)) { + throw new Error('Same struct with different number of args encountered'); + } + for (let i = 0; i < unifiedStruct.args.length; i++) { + const argTypes = structs.map(struct => struct.args[i]); + unifiedStruct.args[i] = this.unifyTypes(argTypes, generics, variants); + } + return unifiedStruct; + } + } + + case 'constant': { + const constants = types as Constant[]; + if (constants.every(constant => constant.value === constants[0].value)) { + return constants[0]; + } else { + return this.buildBindingAndPushToVariants(types, generics, variants, true); + } + } + + default: { + const exhaustiveCheck: never = types[0]; + throw new Error(`Unhandled abi type: ${exhaustiveCheck}`); + } + } + } + + /** + * We consider a struct to be the same if it has the same name and field names. + * Structs with the same id will be unified into a single type by the demonomorphizer. + */ + public static buildIdForStruct(struct: StructType): string { + const name = struct.path.split('::').pop()!; + const fields = struct.fields.map(field => field.name).join(','); + return `${name}(${fields})`; + } + + private buildBindingAndPushToVariants( + concreteTypes: AbiTypeWithGenerics[], + generics: BindingId[], + variants: Struct[], + isNumeric = false, + ): AbiTypeWithGenerics { + const bindingId = new BindingId(this.lastBindingId++, isNumeric); + + for (let i = 0; i < variants.length; i++) { + const variant = variants[i]; + const concreteType = concreteTypes[i]; + variant.args.push(concreteType); + } + + generics.push(bindingId); + return { kind: 'binding', id: bindingId }; + } + + private buildNumericBindingAndPushToVariants( + concreteNumbers: number[], + generics: BindingId[], + variants: Struct[], + ): BindingId { + const bindingId = new BindingId(this.lastBindingId++, true); + + for (let i = 0; i < variants.length; i++) { + const variant = variants[i]; + variant.args.push({ kind: 'constant', value: concreteNumbers[i] }); + } + + generics.push(bindingId); + return bindingId; + } +} + +function allDeepEqual(arr: T[]): boolean { + if (arr.length === 0) { + return true; + } + const first = JSON.stringify(arr[0]); + for (let i = 0; i < arr.length; i++) { + if (JSON.stringify(arr[i]) !== first) { + return false; + } + } + return true; +} diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts index 8b8f29d890f..c948939a196 100644 --- a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts @@ -1,9 +1,18 @@ -import { type AbiType } from '@aztec/foundation/abi'; import { createConsoleLogger } from '@aztec/foundation/log'; import { type NoirCompiledCircuit, type NoirFunctionAbi } from '@aztec/types/noir'; +import { pascalCase } from 'change-case'; import fs from 'fs/promises'; +import { + type AbiTypeWithGenerics, + type BindingId, + type StructType, + findAllStructsInType, + mapAbiTypeToAbiTypeWithGenerics, +} from './abi_type_with_generics.js'; +import { Demonomorphizer } from './demonomorphizer.js'; + const log = createConsoleLogger('aztec:noir-contracts'); /** @@ -30,52 +39,6 @@ type PrimitiveTypesUsed = { tsType: string; }; -const noirPrimitiveTypesToTsTypes = new Map(); - -/** - * Typescript does not allow us to check for equality of non-primitive types - * easily, so we create a addIfUnique function that will only add an item - * to the map if it is not already there by using JSON.stringify. - * @param item - The item to add to the map. - */ -function addIfUnique(item: PrimitiveTypesUsed) { - const key = JSON.stringify(item); - if (!noirPrimitiveTypesToTsTypes.has(key)) { - noirPrimitiveTypesToTsTypes.set(key, item); - } -} - -/** - * Converts an ABI type to a TypeScript type. - * @param type - The ABI type to convert. - * @returns The typescript code to define the type. - */ -function abiTypeToTs(type: AbiType): string { - switch (type.kind) { - case 'integer': { - let tsIntType = ''; - if (type.sign === 'signed') { - tsIntType = `i${type.width}`; - } else { - tsIntType = `u${type.width}`; - } - addIfUnique({ aliasName: tsIntType, tsType: 'string' }); - return tsIntType; - } - case 'boolean': - return `boolean`; - case 'array': - return `FixedLengthArray<${abiTypeToTs(type.type)}, ${type.length}>`; - case 'struct': - return getLastComponentOfPath(type.path); - case 'field': - addIfUnique({ aliasName: 'Field', tsType: 'string' }); - return 'Field'; - default: - throw new Error(`Unknown ABI type ${type}`); - } -} - /** * Returns the last component of a path, e.g. "foo::bar::baz" -\> "baz" * Note: that if we have a path such as "Baz", we will return "Baz". @@ -102,99 +65,217 @@ function getLastComponentOfPath(str: string): string { } /** - * Generates TypeScript interfaces for the structs used in the ABI. - * @param type - The ABI type to generate the interface for. - * @param output - The set of structs that we have already generated bindings for. - * @returns The TypeScript code to define the struct. + * Replaces a numeric binding with the corresponding generics name or the actual value. */ -function generateStructInterfaces(type: AbiType, output: Set): string { - let result = ''; - - // Edge case to handle the array of structs case. - if ( - type.kind === 'array' && - ((type.type.kind === 'struct' && !output.has(getLastComponentOfPath(type.type.path))) || type.type.kind === 'array') - ) { - result += generateStructInterfaces(type.type, output); +function replaceNumericBinding(id: number | BindingId, genericsNameMap: Map): string { + if (typeof id === 'number') { + return id.toString(); + } else { + return genericsNameMap.get(id.id) ?? 'unknown'; } +} - if (type.kind !== 'struct') { - return result; +class TypingsGenerator { + /** All the types in the ABIs */ + private allTypes: AbiTypeWithGenerics[] = []; + /** The demonomorphized ABIs of the circuits */ + private demonomorphizedAbis: { + circuitName: string; + params: { name: string; type: AbiTypeWithGenerics }[]; + returnType?: AbiTypeWithGenerics; + }[] = []; + /** Maps struct id to name for structs with the same name and different field sets */ + private structIdToTsName = new Map(); + /** Collect all the primitives used in the types to add them to the codegen */ + private primitiveTypesUsed = new Map(); + + constructor(circuits: { abi: NoirFunctionAbi; circuitName: string }[]) { + // Map all the types used in the ABIs to the demonomorphized types + for (const { abi, circuitName } of circuits) { + const params = abi.parameters.map(param => { + const type = mapAbiTypeToAbiTypeWithGenerics(param.type); + this.allTypes.push(type); + return { name: param.name, type }; + }); + if (abi.return_type) { + const returnType = mapAbiTypeToAbiTypeWithGenerics(abi.return_type.abi_type); + this.allTypes.push(returnType); + this.demonomorphizedAbis.push({ circuitName, params, returnType }); + } else { + this.demonomorphizedAbis.push({ circuitName, params }); + } + } + // Demononmorphize the types + Demonomorphizer.demonomorphize(this.allTypes); } - // List of structs encountered while viewing this type that we need to generate - // bindings for. - const typesEncountered = new Set(); - - // Codegen the struct and then its fields, so that the structs fields - // are defined before the struct itself. - let codeGeneratedStruct = ''; - let codeGeneratedStructFields = ''; - - const structName = getLastComponentOfPath(type.path); - if (!output.has(structName)) { - codeGeneratedStruct += `export interface ${structName} {\n`; - for (const field of type.fields) { - codeGeneratedStruct += ` ${field.name}: ${abiTypeToTs(field.type)};\n`; - typesEncountered.add(field.type); + public codegen(): string { + this.primitiveTypesUsed = new Map(); + const structsCode = this.codegenAllStructs(); + const interfacesCode = this.codegenAllInterfaces(); + const primitivesCode = this.codegenAllPrimitives(); + + return ` + /* Autogenerated file, do not edit! */ + /* eslint-disable */ + ${primitivesCode} + ${structsCode} + ${interfacesCode}`; + } + + private codegenAllStructs(): string { + const allStructs = this.allTypes.flatMap(findAllStructsInType); + // First, deduplicate the structs used + const structTypesToExport = new Map(); + for (const struct of allStructs) { + const id = Demonomorphizer.buildIdForStruct(struct.structType); + if (structTypesToExport.has(id)) { + continue; + } + structTypesToExport.set(id, struct.structType); } - codeGeneratedStruct += `}\n\n`; - output.add(structName); - // Generate code for the encountered structs in the field above - for (const type of typesEncountered) { - codeGeneratedStructFields += generateStructInterfaces(type, output); + // Then, we have to consider the case where we have struct with the same name but different fields. + // For those, we'll naively append a number to the name. + const idsPerName = new Map(); + for (const [id, structType] of structTypesToExport.entries()) { + const name = getLastComponentOfPath(structType.path); + const ids = idsPerName.get(name) ?? []; + ids.push(id); + idsPerName.set(name, ids); + } + + this.structIdToTsName = new Map(); + for (const [name, ids] of idsPerName.entries()) { + if (ids.length !== 1) { + ids.forEach((id, index) => { + this.structIdToTsName.set(id, `${name}${index + 1}`); + }); + } } + // Now we can just generate the code for the structs + let resultCode = ''; + + for (const structType of structTypesToExport.values()) { + resultCode += this.codegenStructType(structType); + } + + return resultCode; } - return codeGeneratedStructFields + '\n' + codeGeneratedStruct; -} + private getStructName(structType: StructType): string { + return ( + this.structIdToTsName.get(Demonomorphizer.buildIdForStruct(structType)) || getLastComponentOfPath(structType.path) + ); + } -/** - * Generates a TypeScript interface for the ABI. - * @param abiObj - The ABI to generate the interface for. - * @returns The TypeScript code to define the interface. - */ -function generateTsInterface(abiObj: NoirFunctionAbi): string { - let result = ``; - const outputStructs = new Set(); + private codegenStructType(structType: StructType): string { + // Generate names for the generic bindings. + const genericsNameMap = new Map(); + structType.generics.forEach((generic, index) => { + genericsNameMap.set(generic.id, String.fromCharCode('A'.charCodeAt(0) + index)); + }); - // Define structs for composite types - for (const param of abiObj.parameters) { - result += generateStructInterfaces(param.type, outputStructs); + const name = this.getStructName(structType); + const generics = structType.generics.length + ? `<${structType.generics + .map(generic => `${genericsNameMap.get(generic.id)}${generic.isNumeric ? ' extends number' : ''}`) + .join(', ')}>` + : ''; + + let resultCode = `export interface ${name}${generics} {\n`; + + for (const field of structType.fields) { + resultCode += ` ${field.name}: ${this.codegenType(field.type, genericsNameMap)};\n`; + } + + resultCode += '}\n\n'; + + return resultCode; } - // Generating Return type, if it exists - // - if (abiObj.return_type != null) { - result += generateStructInterfaces(abiObj.return_type.abi_type, outputStructs); - result += `export type ReturnType = ${abiTypeToTs(abiObj.return_type.abi_type)};\n`; + private codegenType(type: AbiTypeWithGenerics, genericsNameMap: Map): string { + switch (type.kind) { + case 'field': + this.addIfUnique({ aliasName: 'Field', tsType: 'string' }); + return 'Field'; + case 'boolean': + return 'boolean'; + case 'integer': { + let tsIntType = ''; + if (type.sign === 'signed') { + tsIntType = `i${type.width}`; + } else { + tsIntType = `u${type.width}`; + } + this.addIfUnique({ aliasName: tsIntType, tsType: 'string' }); + return tsIntType; + } + case 'binding': + return genericsNameMap.get(type.id.id) ?? 'unknown'; + case 'constant': + return type.value.toString(); + case 'string': + return `string`; + case 'array': + return `FixedLengthArray<${this.codegenType(type.type, genericsNameMap)}, ${replaceNumericBinding( + type.length, + genericsNameMap, + )}>`; + case 'tuple': + throw new Error('Unimplemented'); + case 'struct': { + const name = this.getStructName(type.structType); + if (type.args.length) { + const args = type.args.map(arg => this.codegenType(arg, genericsNameMap)).join(', '); + return `${name}<${args}>`; + } else { + return name; + } + } + } } - // Generating Input type - result += '\nexport interface InputType {\n'; - for (const param of abiObj.parameters) { - result += ` ${param.name}: ${abiTypeToTs(param.type)};\n`; + /** + * Typescript does not allow us to check for equality of non-primitive types + * easily, so we create a addIfUnique function that will only add an item + * to the map if it is not already there by using JSON.stringify. + * @param item - The item to add to the map. + */ + private addIfUnique(item: PrimitiveTypesUsed) { + const key = JSON.stringify(item); + if (!this.primitiveTypesUsed.has(key)) { + this.primitiveTypesUsed.set(key, item); + } } - result += '}'; - // Add the primitive Noir types that do not have a 1-1 mapping to TypeScript. - let primitiveTypeAliases = ''; - for (const [, value] of noirPrimitiveTypesToTsTypes) { - primitiveTypeAliases += `\nexport type ${value.aliasName} = ${value.tsType};`; + /** + * Codegen all the interfaces for the circuits. + * For a circuit named Foo, we'll codegen FooInputType and FooReturnType. + */ + private codegenAllInterfaces(): string { + let resultCode = ''; + for (const { circuitName, params, returnType } of this.demonomorphizedAbis) { + resultCode += this.codegenStructType({ + path: `${circuitName}InputType`, + fields: params, + generics: [], + }); + if (returnType) { + resultCode += `export type ${circuitName}ReturnType = ${this.codegenType(returnType, new Map())};\n`; + } + } + return resultCode; } - const fixedLengthArray = - '\nexport type FixedLengthArray = L extends 0 ? never[]: T[] & { length: L }'; - - return ( - `/* Autogenerated file, do not edit! */\n\n/* eslint-disable */\n` + - fixedLengthArray + - '\n' + - primitiveTypeAliases + - '\n' + - result - ); + private codegenAllPrimitives(): string { + let primitiveTypeAliases = + 'export type FixedLengthArray = L extends 0 ? never[]: T[] & { length: L }\n'; + for (const [, value] of this.primitiveTypesUsed) { + primitiveTypeAliases += `export type ${value.aliasName} = ${value.tsType};\n`; + } + return primitiveTypeAliases; + } } const circuits = [ @@ -220,14 +301,19 @@ const main = async () => { await fs.mkdir('./src/types', { recursive: true }); } + const allAbis = []; + + // Collect all abis for (const circuit of circuits) { const rawData = await fs.readFile(`./src/target/${circuit}.json`, 'utf-8'); const abiObj: NoirCompiledCircuit = JSON.parse(rawData); - const generatedInterface = generateTsInterface(abiObj.abi); - - const outputFile = `./src/types/${circuit}_types.ts`; - await fs.writeFile(outputFile, generatedInterface); + allAbis.push({ + abi: abiObj.abi, + circuitName: pascalCase(circuit), + }); } + const interfaces = new TypingsGenerator(allAbis).codegen(); + await fs.writeFile('./src/types/index.ts', interfaces); }; try { diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index a891b6c775c..ed2295e907c 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1,5 +1,4 @@ import { - type ARCHIVE_HEIGHT, AggregationObject, AppendOnlyTreeSnapshot, AztecAddress, @@ -16,7 +15,6 @@ import { type ContractStorageRead, type ContractStorageUpdateRequest, EthAddress, - type FUNCTION_TREE_HEIGHT, Fr, FunctionData, FunctionSelector, @@ -119,120 +117,101 @@ import { import { toBufferBE } from '@aztec/foundation/bigint-buffer'; import { type Tuple, mapTuple, toTruncField } from '@aztec/foundation/serialize'; -import { type BaseParityInputs as BaseParityInputsNoir } from './types/parity_base_types.js'; -import { - type RootParityInput as ParityRootParityInputNoir, - type RootParityInputs as RootParityInputsNoir, -} from './types/parity_root_types.js'; -import { - type CallContext as CallContextNoir, - type CallRequest as CallRequestNoir, - type CallerContext as CallerContextNoir, - type CombinedConstantData as CombinedConstantDataNoir, - type FunctionData as FunctionDataNoir, - type FunctionLeafMembershipWitness as FunctionLeafMembershipWitnessNoir, - type FunctionSelector as FunctionSelectorNoir, - type GasFees as GasFeesNoir, - type GasSettings as GasSettingsNoir, - type L2ToL1Message as L2ToL1MessageNoir, - type MaxBlockNumber as MaxBlockNumberNoir, - type AztecAddress as NoirAztecAddress, - type EthAddress as NoirEthAddress, - type Field as NoirField, - type GrumpkinPoint as NoirPoint, - type NoteHashContext as NoteHashContextNoir, - type NoteHash as NoteHashNoir, - type NullifierKeyValidationRequestContext as NullifierKeyValidationRequestContextNoir, - type NullifierKeyValidationRequest as NullifierKeyValidationRequestNoir, - type Nullifier as NullifierNoir, - type PrivateAccumulatedData as PrivateAccumulatedDataNoir, - type PrivateCallData as PrivateCallDataNoir, - type PrivateCallStackItem as PrivateCallStackItemNoir, - type PrivateCircuitPublicInputs as PrivateCircuitPublicInputsNoir, - type PrivateKernelCircuitPublicInputs as PrivateKernelCircuitPublicInputsNoir, - type PrivateKernelInitCircuitPrivateInputs as PrivateKernelInitCircuitPrivateInputsNoir, - type PublicDataRead as PublicDataReadNoir, - type ReadRequestContext as ReadRequestContextNoir, - type ReadRequest as ReadRequestNoir, - type RollupValidationRequests as RollupValidationRequestsNoir, - type SideEffect as SideEffectNoir, - type TxContext as TxContextNoir, - type TxRequest as TxRequestNoir, - type ValidationRequests as ValidationRequestsNoir, -} from './types/private_kernel_init_types.js'; -import { - type PrivateKernelInnerCircuitPrivateInputs as PrivateKernelInnerCircuitPrivateInputsNoir, - type PrivateKernelInnerHints as PrivateKernelInnerHintsNoir, -} from './types/private_kernel_inner_types.js'; -import { type PrivateKernelTailToPublicCircuitPrivateInputs as PrivateKernelTailToPublicCircuitPrivateInputsNoir } from './types/private_kernel_tail_to_public_types.js'; -import { - type CombinedAccumulatedData as CombinedAccumulatedDataNoir, - type Gas as GasNoir, - type GrumpkinPrivateKey as GrumpkinPrivateKeyNoir, - type NoteHashLeafPreimage as NoteHashLeafPreimageNoir, - type NoteHashMembershipWitness as NoteHashMembershipWitnessNoir, - type NoteHashReadRequestHints as NoteHashReadRequestHintsNoir, - type NoteHashSettledReadHint as NoteHashSettledReadHintNoir, - type NullifierReadRequestHints as NullifierReadRequestHintsNoir, - type NullifierSettledReadHint as NullifierSettledReadHintNoir, - type PendingReadHint as PendingReadHintNoir, - type PrivateKernelData as PrivateKernelDataNoir, - type PrivateKernelTailCircuitPrivateInputs as PrivateKernelTailCircuitPrivateInputsNoir, - type PrivateKernelTailHints as PrivateKernelTailHintsNoir, - type PrivateKernelTailOutputs as PrivateKernelTailOutputsNoir, - type ReadRequestStatus as ReadRequestStatusNoir, -} from './types/private_kernel_tail_types.js'; -import { - type PublicAccumulatedData as PublicAccumulatedDataNoir, - type PublicKernelData as PublicKernelDataNoir, -} from './types/public_kernel_app_logic_types.js'; -import { - type PublicCallData as PublicCallDataNoir, - type PublicCallStackItem as PublicCallStackItemNoir, - type PublicCircuitPublicInputs as PublicCircuitPublicInputsNoir, - type PublicKernelCircuitPublicInputs as PublicKernelCircuitPublicInputsNoir, - type PublicKernelSetupCircuitPrivateInputs as PublicKernelSetupCircuitPrivateInputsNoir, - type StorageRead as StorageReadNoir, - type StorageUpdateRequest as StorageUpdateRequestNoir, -} from './types/public_kernel_setup_types.js'; -import { - type LeafDataReadHint as LeafDataReadHintNoir, - type NullifierNonExistentReadRequestHints as NullifierNonExistentReadRequestHintsNoir, - type NullifierNonMembershipHint as NullifierNonMembershipHintNoir, - type PublicDataHint as PublicDataHintNoir, - type PublicDataReadRequestHints as PublicDataReadRequestHintsNoir, - type PublicDataUpdateRequest as PublicDataUpdateRequestNoir, - type PublicKernelTailCircuitPrivateInputs as PublicKernelTailCircuitPrivateInputsNoir, -} from './types/public_kernel_tail_types.js'; -import { - type ArchiveRootMembershipWitness as ArchiveRootMembershipWitnessNoir, - type BaseRollupInputs as BaseRollupInputsNoir, - type KernelCircuitPublicInputs as KernelCircuitPublicInputsNoir, - type KernelData as KernelDataNoir, - type NullifierLeafPreimage as NullifierLeafPreimageNoir, - type NullifierMembershipWitness as NullifierMembershipWitnessNoir, - type PublicDataMembershipWitness as PublicDataMembershipWitnessNoir, - type PublicDataTreeLeaf as PublicDataTreeLeafNoir, - type PublicDataTreeLeafPreimage as PublicDataTreeLeafPreimageNoir, - type StateDiffHints as StateDiffHintsNoir, -} from './types/rollup_base_types.js'; -import { type MergeRollupInputs as MergeRollupInputsNoir } from './types/rollup_merge_types.js'; -import { - type AppendOnlyTreeSnapshot as AppendOnlyTreeSnapshotNoir, - type BaseOrMergeRollupPublicInputs as BaseOrMergeRollupPublicInputsNoir, - type ConstantRollupData as ConstantRollupDataNoir, - type ContentCommitment as ContentCommitmentNoir, - type Field, - type GlobalVariables as GlobalVariablesNoir, - type Header as HeaderNoir, - type ParityPublicInputs as ParityPublicInputsNoir, - type PartialStateReference as PartialStateReferenceNoir, - type PreviousRollupData as PreviousRollupDataNoir, - type RootRollupInputs as RootRollupInputsNoir, - type RootRollupParityInput as RootRollupParityInputNoir, - type RootRollupPublicInputs as RootRollupPublicInputsNoir, - type StateReference as StateReferenceNoir, -} from './types/rollup_root_types.js'; +import type { + AppendOnlyTreeSnapshot as AppendOnlyTreeSnapshotNoir, + BaseOrMergeRollupPublicInputs as BaseOrMergeRollupPublicInputsNoir, + BaseParityInputs as BaseParityInputsNoir, + BaseRollupInputs as BaseRollupInputsNoir, + CallContext as CallContextNoir, + CallRequest as CallRequestNoir, + CallerContext as CallerContextNoir, + CombinedAccumulatedData as CombinedAccumulatedDataNoir, + CombinedConstantData as CombinedConstantDataNoir, + ConstantRollupData as ConstantRollupDataNoir, + ContentCommitment as ContentCommitmentNoir, + Field, + FixedLengthArray, + FunctionData as FunctionDataNoir, + FunctionSelector as FunctionSelectorNoir, + GasFees as GasFeesNoir, + Gas as GasNoir, + GasSettings as GasSettingsNoir, + GlobalVariables as GlobalVariablesNoir, + GrumpkinPrivateKey as GrumpkinPrivateKeyNoir, + Header as HeaderNoir, + KernelCircuitPublicInputs as KernelCircuitPublicInputsNoir, + KernelData as KernelDataNoir, + L2ToL1Message as L2ToL1MessageNoir, + LeafDataReadHint as LeafDataReadHintNoir, + MaxBlockNumber as MaxBlockNumberNoir, + MembershipWitness as MembershipWitnessNoir, + MergeRollupInputs as MergeRollupInputsNoir, + AztecAddress as NoirAztecAddress, + EthAddress as NoirEthAddress, + Field as NoirField, + GrumpkinPoint as NoirPoint, + NoteHashContext as NoteHashContextNoir, + NoteHashLeafPreimage as NoteHashLeafPreimageNoir, + NoteHash as NoteHashNoir, + NoteHashReadRequestHints as NoteHashReadRequestHintsNoir, + NoteHashSettledReadHint as NoteHashSettledReadHintNoir, + NullifierKeyValidationRequestContext as NullifierKeyValidationRequestContextNoir, + NullifierKeyValidationRequest as NullifierKeyValidationRequestNoir, + NullifierLeafPreimage as NullifierLeafPreimageNoir, + Nullifier as NullifierNoir, + NullifierNonExistentReadRequestHints as NullifierNonExistentReadRequestHintsNoir, + NullifierNonMembershipHint as NullifierNonMembershipHintNoir, + NullifierReadRequestHints as NullifierReadRequestHintsNoir, + NullifierSettledReadHint as NullifierSettledReadHintNoir, + ParityPublicInputs as ParityPublicInputsNoir, + RootParityInput as ParityRootParityInputNoir, + PartialStateReference as PartialStateReferenceNoir, + PendingReadHint as PendingReadHintNoir, + PreviousRollupData as PreviousRollupDataNoir, + PrivateAccumulatedData as PrivateAccumulatedDataNoir, + PrivateCallData as PrivateCallDataNoir, + PrivateCallStackItem as PrivateCallStackItemNoir, + PrivateCircuitPublicInputs as PrivateCircuitPublicInputsNoir, + PrivateKernelCircuitPublicInputs as PrivateKernelCircuitPublicInputsNoir, + PrivateKernelData as PrivateKernelDataNoir, + PrivateKernelInitCircuitPrivateInputs as PrivateKernelInitCircuitPrivateInputsNoir, + PrivateKernelInnerCircuitPrivateInputs as PrivateKernelInnerCircuitPrivateInputsNoir, + PrivateKernelInnerHints as PrivateKernelInnerHintsNoir, + PrivateKernelTailCircuitPrivateInputs as PrivateKernelTailCircuitPrivateInputsNoir, + PrivateKernelTailHints as PrivateKernelTailHintsNoir, + PrivateKernelTailOutputs as PrivateKernelTailOutputsNoir, + PrivateKernelTailToPublicCircuitPrivateInputs as PrivateKernelTailToPublicCircuitPrivateInputsNoir, + PublicAccumulatedData as PublicAccumulatedDataNoir, + PublicCallData as PublicCallDataNoir, + PublicCallStackItem as PublicCallStackItemNoir, + PublicCircuitPublicInputs as PublicCircuitPublicInputsNoir, + PublicDataHint as PublicDataHintNoir, + PublicDataRead as PublicDataReadNoir, + PublicDataReadRequestHints as PublicDataReadRequestHintsNoir, + PublicDataTreeLeaf as PublicDataTreeLeafNoir, + PublicDataTreeLeafPreimage as PublicDataTreeLeafPreimageNoir, + PublicDataUpdateRequest as PublicDataUpdateRequestNoir, + PublicKernelCircuitPublicInputs as PublicKernelCircuitPublicInputsNoir, + PublicKernelData as PublicKernelDataNoir, + PublicKernelSetupCircuitPrivateInputs as PublicKernelSetupCircuitPrivateInputsNoir, + PublicKernelTailCircuitPrivateInputs as PublicKernelTailCircuitPrivateInputsNoir, + ReadRequestContext as ReadRequestContextNoir, + ReadRequest as ReadRequestNoir, + ReadRequestStatus as ReadRequestStatusNoir, + RollupValidationRequests as RollupValidationRequestsNoir, + RootParityInputs as RootParityInputsNoir, + RootRollupInputs as RootRollupInputsNoir, + RootRollupParityInput as RootRollupParityInputNoir, + RootRollupPublicInputs as RootRollupPublicInputsNoir, + SideEffect as SideEffectNoir, + StateDiffHints as StateDiffHintsNoir, + StateReference as StateReferenceNoir, + StorageRead as StorageReadNoir, + StorageUpdateRequest as StorageUpdateRequestNoir, + TxContext as TxContextNoir, + TxRequest as TxRequestNoir, + ValidationRequests as ValidationRequestsNoir, +} from './types/index.js'; /* eslint-disable camelcase */ @@ -775,20 +754,6 @@ export function mapPrivateCallStackItemToNoir(privateCallStackItem: PrivateCallS }; } -/** - * Maps a function leaf membership witness to a noir function leaf membership witness. - * @param membershipWitness - The membership witness. - * @returns The noir function leaf membership witness. - */ -function mapFunctionLeafMembershipWitnessToNoir( - membershipWitness: MembershipWitness, -): FunctionLeafMembershipWitnessNoir { - return { - leaf_index: membershipWitness.leafIndex.toString(), - sibling_path: mapTuple(membershipWitness.siblingPath, mapFieldToNoir), - }; -} - /** * Maps a private call data to a noir private call data. * @param privateCallData - The private call data. @@ -801,9 +766,7 @@ export function mapPrivateCallDataToNoir(privateCallData: PrivateCallData): Priv public_call_stack: mapTuple(privateCallData.publicCallStack, mapCallRequestToNoir), proof: {}, vk: {}, - function_leaf_membership_witness: mapFunctionLeafMembershipWitnessToNoir( - privateCallData.functionLeafMembershipWitness, - ), + function_leaf_membership_witness: mapMembershipWitnessToNoir(privateCallData.functionLeafMembershipWitness), contract_class_artifact_hash: mapFieldToNoir(privateCallData.contractClassArtifactHash), contract_class_public_bytecode_commitment: mapFieldToNoir(privateCallData.contractClassPublicBytecodeCommitment), public_keys_hash: mapWrappedFieldToNoir(privateCallData.publicKeysHash), @@ -931,7 +894,7 @@ function mapNoteHashSettledReadHintToNoir( ): NoteHashSettledReadHintNoir { return { read_request_index: mapNumberToNoir(hint.readRequestIndex), - membership_witness: mapNoteHashMembershipWitnessToNoir(hint.membershipWitness), + membership_witness: mapMembershipWitnessToNoir(hint.membershipWitness), leaf_preimage: mapNoteHashLeafPreimageToNoir(hint.leafPreimage), }; } @@ -941,7 +904,7 @@ function mapNullifierSettledReadHintToNoir( ): NullifierSettledReadHintNoir { return { read_request_index: mapNumberToNoir(hint.readRequestIndex), - membership_witness: mapNullifierMembershipWitnessToNoir(hint.membershipWitness), + membership_witness: mapMembershipWitnessToNoir(hint.membershipWitness), leaf_preimage: mapNullifierLeafPreimageToNoir(hint.leafPreimage), }; } @@ -967,7 +930,7 @@ function mapNullifierNonMembershipHintToNoir( ): NullifierNonMembershipHintNoir { return { low_leaf_preimage: mapNullifierLeafPreimageToNoir(hint.leafPreimage), - membership_witness: mapNullifierMembershipWitnessToNoir(hint.membershipWitness), + membership_witness: mapMembershipWitnessToNoir(hint.membershipWitness), }; } @@ -987,7 +950,7 @@ function mapPublicDataHintToNoir(hint: PublicDataHint): PublicDataHintNoir { leaf_slot: mapFieldToNoir(hint.leafSlot), value: mapFieldToNoir(hint.value), override_counter: mapNumberToNoir(hint.overrideCounter), - membership_witness: mapPublicDataMembershipWitnessToNoir(hint.membershipWitness), + membership_witness: mapMembershipWitnessToNoir(hint.membershipWitness), leaf_preimage: mapPublicDataTreePreimageToNoir(hint.leafPreimage), }; } @@ -1957,52 +1920,11 @@ export function mapNullifierLeafPreimageToNoir( }; } -function mapNoteHashMembershipWitnessToNoir( - membershipWitness: MembershipWitness, -): NoteHashMembershipWitnessNoir { - return { - leaf_index: membershipWitness.leafIndex.toString(), - sibling_path: mapTuple(membershipWitness.siblingPath, mapFieldToNoir), - }; -} - -/** - * Maps a nullifier membership witness to noir. - * @param membershipWitness - The nullifier membership witness. - * @returns The noir nullifier membership witness. - */ -export function mapNullifierMembershipWitnessToNoir( - membershipWitness: MembershipWitness, -): NullifierMembershipWitnessNoir { - return { - leaf_index: membershipWitness.leafIndex.toString(), - sibling_path: mapTuple(membershipWitness.siblingPath, mapFieldToNoir), - }; -} - -/** - * Maps a membership witness of the public data tree to noir. - */ -export function mapPublicDataMembershipWitnessToNoir( - membershipWitness: MembershipWitness, -): PublicDataMembershipWitnessNoir { - return { - leaf_index: membershipWitness.leafIndex.toString(), - sibling_path: mapTuple(membershipWitness.siblingPath, mapFieldToNoir), - }; -} - -/** - * Maps a membership witness of the blocks tree to noir. - * @param membershipWitness - The membership witness. - * @returns The noir membership witness. - */ -export function mapArchiveRootMembershipWitnessToNoir( - membershipWitness: MembershipWitness, -): ArchiveRootMembershipWitnessNoir { +function mapMembershipWitnessToNoir(witness: MembershipWitness): MembershipWitnessNoir { + const siblingPath = mapTuple(witness.siblingPath, mapFieldToNoir) as FixedLengthArray; return { - leaf_index: membershipWitness.leafIndex.toString(), - sibling_path: mapTuple(membershipWitness.siblingPath, mapFieldToNoir), + leaf_index: witness.leafIndex.toString(), + sibling_path: siblingPath, }; } @@ -2053,7 +1975,7 @@ export function mapStateDiffHintsToNoir(hints: StateDiffHints): StateDiffHintsNo nullifier_predecessor_preimages: mapTuple(hints.nullifierPredecessorPreimages, mapNullifierLeafPreimageToNoir), nullifier_predecessor_membership_witnesses: mapTuple( hints.nullifierPredecessorMembershipWitnesses, - mapNullifierMembershipWitnessToNoir, + (witness: MembershipWitness) => mapMembershipWitnessToNoir(witness), ), sorted_nullifiers: mapTuple(hints.sortedNullifiers, mapFieldToNoir), sorted_nullifier_indexes: mapTuple(hints.sortedNullifierIndexes, (index: number) => mapNumberToNoir(index)), @@ -2104,10 +2026,10 @@ export function mapBaseRollupInputsToNoir(inputs: BaseRollupInputs): BaseRollupI low_public_data_writes_witnesses: mapTuple( inputs.lowPublicDataWritesMembershipWitnesses, - mapPublicDataMembershipWitnessToNoir, + (witness: MembershipWitness) => mapMembershipWitnessToNoir(witness), ), - archive_root_membership_witness: mapArchiveRootMembershipWitnessToNoir(inputs.archiveRootMembershipWitness), + archive_root_membership_witness: mapMembershipWitnessToNoir(inputs.archiveRootMembershipWitness), constants: mapConstantRollupDataToNoir(inputs.constants), }; } diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index f2539b2eb46..65a9882c947 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -592,6 +592,7 @@ __metadata: "@noir-lang/types": "portal:../../noir/packages/types" "@types/jest": ^29.5.0 "@types/node": ^18.7.23 + change-case: ^5.4.4 jest: ^29.5.0 levelup: ^5.1.1 memdown: ^6.1.1 @@ -5255,6 +5256,13 @@ __metadata: languageName: node linkType: hard +"change-case@npm:^5.4.4": + version: 5.4.4 + resolution: "change-case@npm:5.4.4" + checksum: a22a25a763719658424ffbcd41e931d2d19cc22399cc765dca447fbe1eaf13e179d5e8ab1677af75f2e814dbddf74e42ffdecb526cd5bc906cc859f62aa154b2 + languageName: node + linkType: hard + "char-regex@npm:^1.0.2": version: 1.0.2 resolution: "char-regex@npm:1.0.2"