diff --git a/avm-transpiler/src/instructions.rs b/avm-transpiler/src/instructions.rs index f2ab5288100d..de449649f51c 100644 --- a/avm-transpiler/src/instructions.rs +++ b/avm-transpiler/src/instructions.rs @@ -7,6 +7,7 @@ use crate::opcodes::AvmOpcode; pub const ALL_DIRECT: u8 = 0b00000000; pub const ZEROTH_OPERAND_INDIRECT: u8 = 0b00000001; pub const FIRST_OPERAND_INDIRECT: u8 = 0b00000010; +pub const SECOND_OPERAND_INDIRECT: u8 = 0b00000100; pub const ZEROTH_FIRST_OPERANDS_INDIRECT: u8 = 0b00000011; /// A simple representation of an AVM instruction for the purpose diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index b3417d18ad2f..9e1d71b8771d 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -7,7 +7,7 @@ use acvm::brillig_vm::brillig::{ use crate::instructions::{ AvmInstruction, AvmOperand, AvmTypeTag, ALL_DIRECT, FIRST_OPERAND_INDIRECT, - ZEROTH_OPERAND_INDIRECT, + SECOND_OPERAND_INDIRECT, ZEROTH_OPERAND_INDIRECT, }; use crate::opcodes::AvmOpcode; use crate::utils::{dbg_print_avm_program, dbg_print_brillig_program}; @@ -250,7 +250,9 @@ fn handle_foreign_call( } "poseidon" => { handle_single_field_hash_instruction(avm_instrs, function, destinations, inputs) - } + }, + "storageWrite" => emit_storage_write(avm_instrs, destinations, inputs), + "storageRead" => emit_storage_read(avm_instrs, destinations, inputs), _ => handle_getter_instruction(avm_instrs, function, destinations, inputs), } } @@ -270,7 +272,7 @@ fn handle_emit_note_hash_or_nullifier( "EMITNOTEHASH" }; - if destinations.len() != 0 || inputs.len() != 1 { + if !destinations.is_empty() || inputs.len() != 1 { panic!( "Transpiler expects ForeignCall::{} to have 0 destinations and 1 input, got {} and {}", function_name, @@ -299,6 +301,88 @@ fn handle_emit_note_hash_or_nullifier( }); } +/// Emit a storage write opcode +/// The current implementation writes an array of values into storage ( contiguous slots in memory ) +fn emit_storage_write( + avm_instrs: &mut Vec, + destinations: &Vec, + inputs: &Vec) + { + // For the foreign calls we want to handle, we do not want inputs, as they are getters + assert!(inputs.len() == 2); + assert!(destinations.len() == 1); // TODO: we want this to be empty - change aztec nr? + + let slot_offset_maybe = inputs[0]; + let slot_offset = match slot_offset_maybe { + ValueOrArray::MemoryAddress(slot_offset) => slot_offset.0, + _ => panic!("ForeignCall address destination should be a single value"), + }; + + let src_offset_maybe = inputs[1]; + let (src_offset, src_size) = match src_offset_maybe { + ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer.0, size), + _ => panic!("Storage write address inputs should be an array of values"), + }; + + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::SSTORE, + indirect: Some(ZEROTH_OPERAND_INDIRECT), + operands: vec![ + AvmOperand::U32 { + value: src_offset as u32, + }, + AvmOperand::U32 { + value: src_size as u32, + }, + AvmOperand::U32 { + value: slot_offset as u32, + }, + ], + ..Default::default() + }) +} + +/// Emit a storage read opcode +/// The current implementation reads an array of values from storage ( contiguous slots in memory ) +fn emit_storage_read( + avm_instrs: &mut Vec, + destinations: &Vec, + inputs: &Vec +) { + // For the foreign calls we want to handle, we do not want inputs, as they are getters + assert!(inputs.len() == 2); // output, len - but we dont use this len - its for the oracle + assert!(destinations.len() == 1); + + let slot_offset_maybe = inputs[0]; + let slot_offset = match slot_offset_maybe { + ValueOrArray::MemoryAddress(slot_offset) => slot_offset.0, + _ => panic!("ForeignCall address destination should be a single value"), + }; + + let dest_offset_maybe = destinations[0]; + let (dest_offset, src_size) = match dest_offset_maybe { + ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer.0, size), + _ => panic!("Storage write address inputs should be an array of values"), + }; + + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::SLOAD, + indirect: Some(SECOND_OPERAND_INDIRECT), + operands: vec![ + AvmOperand::U32 { + value: slot_offset as u32, + }, + AvmOperand::U32 { + value: src_size as u32, + }, + AvmOperand::U32 { + value: dest_offset as u32, + }, + ], + ..Default::default() + }) +} + /// Handle an AVM NULLIFIEREXISTS instruction /// (a nullifierExists brillig foreign call was encountered) /// Adds the new instruction to the avm instructions list. diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index b827f3c1f2e9..fef8d16373d7 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -123,4 +123,5 @@ library Constants { uint256 internal constant CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP_UNPADDED = 52; uint256 internal constant L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP = 64; uint256 internal constant LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 64; + uint256 internal constant APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; } diff --git a/noir-projects/aztec-nr/aztec/src/context.nr b/noir-projects/aztec-nr/aztec/src/context.nr index 37eb6bb45fa5..d0a2c5598477 100644 --- a/noir-projects/aztec-nr/aztec/src/context.nr +++ b/noir-projects/aztec-nr/aztec/src/context.nr @@ -12,18 +12,23 @@ use avm::AVMContext; struct Context { private: Option<&mut PrivateContext>, public: Option<&mut PublicContext>, + public_vm: Option<&mut AVMContext>, } impl Context { pub fn private(context: &mut PrivateContext) -> Context { - Context { private: Option::some(context), public: Option::none() } + Context { private: Option::some(context), public: Option::none(), public_vm: Option::none() } } pub fn public(context: &mut PublicContext) -> Context { - Context { public: Option::some(context), private: Option::none() } + Context { public: Option::some(context), private: Option::none(), public_vm: Option::none() } + } + + pub fn public_vm(context: &mut AVMContext) -> Context { + Context { public_vm: Option::some(context), public: Option::none(), private: Option::none() } } pub fn none() -> Context { - Context { public: Option::none(), private: Option::none() } + Context { public: Option::none(), private: Option::none(), public_vm: Option::none() } } } diff --git a/noir-projects/aztec-nr/aztec/src/messaging/l1_to_l2_message_getter_data.nr b/noir-projects/aztec-nr/aztec/src/messaging/l1_to_l2_message_getter_data.nr index 25da5bfec567..579954b9e525 100644 --- a/noir-projects/aztec-nr/aztec/src/messaging/l1_to_l2_message_getter_data.nr +++ b/noir-projects/aztec-nr/aztec/src/messaging/l1_to_l2_message_getter_data.nr @@ -7,13 +7,13 @@ struct L1ToL2MessageGetterData { leaf_index: Field } -pub fn l1_to_l2_message_getter_len() -> u64 { +pub fn l1_to_l2_message_getter_len() -> u32 { L1_TO_L2_MESSAGE_LENGTH + 1 + L1_TO_L2_MSG_TREE_HEIGHT } pub fn make_l1_to_l2_message_getter_data( fields: [Field; N], - start: u64, + start: u32, secret: Field ) -> L1ToL2MessageGetterData { L1ToL2MessageGetterData { diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr index 85b0f0d37ed8..218bc9676b49 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr @@ -106,7 +106,7 @@ impl NoteGetterOptions { pub fn with_filter( filter: fn([Option; MAX_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option; MAX_READ_REQUESTS_PER_CALL], filter_args: FILTER_ARGS - ) -> Self where Note: NoteInterface { +) -> Self where Note: NoteInterface { NoteGetterOptions { selects: BoundedVec::new(), sorts: BoundedVec::new(), diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr index f59ae02a838b..5ad9d9ec7c23 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr @@ -4,7 +4,7 @@ use dep::protocol_types::{ utils::arr_copy_slice }; -global LEAF_PREIMAGE_LENGTH: u64 = 4; +global LEAF_PREIMAGE_LENGTH: u32 = 4; global PUBLIC_DATA_WITNESS: Field = 45; struct PublicDataWitness { @@ -23,7 +23,7 @@ unconstrained pub fn get_public_data_witness(block_number: u32, leaf_slot: Field let fields = get_public_data_witness_oracle(block_number, leaf_slot); PublicDataWitness { index: fields[0], - leaf_preimage: PublicDataTreeLeafPreimage { slot: fields[1], value: fields[2], next_index: fields[3] as u64, next_slot: fields[4] }, + leaf_preimage: PublicDataTreeLeafPreimage { slot: fields[1], value: fields[2], next_index: fields[3] as u32, next_slot: fields[4] }, path: arr_copy_slice(fields, [0; PUBLIC_DATA_TREE_HEIGHT], 1 + LEAF_PREIMAGE_LENGTH) } } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr index 02194699c8ff..b0a7d35600a0 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr @@ -101,14 +101,14 @@ unconstrained pub fn get_notes( status, placeholder_fields ); - let num_notes = fields[0] as u64; + let num_notes = fields[0] as u32; let contract_address = AztecAddress::from_field(fields[1]); for i in 0..placeholder_opt_notes.len() { - if i < num_notes { + if i as u32 < num_notes { // lengths named as per typescript. - let return_header_length: u64 = 2; // num_notes & contract_address. - let extra_preimage_length: u64 = 2; // nonce & is_transient. - let read_offset: u64 = return_header_length + i * (N + extra_preimage_length); + let return_header_length: u32 = 2; // num_notes & contract_address. + let extra_preimage_length: u32 = 2; // nonce & is_transient. + let read_offset: u32 = return_header_length + i * (N + extra_preimage_length); let nonce = fields[read_offset]; let is_transient = fields[read_offset + 1] as bool; let header = NoteHeader { contract_address, nonce, storage_slot, is_transient }; diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index 8050704f67f1..7f6d08ec0b34 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -1,6 +1,7 @@ contract AvmTest { // Libs use dep::aztec::protocol_types::address::{AztecAddress, EthAddress}; + use dep::aztec::state_vars::PublicMutable; // avm lib use dep::aztec::avm::hash::{keccak256, poseidon, sha256}; @@ -8,7 +9,21 @@ contract AvmTest { #[aztec(private)] fn constructor() {} - // Public-vm macro will prefix avm to the function name for transpilation + struct Storage { + owner: PublicMutable + } + + #[aztec(public-vm)] + fn setAdmin() { + storage.owner.write(context.sender()); + } + + #[aztec(public-vm)] + fn setAndRead() -> pub AztecAddress { + storage.owner.write(context.sender()); + storage.owner.read() + } + #[aztec(public-vm)] fn addArgsReturn(argA: Field, argB: Field) -> pub Field { argA + argB @@ -40,7 +55,6 @@ contract AvmTest { // fn setOpcodeUint128() -> pub u128 { // 1 << 120 as u128 // } - // Field should fit in 128 bits // ACIR only supports fields of up to 126 bits! // Same with internal fields for unconstrained functions, apprently. diff --git a/noir-projects/noir-protocol-circuits/src/crates/bug-collecting-crate/array_len.nr b/noir-projects/noir-protocol-circuits/src/crates/bug-collecting-crate/array_len.nr index d92b88511102..579e4b882e23 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/bug-collecting-crate/array_len.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/bug-collecting-crate/array_len.nr @@ -1 +1 @@ -array.len() should return a u64 \ No newline at end of file +array.len() should return a u32 \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_tail.nr index 55e8b64a2324..a234882f5884 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -20,11 +20,11 @@ use dep::types::{ struct PrivateKernelTailCircuitPrivateInputs { previous_kernel: PrivateKernelInnerData, sorted_new_note_hashes: [SideEffect; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_new_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - read_commitment_hints: [u64; MAX_READ_REQUESTS_PER_TX], + sorted_new_note_hashes_indexes: [u32; MAX_NEW_NOTE_HASHES_PER_TX], + read_commitment_hints: [u32; MAX_READ_REQUESTS_PER_TX], sorted_new_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX], - sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], - nullifier_commitment_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX], + sorted_new_nullifiers_indexes: [u32; MAX_NEW_NULLIFIERS_PER_TX], + nullifier_commitment_hints: [u32; MAX_NEW_NULLIFIERS_PER_TX], master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], } @@ -64,7 +64,7 @@ impl PrivateKernelTailCircuitPrivateInputs { // match reads to commitments from the previous call(s) for rr_idx in 0..MAX_READ_REQUESTS_PER_TX { let read_request = read_requests.get_unchecked(rr_idx); - let read_commitment_hint = self.read_commitment_hints[rr_idx] as u64; + let read_commitment_hint = self.read_commitment_hints[rr_idx] as u32; if (read_request.value != 0) { let hash = new_note_hashes.get_unchecked(read_commitment_hint); @@ -79,7 +79,7 @@ impl PrivateKernelTailCircuitPrivateInputs { public_inputs.end.read_requests = BoundedVec::new(); } - fn assert_sorted_counters(original: [T; N], sorted: [T; N], indexes: [u64; N]) where T: Eq + Ordered + Empty { + fn assert_sorted_counters(original: [T; N], sorted: [T; N], indexes: [u32; N]) where T: Eq + Ordered + Empty { let mut prev_was_empty = false; for i in 0..N { @@ -126,7 +126,7 @@ impl PrivateKernelTailCircuitPrivateInputs { let nullifier = new_nullifiers[n_idx]; // TODO - should not be able to squash the first nullifier. let nullified_note_hash = nullifier.note_hash; - let hint_pos = self.nullifier_commitment_hints[n_idx] as u64; + let hint_pos = self.nullifier_commitment_hints[n_idx] as u32; // Nullified_commitment of value `0` implies non-transient (persistable) // nullifier in which case no attempt will be made to match it to a hash. @@ -134,7 +134,7 @@ impl PrivateKernelTailCircuitPrivateInputs { // 0-valued nullified_note_hash is empty and will be ignored if nullified_note_hash != 0 { assert( - hint_pos < MAX_NEW_NOTE_HASHES_PER_TX as u64, "New nullifier is transient but hint is invalid" + hint_pos < MAX_NEW_NOTE_HASHES_PER_TX as u32, "New nullifier is transient but hint is invalid" ); let hash = new_note_hashes[hint_pos]; assert_eq(nullified_note_hash, hash.value, "Hinted hash does not match"); @@ -145,7 +145,7 @@ impl PrivateKernelTailCircuitPrivateInputs { // squash both the nullifier and the hash // (set to 0 here and then rearrange array after loop) new_note_hashes[hint_pos] = SideEffect::empty(); - new_nullifiers[n_idx as u64] = SideEffectLinkedToNoteHash::empty(); + new_nullifiers[n_idx as u32] = SideEffectLinkedToNoteHash::empty(); } // non-transient (persistable) nullifiers are just kept in new_nullifiers array and forwarded // to public inputs (used later by base rollup circuit) @@ -240,8 +240,8 @@ mod tests { struct PrivateKernelOrderingInputsBuilder { previous_kernel: PreviousKernelDataBuilder, - read_commitment_hints: [u64; MAX_READ_REQUESTS_PER_TX], - nullifier_commitment_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX], + read_commitment_hints: [u32; MAX_READ_REQUESTS_PER_TX], + nullifier_commitment_hints: [u32; MAX_NEW_NULLIFIERS_PER_TX], } impl PrivateKernelOrderingInputsBuilder { @@ -272,32 +272,32 @@ mod tests { compute_unique_siloed_note_hashes(first_nullifier.value, commitments) } - pub fn append_transient_commitments(&mut self, num_commitments: u64) { + pub fn append_transient_commitments(&mut self, num_commitments: u32) { // All new note hashes aggregated in the previous kernel are transient commitments. self.previous_kernel.append_new_note_hashes(num_commitments); } - pub fn add_transient_read(&mut self, commitment_index: u64) { + pub fn add_transient_read(&mut self, commitment_index: u32) { let read_request_index = self.previous_kernel.add_read_request_for_transient_commitment(commitment_index); self.read_commitment_hints[read_request_index] = commitment_index; } - pub fn append_nullifiers(&mut self, num_nullifiers: u64) { + pub fn append_nullifiers(&mut self, num_nullifiers: u32) { self.previous_kernel.append_new_nullifiers_from_private(num_nullifiers); } - pub fn nullify_transient_commitment(&mut self, nullifier_index: Field, commitment_index: u64) { + pub fn nullify_transient_commitment(&mut self, nullifier_index: Field, commitment_index: u32) { self.previous_kernel.end.new_nullifiers.storage[nullifier_index].note_hash = self.previous_kernel.end.new_note_hashes.get(commitment_index).value; self.nullifier_commitment_hints[nullifier_index] = commitment_index; } - fn sort_sideffects(original: [T; N]) -> ([T; N], [u64; N]) where T: Ordered + Eq + Empty { + fn sort_sideffects(original: [T; N]) -> ([T; N], [u32; N]) where T: Ordered + Eq + Empty { let mut indexes = [0; N]; for i in 0..N { indexes[i] = i; } let sorted_indexes = indexes.sort_via( - |a_index: u64, b_index: u64| { + |a_index: u32, b_index: u32| { let a = original[a_index]; let b = original[b_index]; if is_empty(b) { @@ -309,7 +309,7 @@ mod tests { } } ); - let sorted_sideffects = sorted_indexes.map(|i: u64| original[i]); + let sorted_sideffects = sorted_indexes.map(|i: u32| original[i]); let mut reverse_map = [0; N]; for i in 0..N { reverse_map[sorted_indexes[i]] = i; diff --git a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr index 67777b378f92..57cd7b4e6eb3 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -45,7 +45,7 @@ struct BaseRollupInputs { // TODO: The following 6 values are eventually going to be nuked from here. See discussion: // https://aztecprotocol.slack.com/archives/C060PU5R327/p1701965354071269 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], + sorted_public_data_writes_indexes: [u32; 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], public_data_reads_preimages: [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_READS_PER_TX], @@ -195,7 +195,7 @@ impl BaseRollupInputs { ((low_leaf.next_index == 0) & (low_leaf.next_nullifier == 0)) ) }, - |low_leaf: NullifierLeafPreimage, nullifier: Field, nullifier_index: u64| { // Update low leaf + |low_leaf: NullifierLeafPreimage, nullifier: Field, nullifier_index: u32| { // Update low leaf NullifierLeafPreimage{ nullifier : low_leaf.nullifier, next_nullifier : nullifier, @@ -382,7 +382,7 @@ fn insert_public_data_update_requests( prev_snapshot: AppendOnlyTreeSnapshot, public_data_writes: [PublicDataTreeLeaf; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], 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], + sorted_public_data_writes_indexes: [u32; 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], public_data_writes_subtree_sibling_path: [Field; PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH] @@ -417,7 +417,7 @@ fn insert_public_data_update_requests( (!is_low_empty) & (is_update | is_in_range) }, - |low_preimage: PublicDataTreeLeafPreimage, write: PublicDataTreeLeaf, write_index: u64| { // Update low leaf + |low_preimage: PublicDataTreeLeafPreimage, write: PublicDataTreeLeaf, write_index: u32| { // Update low leaf let is_update = low_preimage.slot == write.slot; if is_update { PublicDataTreeLeafPreimage{ @@ -493,7 +493,7 @@ fn validate_public_data_reads( #[test] fn consistent_not_hash_subtree_width() { assert_eq( - MAX_NEW_NOTE_HASHES_PER_TX, 2.pow_32(NOTE_HASH_SUBTREE_HEIGHT as Field) as u64, "note hash subtree width is incorrect" + MAX_NEW_NOTE_HASHES_PER_TX, 2.pow_32(NOTE_HASH_SUBTREE_HEIGHT as Field) as u32, "note hash subtree width is incorrect" ); } @@ -589,13 +589,13 @@ mod tests { use dep::std::option::Option; struct NullifierInsertion { - existing_index: u64, + existing_index: u32, value: Field, } struct SortedTuple { value: T, - original_index: u64, + original_index: u32, } global MAX_NEW_NULLIFIERS_PER_TEST = 4; @@ -619,12 +619,12 @@ mod tests { public_data_tree: &mut NonEmptyMerkleTree, kernel_data: &mut PublicKernelData, snapshot: AppendOnlyTreeSnapshot, - public_data_writes: BoundedVec<(u64, PublicDataTreeLeaf), 2>, + public_data_writes: BoundedVec<(u32, PublicDataTreeLeaf), 2>, mut pre_existing_public_data: [PublicDataTreeLeafPreimage; EXISTING_LEAVES] - ) -> ([Field; PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH], [PublicDataTreeLeaf; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], [PublicDataMembershipWitness; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_READS_PER_TX], [PublicDataMembershipWitness; MAX_PUBLIC_DATA_READS_PER_TX], [PublicDataTreeLeafPreimage; EXISTING_LEAVES]) { + ) -> ([Field; PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH], [PublicDataTreeLeaf; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], [u32; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], [PublicDataMembershipWitness; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_READS_PER_TX], [PublicDataMembershipWitness; MAX_PUBLIC_DATA_READS_PER_TX], [PublicDataTreeLeafPreimage; EXISTING_LEAVES]) { let mut subtree_path: [Field; PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH] = dep::std::unsafe::zeroed(); let mut sorted_public_data_writes: [PublicDataTreeLeaf; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] = dep::std::unsafe::zeroed(); - let mut sorted_public_data_writes_indexes: [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] = dep::std::unsafe::zeroed(); + let mut sorted_public_data_writes_indexes: [u32; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] = dep::std::unsafe::zeroed(); let mut low_public_data_writes_preimages: [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] = dep::std::unsafe::zeroed(); let mut low_public_data_writes_witnesses: [PublicDataMembershipWitness; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] = dep::std::unsafe::zeroed(); let mut public_data_reads_preimages: [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_READS_PER_TX] = dep::std::unsafe::zeroed(); @@ -643,12 +643,12 @@ mod tests { } let mut sorted_write_tuples = sort_high_to_low( public_data_writes.storage, - |(_, leaf_a): (u64, PublicDataTreeLeaf),(_,leaf_b):(u64, PublicDataTreeLeaf)| full_field_less_than(leaf_a.slot, leaf_b.slot) + |(_, leaf_a): (u32, PublicDataTreeLeaf),(_,leaf_b):(u32, PublicDataTreeLeaf)| full_field_less_than(leaf_a.slot, leaf_b.slot) ); for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { - if (i as u64) < MAX_PUBLIC_DATA_WRITES_PER_TEST { - let (low_leaf_index, leaf): (u64, PublicDataTreeLeaf) = sorted_write_tuples[i].value; + if (i as u32) < MAX_PUBLIC_DATA_WRITES_PER_TEST { + let (low_leaf_index, leaf): (u32, PublicDataTreeLeaf) = sorted_write_tuples[i].value; sorted_public_data_writes[i] = leaf; sorted_public_data_writes_indexes[i] = sorted_write_tuples[i].original_index; @@ -688,7 +688,7 @@ mod tests { } } - subtree_path = BaseRollupInputsBuilder::extract_subtree_sibling_path(public_data_tree.get_sibling_path(snapshot.next_available_leaf_index as u64), [0; PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH]); + subtree_path = BaseRollupInputsBuilder::extract_subtree_sibling_path(public_data_tree.get_sibling_path(snapshot.next_available_leaf_index as u32), [0; PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH]); ( subtree_path, sorted_public_data_writes, sorted_public_data_writes_indexes, low_public_data_writes_preimages, low_public_data_writes_witnesses, public_data_reads_preimages, public_data_reads_witnesses, pre_existing_public_data @@ -702,8 +702,8 @@ mod tests { pre_existing_contracts: [Field; 2], pre_existing_public_data: [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], pre_existing_blocks: [Field; 2], - public_data_reads: BoundedVec, - public_data_writes:BoundedVec<(u64, PublicDataTreeLeaf), MAX_PUBLIC_DATA_WRITES_PER_TEST>, + public_data_reads: BoundedVec, + public_data_writes:BoundedVec<(u32, PublicDataTreeLeaf), MAX_PUBLIC_DATA_WRITES_PER_TEST>, new_nullifiers: BoundedVec, constants: ConstantRollupData, } @@ -743,7 +743,7 @@ mod tests { nullifier_tree: &mut NonEmptyMerkleTree, kernel_data: &mut PublicKernelData, 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], [NullifierMembershipWitness; MAX_NEW_NULLIFIERS_PER_TX], [Field; MAX_NEW_NULLIFIERS_PER_TX], [u32; MAX_NEW_NULLIFIERS_PER_TX]) { let mut nullifier_predecessor_preimages: [NullifierLeafPreimage; MAX_NEW_NULLIFIERS_PER_TX] = dep::std::unsafe::zeroed(); let mut low_nullifier_membership_witness: [NullifierMembershipWitness; MAX_NEW_NULLIFIERS_PER_TX] = dep::std::unsafe::zeroed(); @@ -768,7 +768,7 @@ mod tests { let mut pre_existing_nullifiers = self.pre_existing_nullifiers; for i in 0..MAX_NEW_NULLIFIERS_PER_TEST { - if (i as u64) < (self.new_nullifiers.len()) { + if (i as u32) < (self.new_nullifiers.len()) { let sorted_tuple = sorted_new_nullifier_tuples[i]; let new_nullifier = sorted_tuple.value; let original_index = sorted_tuple.original_index; @@ -785,7 +785,7 @@ mod tests { }; low_preimage.next_nullifier = new_nullifier; - low_preimage.next_index = start_nullifier_tree_snapshot.next_available_leaf_index as u64 + original_index; + low_preimage.next_index = start_nullifier_tree_snapshot.next_available_leaf_index as u32 + original_index; pre_existing_nullifiers[low_index] = low_preimage; nullifier_tree.update_leaf(low_index, low_preimage.hash()); @@ -1043,7 +1043,7 @@ mod tests { for i in 0..new_note_hashes.len() { expected_commitments_tree.update_leaf( - (i as u64) + (MAX_NEW_NOTE_HASHES_PER_TX as u64), + (i as u32) + (MAX_NEW_NOTE_HASHES_PER_TX as u32), new_note_hashes[i] ); } diff --git a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/base/state_diff_hints.nr b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/base/state_diff_hints.nr index a15bb81021f7..bfdae2ecf5dc 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/base/state_diff_hints.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/base/state_diff_hints.nr @@ -12,7 +12,7 @@ struct StateDiffHints { nullifier_predecessor_membership_witnesses: [NullifierMembershipWitness; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers: [Field; MAX_NEW_NULLIFIERS_PER_TX], - sorted_nullifier_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], + sorted_nullifier_indexes: [u32; MAX_NEW_NULLIFIERS_PER_TX], // For inserting the new subtrees into their respective trees: // Note: the insertion leaf index can be derived from the snapshots' `next_available_leaf_index` values (tree diff --git a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/components.nr index a634fc74e70c..c7185a8c8401 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/components.nr @@ -116,7 +116,7 @@ pub fn insert_subtree_to_snapshot_tree( let new_root = root_from_sibling_path(subtreeRootToInsert, leafIndexAtDepth as Field, siblingPath); // 2^subtreeDepth is the number of leaves added. 2^x = 1 << x - let new_next_available_leaf_index = (snapshot.next_available_leaf_index as u64) + (1 << (subtreeDepth as u64)); + let new_next_available_leaf_index = (snapshot.next_available_leaf_index as u32) + (1 << (subtreeDepth as u32)); AppendOnlyTreeSnapshot { root: new_root, next_available_leaf_index: new_next_available_leaf_index as u32 } } diff --git a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/indexed_tree.nr b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/indexed_tree.nr index fc9ba43d74fa..519e20851ea1 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/indexed_tree.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/indexed_tree.nr @@ -5,7 +5,7 @@ use dep::types::abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, member fn check_permutation( original_array: [T; N], sorted_array: [T; N], - indexes: [u64; N], + indexes: [u32; N], is_equal: fn(T, T) -> bool ) { let mut seen_value = [false; N]; @@ -50,7 +50,7 @@ pub fn batch_insert; SubtreeWidth], @@ -58,7 +58,7 @@ pub fn batch_insert bool, hash_leaf: fn(Leaf) -> Field, is_valid_low_leaf: fn(Leaf, Value) -> bool, - update_low_leaf: fn(Leaf, Value, u64) -> Leaf, + update_low_leaf: fn(Leaf, Value, u32) -> Leaf, build_insertion_leaf: fn(Value, Leaf) -> Leaf, _subtree_height: [Field; SubtreeHeight], _tree_height: [Field; TreeHeight] @@ -98,7 +98,7 @@ pub fn batch_insert(leaves: [Field; N]) -> Field { // // Would be good if we could use width since the compute_subtree // algorithm uses depth. -pub fn calculate_empty_tree_root(depth: u64) -> Field { +pub fn calculate_empty_tree_root(depth: u32) -> Field { if depth == 0 { 0 } else if depth == 1 { diff --git a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/root.nr b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/root.nr index 34312802a4ea..0e77294b0371 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/root.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/root.nr @@ -79,7 +79,7 @@ impl RootRollupInputs { // See `test_message_input_flattened_length` on keeping this in sync, // why its here and how this constant was computed. -global NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP_NUM_BYTES: u64 = 512; +global NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP_NUM_BYTES: u32 = 512; // Computes the messages hash from the leaves array // diff --git a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/tests/merkle_tree_utils.nr b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/tests/merkle_tree_utils.nr index 5857980ea7b2..cb0042dd6827 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/tests/merkle_tree_utils.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/rollup-lib/src/tests/merkle_tree_utils.nr @@ -11,7 +11,7 @@ pub fn compute_zero_hashes(mut hashes: [Field; N]) -> [Field; N] { } impl MerkleTree { - fn update_leaf(&mut self, index: u64, value: Field, _tree_height: [Field; K]) { + fn update_leaf(&mut self, index: u32, value: Field, _tree_height: [Field; K]) { self.leaves[index] = value; let mut sibling_index = MerkleTree::sibling_index(index); @@ -21,9 +21,9 @@ impl MerkleTree { (self.leaves[sibling_index], value) }; - let mut current_width: u64 = N / 2; - let mut layer_offset: u64 = 0; - let mut node_index: u64 = index / 2 + layer_offset; + let mut current_width: u32 = N / 2; + let mut layer_offset: u32 = 0; + let mut node_index: u32 = index / 2 + layer_offset; for _ in 0..K { self.nodes[node_index] = dep::std::hash::pedersen_hash([left_node, right_node]); sibling_index = MerkleTree::sibling_index(node_index); @@ -43,7 +43,7 @@ impl MerkleTree { } } - pub fn sibling_index(index: u64) -> u64 { + pub fn sibling_index(index: u32) -> u32 { if index % 2 == 0 { index + 1 } else { index - 1 } } } @@ -103,10 +103,10 @@ impl NonEmptyMerkl NonEmptyMerkleTree { subtree, zero_hashes, left_supertree_branch, _phantom_subtree_height: _subtree_height } } - pub fn get_sibling_path(self, leaf_index: u64) -> [Field; TREE_HEIGHT] { + pub fn get_sibling_path(self, leaf_index: u32) -> [Field; TREE_HEIGHT] { let mut path = [0; TREE_HEIGHT]; - let mut current_index = leaf_index as u64; - let mut subtree_width = SUBTREE_ITEMS as u64; + let mut current_index = leaf_index as u32; + let mut subtree_width = SUBTREE_ITEMS as u32; let mut sibling_index = MerkleTree::sibling_index(current_index); @@ -116,7 +116,7 @@ impl NonEmptyMerkl 0 }; - let mut subtree_offset: u64 = 0; + let mut subtree_offset: u32 = 0; for i in 1..TREE_HEIGHT { current_index = current_index / 2; @@ -138,8 +138,8 @@ impl NonEmptyMerkl path } - pub fn update_leaf(&mut self, index: u64, value: Field) { - assert(index < SUBTREE_ITEMS as u64, "index must be less than the number of leaves in the subtree"); + pub fn update_leaf(&mut self, index: u32, value: Field) { + assert(index < SUBTREE_ITEMS as u32, "index must be less than the number of leaves in the subtree"); self.subtree.update_leaf(index, value, [0; SUBTREE_HEIGHT]); diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/abis/append_only_tree_snapshot.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/abis/append_only_tree_snapshot.nr index 83925d95897f..3d1390f148b1 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/abis/append_only_tree_snapshot.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/abis/append_only_tree_snapshot.nr @@ -1,13 +1,13 @@ use dep::std::cmp::Eq; +use crate::constants::APPEND_ONLY_TREE_SNAPSHOT_LENGTH; + struct AppendOnlyTreeSnapshot { root : Field, // TODO(Alvaro) change this to a u64 next_available_leaf_index : u32 } -global APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u64 = 2; - impl AppendOnlyTreeSnapshot { pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] { [self.root, self.next_available_leaf_index as Field] diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/abis/nullifier_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/abis/nullifier_leaf_preimage.nr index ee5b89b2bc8c..084343badd66 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/abis/nullifier_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/abis/nullifier_leaf_preimage.nr @@ -1,16 +1,16 @@ -global NULLIFIER_LEAF_PREIMAGE_LENGTH: u64 = 3; +global NULLIFIER_LEAF_PREIMAGE_LENGTH: u32 = 3; use crate::traits::{Empty, Hash}; struct NullifierLeafPreimage { nullifier : Field, next_nullifier :Field, - next_index : u64, + next_index : u32, } impl Empty for NullifierLeafPreimage { fn empty() -> Self { - Self { + Self { nullifier : 0, next_nullifier : 0, next_index : 0, @@ -38,6 +38,6 @@ impl NullifierLeafPreimage { } pub fn deserialize(fields: [Field; NULLIFIER_LEAF_PREIMAGE_LENGTH]) -> Self { - Self { nullifier: fields[0], next_nullifier: fields[1], next_index: fields[2] as u64 } + Self { nullifier: fields[0], next_nullifier: fields[1], next_index: fields[2] as u32 } } } diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/constants.nr index 690da1a59d5c..0a30a3f9a249 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/constants.nr @@ -1,5 +1,5 @@ -global ARGS_LENGTH: u64 = 16; -global RETURN_VALUES_LENGTH: u64 = 4; +global ARGS_LENGTH: u32 = 16; +global RETURN_VALUES_LENGTH: u32 = 4; /** * Convention for constant array lengths are mainly divided in 2 classes: @@ -23,80 +23,80 @@ global RETURN_VALUES_LENGTH: u64 = 4; // docs:start:constants // "PER CALL" CONSTANTS -global MAX_NEW_NOTE_HASHES_PER_CALL: u64 = 16; -global MAX_NEW_NULLIFIERS_PER_CALL: u64 = 16; -global MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL: u64 = 4; -global MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL: u64 = 4; -global MAX_NEW_L2_TO_L1_MSGS_PER_CALL: u64 = 2; -global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL: u64 = 16; -global MAX_PUBLIC_DATA_READS_PER_CALL: u64 = 16; -global MAX_READ_REQUESTS_PER_CALL: u64 = 32; -global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 1; +global MAX_NEW_NOTE_HASHES_PER_CALL: u32 = 16; +global MAX_NEW_NULLIFIERS_PER_CALL: u32 = 16; +global MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL: u32 = 4; +global MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL: u32 = 4; +global MAX_NEW_L2_TO_L1_MSGS_PER_CALL: u32 = 2; +global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL: u32 = 16; +global MAX_PUBLIC_DATA_READS_PER_CALL: u32 = 16; +global MAX_READ_REQUESTS_PER_CALL: u32 = 32; +global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u32 = 1; // "PER TRANSACTION" CONSTANTS -global MAX_NEW_NOTE_HASHES_PER_TX: u64 = 64; -global MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX: u64 = 8; -global MAX_REVERTIBLE_NOTE_HASHES_PER_TX: u64 = 56; - -global MAX_NEW_NULLIFIERS_PER_TX: u64 = 64; -global MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX: u64 = 8; -global MAX_REVERTIBLE_NULLIFIERS_PER_TX: u64 = 56; - -global MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX: u64 = 8; - -global MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX: u64 = 8; -global MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX: u64 = 3; -global MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX: u64 = 5; - -global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u64 = 32; -global MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u64 = 16; -global MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u64 = 16; - -global MAX_PUBLIC_DATA_READS_PER_TX: u64 = 32; -global MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX: u64 = 16; -global MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX: u64 = 16; - -global MAX_NEW_L2_TO_L1_MSGS_PER_TX: u64 = 2; -global MAX_NEW_CONTRACTS_PER_TX: u64 = 1; -global MAX_READ_REQUESTS_PER_TX: u64 = 128; -global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u64 = 4; -global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; -global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; +global MAX_NEW_NOTE_HASHES_PER_TX: u32 = 64; +global MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX: u32 = 8; +global MAX_REVERTIBLE_NOTE_HASHES_PER_TX: u32 = 56; + +global MAX_NEW_NULLIFIERS_PER_TX: u32 = 64; +global MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX: u32 = 8; +global MAX_REVERTIBLE_NULLIFIERS_PER_TX: u32 = 56; + +global MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX: u32 = 8; + +global MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX: u32 = 8; +global MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX: u32 = 3; +global MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX: u32 = 5; + +global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u32 = 32; +global MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u32 = 16; +global MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u32 = 16; + +global MAX_PUBLIC_DATA_READS_PER_TX: u32 = 32; +global MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX: u32 = 16; +global MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX: u32 = 16; + +global MAX_NEW_L2_TO_L1_MSGS_PER_TX: u32 = 2; +global MAX_NEW_CONTRACTS_PER_TX: u32 = 1; +global MAX_READ_REQUESTS_PER_TX: u32 = 128; +global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u32 = 4; +global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u32 = 1; +global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: u32 = 1; // docs:end:constants // ROLLUP CONTRACT CONSTANTS - constants used only in l1-contracts -global NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP: u64 = 16; +global NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP: u32 = 16; // TREES RELATED CONSTANTS -global VK_TREE_HEIGHT: u64 = 3; -global FUNCTION_TREE_HEIGHT: u64 = 5; -global CONTRACT_TREE_HEIGHT: u64 = 16; -global NOTE_HASH_TREE_HEIGHT: u64 = 32; -global PUBLIC_DATA_TREE_HEIGHT: u64 = 40; -global NULLIFIER_TREE_HEIGHT: u64 = 20; -global L1_TO_L2_MSG_TREE_HEIGHT: u64 = 16; -global ROLLUP_VK_TREE_HEIGHT: u64 = 8; +global VK_TREE_HEIGHT: u32 = 3; +global FUNCTION_TREE_HEIGHT: u32 = 5; +global CONTRACT_TREE_HEIGHT: u32 = 16; +global NOTE_HASH_TREE_HEIGHT: u32 = 32; +global PUBLIC_DATA_TREE_HEIGHT: u32 = 40; +global NULLIFIER_TREE_HEIGHT: u32 = 20; +global L1_TO_L2_MSG_TREE_HEIGHT: u32 = 16; +global ROLLUP_VK_TREE_HEIGHT: u32 = 8; global ARTIFACT_FUNCTION_TREE_MAX_HEIGHT = 5; // SUB-TREES RELATED CONSTANTS -global CONTRACT_SUBTREE_HEIGHT: u64 = 0; -global CONTRACT_SUBTREE_SIBLING_PATH_LENGTH: u64 = 16; -global NOTE_HASH_SUBTREE_HEIGHT: u64 = 6; -global NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH: u64 = 26; -global NULLIFIER_SUBTREE_HEIGHT: u64 = 6; -global PUBLIC_DATA_SUBTREE_HEIGHT: u64 = 5; -global ARCHIVE_HEIGHT: u64 = 16; -global NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH: u64 = 14; -global PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH: u64 = 35; -global L1_TO_L2_MSG_SUBTREE_HEIGHT: u64 = 4; -global L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH: u64 = 12; +global CONTRACT_SUBTREE_HEIGHT: u32 = 0; +global CONTRACT_SUBTREE_SIBLING_PATH_LENGTH: u32 = 16; +global NOTE_HASH_SUBTREE_HEIGHT: u32 = 6; +global NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH: u32 = 26; +global NULLIFIER_SUBTREE_HEIGHT: u32 = 6; +global PUBLIC_DATA_SUBTREE_HEIGHT: u32 = 5; +global ARCHIVE_HEIGHT: u32 = 16; +global NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH: u32 = 14; +global PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH: u32 = 35; +global L1_TO_L2_MSG_SUBTREE_HEIGHT: u32 = 4; +global L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH: u32 = 12; // MISC CONSTANTS global FUNCTION_SELECTOR_NUM_BYTES: Field = 4; // sha256 hash is stored in two fields to accommodate all 256-bits of the hash -global NUM_FIELDS_PER_SHA256: u64 = 2; -global ARGS_HASH_CHUNK_LENGTH: u64 = 32; -global ARGS_HASH_CHUNK_COUNT: u64 = 32; +global NUM_FIELDS_PER_SHA256: u32 = 2; +global ARGS_HASH_CHUNK_LENGTH: u32 = 32; +global ARGS_HASH_CHUNK_COUNT: u32 = 32; // The following is used in immutable state variables to compute an initialization slot whose value is used to // determine whether a given variable has been initialized (by asserting that the value in the slot is 0). // The initialization slot is computed by adding the constant bellow to the variable's storage slot. This constant has @@ -104,12 +104,12 @@ global ARGS_HASH_CHUNK_COUNT: u64 = 32; global INITIALIZATION_SLOT_SEPARATOR: Field = 1000_000_000; // CONTRACT CLASS CONSTANTS -global MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u64 = 8000; +global MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u32 = 8000; // Bytecode size for private functions is per function, not for the entire contract. // Note that private functions bytecode includes a mix of acir and brillig. -global MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS: u64 = 500; +global MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS: u32 = 500; // Same for unconstrained functions: the size is per function. -global MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS: u64 = 500; +global MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS: u32 = 500; // Since we are not yet emitting selectors we'll use this magic value to identify events emitted by the ClassRegisterer. // This is just a stopgap until we implement proper selectors. // sha224sum 'struct ContractClassRegistered {contract_class_id: ContractClassId, version: Field, artifact_hash: Field, private_functions_root: Field, packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS] }' @@ -128,47 +128,47 @@ global DEPLOYER_CONTRACT_ADDRESS = 0x0747a20ed0c86035e44ea5606f30de459f40b55c5e8 // Some are defined here because Noir doesn't yet support globals referencing other globals yet. // Move these constants to a noir file once the issue below is resolved: // https://github.com/noir-lang/noir/issues/1734 -global L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH: u64 = 25; -global MAX_NOTE_FIELDS_LENGTH: u64 = 20; +global L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH: u32 = 25; +global MAX_NOTE_FIELDS_LENGTH: u32 = 20; // GET_NOTE_ORACLE_RETURN_LENGT = MAX_NOTE_FIELDS_LENGTH + 1 + 2 // The plus 1 is 1 extra field for nonce. // + 2 for EXTRA_DATA: [number_of_return_notes, contract_address] -global GET_NOTE_ORACLE_RETURN_LENGTH: u64 = 23; -global MAX_NOTES_PER_PAGE: u64 = 10; +global GET_NOTE_ORACLE_RETURN_LENGTH: u32 = 23; +global MAX_NOTES_PER_PAGE: u32 = 10; // VIEW_NOTE_ORACLE_RETURN_LENGTH = MAX_NOTES_PER_PAGE * (MAX_NOTE_FIELDS_LENGTH + 1) + 2; -global VIEW_NOTE_ORACLE_RETURN_LENGTH: u64 = 212; +global VIEW_NOTE_ORACLE_RETURN_LENGTH: u32 = 212; // LENGTH OF STRUCTS SERIALIZED TO FIELDS global AZTEC_ADDRESS_LENGTH = 1; -global CALL_CONTEXT_LENGTH: u64 = 8; -global CONTENT_COMMITMENT_LENGTH: u64 = 7; -global CONTRACT_DEPLOYMENT_DATA_LENGTH: u64 = 6; -global CONTRACT_INSTANCE_LENGTH: u64 = 6; -global CONTRACT_STORAGE_READ_LENGTH: u64 = 2; -global CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: u64 = 2; +global CALL_CONTEXT_LENGTH: u32 = 8; +global CONTENT_COMMITMENT_LENGTH: u32 = 7; +global CONTRACT_DEPLOYMENT_DATA_LENGTH: u32 = 6; +global CONTRACT_INSTANCE_LENGTH: u32 = 6; +global CONTRACT_STORAGE_READ_LENGTH: u32 = 2; +global CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: u32 = 2; global ETH_ADDRESS_LENGTH = 1; -global FUNCTION_DATA_LENGTH: u64 = 4; -global FUNCTION_LEAF_PREIMAGE_LENGTH: u64 = 5; -global GLOBAL_VARIABLES_LENGTH: u64 = 6; -global HEADER_LENGTH: u64 = 25; // 2 for last_archive, 7 for content commitment, 10 for state reference, 6 for global vars -global L1_TO_L2_MESSAGE_LENGTH: u64 = 8; -global L2_TO_L1_MESSAGE_LENGTH: u64 = 2; -global NEW_CONTRACT_DATA_LENGTH: u64 = 3; +global FUNCTION_DATA_LENGTH: u32 = 4; +global FUNCTION_LEAF_PREIMAGE_LENGTH: u32 = 5; +global GLOBAL_VARIABLES_LENGTH: u32 = 6; +global HEADER_LENGTH: u32 = 25; // 2 for last_archive, 7 for content commitment, 10 for state reference, 6 for global vars +global L1_TO_L2_MESSAGE_LENGTH: u32 = 8; +global L2_TO_L1_MESSAGE_LENGTH: u32 = 2; +global NEW_CONTRACT_DATA_LENGTH: u32 = 3; global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; -global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 8; -global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = 219; +global PARTIAL_STATE_REFERENCE_LENGTH: u32 = 8; +global PRIVATE_CALL_STACK_ITEM_LENGTH: u32 = 219; // Change this ONLY if you have changed the PrivateCircuitPublicInputs structure. // In other words, if the structure/size of the public inputs of a function call changes then we should change this // constant as well PRIVATE_CALL_STACK_ITEM_LENGTH -global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 214; +global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = 214; // Change this ONLY if you have changed the PublicCircuitPublicInputs structure. -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 194; -global STATE_REFERENCE_LENGTH: u64 = 10; // 2 for snap + 8 for partial -global TX_CONTEXT_DATA_LENGTH: u64 = 11; -global TX_REQUEST_LENGTH: u64 = 17; +global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = 194; +global STATE_REFERENCE_LENGTH: u32 = 10; // 2 for snap + 8 for partial +global TX_CONTEXT_DATA_LENGTH: u32 = 11; +global TX_REQUEST_LENGTH: u32 = 17; -global GET_NOTES_ORACLE_RETURN_LENGTH: u64 = 674; +global GET_NOTES_ORACLE_RETURN_LENGTH: u32 = 674; global NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; global PUBLIC_DATA_WRITES_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; @@ -232,3 +232,5 @@ global GENERATOR_INDEX__VK = 41; global GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS = 42; global GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS = 43; global GENERATOR_INDEX__FUNCTION_ARGS = 44; + +global APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2; diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/hash.nr index 55c416efcf40..26960bf45f8b 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/hash.nr @@ -282,7 +282,7 @@ pub fn compute_logs_hash( ) } -pub fn compute_note_hash_nonce(first_nullifier: Field, commitment_index: u64) -> Field { +pub fn compute_note_hash_nonce(first_nullifier: Field, commitment_index: u32) -> Field { pedersen_hash( [ first_nullifier, diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/header.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/header.nr index ece1d741a961..5c97745e79f6 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/header.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/header.nr @@ -1,11 +1,11 @@ use crate::{ abis::{ - append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH}, + append_only_tree_snapshot::AppendOnlyTreeSnapshot, global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH} }, constants::{ GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, NUM_FIELDS_PER_SHA256, STATE_REFERENCE_LENGTH, - CONTENT_COMMITMENT_LENGTH + CONTENT_COMMITMENT_LENGTH, APPEND_ONLY_TREE_SNAPSHOT_LENGTH }, hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize}, utils::{arr_copy_slice}, content_commitment::ContentCommitment diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/public_data_tree_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/public_data_tree_leaf_preimage.nr index dcc84fe7026b..dc84f6ee903c 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/public_data_tree_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/public_data_tree_leaf_preimage.nr @@ -4,7 +4,7 @@ struct PublicDataTreeLeafPreimage { slot : Field, value: Field, next_slot :Field, - next_index : u64, + next_index : u32, } impl Empty for PublicDataTreeLeafPreimage { diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/fixtures/read_requests.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/fixtures/read_requests.nr index f23ef8080eff..ce4fcb0be6c7 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/fixtures/read_requests.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/fixtures/read_requests.nr @@ -2,16 +2,16 @@ use crate::abis::{membership_witness::ReadRequestMembershipWitness, side_effect: use crate::tests::fixtures; use crate::constants::{MAX_READ_REQUESTS_PER_CALL}; -pub fn generate_read_requests(how_many: u64) -> (BoundedVec, BoundedVec) { +pub fn generate_read_requests(how_many: u32) -> (BoundedVec, BoundedVec) { generate_read_requests_with_config(how_many, false, [0; MAX_READ_REQUESTS_PER_CALL]) } -pub fn generate_transient_read_requests(how_many: u64) -> (BoundedVec, BoundedVec) { +pub fn generate_transient_read_requests(how_many: u32) -> (BoundedVec, BoundedVec) { generate_read_requests_with_config(how_many, true, [0; MAX_READ_REQUESTS_PER_CALL]) } pub fn generate_read_requests_with_config( - how_many: u64, + how_many: u32, is_transient: bool, hints_to_commitment: [Field; MAX_READ_REQUESTS_PER_CALL] ) -> (BoundedVec, BoundedVec) { diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/kernel_data_builder.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/kernel_data_builder.nr index 4a22a03cb5a2..b8fd6412f603 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/kernel_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/kernel_data_builder.nr @@ -79,7 +79,7 @@ impl PreviousKernelDataBuilder { pub fn append_public_data_update_requests(&mut self, num_updates: Field) { let value_offset = self.end.public_data_update_requests.len(); for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { - if i as u64 < num_updates as u64 { + if i as u32 < num_updates as u32 { let update_request = PublicDataUpdateRequest { // The default leaf index is its index + 23. leaf_slot: (value_offset + i + 23) as Field, @@ -94,7 +94,7 @@ impl PreviousKernelDataBuilder { pub fn append_public_data_read_requests(&mut self, num_reads: Field) { let value_offset = self.end.public_data_reads.len(); for i in 0..MAX_PUBLIC_DATA_READS_PER_TX { - if i as u64 < num_reads as u64 { + if i as u32 < num_reads as u32 { let read_request = PublicDataRead { // The default leaf index is its index + 34. leaf_slot: (value_offset + i + 34) as Field, @@ -112,7 +112,7 @@ impl PreviousKernelDataBuilder { counter } - pub fn add_read_request_for_transient_commitment(&mut self, commitment_index: u64) -> u64 { + pub fn add_read_request_for_transient_commitment(&mut self, commitment_index: u32) -> u32 { let new_read_request_index = self.end.read_requests.len(); let commitment = self.end.new_note_hashes.get(commitment_index); let read_request = SideEffect { value: commitment.value, counter: self.next_sideffect_counter() }; @@ -120,7 +120,7 @@ impl PreviousKernelDataBuilder { new_read_request_index } - pub fn append_new_note_hashes(&mut self, num_new_note_hashes: u64) { + pub fn append_new_note_hashes(&mut self, num_new_note_hashes: u32) { let mocked_value_offset = self.end.new_note_hashes.len() + 1; for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { if i < num_new_note_hashes { @@ -132,7 +132,7 @@ impl PreviousKernelDataBuilder { } } - pub fn append_new_nullifiers_from_private(&mut self, num_extra_nullifier: u64) { + pub fn append_new_nullifiers_from_private(&mut self, num_extra_nullifier: u32) { // in private kernel, the nullifiers have not yet been partitioned // (that is part of the job of the private kernel tail) // so the tx nullifier is in `end` @@ -152,7 +152,7 @@ impl PreviousKernelDataBuilder { } } - pub fn append_new_nullifiers_from_public(&mut self, num_extra_nullifier: u64) { + pub fn append_new_nullifiers_from_public(&mut self, num_extra_nullifier: u32) { let first_nullifier = self.end_non_revertible.new_nullifiers.get(0); let mocked_value_offset = first_nullifier.value + self.end.new_nullifiers.len() as Field; for i in 1..MAX_NEW_NULLIFIERS_PER_TX { @@ -169,7 +169,7 @@ impl PreviousKernelDataBuilder { } } - pub fn append_new_nullifiers_non_revertible(&mut self, num_extra_nullifier: u64) { + pub fn append_new_nullifiers_non_revertible(&mut self, num_extra_nullifier: u32) { let first_nullifier = self.end_non_revertible.new_nullifiers.get(0); let mocked_value_offset = first_nullifier.value + self.end_non_revertible.new_nullifiers.len() as Field; for i in 1..MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX { diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/private_call_data_builder.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/private_call_data_builder.nr index 85c4f08c7bea..7746e022af95 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/private_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/private_call_data_builder.nr @@ -108,13 +108,13 @@ impl PrivateCallDataBuilder { } } - pub fn append_private_call_requests(&mut self, num_requests: u64, is_delegate_call: bool) { + pub fn append_private_call_requests(&mut self, num_requests: u32, is_delegate_call: bool) { let (hashes, call_requests) = self.generate_call_requests(self.private_call_stack, num_requests, is_delegate_call); self.public_inputs.private_call_stack_hashes.extend_from_bounded_vec(hashes); self.private_call_stack.extend_from_bounded_vec(call_requests); } - pub fn append_public_call_requests(&mut self, num_requests: u64, is_delegate_call: bool) { + pub fn append_public_call_requests(&mut self, num_requests: u32, is_delegate_call: bool) { let (hashes, call_requests) = self.generate_call_requests(self.public_call_stack, num_requests, is_delegate_call); self.public_inputs.public_call_stack_hashes.extend_from_bounded_vec(hashes); self.public_call_stack.extend_from_bounded_vec(call_requests); @@ -123,7 +123,7 @@ impl PrivateCallDataBuilder { fn generate_call_requests( self, requests: BoundedVec, - num_requests: u64, + num_requests: u32, is_delegate_call: bool ) -> (BoundedVec, BoundedVec) { let value_offset = requests.len(); @@ -156,13 +156,13 @@ impl PrivateCallDataBuilder { (hashes, call_requests) } - pub fn append_read_requests(&mut self, num_read_requests: u64) { + pub fn append_read_requests(&mut self, num_read_requests: u32) { let (read_requests, read_request_membership_witnesses) = fixtures::read_requests::generate_read_requests(num_read_requests); self.public_inputs.read_requests.extend_from_bounded_vec(read_requests); self.read_request_membership_witnesses.extend_from_bounded_vec(read_request_membership_witnesses); } - pub fn append_transient_read_requests(&mut self, num_read_requests: u64) { + pub fn append_transient_read_requests(&mut self, num_read_requests: u32) { let (read_requests, read_request_membership_witnesses) = fixtures::read_requests::generate_transient_read_requests(num_read_requests); self.public_inputs.read_requests.extend_from_bounded_vec(read_requests); self.read_request_membership_witnesses.extend_from_bounded_vec(read_request_membership_witnesses); diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/public_call_data_builder.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/public_call_data_builder.nr index 7ac3af533b50..7a9257e67c20 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/public_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/tests/public_call_data_builder.nr @@ -75,15 +75,15 @@ impl PublicCallDataBuilder { *self } - pub fn append_public_call_requests_for_regular_calls(&mut self, num_requests: u64) { + pub fn append_public_call_requests_for_regular_calls(&mut self, num_requests: u32) { self.append_public_call_requests(num_requests, false); } - pub fn append_public_call_requests_for_delegate_calls(&mut self, num_requests: u64) { + pub fn append_public_call_requests_for_delegate_calls(&mut self, num_requests: u32) { self.append_public_call_requests(num_requests, true); } - pub fn append_public_call_requests(&mut self, num_requests: u64, is_delegate_call: bool) { + pub fn append_public_call_requests(&mut self, num_requests: u32, is_delegate_call: bool) { let value_offset = self.public_inputs.public_call_stack_hashes.len(); let mut caller_context = CallerContext::empty(); if is_delegate_call { @@ -114,7 +114,7 @@ impl PublicCallDataBuilder { pub fn append_read_requests(&mut self, num_reads: Field) { let value_offset = self.public_inputs.contract_storage_reads.len(); for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { - if i as u64 < num_reads as u64 { + if i as u32 < num_reads as u32 { let read_request = StorageRead { // The default storage slot is its index + 1. storage_slot: (value_offset + i + 1) as Field, @@ -128,7 +128,7 @@ impl PublicCallDataBuilder { pub fn append_empty_read_requests(&mut self, num_reads: Field) { for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { - if i as u64 < num_reads as u64 { + if i as u32 < num_reads as u32 { self.public_inputs.contract_storage_reads.push(StorageRead::empty()); } } @@ -137,7 +137,7 @@ impl PublicCallDataBuilder { pub fn append_update_requests(&mut self, num_updates: Field) { let value_offset = self.public_inputs.contract_storage_update_requests.len(); for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL { - if i as u64 < num_updates as u64 { + if i as u32 < num_updates as u32 { let update_request = StorageUpdateRequest { // The default storage slot is its index + 1. storage_slot: (value_offset + i + 1) as Field, @@ -151,7 +151,7 @@ impl PublicCallDataBuilder { pub fn append_empty_update_requests(&mut self, num_updates: Field) { for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL { - if i as u64 < num_updates as u64 { + if i as u32 < num_updates as u32 { self.public_inputs.contract_storage_update_requests.push(StorageUpdateRequest::empty()); } } diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/utils.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/utils.nr index 547ff3ea09e2..95561df1094e 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/utils.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/utils.nr @@ -12,7 +12,7 @@ pub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field { if predicate { lhs } else { rhs } } -pub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u64) -> [T; M] { +pub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] { for i in 0..dst.len() { dst[i] = src[i + offset]; } diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/utils/arrays.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/utils/arrays.nr index 4cd8dd3e1969..9cdd5c4c1552 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/utils/arrays.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/utils/arrays.nr @@ -30,12 +30,12 @@ pub fn validate_array(array: [T; N]) where T: Empty + Eq { first_zero_pos = i; } } - assert((last_non_zero_pos as u64) <= (first_zero_pos as u64), "invalid array"); + assert((last_non_zero_pos as u32) <= (first_zero_pos as u32), "invalid array"); } // Helper method to determine the number of non-zero/empty elements in a validated array (ie, validate_array(array) // should be true). -pub fn array_length(array: [T; N]) -> u64 where T: Empty + Eq { +pub fn array_length(array: [T; N]) -> u32 where T: Empty + Eq { let mut length = 0; let mut end = false; for elem in array { diff --git a/noir-projects/noir-protocol-circuits/src/crates/types/src/utils/reader.nr b/noir-projects/noir-protocol-circuits/src/crates/types/src/utils/reader.nr index dffc118e7d8e..17c441ccb7c2 100644 --- a/noir-projects/noir-protocol-circuits/src/crates/types/src/utils/reader.nr +++ b/noir-projects/noir-protocol-circuits/src/crates/types/src/utils/reader.nr @@ -1,6 +1,6 @@ struct Reader { data: [Field; N], - offset: u64, + offset: u32, } impl Reader { diff --git a/noir/acvm-repo/acir_field/src/generic_ark.rs b/noir/acvm-repo/acir_field/src/generic_ark.rs index 3178011a0755..531904e639a6 100644 --- a/noir/acvm-repo/acir_field/src/generic_ark.rs +++ b/noir/acvm-repo/acir_field/src/generic_ark.rs @@ -254,6 +254,10 @@ impl FieldElement { (self.num_bits() <= 64).then(|| self.to_u128() as u64) } + pub fn try_to_u32(&self) -> Option { + (self.num_bits() <= 32).then(|| self.to_u128() as u32) + } + /// Computes the inverse or returns zero if the inverse does not exist /// Before using this FieldElement, please ensure that this behavior is necessary pub fn inverse(&self) -> FieldElement { diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index 156ba1d5b08b..46cb81256700 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -673,8 +673,14 @@ fn transform_function( /// Transform a function to work with AVM bytecode fn transform_vm_function( func: &mut NoirFunction, - _storage_defined: bool, + storage_defined: bool, ) -> Result<(), AztecMacroError> { + // Create access to storage + if storage_defined { + let storage = abstract_storage("public_vm", true); + func.def.body.0.insert(0, storage); + } + // Push Avm context creation to the beginning of the function let create_context = create_avm_context()?; func.def.body.0.insert(0, create_context); diff --git a/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index f01f60252f64..a0e558e04b62 100644 --- a/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -596,6 +596,7 @@ impl<'block> BrilligBlock<'block> { }; let index_variable = self.convert_ssa_single_addr_value(*index, dfg); + // dbg!("validate", &index_variable); self.validate_array_index(array_variable, index_variable); self.retrieve_variable_from_array( array_pointer, @@ -754,6 +755,8 @@ impl<'block> BrilligBlock<'block> { _ => unreachable!("ICE: validate array index on non-array"), }; + // dbg!("validate array index", &size_as_register, &index_register); + let condition = self.brillig_context.allocate_register(); self.brillig_context.memory_op( @@ -1229,6 +1232,7 @@ impl<'block> BrilligBlock<'block> { self.variables.allocate_constant(self.brillig_context, value_id, dfg); let register_index = new_variable.extract_single_addr(); + // println!("GET THE BIT SIZE FROM SSA TYPE"); self.brillig_context.const_instruction( register_index.address, (*constant).into(), diff --git a/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs b/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs index f463bd4de4d5..1d25768e28a7 100644 --- a/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs +++ b/noir/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs @@ -132,6 +132,7 @@ impl BlockVariables { value_id: ValueId, dfg: &DataFlowGraph, ) -> BrilligVariable { + // dbg!("allocate constant"); let value_id = dfg.resolve(value_id); let constant = allocate_value(value_id, brillig_context, dfg); self.available_constants.insert(value_id, constant); @@ -189,10 +190,14 @@ pub(crate) fn allocate_value( let typ = dfg.type_of_value(value_id); match typ { - Type::Numeric(numeric_type) => BrilligVariable::SingleAddr(SingleAddrVariable { - address: brillig_context.allocate_register(), - bit_size: numeric_type.bit_size(), - }), + Type::Numeric(numeric_type) => { + let bit_size = numeric_type.bit_size(); + // dbg!(bit_size); + BrilligVariable::SingleAddr(SingleAddrVariable { + address: brillig_context.allocate_register(), + bit_size: bit_size, + }) + } Type::Reference(_) => BrilligVariable::SingleAddr(SingleAddrVariable { address: brillig_context.allocate_register(), bit_size: BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, diff --git a/noir/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/noir/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 90608974f985..7eb214c54e7a 100644 --- a/noir/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/noir/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -41,8 +41,8 @@ use num_bigint::BigUint; /// constrained functions in terms of syntax compatibility. pub(crate) const BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE: u32 = 127; /// The Brillig VM does not apply a limit to the memory address space, -/// As a convention, we take use 64 bits. This means that we assume that -/// memory has 2^64 memory slots. +/// As a convention, we take use 32 bits. This means that we assume that +/// memory has 2^32 memory slots. pub(crate) const BRILLIG_MEMORY_ADDRESSING_BIT_SIZE: u32 = 32; // Registers reserved in runtime for special purposes. @@ -221,6 +221,7 @@ impl BrilligContext { index: MemoryAddress, result: MemoryAddress, ) { + // dbg!("Array Get"); self.debug_show.array_get(array_ptr, index, result); // Computes array_ptr + index, ie array[index] let index_of_element_in_memory = self.allocate_register(); @@ -557,7 +558,11 @@ impl BrilligContext { constant: Value, bit_size: u32, ) { + // dbg!("const instruction", result, constant, bit_size); self.debug_show.const_instruction(result, constant); + + // TODO: temporarily to unblock me ass + // let bit_s = std::cmp::min(32, bit_size); self.push_opcode(BrilligOpcode::Const { destination: result, value: constant, bit_size }); } diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 8d4d06685344..556d4e185a6c 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -675,6 +675,8 @@ impl Context { } }; + // dbg!(index); + if self.handle_constant_index(instruction, dfg, index, array, store_value)? { return Ok(()); } @@ -726,13 +728,13 @@ impl Context { AcirValue::Array(array) => { if let Some(index_const) = index_const { let array_size = array.len(); - let index = match index_const.try_to_u64() { + let index = match index_const.try_to_u32() { Some(index_const) => index_const as usize, None => { let call_stack = self.acir_context.get_call_stack(); return Err(RuntimeError::TypeConversion { from: "array index".to_string(), - into: "u64".to_string(), + into: "u32".to_string(), call_stack, }); } @@ -1926,10 +1928,10 @@ impl Context { // Check that we are above the lower bound of the insertion index let greater_eq_than_idx = - self.acir_context.more_than_eq_var(current_index, flat_user_index, 64)?; + self.acir_context.more_than_eq_var(current_index, flat_user_index, 32)?; // Check that we are below the upper bound of the insertion index let less_than_idx = - self.acir_context.less_than_var(current_index, max_flat_user_index, 64)?; + self.acir_context.less_than_var(current_index, max_flat_user_index, 32)?; // Read from the original slice the value we want to insert into our new slice. // We need to make sure that we read the previous element when our current index is greater than insertion index. diff --git a/noir/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/noir/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 9d27554dcaa0..2d278a9f6e36 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -221,6 +221,7 @@ impl FunctionBuilder { operator: BinaryOp, rhs: ValueId, ) -> ValueId { + // dbg!(lhs, rhs, operator); assert_eq!( self.type_of_value(lhs), self.type_of_value(rhs), @@ -296,6 +297,7 @@ impl FunctionBuilder { element_type: Type, ) -> ValueId { let element_type = Some(vec![element_type]); + // dbg!(&element_type); self.insert_instruction(Instruction::ArrayGet { array, index }, element_type).first() } diff --git a/noir/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/noir/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index 0b6c7074e45d..a3410fc1e4e5 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -464,8 +464,9 @@ impl Instruction { let array = dfg.get_array_constant(*array); let index = dfg.get_numeric_constant(*index); if let (Some((array, _)), Some(index)) = (array, index) { + // TODO(md): FORCE THE SSA WORD SIZE TO ALIGN WITH AVM / BRILLIG let index = - index.try_to_u64().expect("Expected array index to fit in u64") as usize; + index.try_to_u32().expect("Expected array index to fit in u32") as usize; if index < array.len() { return SimplifiedTo(array[index]); } @@ -477,7 +478,7 @@ impl Instruction { let index = dfg.get_numeric_constant(*index); if let (Some((array, element_type)), Some(index)) = (array, index) { let index = - index.try_to_u64().expect("Expected array index to fit in u64") as usize; + index.try_to_u32().expect("Expected array index to fit in u32") as usize; if index < array.len() { let new_array = dfg.make_array(array.update(index, *value), element_type); diff --git a/noir/compiler/noirc_evaluator/src/ssa/ir/types.rs b/noir/compiler/noirc_evaluator/src/ssa/ir/types.rs index ea3f53932457..9784795de80d 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ir/types.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ir/types.rs @@ -21,6 +21,7 @@ pub enum NumericType { impl NumericType { /// Returns the bit size of the provided numeric type. pub(crate) fn bit_size(self: &NumericType) -> u32 { + // println!("getting numeric type bitsize"); match self { NumericType::NativeField => FieldElement::max_num_bits(), NumericType::Unsigned { bit_size } | NumericType::Signed { bit_size } => *bit_size, @@ -92,7 +93,7 @@ impl Type { /// Creates the type of an array's length. pub(crate) fn length_type() -> Type { - Type::unsigned(64) + Type::unsigned(32) } /// Returns the bit size of the provided numeric type. diff --git a/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 9c760c013a9e..80128042c1ee 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -730,9 +730,10 @@ impl<'a> FunctionContext<'a> { address } - /// Array indexes are u64s. This function casts values used as indexes to u64. + // TODO: HACK + /// Array indexes are u32s. This function casts values used as indexes to u32. pub(super) fn make_array_index(&mut self, index: ValueId) -> ValueId { - self.builder.insert_cast(index, Type::unsigned(64)) + self.builder.insert_cast(index, Type::unsigned(32)) } /// Define a local variable to be some Values that can later be retrieved @@ -980,12 +981,12 @@ impl<'a> FunctionContext<'a> { ) -> ValueId { let index = self.make_array_index(index); let element_size = - self.builder.numeric_constant(self.element_size(array), Type::unsigned(64)); + self.builder.numeric_constant(self.element_size(array), Type::unsigned(32)); // The actual base index is the user's index * the array element type's size let mut index = self.builder.set_location(location).insert_binary(index, BinaryOp::Mul, element_size); - let one = self.builder.numeric_constant(FieldElement::one(), Type::unsigned(64)); + let one = self.builder.numeric_constant(FieldElement::one(), Type::unsigned(32)); new_value.for_each(|value| { let value = value.eval(self); diff --git a/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index d95295ae3c97..b5505f0355fd 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -128,6 +128,9 @@ impl<'a> FunctionContext<'a> { } fn codegen_expression(&mut self, expr: &Expression) -> Result { + + // dbg!(expr); + match expr { Expression::Ident(ident) => Ok(self.codegen_ident(ident)), Expression::Literal(literal) => self.codegen_literal(literal), @@ -186,6 +189,10 @@ impl<'a> FunctionContext<'a> { fn codegen_literal(&mut self, literal: &ast::Literal) -> Result { match literal { ast::Literal::Array(array) => { + + // dbg!(&array); + + // TODO(md): need to double check this array upstream - is the let elements = try_vecmap(&array.contents, |element| self.codegen_expression(element))?; @@ -347,6 +354,8 @@ impl<'a> FunctionContext<'a> { } fn codegen_binary(&mut self, binary: &ast::Binary) -> Result { + // TODO: crashing in here + // dbg!(&binary); let lhs = self.codegen_non_tuple_expression(&binary.lhs)?; let rhs = self.codegen_non_tuple_expression(&binary.rhs)?; Ok(self.insert_binary(lhs, binary.operator, rhs, binary.location)) @@ -389,10 +398,12 @@ impl<'a> FunctionContext<'a> { // base_index = index * type_size let index = self.make_array_index(index); let type_size = Self::convert_type(element_type).size_of_type(); - let type_size = self.builder.numeric_constant(type_size as u128, Type::unsigned(64)); + let type_size = self.builder.numeric_constant(type_size as u128, Type::unsigned(32)); let base_index = self.builder.set_location(location).insert_binary(index, BinaryOp::Mul, type_size); + // dbg!(index, type_size, base_index); + let mut field_index = 0u128; Ok(Self::map_type(element_type, |typ| { let offset = self.make_offset(base_index, field_index); @@ -472,6 +483,8 @@ impl<'a> FunctionContext<'a> { // this is the 'i' in `for i in start .. end { block }` let index_type = Self::convert_non_tuple_type(&for_expr.index_type); + // dbg!(index_type.clone()); + let loop_index = self.builder.add_block_parameter(loop_entry, index_type); self.builder.set_location(for_expr.start_range_location); diff --git a/noir/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 7f9e48353a70..79b139b9bdc6 100644 --- a/noir/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -1219,6 +1219,7 @@ impl<'a> Resolver<'a> { ); (decl, this.resolve_expression(block)) }); + // dbg!(&identifier); HirStatement::For(HirForStatement { start_range, diff --git a/noir/compiler/noirc_frontend/src/hir_def/types.rs b/noir/compiler/noirc_frontend/src/hir_def/types.rs index e105da1ccf07..d1a0a2c5119d 100644 --- a/noir/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/compiler/noirc_frontend/src/hir_def/types.rs @@ -554,7 +554,7 @@ impl Type { } pub fn default_range_loop_type() -> Type { - Type::Integer(Signedness::Unsigned, IntegerBitSize::SixtyFour) + Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo) } pub fn type_variable(id: TypeVariableId) -> Type { diff --git a/noir/noir_stdlib/src/array.nr b/noir/noir_stdlib/src/array.nr index 3da4b6491744..e67ef658517d 100644 --- a/noir/noir_stdlib/src/array.nr +++ b/noir/noir_stdlib/src/array.nr @@ -4,7 +4,7 @@ use crate::cmp::{Ord}; // by the methods in the `slice` module impl [T; N] { #[builtin(array_len)] - pub fn len(self) -> u64 {} + pub fn len(self) -> u32 {} pub fn sort(self) -> Self where T: Ord { self.sort_via(|a: T, b: T| a <= b) @@ -31,7 +31,7 @@ impl [T; N] { } /// Returns the index of the elements in the array that would sort it, using the provided custom sorting function. - unconstrained fn get_sorting_index(self, ordering: fn[Env](T, T) -> bool) -> [u64; N] { + unconstrained fn get_sorting_index(self, ordering: fn[Env](T, T) -> bool) -> [u32; N] { let mut result = [0; N]; let mut a = self; for i in 0..N { @@ -116,7 +116,7 @@ impl [T; N] { // helper function used to look up the position of a value in an array of Field // Note that function returns 0 if the value is not found -unconstrained fn find_index(a: [u64; N], find: u64) -> u64 { +unconstrained fn find_index(a: [u32; N], find: u32) -> u32 { let mut result = 0; for i in 0..a.len() { if a[i] == find { diff --git a/noir/noir_stdlib/src/collections/bounded_vec.nr b/noir/noir_stdlib/src/collections/bounded_vec.nr index 752b96d6591f..c21f54a16316 100644 --- a/noir/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir/noir_stdlib/src/collections/bounded_vec.nr @@ -1,6 +1,6 @@ struct BoundedVec { storage: [T; MaxLen], - len: u64, + len: u32, } impl BoundedVec { @@ -9,27 +9,27 @@ impl BoundedVec { BoundedVec { storage: [zeroed; MaxLen], len: 0 } } - pub fn get(mut self: Self, index: u64) -> T { - assert(index as u64 < self.len); + pub fn get(mut self: Self, index: u32) -> T { + assert(index as u32 < self.len); self.storage[index] } - pub fn get_unchecked(mut self: Self, index: u64) -> T { + pub fn get_unchecked(mut self: Self, index: u32) -> T { self.storage[index] } pub fn push(&mut self, elem: T) { - assert(self.len < MaxLen as u64, "push out of bounds"); + assert(self.len < MaxLen as u32, "push out of bounds"); self.storage[self.len] = elem; self.len += 1; } - pub fn len(self) -> u64 { + pub fn len(self) -> u32 { self.len } - pub fn max_len(_self: BoundedVec) -> u64 { + pub fn max_len(_self: BoundedVec) -> u32 { MaxLen } @@ -41,7 +41,7 @@ impl BoundedVec { pub fn extend_from_array(&mut self, array: [T; Len]) { let new_len = self.len + array.len(); - assert(new_len as u64 <= MaxLen as u64, "extend_from_array out of bounds"); + assert(new_len as u32 <= MaxLen as u32, "extend_from_array out of bounds"); for i in 0..array.len() { self.storage[self.len + i] = array[i]; } @@ -51,7 +51,7 @@ impl BoundedVec { pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) { let append_len = vec.len(); let new_len = self.len + append_len; - assert(new_len as u64 <= MaxLen as u64, "extend_from_bounded_vec out of bounds"); + assert(new_len as u32 <= MaxLen as u32, "extend_from_bounded_vec out of bounds"); let mut exceeded_len = false; for i in 0..Len { @@ -64,7 +64,7 @@ impl BoundedVec { } pub fn pop(&mut self) -> T { - assert(self.len as u64 > 0); + assert(self.len as u32 > 0); self.len -= 1; let elem = self.storage[self.len]; diff --git a/noir/noir_stdlib/src/collections/map.nr b/noir/noir_stdlib/src/collections/map.nr index 056299b42387..67957f6e6285 100644 --- a/noir/noir_stdlib/src/collections/map.nr +++ b/noir/noir_stdlib/src/collections/map.nr @@ -18,7 +18,7 @@ struct HashMap { _table: [Slot; N], // Amount of valid elements in the map. - _len: u64, + _len: u32, _build_hasher: B } @@ -257,12 +257,12 @@ impl HashMap { } // Amount of active key-value entries. - pub fn len(self) -> u64 { + pub fn len(self) -> u32 { self._len } // Get the compile-time map capacity. - pub fn capacity(_self: Self) -> u64 { + pub fn capacity(_self: Self) -> u32 { N } @@ -282,7 +282,7 @@ impl HashMap { for attempt in 0..N { if !break { - let index = self.quadratic_probe(hash, attempt as u64); + let index = self.quadratic_probe(hash, attempt as u32); let slot = self._table[index]; // Not marked as deleted and has key-value. @@ -316,7 +316,7 @@ impl HashMap { for attempt in 0..N { if !break { - let index = self.quadratic_probe(hash, attempt as u64); + let index = self.quadratic_probe(hash, attempt as u32); let mut slot = self._table[index]; let mut insert = false; @@ -354,7 +354,7 @@ impl HashMap { for attempt in 0..N { if !break { - let index = self.quadratic_probe(hash, attempt as u64); + let index = self.quadratic_probe(hash, attempt as u32); let mut slot = self._table[index]; // Not marked as deleted and has key-value. @@ -375,21 +375,21 @@ impl HashMap { fn hash( self, key: K - ) -> u64 + ) -> u32 where K: Hash, B: BuildHasher, H: Hasher { let mut hasher = self._build_hasher.build_hasher(); key.hash(&mut hasher); - hasher.finish() as u64 + hasher.finish() as u32 } // Probing scheme: quadratic function. // We use 0.5 constant near variadic attempt and attempt^2 monomials. // This ensures good uniformity of distribution for table sizes // equal to prime numbers or powers of two. - fn quadratic_probe(_self: Self, hash: u64, attempt: u64) -> u64 { + fn quadratic_probe(_self: Self, hash: u32, attempt: u32) -> u32 { (hash + (attempt + attempt * attempt) / 2) % N } diff --git a/noir/noir_stdlib/src/collections/vec.nr b/noir/noir_stdlib/src/collections/vec.nr index deec98185ff7..d43628c9d7e6 100644 --- a/noir/noir_stdlib/src/collections/vec.nr +++ b/noir/noir_stdlib/src/collections/vec.nr @@ -17,7 +17,7 @@ impl Vec { /// Get an element from the vector at the given index. /// Panics if the given index /// points beyond the end of the vector. - pub fn get(self, index: u64) -> T { + pub fn get(self, index: u32) -> T { self.slice[index] } @@ -40,20 +40,20 @@ impl Vec { /// Insert an element at a specified index, shifting all elements /// after it to the right - pub fn insert(&mut self, index: u64, elem: T) { + pub fn insert(&mut self, index: u32, elem: T) { self.slice = self.slice.insert(index, elem); } /// Remove an element at a specified index, shifting all elements /// after it to the left, returning the removed element - pub fn remove(&mut self, index: u64) -> T { + pub fn remove(&mut self, index: u32) -> T { let (new_slice, elem) = self.slice.remove(index); self.slice = new_slice; elem } /// Returns the number of elements in the vector - pub fn len(self) -> u64 { + pub fn len(self) -> u32 { self.slice.len() } } diff --git a/noir/noir_stdlib/src/hash/poseidon.nr b/noir/noir_stdlib/src/hash/poseidon.nr index b1a7c4a2367e..baa7387ae725 100644 --- a/noir/noir_stdlib/src/hash/poseidon.nr +++ b/noir/noir_stdlib/src/hash/poseidon.nr @@ -47,7 +47,7 @@ fn permute(pos_conf: PoseidonConfig, mut state: [Field; O]) -> [F } state = apply_matrix(mds, state); // Apply MDS matrix - count = count + t as u64; + count = count + t as u32; } state diff --git a/noir/noir_stdlib/src/hash/poseidon/bn254.nr b/noir/noir_stdlib/src/hash/poseidon/bn254.nr index 37b08e3c8fb8..00534546308b 100644 --- a/noir/noir_stdlib/src/hash/poseidon/bn254.nr +++ b/noir/noir_stdlib/src/hash/poseidon/bn254.nr @@ -27,7 +27,7 @@ pub fn permute(pos_conf: PoseidonConfig, mut state: [Field; O]) - } state = apply_matrix(mds, state); // Apply MDS matrix - count = count + t as u64; + count = count + t as u32; } // Partial rounds for _r in 0..rp { @@ -37,7 +37,7 @@ pub fn permute(pos_conf: PoseidonConfig, mut state: [Field; O]) - state[0] = state[0].pow_32(alpha); state = apply_matrix(mds, state); // Apply MDS matrix - count = count + t as u64; + count = count + t as u32; } // Second half of full rounds for _r in 0..rf / 2 { @@ -49,7 +49,7 @@ pub fn permute(pos_conf: PoseidonConfig, mut state: [Field; O]) - } state = apply_matrix(mds, state); // Apply MDS matrix - count = count + t as u64; + count = count + t as u32; } state diff --git a/noir/noir_stdlib/src/sha256.nr b/noir/noir_stdlib/src/sha256.nr index 2f686a64165b..c682e215fe36 100644 --- a/noir/noir_stdlib/src/sha256.nr +++ b/noir/noir_stdlib/src/sha256.nr @@ -18,7 +18,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { let mut msg_block: [u8; 64] = [0; 64]; let mut h: [u32; 8] = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; // Intermediate hash, starting with the canonical initial value let mut out_h: [u8; 32] = [0; 32]; // Digest as sequence of bytes - let mut i: u64 = 0; // Message byte pointer + let mut i: u32 = 0; // Message byte pointer for k in 0..N { // Populate msg_block msg_block[i as Field] = msg[k]; diff --git a/noir/noir_stdlib/src/slice.nr b/noir/noir_stdlib/src/slice.nr index ea8d09d14ce5..955f9a1fc8fd 100644 --- a/noir/noir_stdlib/src/slice.nr +++ b/noir/noir_stdlib/src/slice.nr @@ -24,13 +24,13 @@ impl [T] { /// Insert an element at a specified index, shifting all elements /// after it to the right #[builtin(slice_insert)] - pub fn insert(self, index: u64, elem: T) -> Self {} + pub fn insert(self, index: u32, elem: T) -> Self {} /// Remove an element at a specified index, shifting all elements /// after it to the left, returning the altered slice and /// the removed element #[builtin(slice_remove)] - pub fn remove(self, index: u64) -> (Self, T) {} + pub fn remove(self, index: u32) -> (Self, T) {} // Append each element of the `other` slice to the end of `self`. // This returns a new slice and leaves both input slices unchanged. diff --git a/noir/test_programs/compile_success_empty/numeric_generics/src/main.nr b/noir/test_programs/compile_success_empty/numeric_generics/src/main.nr index 1e03a382fed3..997db41331d5 100644 --- a/noir/test_programs/compile_success_empty/numeric_generics/src/main.nr +++ b/noir/test_programs/compile_success_empty/numeric_generics/src/main.nr @@ -25,7 +25,7 @@ struct MyStruct { impl MyStruct { fn insert(mut self: Self, index: Field, elem: Field) -> Self { // Regression test for numeric generics on impls - assert(index as u64 < S as u64); + assert(index as u32 < S as u32); self.data[index] = elem; self diff --git a/noir/test_programs/execution_success/array_len/src/main.nr b/noir/test_programs/execution_success/array_len/src/main.nr index f846cfb9844a..45c09b8a2823 100644 --- a/noir/test_programs/execution_success/array_len/src/main.nr +++ b/noir/test_programs/execution_success/array_len/src/main.nr @@ -1,12 +1,12 @@ -fn len_plus_1(array: [T; N]) -> u64 { +fn len_plus_1(array: [T; N]) -> u32 { array.len() + 1 } -fn add_lens(a: [T; N], b: [Field; M]) -> u64 { +fn add_lens(a: [T; N], b: [Field; M]) -> u32 { a.len() + b.len() } -fn nested_call(b: [Field; N]) -> u64 { +fn nested_call(b: [Field; N]) -> u32 { len_plus_1(b) } diff --git a/noir/test_programs/execution_success/regression/src/main.nr b/noir/test_programs/execution_success/regression/src/main.nr index 8dc42cb5f10f..66e6645403bf 100644 --- a/noir/test_programs/execution_success/regression/src/main.nr +++ b/noir/test_programs/execution_success/regression/src/main.nr @@ -21,8 +21,8 @@ impl Eq for U4 { } fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Field) { - assert(2 * input.len() <= NIBBLE_LENGTH as u64); - assert(length as u64 <= input.len()); + assert(2 * input.len() <= NIBBLE_LENGTH as u32); + assert(length as u32 <= input.len()); let mut nibble = [U4::zero(); NIBBLE_LENGTH]; @@ -32,7 +32,7 @@ fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Fie if parity == 1 { nibble[0] = U4::from_u8(input[0] & 0x0f); for i in 1..input.len() { - if i as u64 < length as u64 { + if i as u32 < length as u32 { let x = input[i]; nibble[2*i - 1] = U4::from_u8(x >> 4); nibble[2*i] = U4::from_u8(x & 0x0f); @@ -40,7 +40,7 @@ fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Fie } } else { for i in 0..2 { - if (i as u64) < length as u64 - 1 { + if (i as u32) < length as u32 - 1 { let x = input[i + 1]; nibble[2*i] = U4::from_u8(x >> 4); nibble[2*i + 1] = U4::from_u8(x & 0x0f); diff --git a/noir/test_programs/execution_success/slice_dynamic_index/src/main.nr b/noir/test_programs/execution_success/slice_dynamic_index/src/main.nr index 41fc9a645c10..a067d1482982 100644 --- a/noir/test_programs/execution_success/slice_dynamic_index/src/main.nr +++ b/noir/test_programs/execution_success/slice_dynamic_index/src/main.nr @@ -124,12 +124,12 @@ fn dynamic_slice_merge_if(mut slice: [Field], x: Field) { assert(first_elem == 12); assert(rest_of_slice.len() == 6); - slice = rest_of_slice.insert(x as u64 - 2, 20); + slice = rest_of_slice.insert(x as u32 - 2, 20); assert(slice[2] == 20); assert(slice[6] == 30); assert(slice.len() == 7); - let (removed_slice, removed_elem) = slice.remove(x as u64 - 1); + let (removed_slice, removed_elem) = slice.remove(x as u32 - 1); // The deconstructed tuple assigns to the slice but is not seen outside of the if statement // without a direct assignment slice = removed_slice; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 5213d7fe1032..d6ebc515b027 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -108,6 +108,7 @@ export const CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP = 64; export const CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP_UNPADDED = 52; export const L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP = 64; export const LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 64; +export const APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2; export enum GeneratorIndex { NOTE_HASH = 1, NOTE_HASH_NONCE = 2, diff --git a/yarn-project/noir-contracts.js/scripts/generate-types.sh b/yarn-project/noir-contracts.js/scripts/generate-types.sh index 8532ef04ca39..4ae8eb0790cb 100755 --- a/yarn-project/noir-contracts.js/scripts/generate-types.sh +++ b/yarn-project/noir-contracts.js/scripts/generate-types.sh @@ -30,11 +30,13 @@ for ABI in $(find ../../noir-projects/noir-contracts/target -maxdepth 1 -type f CONTRACT=$(jq -r .name "artifacts/$filename") echo "Creating types for $CONTRACT using artifacts/$filename..." - node --no-warnings ../noir-compiler/dest/cli.js codegen -o $OUT_DIR --ts "artifacts/$filename" + node --no-warnings ../noir-compiler/dest/cli.js codegen -o $OUT_DIR --ts "artifacts/$filename" & # Add contract import/export to index.ts. echo "export * from './${CONTRACT}.js';" >>$INDEX done +wait + echo "Formatting..." yarn formatting:fix diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 977ece373b92..a17cbf15a115 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -147,6 +147,68 @@ describe('AVM simulator', () => { }); }); + describe('Storage accesses', () => { + it('Should set a single value in storage', async () => { + // We want to set + const calldata: Fr[] = []; + // We are setting the owner + const slot = 1n; + const sender = AztecAddress.fromField(new Fr(1)); + const address = AztecAddress.fromField(new Fr(420)); + + // Get contract function artifact + const artifact = AvmTestContractArtifact.functions.find(f => f.name === 'avm_setAdmin')!; + + // Decode bytecode into instructions + const bytecode = Buffer.from(artifact.bytecode, 'base64'); + + const context = initContext({ + env: initExecutionEnvironment({ calldata, sender, address, storageAddress: address }), + }); + jest + .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') + .mockReturnValue(Promise.resolve(bytecode)); + + const simulator = new AvmSimulator(context); + const results = await simulator.execute(); + expect(results.reverted).toBe(false); + + // Contract 420 - Storage slot 1 should contain the value 1 + const worldState = context.persistableState.flush(); + + const storageSlot = worldState.currentStorageValue.get(address.toBigInt())!; + const adminSlotValue = storageSlot.get(slot)!; + expect(adminSlotValue).toEqual(sender.toField()); + }); + + it('Should read a value from storage', async () => { + const calldata: Fr[] = []; + // We are setting the owner + const sender = AztecAddress.fromField(new Fr(1)); + const address = AztecAddress.fromField(new Fr(420)); + + // Get contract function artifact + const artifact = AvmTestContractArtifact.functions.find(f => f.name === 'avm_setAndRead')!; + + // Decode bytecode into instructions + const bytecode = Buffer.from(artifact.bytecode, 'base64'); + + const context = initContext({ + env: initExecutionEnvironment({ calldata, sender, address, storageAddress: address }), + }); + jest + .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') + .mockReturnValue(Promise.resolve(bytecode)); + + const simulator = new AvmSimulator(context); + const results = await simulator.execute(); + expect(results.reverted).toBe(false); + + const returnData = results.output; + expect(returnData[0]).toEqual(sender.toField()); + }); + }); + describe('Test env getters from noir contract', () => { const testEnvGetter = async (valueName: string, value: any, functionName: string, globalVar: boolean = false) => { const getterArtifact = AvmTestContractArtifact.functions.find(f => f.name === functionName)!; diff --git a/yarn-project/simulator/src/avm/journal/journal.test.ts b/yarn-project/simulator/src/avm/journal/journal.test.ts index dabeee98751f..9f7f7054c728 100644 --- a/yarn-project/simulator/src/avm/journal/journal.test.ts +++ b/yarn-project/simulator/src/avm/journal/journal.test.ts @@ -35,7 +35,7 @@ describe('journal', () => { expect(cacheMissResult).toEqual(storedValue); // Write to storage - journal.writeStorage(contractAddress, key, cachedValue); + journal.writeStorage(contractAddress, key, [cachedValue]); // Get the storage value const cachedResult = await journal.readStorage(contractAddress, key); @@ -116,7 +116,7 @@ describe('journal', () => { const logs = [new Fr(1), new Fr(2)]; const logsT1 = [new Fr(3), new Fr(4)]; - journal.writeStorage(contractAddress, key, value); + journal.writeStorage(contractAddress, key, [value]); await journal.readStorage(contractAddress, key); journal.writeNoteHash(commitment); journal.writeLog(logs); @@ -125,7 +125,7 @@ describe('journal', () => { await journal.checkNullifierExists(contractAddress, commitment); const childJournal = new AvmPersistableStateManager(journal.hostStorage, journal); - childJournal.writeStorage(contractAddress, key, valueT1); + childJournal.writeStorage(contractAddress, key, [valueT1]); await childJournal.readStorage(contractAddress, key); childJournal.writeNoteHash(commitmentT1); childJournal.writeLog(logsT1); @@ -182,7 +182,7 @@ describe('journal', () => { const logs = [new Fr(1), new Fr(2)]; const logsT1 = [new Fr(3), new Fr(4)]; - journal.writeStorage(contractAddress, key, value); + journal.writeStorage(contractAddress, key, [value]); await journal.readStorage(contractAddress, key); journal.writeNoteHash(commitment); await journal.writeNullifier(contractAddress, commitment); @@ -191,7 +191,7 @@ describe('journal', () => { journal.writeL1Message(logs); const childJournal = new AvmPersistableStateManager(journal.hostStorage, journal); - childJournal.writeStorage(contractAddress, key, valueT1); + childJournal.writeStorage(contractAddress, key, [valueT1]); await childJournal.readStorage(contractAddress, key); childJournal.writeNoteHash(commitmentT1); await childJournal.writeNullifier(contractAddress, commitmentT1); diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index b55b8d8f3386..272463b90dd3 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -73,11 +73,11 @@ export class AvmPersistableStateManager { * @param slot - the slot in the contract's storage being written to * @param value - the value being written to the slot */ - public writeStorage(storageAddress: Fr, slot: Fr, value: Fr) { + public writeStorage(storageAddress: Fr, slot: Fr, values: /*temporarily an array*/ Fr[]) { // Cache storage writes for later reference/reads - this.publicStorage.write(storageAddress, slot, value); + this.publicStorage.write(storageAddress, slot, values); // Trace all storage writes (even reverted ones) - this.trace.tracePublicStorageWrite(storageAddress, slot, value); + this.trace.tracePublicStorageWrite(storageAddress, slot, values); } /** diff --git a/yarn-project/simulator/src/avm/journal/public_storage.test.ts b/yarn-project/simulator/src/avm/journal/public_storage.test.ts index d8b79fc79c0a..7bf6c0d6ecc1 100644 --- a/yarn-project/simulator/src/avm/journal/public_storage.test.ts +++ b/yarn-project/simulator/src/avm/journal/public_storage.test.ts @@ -29,7 +29,7 @@ describe('avm public storage', () => { const slot = new Fr(2); const value = new Fr(3); // Write to cache - publicStorage.write(contractAddress, slot, value); + publicStorage.write(contractAddress, slot, [value]); const [exists, gotValue] = await publicStorage.read(contractAddress, slot); // exists because it was previously written expect(exists).toEqual(true); @@ -53,7 +53,7 @@ describe('avm public storage', () => { const value = new Fr(3); const childStorage = new PublicStorage(publicDb, publicStorage); - publicStorage.write(contractAddress, slot, value); + publicStorage.write(contractAddress, slot, [value]); const [exists, gotValue] = await childStorage.read(contractAddress, slot); // exists because it was previously written! expect(exists).toEqual(true); @@ -75,13 +75,13 @@ describe('avm public storage', () => { expect(cacheMissResult).toEqual(storedValue); // Write to storage - publicStorage.write(contractAddress, slot, parentValue); + publicStorage.write(contractAddress, slot, [parentValue]); // Reading from child should give value written in parent const [, valueFromParent] = await childStorage.read(contractAddress, slot); expect(valueFromParent).toEqual(parentValue); // Now write a value directly in child - childStorage.write(contractAddress, slot, cachedValue); + childStorage.write(contractAddress, slot, [cachedValue]); // Reading should now give the value written in child const [, cachedResult] = await childStorage.read(contractAddress, slot); @@ -99,11 +99,11 @@ describe('avm public storage', () => { const valueT1 = new Fr(2); // Write initial value to parent - publicStorage.write(contractAddress, slot, value); + publicStorage.write(contractAddress, slot, [value]); const childStorage = new PublicStorage(publicDb, publicStorage); // Write valueT1 to child - childStorage.write(contractAddress, slot, valueT1); + childStorage.write(contractAddress, slot, [valueT1]); // Parent accepts child's staged writes publicStorage.acceptAndMerge(childStorage); diff --git a/yarn-project/simulator/src/avm/journal/public_storage.ts b/yarn-project/simulator/src/avm/journal/public_storage.ts index f6b3b7a35d86..a154d937ec86 100644 --- a/yarn-project/simulator/src/avm/journal/public_storage.ts +++ b/yarn-project/simulator/src/avm/journal/public_storage.ts @@ -63,8 +63,12 @@ export class PublicStorage { * @param slot - the slot in the contract's storage being written to * @param value - the value being written to the slot */ - public write(storageAddress: Fr, key: Fr, value: Fr) { - this.cache.write(storageAddress, key, value); + public write(storageAddress: Fr, key: Fr, values: Fr[]) { + for (const [index, value] of Object.entries(values)) { + // TODO: yuck + const adjustedIndex = key.add(new Fr(BigInt(index))); + this.cache.write(storageAddress, adjustedIndex, value); + } } /** diff --git a/yarn-project/simulator/src/avm/journal/trace.test.ts b/yarn-project/simulator/src/avm/journal/trace.test.ts index e26ecb185e42..f19869621aeb 100644 --- a/yarn-project/simulator/src/avm/journal/trace.test.ts +++ b/yarn-project/simulator/src/avm/journal/trace.test.ts @@ -57,7 +57,7 @@ describe('world state access trace', () => { const commitment = new Fr(10); let counter = 0; - trace.tracePublicStorageWrite(contractAddress, slot, value); + trace.tracePublicStorageWrite(contractAddress, slot, [value]); counter++; trace.tracePublicStorageRead(contractAddress, slot, value); counter++; @@ -67,7 +67,7 @@ describe('world state access trace', () => { counter++; trace.traceNewNullifier(contractAddress, commitment); counter++; - trace.tracePublicStorageWrite(contractAddress, slot, value); + trace.tracePublicStorageWrite(contractAddress, slot, [value]); counter++; trace.tracePublicStorageRead(contractAddress, slot, value); counter++; @@ -107,14 +107,14 @@ describe('world state access trace', () => { leafIndex: nullifierLeafIndexT1, }; - trace.tracePublicStorageWrite(contractAddress, slot, value); + trace.tracePublicStorageWrite(contractAddress, slot, [value]); trace.tracePublicStorageRead(contractAddress, slot, value); trace.traceNewNoteHash(contractAddress, commitment); trace.traceNullifierCheck(contractAddress, commitment, nullifierExists, nullifierIsPending, nullifierLeafIndex); trace.traceNewNullifier(contractAddress, commitment); const childTrace = new WorldStateAccessTrace(trace); - childTrace.tracePublicStorageWrite(contractAddress, slot, valueT1); + childTrace.tracePublicStorageWrite(contractAddress, slot, [valueT1]); childTrace.tracePublicStorageRead(contractAddress, slot, valueT1); childTrace.traceNewNoteHash(contractAddress, commitmentT1); childTrace.traceNullifierCheck( diff --git a/yarn-project/simulator/src/avm/journal/trace.ts b/yarn-project/simulator/src/avm/journal/trace.ts index dcd266a43132..5cfc0eec605a 100644 --- a/yarn-project/simulator/src/avm/journal/trace.ts +++ b/yarn-project/simulator/src/avm/journal/trace.ts @@ -45,8 +45,8 @@ export class WorldStateAccessTrace { this.incrementAccessCounter(); } - public tracePublicStorageWrite(storageAddress: Fr, slot: Fr, value: Fr) { - // TODO(4805): check if some threshold is reached for max storage writes + public tracePublicStorageWrite(storageAddress: Fr, slot: Fr, values: Fr[]) { + // TODO: check if some threshold is reached for max storage writes // (need access to parent length, or trace needs to be initialized with parent's contents) //const traced: TracedPublicStorageWrite = { // callPointer: Fr.ZERO, @@ -57,8 +57,14 @@ export class WorldStateAccessTrace { // endLifetime: Fr.ZERO, //}; //this.publicStorageWrites.push(traced); - this.journalWrite(storageAddress, slot, value); - this.incrementAccessCounter(); + + for (const [index, value] of Object.entries(values)) { + // TODO: yuck + const adjustedSlot = slot.add(new Fr(BigInt(index))); + + this.journalWrite(storageAddress, adjustedSlot, value); + this.incrementAccessCounter(); + } } public traceNewNoteHash(_storageAddress: Fr, noteHash: Fr) { diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts index e557f3242782..ba53dfd18333 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts @@ -70,7 +70,7 @@ describe('External Calls', () => { const successOffset = 7; const otherContextInstructionsBytecode = encodeToBytecode([ new CalldataCopy(/*indirect=*/ 0, /*csOffset=*/ 0, /*copySize=*/ argsSize, /*dstOffset=*/ 0), - new SStore(/*indirect=*/ 0, /*srcOffset=*/ 0, /*slotOffset=*/ 0), + new SStore(/*indirect=*/ 0, /*srcOffset=*/ 0, /*size=*/ 1, /*slotOffset=*/ 0), new Return(/*indirect=*/ 0, /*retOffset=*/ 0, /*size=*/ 2), ]); @@ -101,6 +101,7 @@ describe('External Calls', () => { // Check that the storage call has been merged into the parent journal const { currentStorageValue } = context.persistableState.flush(); + console.log() expect(currentStorageValue.size).toEqual(1); const nestedContractWrites = currentStorageValue.get(addr.toBigInt()); @@ -159,7 +160,7 @@ describe('External Calls', () => { const otherContextInstructions: Instruction[] = [ new CalldataCopy(/*indirect=*/ 0, /*csOffset=*/ 0, /*copySize=*/ argsSize, /*dstOffset=*/ 0), - new SStore(/*indirect=*/ 0, /*srcOffset=*/ 1, /*slotOffset=*/ 0), + new SStore(/*indirect=*/ 0, /*srcOffset=*/ 1, /*size=*/ 1, /*slotOffset=*/ 0), ]; const otherContextInstructionsBytecode = encodeToBytecode(otherContextInstructions); diff --git a/yarn-project/simulator/src/avm/opcodes/hashing.test.ts b/yarn-project/simulator/src/avm/opcodes/hashing.test.ts index 452b997a62fa..794abb1468f6 100644 --- a/yarn-project/simulator/src/avm/opcodes/hashing.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/hashing.test.ts @@ -64,6 +64,24 @@ describe('Hashing Opcodes', () => { const result = context.machineState.memory.get(dstOffset); expect(result).toEqual(new Field(expectedHash)); }); + + it('Should hash correctly - indirect pos', async () => { + const args = [new Field(1n), new Field(2n), new Field(3n)]; + const indirect = 1; + const hashOffset = 0; + const realLocation = 4; + + context.machineState.memory.set(hashOffset, new Uint32(realLocation)); + context.machineState.memory.setSlice(realLocation, args); + + const dstOffset = 3; + + const expectedHash = poseidonHash(args.map(field => field.toBuffer())); + await new Poseidon2(indirect, dstOffset, hashOffset, args.length).execute(context); + + const result = context.machineState.memory.get(dstOffset); + expect(result).toEqual(new Field(expectedHash)); + }); }); describe('Keccak', () => { @@ -126,7 +144,6 @@ describe('Hashing Opcodes', () => { expect(combined).toEqual(expectedHash); }); - // TODO: indirect }); describe('Sha256', () => { @@ -245,5 +262,24 @@ describe('Hashing Opcodes', () => { const result = context.machineState.memory.get(dstOffset); expect(result).toEqual(new Field(expectedHash)); }); + + it('Should hash correctly - indirect', async () => { + const args = [new Field(1n), new Field(2n), new Field(3n)]; + const indirect = 1; + const hashOffset = 0; + const realLocation = 4; + + context.machineState.memory.set(hashOffset, new Uint32(realLocation)); + context.machineState.memory.setSlice(realLocation, args); + + const dstOffset = 3; + + const inputBuffer = args.map(field => field.toBuffer()); + const expectedHash = pedersenHash(inputBuffer); + await new Pedersen(indirect, dstOffset, hashOffset, args.length).execute(context); + + const result = context.machineState.memory.get(dstOffset); + expect(result).toEqual(new Field(expectedHash)); + }); }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/storage.test.ts b/yarn-project/simulator/src/avm/opcodes/storage.test.ts index bd53a1d3324d..13e62f7193f4 100644 --- a/yarn-project/simulator/src/avm/opcodes/storage.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/storage.test.ts @@ -28,9 +28,15 @@ describe('Storage Instructions', () => { SStore.opcode, // opcode 0x01, // indirect ...Buffer.from('12345678', 'hex'), // srcOffset - ...Buffer.from('a2345678', 'hex'), // slotOffset + ...Buffer.from('a2345678', 'hex'), // size + ...Buffer.from('3456789a', 'hex'), // slotOffset ]); - const inst = new SStore(/*indirect=*/ 0x01, /*srcOffset=*/ 0x12345678, /*slotOffset=*/ 0xa2345678); + const inst = new SStore( + /*indirect=*/ 0x01, + /*srcOffset=*/ 0x12345678, + /*size=*/ 0xa2345678, + /*slotOffset=*/ 0x3456789a, + ); expect(SStore.deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); @@ -43,9 +49,9 @@ describe('Storage Instructions', () => { context.machineState.memory.set(0, a); context.machineState.memory.set(1, b); - await new SStore(/*indirect=*/ 0, /*srcOffset=*/ 0, /*slotOffset=*/ 1).execute(context); + await new SStore(/*indirect=*/ 0, /*srcOffset=*/ 1, /*size=*/ 1, /*slotOffset=*/ 0).execute(context); - expect(journal.writeStorage).toHaveBeenCalledWith(address, new Fr(a.toBigInt()), new Fr(b.toBigInt())); + expect(journal.writeStorage).toHaveBeenCalledWith(address, new Fr(a.toBigInt()), [new Fr(b.toBigInt())]); }); it('Should not be able to write to storage in a static call', async () => { @@ -60,7 +66,8 @@ describe('Storage Instructions', () => { context.machineState.memory.set(0, a); context.machineState.memory.set(1, b); - const instruction = () => new SStore(/*indirect=*/ 0, /*srcOffset=*/ 0, /*slotOffset=*/ 1).execute(context); + const instruction = () => + new SStore(/*indirect=*/ 0, /*srcOffset=*/ 0, /*size=*/ 1, /*slotOffset=*/ 1).execute(context); await expect(instruction()).rejects.toThrow(StaticCallStorageAlterError); }); }); @@ -71,9 +78,15 @@ describe('Storage Instructions', () => { SLoad.opcode, // opcode 0x01, // indirect ...Buffer.from('12345678', 'hex'), // slotOffset - ...Buffer.from('a2345678', 'hex'), // dstOffset + ...Buffer.from('a2345678', 'hex'), // size + ...Buffer.from('3456789a', 'hex'), // dstOffset ]); - const inst = new SLoad(/*indirect=*/ 0x01, /*slotOffset=*/ 0x12345678, /*dstOffset=*/ 0xa2345678); + const inst = new SLoad( + /*indirect=*/ 0x01, + /*slotOffset=*/ 0x12345678, + /*size=*/ 0xa2345678, + /*dstOffset=*/ 0x3456789a, + ); expect(SLoad.deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); @@ -90,7 +103,7 @@ describe('Storage Instructions', () => { context.machineState.memory.set(0, a); context.machineState.memory.set(1, b); - await new SLoad(/*indirect=*/ 0, /*slotOffset=*/ 0, /*dstOffset=*/ 1).execute(context); + await new SLoad(/*indirect=*/ 0, /*slotOffset=*/ 0, /*size=*/ 1, /*dstOffset=*/ 1).execute(context); expect(journal.readStorage).toHaveBeenCalledWith(address, new Fr(a.toBigInt())); diff --git a/yarn-project/simulator/src/avm/opcodes/storage.ts b/yarn-project/simulator/src/avm/opcodes/storage.ts index 1090d5d35403..46dbf02509a6 100644 --- a/yarn-project/simulator/src/avm/opcodes/storage.ts +++ b/yarn-project/simulator/src/avm/opcodes/storage.ts @@ -4,6 +4,7 @@ import type { AvmContext } from '../avm_context.js'; import { Field } from '../avm_memory_types.js'; import { InstructionExecutionError } from '../errors.js'; import { Opcode, OperandType } from '../serialization/instruction_serialization.js'; +import { Addressing } from './addressing_mode.js'; import { Instruction } from './instruction.js'; abstract class BaseStorageInstruction extends Instruction { @@ -13,9 +14,15 @@ abstract class BaseStorageInstruction extends Instruction { OperandType.UINT8, OperandType.UINT32, OperandType.UINT32, + OperandType.UINT32, ]; - constructor(protected indirect: number, protected aOffset: number, protected bOffset: number) { + constructor( + protected indirect: number, + protected aOffset: number, + protected /*temporary*/ size: number, + protected bOffset: number, + ) { super(); } } @@ -24,8 +31,8 @@ export class SStore extends BaseStorageInstruction { static readonly type: string = 'SSTORE'; static readonly opcode = Opcode.SSTORE; - constructor(indirect: number, srcOffset: number, slotOffset: number) { - super(indirect, srcOffset, slotOffset); + constructor(indirect: number, srcOffset: number, /*temporary*/ srcSize: number, slotOffset: number) { + super(indirect, srcOffset, srcSize, slotOffset); } async execute(context: AvmContext): Promise { @@ -33,14 +40,12 @@ export class SStore extends BaseStorageInstruction { throw new StaticCallStorageAlterError(); } - const slot = context.machineState.memory.get(this.aOffset); - const data = context.machineState.memory.get(this.bOffset); + const [srcOffset, slotOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.bOffset], context.machineState.memory); - context.persistableState.writeStorage( - context.environment.storageAddress, - new Fr(slot.toBigInt()), - new Fr(data.toBigInt()), - ); + const slot = context.machineState.memory.get(slotOffset).toFr(); + const data = context.machineState.memory.getSlice(srcOffset, this.size).map(field => field.toFr()); + + context.persistableState.writeStorage(context.environment.storageAddress, slot, data); context.machineState.incrementPc(); } @@ -50,19 +55,27 @@ export class SLoad extends BaseStorageInstruction { static readonly type: string = 'SLOAD'; static readonly opcode = Opcode.SLOAD; - constructor(indirect: number, slotOffset: number, dstOffset: number) { - super(indirect, slotOffset, dstOffset); + constructor(indirect: number, slotOffset: number, size: number, dstOffset: number) { + super(indirect, slotOffset, size, dstOffset); } async execute(context: AvmContext): Promise { - const slot = context.machineState.memory.get(this.aOffset); - - const data: Fr = await context.persistableState.readStorage( - context.environment.storageAddress, - new Fr(slot.toBigInt()), + const [aOffset, size, bOffset] = Addressing.fromWire(this.indirect).resolve( + [this.aOffset, this.size, this.bOffset], + context.machineState.memory, ); - context.machineState.memory.set(this.bOffset, new Field(data)); + const slot = context.machineState.memory.get(aOffset); + + // Write each read value from storage into memory + for (let i = 0; i < size; i++) { + const data: Fr = await context.persistableState.readStorage( + context.environment.storageAddress, + new Fr(slot.toBigInt() + BigInt(i)), + ); + + context.machineState.memory.set(bOffset + i, new Field(data)); + } context.machineState.incrementPc(); }