From d5e71d24411131167666df110332525536fdcf84 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Tue, 3 Dec 2024 11:44:17 +0000 Subject: [PATCH 01/13] remove fee write from public base --- .../base_or_merge_rollup_public_inputs.nr | 18 +- .../src/base/private_base_rollup.nr | 2 +- .../rollup-lib/src/base/public_base_rollup.nr | 368 +----------------- .../rollup-lib/src/base/state_diff_hints.nr | 2 +- .../crates/rollup-lib/src/components.nr | 2 +- .../accumulated_data/avm_accumulated_data.nr | 21 +- .../combined_accumulated_data.nr | 12 +- .../src/abis/avm_circuit_public_inputs.nr | 32 +- .../crates/types/src/abis/gas.nr | 4 +- .../crates/types/src/abis/tree_snapshots.nr | 8 +- .../crates/types/src/abis/tube.nr | 6 +- .../crates/types/src/constants.nr | 4 +- .../crates/types/src/data/public_data_hint.nr | 8 +- .../src/merkle_tree/variable_merkle_tree.nr | 2 +- .../crates/types/src/proof/tube_proof.nr | 2 +- .../crates/types/src/proof/vk_data.nr | 6 +- .../crates/types/src/tests/fixture_builder.nr | 12 +- .../crates/types/src/tests/fixtures.nr | 6 +- 18 files changed, 96 insertions(+), 419 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr index 40a7a09f8fb..33e49dd4384 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr @@ -12,23 +12,23 @@ pub(crate) global MERGE_ROLLUP_TYPE: u32 = 1; pub struct BaseOrMergeRollupPublicInputs { // rollup_type is either 0 (base) or 1 (merge) // TODO(Kev): Why is this a u32 instead of a u8/u16? - rollup_type: u32, - num_txs: u32, - constants: ConstantRollupData, + pub(crate) rollup_type: u32, + pub(crate) num_txs: u32, + pub(crate) constants: ConstantRollupData, - start: PartialStateReference, - end: PartialStateReference, + pub(crate) start: PartialStateReference, + pub(crate) end: PartialStateReference, // We hash public inputs to make them constant-sized (to then be unpacked on-chain) // U128 isn't safe if it's an input to the circuit (it won't automatically constrain the witness) // So we want to constrain it when casting these fields to U128 // We hash public inputs to make them constant-sized (to then be unpacked on-chain) - txs_effects_hash: Field, - out_hash: Field, + pub(crate) txs_effects_hash: Field, + pub(crate) out_hash: Field, - accumulated_fees: Field, - accumulated_mana_used: Field, + pub(crate) accumulated_fees: Field, + pub(crate) accumulated_mana_used: Field, } impl Empty for BaseOrMergeRollupPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr index e1c000a7b78..e54164c1f7c 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr @@ -400,7 +400,7 @@ mod tests { let sorted_new_nullifier_tuples = unsafe { get_sorted_tuple( - self.nullifiers.storage.map(|insertion: NullifierInsertion| insertion.value), + self.nullifiers.storage().map(|insertion: NullifierInsertion| insertion.value), |a, b| full_field_less_than(b, a), ) }; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr index c994027d7ec..c0de2733aa6 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr @@ -6,7 +6,6 @@ use crate::{ base::{ components::{ archive::perform_archive_membership_check, constants::validate_combined_constant_data, - fees::compute_fee_payer_fee_juice_balance_leaf_slot, nullifier_tree::nullifier_tree_batch_insert, public_data_tree::public_data_tree_insert, }, state_diff_hints::PublicBaseStateDiffHints, @@ -15,17 +14,18 @@ use crate::{ }; use dep::types::{ abis::{ - accumulated_data::CombinedAccumulatedData, - append_only_tree_snapshot::AppendOnlyTreeSnapshot, avm_circuit_public_inputs::AvmProofData, - combined_constant_data::CombinedConstantData, log_hash::ScopedLogHash, - nullifier_leaf_preimage::NullifierLeafPreimage, public_data_write::PublicDataWrite, + accumulated_data::{self, CombinedAccumulatedData}, + append_only_tree_snapshot::AppendOnlyTreeSnapshot, + avm_circuit_public_inputs::AvmProofData, + combined_constant_data::CombinedConstantData, + log_hash::ScopedLogHash, + nullifier_leaf_preimage::NullifierLeafPreimage, + public_data_write::PublicDataWrite, tube::PublicTubeData, }, constants::{ - ARCHIVE_HEIGHT, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_SUBTREE_HEIGHT, + ARCHIVE_HEIGHT, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_SUBTREE_HEIGHT, }, - data::{hash::compute_public_data_tree_value, public_data_hint::PublicDataHint}, hash::silo_l2_to_l1_message, merkle_tree::{ append_only_tree, calculate_empty_tree_root, calculate_subtree_root, MembershipWitness, @@ -33,7 +33,7 @@ use dep::types::{ messaging::l2_to_l1_message::ScopedL2ToL1Message, partial_state_reference::PartialStateReference, traits::is_empty, - utils::arrays::{array_merge, find_index_hint}, + utils::arrays::array_merge, }; pub struct PublicBaseRollupInputs { @@ -43,7 +43,6 @@ pub struct PublicBaseRollupInputs { start: PartialStateReference, state_diff_hints: PublicBaseStateDiffHints, - fee_payer_fee_juice_balance_read_hint: PublicDataHint, archive_root_membership_witness: MembershipWitness, constants: ConstantRollupData, @@ -144,15 +143,9 @@ impl PublicBaseRollupInputs { let end_nullifier_tree_snapshot = self.check_nullifier_tree_non_membership_and_insert_to_tree(combined_accumulated_data); - // Inject protocol update requests for deducting tx_fee from fee_payer's balance - let all_public_data_update_requests = self.calculate_all_public_data_update_requests( - self.avm_proof_data.public_inputs.transaction_fee, - combined_accumulated_data, - ); - // Validate public data update requests and update public data tree let end_public_data_tree_snapshot = - self.validate_and_process_public_state(all_public_data_update_requests); + self.validate_and_process_public_state(combined_accumulated_data.public_data_writes); // Calculate the tx effects hash of the transaction let siloed_l2_to_l1_msgs = combined_accumulated_data.l2_to_l1_msgs.map( @@ -170,7 +163,7 @@ impl PublicBaseRollupInputs { combined_accumulated_data, revert_code, self.avm_proof_data.public_inputs.transaction_fee, - all_public_data_update_requests, + combined_accumulated_data.public_data_writes, out_hash, ); @@ -257,90 +250,6 @@ impl PublicBaseRollupInputs { } snapshot } - - // Returns an array with all public data update requests for this tx. This includes all update requests - // generated by app circuits, plus the protocol update requests injected by this circuit. The only protocol - // update request we have at the time of this writing is deducting the tx_fee from the fee_payer balance. - fn calculate_all_public_data_update_requests( - self, - tx_fee: Field, - accumulated_data: CombinedAccumulatedData, - ) -> [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] { - let mut all_update_requests: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] = - [PublicDataWrite::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; - for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { - all_update_requests[i] = accumulated_data.public_data_writes[i]; - } - - let (payment_update_request, payment_update_index) = - self.build_or_patch_payment_update_request(tx_fee, accumulated_data); - all_update_requests[payment_update_index] = payment_update_request; - - all_update_requests - } - - // Deducts the tx_fee from the FeeJuice balance of the fee_payer. If there is already a PublicDataWrite - // in this tx for their balance (because they issued a 'claim' to increase their balance by bridging from L1), - // update it by subtracting the tx_fee. Otherwise, build a new PublicDataWrite to subtract the tx_fee - // from the balance of the fee_payer, using the fee_payer_fee_juice_balance_read_hint to read the current balance. - // Returns the data update request that subtracts the tx_fee from the fee_payer's balance, and the index where it - // should be inserted in the public data update requests array. - fn build_or_patch_payment_update_request( - self, - tx_fee: Field, - accumulated_data: CombinedAccumulatedData, - ) -> (PublicDataWrite, u32) { - let fee_payer = self.tube_data.public_inputs.fee_payer; - - // TODO(@spalladino) Eventually remove the is_zero condition as we should always charge fees to every tx - if !fee_payer.is_zero() { - let read_hint = self.fee_payer_fee_juice_balance_read_hint; - let leaf_slot = compute_fee_payer_fee_juice_balance_leaf_slot(fee_payer); - let existing_update_index = unsafe { - find_index_hint( - accumulated_data.public_data_writes, - |w: PublicDataWrite| w.leaf_slot == leaf_slot, - ) - }; - - if existing_update_index != MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { - // Is there a balance update already in this tx? If so, update it and return its index. - let existing_update = accumulated_data.public_data_writes[existing_update_index]; - assert( - existing_update.leaf_slot == leaf_slot, - "Wrong leaf slot for Fee Juice balance update request", - ); - assert( - !existing_update.value.lt(tx_fee), - "Not enough balance for fee payer after claim to pay for transaction", - ); - - let value = compute_public_data_tree_value(existing_update.value - tx_fee); - let protocol_update_request = PublicDataWrite { leaf_slot, value }; - (protocol_update_request, existing_update_index as u32) - } else { - // Otherwise, build a new one to be inserted into the protocol update requests at the end of the array. - read_hint.validate(self.start.public_data_tree.root); - - let balance = read_hint.value; - assert( - read_hint.leaf_slot == leaf_slot, - "Wrong leaf slot for Fee Juice balance read hint", - ); - assert( - !balance.lt(tx_fee), - "Not enough balance for fee payer to pay for transaction", - ); - - let value = compute_public_data_tree_value(balance - tx_fee); - let protocol_update_request = PublicDataWrite { leaf_slot, value }; - (protocol_update_request, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) - } - } else { - // Nothing to do, just place an empty update request at the end of the array - (PublicDataWrite::empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) - } - } } mod tests { @@ -350,7 +259,6 @@ mod tests { constant_rollup_data::ConstantRollupData, }, base::{ - components::fees::compute_fee_payer_fee_juice_balance_leaf_slot, public_base_rollup::PublicBaseRollupInputs, state_diff_hints::PublicBaseStateDiffHints, }, components::TX_EFFECTS_HASH_INPUT_FIELDS, @@ -360,17 +268,15 @@ mod tests { append_only_tree_snapshot::AppendOnlyTreeSnapshot, nullifier_leaf_preimage::NullifierLeafPreimage, public_data_write::PublicDataWrite, }, - address::{AztecAddress, EthAddress}, + address::EthAddress, constants::{ ARCHIVE_HEIGHT, AVM_VK_INDEX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, - MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_SUBTREE_HEIGHT, - NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NOTE_HASH_TREE_HEIGHT, NULLIFIER_SUBTREE_HEIGHT, - NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, - PRIVATE_KERNEL_EMPTY_INDEX, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - PUBLIC_DATA_TREE_HEIGHT, TUBE_VK_INDEX, + MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NOTE_HASH_TREE_HEIGHT, + NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, + PRIVATE_KERNEL_EMPTY_INDEX, PUBLIC_DATA_TREE_HEIGHT, TUBE_VK_INDEX, }, - data::{public_data_hint::PublicDataHint, PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, + data::{PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, hash::silo_l2_to_l1_message, merkle_tree::MembershipWitness, messaging::l2_to_l1_message::ScopedL2ToL1Message, @@ -462,17 +368,9 @@ mod tests { pre_existing_contracts: [Field; 2], pre_existing_public_data: [PublicDataTreeLeafPreimage; PRE_EXISTING_PUBLIC_DATA_LEAVES], pre_existing_blocks: [Field; 2], - // Public data writes generated by app code - public_data_writes: BoundedVec<(u32, PublicDataTreeLeaf), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX>, - // Public data writes overwritten by the base rollup circuit - overwritten_public_data_writes: [Option; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - // New public data writes to be created by the protocol (eg a data update request for updating fee payer balance) - protocol_public_data_writes: BoundedVec<(u32, PublicDataTreeLeaf), PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX>, + public_data_writes: BoundedVec<(u32, PublicDataTreeLeaf), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX>, nullifiers: BoundedVec, constants: ConstantRollupData, - // Index of the item in the pre_existing_public_data array that contains the fee payer's Fee Juice balance. - // Used for building the public data hint read for the payment update request. If set to none, no hint is built. - fee_payer_fee_juice_balance_pre_existing_public_data_index: Option, } impl PublicBaseRollupInputsBuilder { @@ -496,29 +394,6 @@ mod tests { builder } - fn build_fee_payer_fee_juice_balance_read_hint( - self, - start_public_data_tree: NonEmptyMerkleTree, - ) -> PublicDataHint { - self.fee_payer_fee_juice_balance_pre_existing_public_data_index.map_or( - PublicDataHint::empty(), - |leaf_index_u32: u32| { - let leaf_index = leaf_index_u32 as Field; - let leaf_preimage = self.pre_existing_public_data[leaf_index]; - let membership_witness = MembershipWitness { - leaf_index, - sibling_path: start_public_data_tree.get_sibling_path(leaf_index_u32), - }; - PublicDataHint { - leaf_slot: leaf_preimage.slot, - value: leaf_preimage.value, - membership_witness, - leaf_preimage, - } - }, - ) - } - fn extract_subtree_sibling_path( path: [Field; FULL_HEIGHT], mut sibling_path: [Field; SIBLING_PATH_LENGTH], @@ -542,7 +417,7 @@ mod tests { let sorted_new_nullifier_tuples = unsafe { get_sorted_tuple( - self.nullifiers.storage.map(|insertion: NullifierInsertion| insertion.value), + self.nullifiers.storage().map(|insertion: NullifierInsertion| insertion.value), |a, b| full_field_less_than(b, a), ) }; @@ -643,9 +518,6 @@ mod tests { next_available_leaf_index: self.pre_existing_public_data.len(), }; - let fee_payer_fee_juice_balance_read_hint = - self.build_fee_payer_fee_juice_balance_read_hint(start_public_data_tree); - let start_archive = NonEmptyMerkleTree::new( self.pre_existing_blocks, [0; ARCHIVE_HEIGHT], @@ -673,26 +545,10 @@ mod tests { [0; NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH], ); - let mut final_public_data_writes: BoundedVec<(u32, PublicDataTreeLeaf), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX> = - BoundedVec::new(); - final_public_data_writes.extend_from_array(self.public_data_writes.storage); - final_public_data_writes.extend_from_array(self.protocol_public_data_writes.storage); - for i in 0..self.overwritten_public_data_writes.len() { - if self.overwritten_public_data_writes[i].is_some() { - final_public_data_writes.set( - i, - ( - final_public_data_writes.get(i).0, - self.overwritten_public_data_writes[i].unwrap_unchecked(), - ), - ); - } - } - let (low_public_data_writes_preimages, low_public_data_writes_witnesses, public_data_tree_sibling_paths) = update_public_data_tree( &mut start_public_data_tree, start_public_data_tree_snapshot, - final_public_data_writes.storage(), + self.public_data_writes.storage(), self.pre_existing_public_data, ); @@ -730,7 +586,6 @@ mod tests { sibling_path: start_archive.get_sibling_path(0), }, constants: self.constants, - fee_payer_fee_juice_balance_read_hint, } } @@ -763,13 +618,8 @@ mod tests { ], pre_existing_blocks: [0; 2], public_data_writes: BoundedVec::new(), - overwritten_public_data_writes: [ - Option::none(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX - ], - protocol_public_data_writes: BoundedVec::new(), nullifiers: BoundedVec::new(), constants: ConstantRollupData::empty(), - fee_payer_fee_juice_balance_pre_existing_public_data_index: Option::none(), } } } @@ -1121,184 +971,6 @@ mod tests { assert_eq(outputs.end.public_data_tree.root, expected_public_data_tree.get_root()); } - #[test] - unconstrained fn updates_fee_payer_balance_with_new_data_write() { - let fee_payer = AztecAddress::from_field(0x1234); - let balance_slot = compute_fee_payer_fee_juice_balance_leaf_slot(fee_payer); - let initial_balance = 300_000; - let tx_fee = 100_000; - let expected_balance = 200_000; - - let mut builder = PublicBaseRollupInputsBuilder::new(); - - // Set fee payer - builder.tube_data.fee_payer = fee_payer; - - // Set pre-existing balance - builder.pre_existing_public_data[0] = PublicDataTreeLeafPreimage { - slot: balance_slot, - value: initial_balance, - next_slot: 0, - next_index: 0, - }; - builder.fee_payer_fee_juice_balance_pre_existing_public_data_index = Option::some(0); - - // Set values for computing exact tx_fee - builder.transaction_fee = tx_fee; - - // Set expected protocol data update - builder.protocol_public_data_writes.push(( - 0, PublicDataTreeLeaf { slot: balance_slot, value: expected_balance }, - )); - - let outputs = builder.execute(); - - // The new public data tree should have updated the balance of the fee payer - let updated_leaf = PublicDataTreeLeafPreimage { - slot: balance_slot, - value: expected_balance, - next_slot: 0, - next_index: 0, - }; - let mut expected_public_data_tree = NonEmptyMerkleTree::new( - [updated_leaf.hash(), 0], - [0; PUBLIC_DATA_TREE_HEIGHT], - [0; PUBLIC_DATA_TREE_HEIGHT - 1], - [0; 1], - ); - - assert_eq(outputs.end.public_data_tree.root, expected_public_data_tree.get_root()); - } - - #[test] - unconstrained fn updates_fee_payer_balance_in_existing_data_write() { - let fee_payer = AztecAddress::from_field(0x1234); - let balance_slot = compute_fee_payer_fee_juice_balance_leaf_slot(fee_payer); - let initial_balance = 100_000; - let after_claim_balance = 300_000; - let tx_fee = 100_000; - let expected_balance = 200_000; - - let mut builder = PublicBaseRollupInputsBuilder::new(); - - // Set fee payer - builder.tube_data.fee_payer = fee_payer; - - // Set pre-existing balance, but set no hint for it since we'll update a user update request - builder.pre_existing_public_data[0] = PublicDataTreeLeafPreimage { - slot: balance_slot, - value: initial_balance, - next_slot: 0, - next_index: 0, - }; - - // Set values for computing exact tx_fee - builder.transaction_fee = tx_fee; - - // Rollup will overwrite the public data write we are about to push - builder.overwritten_public_data_writes[builder.public_data_writes.len()] = Option::some( - PublicDataTreeLeaf { slot: balance_slot, value: expected_balance }, - ); - - // Create an existing data update that corresponds to a claim - builder.public_data_writes.push(( - 0, PublicDataTreeLeaf { slot: balance_slot, value: after_claim_balance }, - )); - - let outputs = builder.execute(); - - // The new public data tree should have updated the balance of the fee payer - let updated_leaf = PublicDataTreeLeafPreimage { - slot: balance_slot, - value: expected_balance, - next_slot: 0, - next_index: 0, - }; - let mut expected_public_data_tree = NonEmptyMerkleTree::new( - [updated_leaf.hash(), 0], - [0; PUBLIC_DATA_TREE_HEIGHT], - [0; PUBLIC_DATA_TREE_HEIGHT - 1], - [0; 1], - ); - - assert_eq(outputs.end.public_data_tree.root, expected_public_data_tree.get_root()); - } - - #[test(should_fail_with = "Not enough balance for fee payer to pay for transaction")] - unconstrained fn fails_to_update_fee_payer_balance_if_not_enough_funds() { - let fee_payer = AztecAddress::from_field(0x1234); - let balance_slot = compute_fee_payer_fee_juice_balance_leaf_slot(fee_payer); - // Set low initial balance so it fails! - let initial_balance = 10_000; - let tx_fee = 100_000; - - let mut builder = PublicBaseRollupInputsBuilder::new(); - - // Set fee payer - builder.tube_data.fee_payer = fee_payer; - - // Set pre-existing balance - builder.pre_existing_public_data[0] = PublicDataTreeLeafPreimage { - slot: balance_slot, - value: initial_balance, - next_slot: 0, - next_index: 0, - }; - builder.fee_payer_fee_juice_balance_pre_existing_public_data_index = Option::some(0); - - // Set values for computing exact tx_fee - builder.transaction_fee = tx_fee; - - // Set expected protocol data update - builder.protocol_public_data_writes.push(( - 0, PublicDataTreeLeaf { slot: balance_slot, value: -90_000 }, - )); - - builder.fails(); - } - - #[test(should_fail_with = "Wrong leaf slot for Fee Juice balance read hint")] - unconstrained fn fails_to_update_fee_payer_balance_if_wrong_read_hint() { - let fee_payer = AztecAddress::from_field(0x1234); - let balance_slot = compute_fee_payer_fee_juice_balance_leaf_slot(fee_payer); - let initial_balance = 300_000; - let expected_balance = 200_000; - let tx_fee = 100_000; - - let mut builder = PublicBaseRollupInputsBuilder::new(); - - // Set fee payer - builder.tube_data.fee_payer = fee_payer; - - // Set pre-existing balance in index 0 - builder.pre_existing_public_data[0] = PublicDataTreeLeafPreimage { - slot: balance_slot, - value: initial_balance, - next_slot: 0, - next_index: 0, - }; - - builder.pre_existing_public_data[1] = PublicDataTreeLeafPreimage { - slot: 1, - value: initial_balance, - next_slot: balance_slot, - next_index: 0, - }; - - // But point the read hint to the wrong one! - builder.fee_payer_fee_juice_balance_pre_existing_public_data_index = Option::some(1); - - // Set values for computing exact tx_fee - builder.transaction_fee = tx_fee; - - // Set expected protocol data update - builder.protocol_public_data_writes.push(( - 0, PublicDataTreeLeaf { slot: balance_slot, value: expected_balance }, - )); - - builder.fails(); - } - #[test] fn valid_previous_kernel_empty() { let builder = unsafe { diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr index 65d27104795..f34019c544d 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr @@ -5,7 +5,7 @@ use dep::types::{ NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, }, - data::{PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, + data::PublicDataTreeLeafPreimage, merkle_tree::MembershipWitness, }; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index 508aa5c2b39..75a56f6519c 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -231,7 +231,7 @@ fn silo_and_hash_unencrypted_logs( // __ // 1 unencrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! |-> 2 types of flexible-length logs - 2 fields for their hashes // 1 contract class logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! __| -global TX_EFFECTS_HASH_INPUT_FIELDS: u32 = 1 +pub(crate) global TX_EFFECTS_HASH_INPUT_FIELDS: u32 = 1 + 1 + MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr index b87516dfbf7..6108c987133 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr @@ -1,8 +1,9 @@ use crate::{ - abis::{gas::Gas, log_hash::ScopedLogHash, public_data_write::PublicDataWrite}, + abis::{log_hash::ScopedLogHash, public_data_write::PublicDataWrite}, constants::{ AVM_ACCUMULATED_DATA_LENGTH, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, - MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Deserialize, Empty, Serialize}, @@ -11,16 +12,16 @@ use crate::{ pub struct AvmAccumulatedData { // The note hashes from private combining with those made in the AVM execution. - note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + pub note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], // The nullifiers from private combining with those made in the AVM execution. - nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + pub nullifiers: [Field; MAX_NULLIFIERS_PER_TX], // The L2 to L1 messages from private combining with those made in the AVM execution. - l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], + pub l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], // TODO(#9589): This should only contain logs emitted from public. // The unencrypted logs emitted from private combining with those made in the AVM execution. - unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + pub unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], // The public data writes made in the AVM execution. - public_data_writes: [PublicDataWrite; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + pub public_data_writes: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], } impl Empty for AvmAccumulatedData { @@ -30,7 +31,9 @@ impl Empty for AvmAccumulatedData { nullifiers: [0; MAX_NULLIFIERS_PER_TX], l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], - public_data_writes: [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + public_data_writes: [ + PublicDataWrite::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + ], } } } @@ -82,7 +85,7 @@ impl Deserialize for AvmAccumulatedData { ), public_data_writes: reader.read_struct_array( PublicDataWrite::deserialize, - [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + [PublicDataWrite::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], ), }; reader.finish(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr index 35d706bbbe3..83921f18c3b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr @@ -3,7 +3,7 @@ use crate::{ constants::{ COMBINED_ACCUMULATED_DATA_LENGTH, MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_LOGS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Deserialize, Empty, Serialize}, @@ -24,7 +24,7 @@ pub struct CombinedAccumulatedData { pub unencrypted_log_preimages_length: Field, pub contract_class_log_preimages_length: Field, - pub public_data_writes: [PublicDataWrite; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + pub public_data_writes: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], } impl Empty for CombinedAccumulatedData { @@ -38,7 +38,9 @@ impl Empty for CombinedAccumulatedData { contract_class_logs_hashes: [ScopedLogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_TX], unencrypted_log_preimages_length: 0, contract_class_log_preimages_length: 0, - public_data_writes: [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + public_data_writes: [ + PublicDataWrite::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + ], } } } @@ -64,7 +66,7 @@ impl Serialize for CombinedAccumulatedData { fields.push(self.unencrypted_log_preimages_length); fields.push(self.contract_class_log_preimages_length); - for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { + for i in 0..MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { fields.extend_from_array(self.public_data_writes[i].serialize()); } @@ -101,7 +103,7 @@ impl Deserialize for CombinedAccumulatedData { contract_class_log_preimages_length: reader.read(), public_data_writes: reader.read_struct_array( PublicDataWrite::deserialize, - [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + [PublicDataWrite::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], ), }; reader.finish(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr index 7affd9031c9..9484d08870d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr @@ -24,25 +24,25 @@ use crate::{ pub struct AvmCircuitPublicInputs { /////////////////////////////////// // Inputs. - global_variables: GlobalVariables, - start_tree_snapshots: TreeSnapshots, - start_gas_used: Gas, - gas_settings: GasSettings, - public_setup_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], - public_app_logic_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], - public_teardown_call_request: PublicCallRequest, - previous_non_revertible_accumulated_data_array_lengths: PrivateToAvmAccumulatedDataArrayLengths, - previous_revertible_accumulated_data_array_lengths: PrivateToAvmAccumulatedDataArrayLengths, - previous_non_revertible_accumulated_data: PrivateToAvmAccumulatedData, - previous_revertible_accumulated_data: PrivateToAvmAccumulatedData, + pub global_variables: GlobalVariables, + pub start_tree_snapshots: TreeSnapshots, + pub start_gas_used: Gas, + pub gas_settings: GasSettings, + pub public_setup_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], + pub public_app_logic_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], + pub public_teardown_call_request: PublicCallRequest, + pub previous_non_revertible_accumulated_data_array_lengths: PrivateToAvmAccumulatedDataArrayLengths, + pub previous_revertible_accumulated_data_array_lengths: PrivateToAvmAccumulatedDataArrayLengths, + pub previous_non_revertible_accumulated_data: PrivateToAvmAccumulatedData, + pub previous_revertible_accumulated_data: PrivateToAvmAccumulatedData, /////////////////////////////////// // Outputs. - end_tree_snapshots: TreeSnapshots, - end_gas_used: Gas, - accumulated_data: AvmAccumulatedData, - transaction_fee: Field, - reverted: bool, + pub end_tree_snapshots: TreeSnapshots, + pub end_gas_used: Gas, + pub accumulated_data: AvmAccumulatedData, + pub transaction_fee: Field, + pub reverted: bool, } impl Empty for AvmCircuitPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr index ccd0c236802..2a2ad1aa12a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr @@ -6,8 +6,8 @@ use crate::{ use std::ops::{Add, Sub}; pub struct Gas { - da_gas: u32, - l2_gas: u32, + pub da_gas: u32, + pub l2_gas: u32, } impl Gas { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_snapshots.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_snapshots.nr index 59863026a5b..7fb6948bfcb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_snapshots.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_snapshots.nr @@ -5,10 +5,10 @@ use crate::{ }; pub struct TreeSnapshots { - l1_to_l2_message_tree: AppendOnlyTreeSnapshot, - note_hash_tree: AppendOnlyTreeSnapshot, - nullifier_tree: AppendOnlyTreeSnapshot, - public_data_tree: AppendOnlyTreeSnapshot, + pub l1_to_l2_message_tree: AppendOnlyTreeSnapshot, + pub note_hash_tree: AppendOnlyTreeSnapshot, + pub nullifier_tree: AppendOnlyTreeSnapshot, + pub public_data_tree: AppendOnlyTreeSnapshot, } impl Eq for TreeSnapshots { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tube.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tube.nr index e36c2ead478..f2ceedee9bc 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tube.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tube.nr @@ -25,9 +25,9 @@ impl Verifiable for PublicTubeData { } pub struct PrivateTubeData { - public_inputs: KernelCircuitPublicInputs, - proof: TubeProof, - vk_data: VkData, + pub public_inputs: KernelCircuitPublicInputs, + pub proof: TubeProof, + pub vk_data: VkData, } impl Verifiable for PrivateTubeData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 3695c499bbf..c5ef0e3c2bf 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -372,7 +372,7 @@ pub global COMBINED_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + 1 /* unencrypted_log_preimages_length */ + (SCOPED_LOG_HASH_LENGTH * MAX_CONTRACT_CLASS_LOGS_PER_TX) + 1 /* contract_class_log_preimages_length */ - + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_WRITE_LENGTH); + + (MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_WRITE_LENGTH); pub global TX_CONSTANT_DATA_LENGTH: u32 = HEADER_LENGTH + TX_CONTEXT_LENGTH + 1 /* vk_tree_root */ @@ -409,7 +409,7 @@ pub global AVM_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) - + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_WRITE_LENGTH); + + (MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_WRITE_LENGTH); pub global PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = TX_CONSTANT_DATA_LENGTH + ROLLUP_VALIDATION_REQUESTS_LENGTH diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_hint.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_hint.nr index f2371ea7871..0e05f3ba021 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_hint.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_hint.nr @@ -6,10 +6,10 @@ use crate::{ }; pub struct PublicDataHint { - leaf_slot: Field, - value: Field, - membership_witness: MembershipWitness, - leaf_preimage: PublicDataTreeLeafPreimage, + pub leaf_slot: Field, + pub value: Field, + pub membership_witness: MembershipWitness, + pub leaf_preimage: PublicDataTreeLeafPreimage, } impl PublicDataHint { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr index 9c353ab02ab..d4c944c3acb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr @@ -89,7 +89,7 @@ impl VariableMerkleTree { } } -mod tests { +pub mod tests { use crate::{ hash::accumulate_sha256, merkle_tree::{merkle_tree::MerkleTree, variable_merkle_tree::VariableMerkleTree}, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/tube_proof.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/tube_proof.nr index 370f28d95de..49115f63d62 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/proof/tube_proof.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/tube_proof.nr @@ -1,7 +1,7 @@ use crate::{constants::TUBE_PROOF_LENGTH, traits::{Deserialize, Empty, Serialize}}; pub struct TubeProof { - fields: [Field; TUBE_PROOF_LENGTH], + pub fields: [Field; TUBE_PROOF_LENGTH], } impl Serialize for TubeProof { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/vk_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/vk_data.nr index 7a62eddd4a3..cede48d01a5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/proof/vk_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/vk_data.nr @@ -5,9 +5,9 @@ use crate::{ use super::verification_key::VerificationKey; pub struct VkData { - vk: VerificationKey, - vk_index: u32, - vk_path: [Field; VK_TREE_HEIGHT], + pub vk: VerificationKey, + pub vk_index: u32, + pub vk_path: [Field; VK_TREE_HEIGHT], } impl VkData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 2780ca84cb0..074baff2587 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -44,7 +44,7 @@ use crate::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PRIVATE_LOGS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, PRIVATE_CALL_REQUEST_LENGTH, PRIVATE_LOG_SIZE_IN_FIELDS, PROTOCOL_CONTRACT_TREE_HEIGHT, PUBLIC_CALL_REQUEST_LENGTH, VK_TREE_HEIGHT, }, @@ -114,7 +114,7 @@ pub struct FixtureBuilder { pub contract_class_logs_hashes: BoundedVec, pub unencrypted_log_preimages_length: Field, pub contract_class_log_preimages_length: Field, - pub public_data_writes: BoundedVec, + pub public_data_writes: BoundedVec, pub private_call_requests: BoundedVec, pub public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_TX>, pub gas_used: Gas, @@ -1017,19 +1017,19 @@ impl FixtureBuilder { fixtures::vk_tree::get_vk_merkle_tree().get_root() } - fn to_private_tube_data(self) -> PrivateTubeData { + pub fn to_private_tube_data(self) -> PrivateTubeData { let mut result: PrivateTubeData = std::mem::zeroed(); result.public_inputs = self.to_kernel_circuit_public_inputs(); result } - fn to_public_tube_data(self) -> PublicTubeData { + pub fn to_public_tube_data(self) -> PublicTubeData { let mut result: PublicTubeData = std::mem::zeroed(); result.public_inputs = self.to_private_to_public_kernel_circuit_public_inputs(true); result } - fn to_avm_accumulated_data(self) -> AvmAccumulatedData { + pub fn to_avm_accumulated_data(self) -> AvmAccumulatedData { AvmAccumulatedData { note_hashes: self.note_hashes.storage().map(|n: ScopedNoteHash| n.note_hash.value), nullifiers: self.nullifiers.storage().map(|n: ScopedNullifier| n.nullifier.value), @@ -1039,7 +1039,7 @@ impl FixtureBuilder { } } - fn to_avm_proof_data(self, reverted: bool) -> AvmProofData { + pub fn to_avm_proof_data(self, reverted: bool) -> AvmProofData { let mut result: AvmProofData = std::mem::zeroed(); result.public_inputs.reverted = reverted; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr index 2522ddc10a3..0469a76cd95 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr @@ -5,9 +5,9 @@ pub(crate) mod vk_tree; use crate::address::AztecAddress; -pub(crate) global MSG_SENDER: AztecAddress = AztecAddress { inner: 27 }; +pub global MSG_SENDER: AztecAddress = AztecAddress { inner: 27 }; -pub(crate) global CHAIN_ID: Field = 1; +pub global CHAIN_ID: Field = 1; -pub(crate) global VERSION: Field = 3; +pub global VERSION: Field = 3; From 7bae8eb4f63b313b8fad16eb9904ab61a17a5068 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Wed, 4 Dec 2024 10:02:13 +0000 Subject: [PATCH 02/13] updated avm simulator --- .../circuit-types/src/test/factories.ts | 5 ++- .../circuit-types/src/tx/processed_tx.ts | 9 ------ .../src/structs/avm/avm_accumulated_data.ts | 10 +++--- .../kernel/combined_accumulated_data.ts | 8 ++--- .../src/structs/rollup/base_rollup_hints.ts | 12 +------ .../circuits.js/src/tests/factories.ts | 13 ++++---- .../src/type_conversion.ts | 5 ++- .../orchestrator/block-building-helpers.ts | 15 +++++---- .../public/enqueued_call_side_effect_trace.ts | 8 ++--- .../simulator/src/public/public_processor.ts | 16 +--------- .../simulator/src/public/public_tx_context.ts | 3 ++ .../src/public/public_tx_simulator.ts | 31 +++++++++++++++++++ .../src/public/transitional_adapters.ts | 26 +++++----------- 13 files changed, 75 insertions(+), 86 deletions(-) diff --git a/yarn-project/circuit-types/src/test/factories.ts b/yarn-project/circuit-types/src/test/factories.ts index 72e2c318edf..0d41bc9d033 100644 --- a/yarn-project/circuit-types/src/test/factories.ts +++ b/yarn-project/circuit-types/src/test/factories.ts @@ -11,7 +11,7 @@ import { GlobalVariables, type Header, MAX_NULLIFIERS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicCircuitPublicInputs, PublicDataWrite, RevertCode, @@ -109,7 +109,7 @@ export function makeBloatedProcessedTx({ ); avmOutput.accumulatedData.l2ToL1Msgs = revertibleData.l2ToL1Msgs; avmOutput.accumulatedData.publicDataWrites = makeTuple( - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, i => new PublicDataWrite(new Fr(i), new Fr(i + 10)), seed + 0x2000, ); @@ -133,7 +133,6 @@ export function makeBloatedProcessedTx({ type: ProvingRequestType.PUBLIC_VM, inputs: avmCircuitInputs, }, - undefined /* feePaymentPublicDataWrite */, gasUsed, RevertCode.OK, undefined /* revertReason */, diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index b52006846b2..3ec315af1aa 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -166,7 +166,6 @@ export function makeProcessedTxFromPrivateOnlyTx( export function makeProcessedTxFromTxWithPublicCalls( tx: Tx, avmProvingRequest: AvmProvingRequest, - feePaymentPublicDataWrite: PublicDataWrite | undefined, gasUsed: GasUsed, revertCode: RevertCode, revertReason: SimulationError | undefined, @@ -176,14 +175,6 @@ export function makeProcessedTxFromTxWithPublicCalls( const constants = CombinedConstantData.combine(tx.data.constants, avmOutput.globalVariables); const publicDataWrites = avmOutput.accumulatedData.publicDataWrites.filter(w => !w.isEmpty()); - if (feePaymentPublicDataWrite) { - const existingIndex = publicDataWrites.findIndex(w => w.leafSlot.equals(feePaymentPublicDataWrite.leafSlot)); - if (existingIndex >= 0) { - publicDataWrites[existingIndex] = feePaymentPublicDataWrite; - } else { - publicDataWrites.push(feePaymentPublicDataWrite); - } - } const privateLogs = [ ...tx.data.forPublic!.nonRevertibleAccumulatedData.privateLogs, diff --git a/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts b/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts index c68d93b13e4..6b64b79fb06 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts @@ -10,7 +10,7 @@ import { MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; @@ -38,7 +38,7 @@ export class AvmAccumulatedData { /** * The public data writes made in the AVM execution. */ - public publicDataWrites: Tuple, + public publicDataWrites: Tuple, ) {} getSize() { @@ -58,7 +58,7 @@ export class AvmAccumulatedData { reader.readArray(MAX_NULLIFIERS_PER_TX, Fr), reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), - reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), + reader.readArray(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), ); } @@ -79,7 +79,7 @@ export class AvmAccumulatedData { reader.readFieldArray(MAX_NULLIFIERS_PER_TX), reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), - reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), + reader.readArray(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), ); } @@ -97,7 +97,7 @@ export class AvmAccumulatedData { makeTuple(MAX_NULLIFIERS_PER_TX, Fr.zero), makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), - makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.empty), + makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.empty), ); } diff --git a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts index b7d683de60e..62e1abefdd2 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts @@ -13,7 +13,7 @@ import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_LOGS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; @@ -63,7 +63,7 @@ export class CombinedAccumulatedData { /** * All the public data update requests made in this transaction. */ - public publicDataWrites: Tuple, + public publicDataWrites: Tuple, ) {} getSize() { @@ -130,7 +130,7 @@ export class CombinedAccumulatedData { reader.readArray(MAX_CONTRACT_CLASS_LOGS_PER_TX, ScopedLogHash), Fr.fromBuffer(reader), Fr.fromBuffer(reader), - reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), + reader.readArray(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), ); } @@ -153,7 +153,7 @@ export class CombinedAccumulatedData { makeTuple(MAX_CONTRACT_CLASS_LOGS_PER_TX, ScopedLogHash.empty), Fr.zero(), Fr.zero(), - makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.empty), + makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.empty), ); } diff --git a/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts index 80f627b4fab..fbec824f915 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts @@ -92,8 +92,6 @@ export class PublicBaseRollupHints { public start: PartialStateReference, /** Hints used while proving state diff validity. */ public stateDiffHints: PublicBaseStateDiffHints, - /** Public data read hint for accessing the balance of the fee payer. */ - public feePayerFeeJuiceBalanceReadHint: PublicDataHint, /** * Membership witnesses of blocks referred by each of the 2 kernels. */ @@ -109,13 +107,7 @@ export class PublicBaseRollupHints { } static getFields(fields: FieldsOf) { - return [ - fields.start, - fields.stateDiffHints, - fields.feePayerFeeJuiceBalanceReadHint, - fields.archiveRootMembershipWitness, - fields.constants, - ] as const; + return [fields.start, fields.stateDiffHints, fields.archiveRootMembershipWitness, fields.constants] as const; } /** @@ -139,7 +131,6 @@ export class PublicBaseRollupHints { return new PublicBaseRollupHints( reader.readObject(PartialStateReference), reader.readObject(PublicBaseStateDiffHints), - reader.readObject(PublicDataHint), MembershipWitness.fromBuffer(reader, ARCHIVE_HEIGHT), reader.readObject(ConstantRollupData), ); @@ -153,7 +144,6 @@ export class PublicBaseRollupHints { return new PublicBaseRollupHints( PartialStateReference.empty(), PublicBaseStateDiffHints.empty(), - PublicDataHint.empty(), MembershipWitness.empty(ARCHIVE_HEIGHT), ConstantRollupData.empty(), ); diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 79d5d63d2c6..ff35a207368 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -59,7 +59,6 @@ import { MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL, MAX_PRIVATE_LOGS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MaxBlockNumber, @@ -317,7 +316,12 @@ export function makeCombinedAccumulatedData(seed = 1, full = false): CombinedAcc tupleGenerator(MAX_CONTRACT_CLASS_LOGS_PER_TX, makeScopedLogHash, seed + 0xa00, ScopedLogHash.empty), // contract class logs fr(seed + 0xd00), // unencrypted_log_preimages_length fr(seed + 0xe00), // contract_class_log_preimages_length - tupleGenerator(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataWrite, seed + 0xd00, PublicDataWrite.empty), + tupleGenerator( + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + makePublicDataWrite, + seed + 0xd00, + PublicDataWrite.empty, + ), ); } @@ -350,7 +354,7 @@ function makeAvmAccumulatedData(seed = 1) { makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x100), makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, makeScopedL2ToL1Message, seed + 0x200), makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, makeScopedLogHash, seed + 0x300), - makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataWrite, seed + 0x400), + makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataWrite, seed + 0x400), ); } @@ -1113,14 +1117,11 @@ function makePublicBaseRollupHints(seed = 1) { const constants = makeConstantBaseRollupData(0x100); - const feePayerFeeJuiceBalanceReadHint = PublicDataHint.empty(); - return PublicBaseRollupHints.from({ start, stateDiffHints, archiveRootMembershipWitness, constants, - feePayerFeeJuiceBalanceReadHint, }); } diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 77ec114a2a8..fa3c81786b5 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -49,7 +49,7 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PRIVATE_LOGS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MaxBlockNumber, type MembershipWitness, @@ -1233,7 +1233,7 @@ export function mapCombinedAccumulatedDataFromNoir(combinedAccumulatedData: Comb mapFieldFromNoir(combinedAccumulatedData.contract_class_log_preimages_length), mapTupleFromNoir( combinedAccumulatedData.public_data_writes, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, mapPublicDataWriteFromNoir, ), ); @@ -2178,7 +2178,6 @@ export function mapPublicBaseRollupInputsToNoir(inputs: PublicBaseRollupInputs): archive_root_membership_witness: mapMembershipWitnessToNoir(inputs.hints.archiveRootMembershipWitness), constants: mapConstantRollupDataToNoir(inputs.hints.constants), - fee_payer_fee_juice_balance_read_hint: mapPublicDataHintToNoir(inputs.hints.feePayerFeeJuiceBalanceReadHint), }; } diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index 9dc700689b6..72122248457 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -95,13 +95,6 @@ export async function buildBaseRollupHints( i < noteHashSubtreeSiblingPathArray.length ? noteHashSubtreeSiblingPathArray[i] : Fr.ZERO, ); - // Create data hint for reading fee payer initial balance in Fee Juice - // If no fee payer is set, read hint should be empty - const leafSlot = computeFeePayerBalanceLeafSlot(tx.data.feePayer); - const feePayerFeeJuiceBalanceReadHint = tx.data.feePayer.isZero() - ? PublicDataHint.empty() - : await getPublicDataHint(db, leafSlot.toBigInt()); - // Update the note hash trees with the new items being inserted to get the new roots // that will be used by the next iteration of the base rollup circuit, skipping the empty ones const noteHashes = padArrayEnd(tx.txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX); @@ -184,7 +177,6 @@ export async function buildBaseRollupHints( return PublicBaseRollupHints.from({ start, stateDiffHints, - feePayerFeeJuiceBalanceReadHint: feePayerFeeJuiceBalanceReadHint, archiveRootMembershipWitness, constants, }); @@ -197,6 +189,13 @@ export async function buildBaseRollupHints( throw new Error(`More than one public data write in a private only tx`); } + // Create data hint for reading fee payer initial balance in Fee Juice + // If no fee payer is set, read hint should be empty + const leafSlot = computeFeePayerBalanceLeafSlot(tx.data.feePayer); + const feePayerFeeJuiceBalanceReadHint = tx.data.feePayer.isZero() + ? PublicDataHint.empty() + : await getPublicDataHint(db, leafSlot.toBigInt()); + const feeWriteLowLeafPreimage = txPublicDataUpdateRequestInfo.lowPublicDataWritesPreimages[0] || PublicDataTreeLeafPreimage.empty(); const feeWriteLowLeafMembershipWitness = diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index 84e85adcd64..191a1e78de6 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -25,7 +25,7 @@ import { MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, NOTE_HASH_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, @@ -232,11 +232,11 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI } if ( this.publicDataWrites.length + this.previousSideEffectArrayLengths.publicDataWrites >= - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX ) { throw new SideEffectLimitReachedError( 'public data (contract storage) write', - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); } @@ -595,7 +595,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI padArrayEnd( this.publicDataWrites.map(w => new PublicDataWrite(w.leafSlot, w.newValue)), PublicDataWrite.empty(), - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ), ); } diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index d6ba69c8302..7cbfd34d9cb 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -284,21 +284,7 @@ export class PublicProcessor { const durationMs = timer.ms(); this.metrics.recordTx(phaseCount, durationMs); - const data = avmProvingRequest.inputs.output; - const feePaymentPublicDataWrite = await this.getFeePaymentPublicDataWrite( - data.accumulatedData.publicDataWrites, - data.transactionFee, - tx.data.feePayer, - ); - - const processedTx = makeProcessedTxFromTxWithPublicCalls( - tx, - avmProvingRequest, - feePaymentPublicDataWrite, - gasUsed, - revertCode, - revertReason, - ); + const processedTx = makeProcessedTxFromTxWithPublicCalls(tx, avmProvingRequest, gasUsed, revertCode, revertReason); const returnValues = processedPhases.find(({ phase }) => phase === TxExecutionPhase.APP_LOGIC)?.returnValues ?? []; diff --git a/yarn-project/simulator/src/public/public_tx_context.ts b/yarn-project/simulator/src/public/public_tx_context.ts index f6fd8e7c9e1..50bda9d45ab 100644 --- a/yarn-project/simulator/src/public/public_tx_context.ts +++ b/yarn-project/simulator/src/public/public_tx_context.ts @@ -10,6 +10,7 @@ import { } from '@aztec/circuit-types'; import { type AvmCircuitPublicInputs, + type AztecAddress, Fr, Gas, type GasSettings, @@ -70,6 +71,7 @@ export class PublicTxContext { private readonly teardownExecutionRequests: PublicExecutionRequest[], public readonly nonRevertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData, public readonly revertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData, + public readonly feePayer: AztecAddress, public trace: PublicEnqueuedCallSideEffectTrace, // FIXME(dbanks12): should be private ) { this.log = createDebugLogger(`aztec:public_tx_context`); @@ -117,6 +119,7 @@ export class PublicTxContext { getExecutionRequestsByPhase(tx, TxExecutionPhase.TEARDOWN), tx.data.forPublic!.nonRevertibleAccumulatedData, tx.data.forPublic!.revertibleAccumulatedData, + tx.data.feePayer, enqueuedCallTrace, ); } diff --git a/yarn-project/simulator/src/public/public_tx_simulator.ts b/yarn-project/simulator/src/public/public_tx_simulator.ts index 7cf250cc1d5..e6dc459c004 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.ts @@ -20,6 +20,7 @@ import { } from '@aztec/circuits.js'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; +import { ProtocolContractAddress } from '@aztec/protocol-contracts'; import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec/telemetry-client'; import { strict as assert } from 'assert'; @@ -29,6 +30,7 @@ import { type AvmPersistableStateManager, AvmSimulator } from '../avm/index.js'; import { NullifierCollisionError } from '../avm/journal/nullifiers.js'; import { getPublicFunctionDebugName } from '../common/debug_fn_name.js'; import { ExecutorMetrics } from './executor_metrics.js'; +import { computeFeePayerBalanceStorageSlot } from './fee_payment.js'; import { type WorldStateDB } from './public_db_sources.js'; import { PublicTxContext } from './public_tx_context.js'; @@ -107,11 +109,14 @@ export class PublicTxSimulator { const appLogicResult: ProcessedPhase = await this.simulateAppLogicPhase(context); processedPhases.push(appLogicResult); } + if (context.hasPhase(TxExecutionPhase.TEARDOWN)) { const teardownResult: ProcessedPhase = await this.simulateTeardownPhase(context); processedPhases.push(teardownResult); } + context.halt(); + await this.payFee(context); const endStateReference = await this.db.getStateReference(); @@ -415,4 +420,30 @@ export class PublicTxSimulator { } } } + + private async payFee(context: PublicTxContext) { + const txFee = context.getTransactionFee(TxExecutionPhase.TEARDOWN); + + if (context.feePayer.isZero()) { + this.log.debug(`No one is paying the fee of ${txFee.toBigInt()}`); + return; + } + + const feeJuiceAddress = ProtocolContractAddress.FeeJuice; + const balanceSlot = computeFeePayerBalanceStorageSlot(context.feePayer); + + this.log.debug(`Deducting ${txFee.toBigInt()} balance in Fee Juice for ${context.feePayer}`); + const stateManager = context.state.getActiveStateManager(); + + const currentBalance = await stateManager.readStorage(feeJuiceAddress, balanceSlot); + + if (currentBalance.lt(txFee)) { + throw new Error( + `Not enough balance for fee payer to pay for transaction (got ${currentBalance.toBigInt()} needs ${txFee.toBigInt()})`, + ); + } + + const updatedBalance = currentBalance.sub(txFee); + await stateManager.writeStorage(feeJuiceAddress, balanceSlot, updatedBalance); + } } diff --git a/yarn-project/simulator/src/public/transitional_adapters.ts b/yarn-project/simulator/src/public/transitional_adapters.ts index 63470f6fc18..51d96545392 100644 --- a/yarn-project/simulator/src/public/transitional_adapters.ts +++ b/yarn-project/simulator/src/public/transitional_adapters.ts @@ -24,7 +24,7 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_CALL, NoteHash, Nullifier, @@ -156,28 +156,18 @@ export function generateAvmCircuitPublicInputs( MAX_L2_TO_L1_MSGS_PER_TX, ); - const dedupedPublicDataWrites: Array = []; - const leafSlotOccurences: Map = new Map(); + // Maps slot to value. Maps in TS are iterable in insertion order, which is exactly what we want for + // squashing "to the left", where the first occurrence of a slot uses the value of the last write to it, + // and the rest occurrences are omitted + const squashedPublicDataWrites: Map = new Map(); for (const publicDataWrite of avmCircuitPublicInputs.accumulatedData.publicDataWrites) { - const slot = publicDataWrite.leafSlot.toBigInt(); - const prevOccurrences = leafSlotOccurences.get(slot) || 0; - leafSlotOccurences.set(slot, prevOccurrences + 1); - } - - for (const publicDataWrite of avmCircuitPublicInputs.accumulatedData.publicDataWrites) { - const slot = publicDataWrite.leafSlot.toBigInt(); - const prevOccurrences = leafSlotOccurences.get(slot) || 0; - if (prevOccurrences === 1) { - dedupedPublicDataWrites.push(publicDataWrite); - } else { - leafSlotOccurences.set(slot, prevOccurrences - 1); - } + squashedPublicDataWrites.set(publicDataWrite.leafSlot.toBigInt(), publicDataWrite.value); } avmCircuitPublicInputs.accumulatedData.publicDataWrites = padArrayEnd( - dedupedPublicDataWrites, + Array.from(squashedPublicDataWrites.entries()).map(([slot, value]) => new PublicDataWrite(new Fr(slot), value)), PublicDataWrite.empty(), - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); //console.log(`AvmCircuitPublicInputs:\n${inspect(avmCircuitPublicInputs)}`); return avmCircuitPublicInputs; From e30e7450b256b11e4be8a0c8935900645beb44da Mon Sep 17 00:00:00 2001 From: sirasistant Date: Wed, 4 Dec 2024 11:13:27 +0000 Subject: [PATCH 03/13] moar changes --- .../simulator/src/avm/avm_simulator.test.ts | 14 +- .../simulator/src/avm/journal/journal.ts | 5 +- .../src/public/dual_side_effect_trace.ts | 3 + .../enqueued_call_side_effect_trace.test.ts | 8 +- .../public/enqueued_call_side_effect_trace.ts | 6 +- .../src/public/public_processor.test.ts | 156 +++++++++--------- .../src/public/public_tx_simulator.test.ts | 10 +- .../src/public/public_tx_simulator.ts | 2 +- .../src/public/side_effect_trace.test.ts | 7 +- .../simulator/src/public/side_effect_trace.ts | 12 +- .../src/public/side_effect_trace_interface.ts | 1 + 11 files changed, 119 insertions(+), 105 deletions(-) diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 06811af1557..3a5c6f97671 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -739,7 +739,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(await context.persistableState.peekStorage(address, slot)).toEqual(value0); expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(1); - expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, slot, value0); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, slot, value0, false); }); it('Should read value in storage (single)', async () => { @@ -767,7 +767,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(results.output).toEqual([value0]); expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(1); - expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, slot, value0); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, slot, value0, false); expect(trace.tracePublicStorageRead).toHaveBeenCalledTimes(1); expect(trace.tracePublicStorageRead).toHaveBeenCalledWith(address, slot, value0); }); @@ -785,8 +785,8 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(await context.persistableState.peekStorage(address, listSlot1)).toEqual(calldata[1]); expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(2); - expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, listSlot0, value0); - expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, listSlot1, value1); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, listSlot0, value0, false); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, listSlot1, value1, false); }); it('Should read a value in storage (list)', async () => { @@ -824,7 +824,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(await context.persistableState.peekStorage(address, mapSlot)).toEqual(value0); expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(1); - expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, mapSlot, value0); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, mapSlot, value0, false); }); it('Should read-add-set a value in storage (map)', async () => { @@ -845,7 +845,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(trace.tracePublicStorageRead).toHaveBeenCalledTimes(1); expect(trace.tracePublicStorageRead).toHaveBeenCalledWith(address, mapSlot, Fr.zero()); expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(1); - expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, mapSlot, value0); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(address, mapSlot, value0, false); }); it('Should read value in storage (map)', async () => { @@ -1209,6 +1209,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { address, slot0, value0, + false, lowLeafPreimage, new Fr(lowLeafIndex), lowLeafPath, @@ -1334,6 +1335,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { address, slot0, value0, + false, lowLeafPreimage, new Fr(lowLeafIndex), lowLeafPath, diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 9a3ffa5273a..a12c3266749 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -148,7 +148,7 @@ 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 async writeStorage(contractAddress: AztecAddress, slot: Fr, value: Fr): Promise { + public async writeStorage(contractAddress: AztecAddress, slot: Fr, value: Fr, protocolWrite = false): Promise { this.log.debug(`Storage write (address=${contractAddress}, slot=${slot}): value=${value}`); // Cache storage writes for later reference/reads this.publicStorage.write(contractAddress, slot, value); @@ -170,6 +170,7 @@ export class AvmPersistableStateManager { contractAddress, slot, value, + protocolWrite, lowLeafPreimage, new Fr(lowLeafIndex), lowLeafPath, @@ -177,7 +178,7 @@ export class AvmPersistableStateManager { insertionPath, ); } else { - this.trace.tracePublicStorageWrite(contractAddress, slot, value); + this.trace.tracePublicStorageWrite(contractAddress, slot, value, protocolWrite); } } diff --git a/yarn-project/simulator/src/public/dual_side_effect_trace.ts b/yarn-project/simulator/src/public/dual_side_effect_trace.ts index f6285e0e355..df12dde3170 100644 --- a/yarn-project/simulator/src/public/dual_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/dual_side_effect_trace.ts @@ -54,6 +54,7 @@ export class DualSideEffectTrace implements PublicSideEffectTraceInterface { contractAddress: AztecAddress, slot: Fr, value: Fr, + protocolWrite: boolean, lowLeafPreimage: PublicDataTreeLeafPreimage, lowLeafIndex: Fr, lowLeafPath: Fr[], @@ -64,6 +65,7 @@ export class DualSideEffectTrace implements PublicSideEffectTraceInterface { contractAddress, slot, value, + protocolWrite, lowLeafPreimage, lowLeafIndex, lowLeafPath, @@ -74,6 +76,7 @@ export class DualSideEffectTrace implements PublicSideEffectTraceInterface { contractAddress, slot, value, + protocolWrite, lowLeafPreimage, lowLeafIndex, lowLeafPath, diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts index 6f84f4de2ad..fc2c49b49c1 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts @@ -70,6 +70,7 @@ describe('Enqueued-call Side Effect Trace', () => { address, slot, value, + false, lowLeafPreimage, lowLeafIndex, lowLeafSiblingPath, @@ -176,7 +177,7 @@ describe('Enqueued-call Side Effect Trace', () => { for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; i++) { const lowLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i), new Fr(i), Fr.ZERO, 0n); const newLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i + 1), new Fr(i + 1), Fr.ZERO, 0n); - trace.tracePublicStorageWrite(address, slot, value, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); + trace.tracePublicStorageWrite(address, slot, value, false, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); } const leafPreimage = new PublicDataTreeLeafPreimage(new Fr(42), new Fr(42), Fr.ZERO, 0n); expect(() => @@ -184,6 +185,7 @@ describe('Enqueued-call Side Effect Trace', () => { AztecAddress.fromNumber(42), new Fr(42), value, + false, leafPreimage, Fr.ZERO, [], @@ -242,7 +244,7 @@ describe('Enqueued-call Side Effect Trace', () => { MAX_UNENCRYPTED_LOGS_PER_TX, ), ); - expect(() => trace.tracePublicStorageWrite(AztecAddress.fromNumber(42), new Fr(42), new Fr(42))).toThrow( + expect(() => trace.tracePublicStorageWrite(AztecAddress.fromNumber(42), new Fr(42), new Fr(42), false)).toThrow( SideEffectLimitReachedError, ); expect(() => trace.traceNewNoteHash(AztecAddress.fromNumber(42), new Fr(42), new Fr(42))).toThrow( @@ -268,7 +270,7 @@ describe('Enqueued-call Side Effect Trace', () => { const lowLeafPreimage = new NullifierLeafPreimage(utxo, Fr.ZERO, 0n); nestedTrace.tracePublicStorageRead(address, slot, value, leafPreimage, Fr.ZERO, []); testCounter++; - nestedTrace.tracePublicStorageWrite(address, slot, value, leafPreimage, Fr.ZERO, [], leafPreimage, []); + nestedTrace.tracePublicStorageWrite(address, slot, value, false, leafPreimage, Fr.ZERO, [], leafPreimage, []); testCounter++; nestedTrace.traceNoteHashCheck(address, utxo, leafIndex, existsDefault, []); // counter does not increment for note hash checks diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index 191a1e78de6..0bbdd0af84f 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -25,6 +25,7 @@ import { MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, NOTE_HASH_TREE_HEIGHT, @@ -220,6 +221,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI contractAddress: AztecAddress, slot: Fr, value: Fr, + protocolWrite: boolean, lowLeafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(), lowLeafIndex: Fr = Fr.zero(), lowLeafPath: Fr[] = emptyPublicDataPath(), @@ -232,11 +234,11 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI } if ( this.publicDataWrites.length + this.previousSideEffectArrayLengths.publicDataWrites >= - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + (protocolWrite ? MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) ) { throw new SideEffectLimitReachedError( 'public data (contract storage) write', - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + protocolWrite ? MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); } diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 7db6b283dc8..7ebc615b092 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -220,83 +220,83 @@ describe('public_processor', () => { expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); }); - it('injects balance update with public enqueued call', async function () { - const txFee = new Fr(567); - mockedAvmOutput.transactionFee = txFee; - - const tx = mockTxWithPublicCalls({ - feePayer, - }); - - const [processed, failed] = await processor.process([tx], 1, handler); - - expect(processed).toHaveLength(1); - expect(processed[0].hash).toEqual(tx.getTxHash()); - expect(processed[0].data.feePayer).toEqual(feePayer); - expect(processed[0].txEffect.transactionFee).toEqual(txFee); - expect(processed[0].txEffect.publicDataWrites[0]).toEqual( - new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), initialBalance.sub(txFee)), - ); - expect(failed).toEqual([]); - - expect(worldStateDB.commit).toHaveBeenCalledTimes(1); - expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(1); - - expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); - }); - - it('tweaks existing balance update from claim', async function () { - const txFee = new Fr(567); - const pendingBalance = new Fr(2000); - const pendingWrites = [ - new PublicDataWrite(new Fr(888n), new Fr(999)), - new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), pendingBalance), - new PublicDataWrite(new Fr(666n), new Fr(777)), - ]; - mockedAvmOutput.transactionFee = txFee; - mockedAvmOutput.accumulatedData.publicDataWrites[0] = pendingWrites[0]; - mockedAvmOutput.accumulatedData.publicDataWrites[1] = pendingWrites[1]; - mockedAvmOutput.accumulatedData.publicDataWrites[2] = pendingWrites[2]; - - const tx = mockTxWithPublicCalls({ - feePayer, - }); - - const [processed, failed] = await processor.process([tx], 1, handler); - - expect(processed).toHaveLength(1); - expect(processed[0].hash).toEqual(tx.getTxHash()); - expect(processed[0].data.feePayer).toEqual(feePayer); - expect(countAccumulatedItems(processed[0].txEffect.publicDataWrites)).toBe(3); - expect(processed[0].txEffect.publicDataWrites.slice(0, 3)).toEqual([ - pendingWrites[0], - new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), pendingBalance.sub(txFee)), - pendingWrites[2], - ]); - expect(failed).toEqual([]); - - expect(worldStateDB.commit).toHaveBeenCalledTimes(1); - expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(1); - - expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); - }); - - it('rejects tx if fee payer has not enough balance', async function () { - const txFee = initialBalance.add(new Fr(1)); - mockedAvmOutput.transactionFee = txFee; - - const tx = mockTxWithPublicCalls({ - feePayer, - }); - - const [processed, failed] = await processor.process([tx], 1, handler); - - expect(processed).toEqual([]); - expect(failed).toHaveLength(1); - expect(failed[0].error.message).toMatch(/Not enough balance/i); - - expect(worldStateDB.commit).toHaveBeenCalledTimes(0); - expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(0); - }); + // it('injects balance update with public enqueued call', async function () { + // const txFee = new Fr(567); + // mockedAvmOutput.transactionFee = txFee; + + // const tx = mockTxWithPublicCalls({ + // feePayer, + // }); + + // const [processed, failed] = await processor.process([tx], 1, handler); + // expect(failed).toEqual([]); + + // expect(processed).toHaveLength(1); + // expect(processed[0].hash).toEqual(tx.getTxHash()); + // expect(processed[0].data.feePayer).toEqual(feePayer); + // expect(processed[0].txEffect.transactionFee).toEqual(txFee); + // expect(processed[0].txEffect.publicDataWrites[0]).toEqual( + // new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), initialBalance.sub(txFee)), + // ); + + // expect(worldStateDB.commit).toHaveBeenCalledTimes(1); + // expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(1); + + // expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); + // }); + + // it('tweaks existing balance update from claim', async function () { + // const txFee = new Fr(567); + // const pendingBalance = new Fr(2000); + // const pendingWrites = [ + // new PublicDataWrite(new Fr(888n), new Fr(999)), + // new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), pendingBalance), + // new PublicDataWrite(new Fr(666n), new Fr(777)), + // ]; + // mockedAvmOutput.transactionFee = txFee; + // mockedAvmOutput.accumulatedData.publicDataWrites[0] = pendingWrites[0]; + // mockedAvmOutput.accumulatedData.publicDataWrites[1] = pendingWrites[1]; + // mockedAvmOutput.accumulatedData.publicDataWrites[2] = pendingWrites[2]; + + // const tx = mockTxWithPublicCalls({ + // feePayer, + // }); + + // const [processed, failed] = await processor.process([tx], 1, handler); + + // expect(processed).toHaveLength(1); + // expect(processed[0].hash).toEqual(tx.getTxHash()); + // expect(processed[0].data.feePayer).toEqual(feePayer); + // expect(countAccumulatedItems(processed[0].txEffect.publicDataWrites)).toBe(3); + // expect(processed[0].txEffect.publicDataWrites.slice(0, 3)).toEqual([ + // pendingWrites[0], + // new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), pendingBalance.sub(txFee)), + // pendingWrites[2], + // ]); + // expect(failed).toEqual([]); + + // expect(worldStateDB.commit).toHaveBeenCalledTimes(1); + // expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(1); + + // expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); + // }); + + // it('rejects tx if fee payer has not enough balance', async function () { + // const txFee = initialBalance.add(new Fr(1)); + // mockedAvmOutput.transactionFee = txFee; + + // const tx = mockTxWithPublicCalls({ + // feePayer, + // }); + + // const [processed, failed] = await processor.process([tx], 1, handler); + + // expect(processed).toEqual([]); + // expect(failed).toHaveLength(1); + // expect(failed[0].error.message).toMatch(/Not enough balance/i); + + // expect(worldStateDB.commit).toHaveBeenCalledTimes(0); + // expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(0); + // }); }); }); diff --git a/yarn-project/simulator/src/public/public_tx_simulator.test.ts b/yarn-project/simulator/src/public/public_tx_simulator.test.ts index c17d1d03bf5..25b52f941ff 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.test.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.test.ts @@ -439,15 +439,9 @@ describe('public_tx_simulator', () => { const numPublicDataWrites = 3; expect(countAccumulatedItems(output.accumulatedData.publicDataWrites)).toBe(numPublicDataWrites); expect(output.accumulatedData.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ - // squashed - // new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotA), fr(0x101)), + new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotA), fr(0x103)), // 0x101 replaced with 0x103 new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotB), fr(0x151)), - - new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotA), fr(0x103)), - // squashed - // new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotC), fr(0x201)), - // new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotC), fr(0x102)), - new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotC), fr(0x152)), + new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotC), fr(0x152)), // 0x201 replaced with 0x102 and then 0x152 ]); }); diff --git a/yarn-project/simulator/src/public/public_tx_simulator.ts b/yarn-project/simulator/src/public/public_tx_simulator.ts index e6dc459c004..70a7d36e673 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.ts @@ -444,6 +444,6 @@ export class PublicTxSimulator { } const updatedBalance = currentBalance.sub(txFee); - await stateManager.writeStorage(feeJuiceAddress, balanceSlot, updatedBalance); + await stateManager.writeStorage(feeJuiceAddress, balanceSlot, updatedBalance, true); } } diff --git a/yarn-project/simulator/src/public/side_effect_trace.test.ts b/yarn-project/simulator/src/public/side_effect_trace.test.ts index 7d7e024e967..531580f3aba 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.test.ts @@ -92,7 +92,7 @@ describe('Side Effect Trace', () => { const lowLeafPreimage = new PublicDataTreeLeafPreimage(slot, value, Fr.ZERO, 0n); const newLeafPreimage = new PublicDataTreeLeafPreimage(slot, value, Fr.ZERO, 0n); - trace.tracePublicStorageWrite(address, slot, value, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); + trace.tracePublicStorageWrite(address, slot, value, false, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); expect(trace.getCounter()).toBe(startCounterPlus1); const pxResult = toPxResult(trace); @@ -263,7 +263,7 @@ describe('Side Effect Trace', () => { for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; i++) { const lowLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i), new Fr(i), Fr.ZERO, 0n); const newLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i + 1), new Fr(i + 1), Fr.ZERO, 0n); - trace.tracePublicStorageWrite(address, slot, value, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); + trace.tracePublicStorageWrite(address, slot, value, false, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); } const leafPreimage = new PublicDataTreeLeafPreimage(new Fr(42), new Fr(42), Fr.ZERO, 0n); expect(() => @@ -271,6 +271,7 @@ describe('Side Effect Trace', () => { AztecAddress.fromNumber(42), new Fr(42), value, + false, leafPreimage, Fr.ZERO, [], @@ -404,7 +405,7 @@ describe('Side Effect Trace', () => { const lowLeafPreimage = new NullifierLeafPreimage(utxo, Fr.ZERO, 0n); nestedTrace.tracePublicStorageRead(address, slot, value, leafPreimage, Fr.ZERO, []); testCounter++; - nestedTrace.tracePublicStorageWrite(address, slot, value, leafPreimage, Fr.ZERO, [], leafPreimage, []); + nestedTrace.tracePublicStorageWrite(address, slot, value, false, leafPreimage, Fr.ZERO, [], leafPreimage, []); testCounter++; nestedTrace.traceNoteHashCheck(address, utxo, leafIndex, existsDefault, []); // counter does not increment for note hash checks diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts index 474e3ff155d..604cb857474 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.ts @@ -30,6 +30,7 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, NOTE_HASH_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, @@ -148,6 +149,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { contractAddress: AztecAddress, slot: Fr, value: Fr, + protocolWrite: boolean, lowLeafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(), lowLeafIndex: Fr = Fr.zero(), lowLeafPath: Fr[] = emptyPublicDataPath(), @@ -158,8 +160,14 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { // if we have real merkle hint content, make sure the value matches the the provided preimage assert(newLeafPreimage.value.equals(value), 'Value mismatch when tracing in public data read'); } - if (this.contractStorageUpdateRequests.length >= MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) { - throw new SideEffectLimitReachedError('contract storage write', MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX); + if ( + this.contractStorageUpdateRequests.length >= + (protocolWrite ? MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) + ) { + throw new SideEffectLimitReachedError( + 'contract storage write', + protocolWrite ? MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); } this.contractStorageUpdateRequests.push( diff --git a/yarn-project/simulator/src/public/side_effect_trace_interface.ts b/yarn-project/simulator/src/public/side_effect_trace_interface.ts index 06a1c6eb563..b3d6c4ac21d 100644 --- a/yarn-project/simulator/src/public/side_effect_trace_interface.ts +++ b/yarn-project/simulator/src/public/side_effect_trace_interface.ts @@ -31,6 +31,7 @@ export interface PublicSideEffectTraceInterface { contractAddress: AztecAddress, slot: Fr, // This is the storage slot not the computed leaf slot value: Fr, + protocolWrite: boolean, lowLeafPreimage?: PublicDataTreeLeafPreimage, lowLeafIndex?: Fr, lowLeafPath?: Fr[], From d37d3eb8c5b88d84f4c4e3508de30edf5a263b3c Mon Sep 17 00:00:00 2001 From: sirasistant Date: Wed, 4 Dec 2024 14:21:47 +0000 Subject: [PATCH 04/13] fix accounting of public data write limits --- .../enqueued_call_side_effect_trace.test.ts | 5 +++ .../public/enqueued_call_side_effect_trace.ts | 39 ++++++++++++++----- .../simulator/src/public/public_tx_context.ts | 1 + .../simulator/src/public/side_effect_trace.ts | 28 ++++++++----- 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts index fc2c49b49c1..eaf52dfe781 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts @@ -17,6 +17,7 @@ import { NoteHash, Nullifier, NullifierLeafPreimage, + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataTreeLeafPreimage, PublicDataUpdateRequest, SerializableContractInstance, @@ -238,6 +239,7 @@ describe('Enqueued-call Side Effect Trace', () => { 0, new SideEffectArrayLengths( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, @@ -247,6 +249,9 @@ describe('Enqueued-call Side Effect Trace', () => { expect(() => trace.tracePublicStorageWrite(AztecAddress.fromNumber(42), new Fr(42), new Fr(42), false)).toThrow( SideEffectLimitReachedError, ); + expect(() => trace.tracePublicStorageWrite(AztecAddress.fromNumber(42), new Fr(42), new Fr(42), true)).toThrow( + SideEffectLimitReachedError, + ); expect(() => trace.traceNewNoteHash(AztecAddress.fromNumber(42), new Fr(42), new Fr(42))).toThrow( SideEffectLimitReachedError, ); diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index 0bbdd0af84f..401b18a4525 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -33,6 +33,7 @@ import { NoteHash, Nullifier, NullifierLeafPreimage, + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, PrivateToAvmAccumulatedData, PrivateToAvmAccumulatedDataArrayLengths, @@ -85,6 +86,7 @@ export type SideEffects = { export class SideEffectArrayLengths { constructor( public readonly publicDataWrites: number, + public readonly protocolPublicDataWrites: number, public readonly noteHashes: number, public readonly nullifiers: number, public readonly l2ToL1Msgs: number, @@ -92,7 +94,7 @@ export class SideEffectArrayLengths { ) {} static empty() { - return new this(0, 0, 0, 0, 0); + return new this(0, 0, 0, 0, 0, 0); } } @@ -108,6 +110,8 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI private enqueuedCalls: PublicCallRequest[] = []; private publicDataWrites: PublicDataUpdateRequest[] = []; + private protocolPublicDataWritesLength: number = 0; + private userPublicDataWritesLength: number = 0; private noteHashes: ScopedNoteHash[] = []; private nullifiers: Nullifier[] = []; private l2ToL1Messages: ScopedL2ToL1Message[] = []; @@ -136,7 +140,8 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI return new PublicEnqueuedCallSideEffectTrace( this.sideEffectCounter, new SideEffectArrayLengths( - this.previousSideEffectArrayLengths.publicDataWrites + this.publicDataWrites.length, + this.previousSideEffectArrayLengths.publicDataWrites + this.userPublicDataWritesLength, + this.previousSideEffectArrayLengths.protocolPublicDataWrites + this.protocolPublicDataWritesLength, this.previousSideEffectArrayLengths.noteHashes + this.noteHashes.length, this.previousSideEffectArrayLengths.nullifiers + this.nullifiers.length, this.previousSideEffectArrayLengths.l2ToL1Msgs + this.l2ToL1Messages.length, @@ -232,14 +237,28 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI // if we have real merkle hint content, make sure the value matches the the provided preimage assert(newLeafPreimage.value.equals(value), 'Value mismatch when tracing in public data read'); } - if ( - this.publicDataWrites.length + this.previousSideEffectArrayLengths.publicDataWrites >= - (protocolWrite ? MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) - ) { - throw new SideEffectLimitReachedError( - 'public data (contract storage) write', - protocolWrite ? MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - ); + if (protocolWrite) { + if ( + this.protocolPublicDataWritesLength + this.previousSideEffectArrayLengths.protocolPublicDataWrites >= + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + ) { + throw new SideEffectLimitReachedError( + 'protocol public data (contract storage) write', + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + } + this.protocolPublicDataWritesLength++; + } else { + if ( + this.userPublicDataWritesLength + this.previousSideEffectArrayLengths.publicDataWrites >= + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + ) { + throw new SideEffectLimitReachedError( + 'public data (contract storage) write', + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + } + this.userPublicDataWritesLength++; } const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot); diff --git a/yarn-project/simulator/src/public/public_tx_context.ts b/yarn-project/simulator/src/public/public_tx_context.ts index 50bda9d45ab..774dbde6d3a 100644 --- a/yarn-project/simulator/src/public/public_tx_context.ts +++ b/yarn-project/simulator/src/public/public_tx_context.ts @@ -90,6 +90,7 @@ export class PublicTxContext { const innerCallTrace = new PublicSideEffectTrace(); const previousAccumulatedDataArrayLengths = new SideEffectArrayLengths( /*publicDataWrites*/ 0, + /*protocolPublicDataWrites*/ 0, countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.noteHashes), countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.nullifiers), countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.l2ToL1Msgs), diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts index 604cb857474..23d23cad724 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.ts @@ -30,13 +30,13 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, NOTE_HASH_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, NoteHash, Nullifier, NullifierLeafPreimage, + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, type PublicCallRequest, PublicDataTreeLeafPreimage, @@ -91,6 +91,8 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { private allUnencryptedLogs: UnencryptedL2Log[] = []; private unencryptedLogsHashes: LogHash[] = []; + private userPublicDataWritesLength = 0; + private protocolPublicDataWritesLength = 0; private publicCallRequests: PublicInnerCallRequest[] = []; private nestedExecutions: PublicFunctionCallResult[] = []; @@ -160,14 +162,22 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { // if we have real merkle hint content, make sure the value matches the the provided preimage assert(newLeafPreimage.value.equals(value), 'Value mismatch when tracing in public data read'); } - if ( - this.contractStorageUpdateRequests.length >= - (protocolWrite ? MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) - ) { - throw new SideEffectLimitReachedError( - 'contract storage write', - protocolWrite ? MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - ); + if (protocolWrite) { + if (this.protocolPublicDataWritesLength >= PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) { + throw new SideEffectLimitReachedError( + 'protocol public data (contract storage) write', + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + } + this.protocolPublicDataWritesLength++; + } else { + if (this.userPublicDataWritesLength >= MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) { + throw new SideEffectLimitReachedError( + 'public data (contract storage) write', + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + } + this.userPublicDataWritesLength++; } this.contractStorageUpdateRequests.push( From 4bf293062697b4f3d68fc4819246ab4e3dbe561f Mon Sep 17 00:00:00 2001 From: sirasistant Date: Wed, 4 Dec 2024 14:41:55 +0000 Subject: [PATCH 05/13] fix tests --- .../src/public/public_processor.test.ts | 102 ++++-------------- .../simulator/src/public/public_processor.ts | 26 ++--- 2 files changed, 26 insertions(+), 102 deletions(-) diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 7ebc615b092..ff19e89ef7a 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -10,7 +10,6 @@ import { } from '@aztec/circuit-types'; import { AvmCircuitInputs, - type AvmCircuitPublicInputs, AztecAddress, Fr, Gas, @@ -19,7 +18,6 @@ import { Header, PublicDataWrite, RevertCode, - countAccumulatedItems, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -39,7 +37,6 @@ describe('public_processor', () => { let root: Buffer; let mockedEnqueuedCallsResult: PublicTxResult; - let mockedAvmOutput: AvmCircuitPublicInputs; let processor: PublicProcessor; @@ -61,7 +58,6 @@ describe('public_processor', () => { root = Buffer.alloc(32, 5); const avmCircuitInputs = AvmCircuitInputs.empty(); - mockedAvmOutput = avmCircuitInputs.output; mockedEnqueuedCallsResult = { avmProvingRequest: { type: ProvingRequestType.PUBLIC_VM, @@ -220,83 +216,25 @@ describe('public_processor', () => { expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); }); - // it('injects balance update with public enqueued call', async function () { - // const txFee = new Fr(567); - // mockedAvmOutput.transactionFee = txFee; - - // const tx = mockTxWithPublicCalls({ - // feePayer, - // }); - - // const [processed, failed] = await processor.process([tx], 1, handler); - // expect(failed).toEqual([]); - - // expect(processed).toHaveLength(1); - // expect(processed[0].hash).toEqual(tx.getTxHash()); - // expect(processed[0].data.feePayer).toEqual(feePayer); - // expect(processed[0].txEffect.transactionFee).toEqual(txFee); - // expect(processed[0].txEffect.publicDataWrites[0]).toEqual( - // new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), initialBalance.sub(txFee)), - // ); - - // expect(worldStateDB.commit).toHaveBeenCalledTimes(1); - // expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(1); - - // expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); - // }); - - // it('tweaks existing balance update from claim', async function () { - // const txFee = new Fr(567); - // const pendingBalance = new Fr(2000); - // const pendingWrites = [ - // new PublicDataWrite(new Fr(888n), new Fr(999)), - // new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), pendingBalance), - // new PublicDataWrite(new Fr(666n), new Fr(777)), - // ]; - // mockedAvmOutput.transactionFee = txFee; - // mockedAvmOutput.accumulatedData.publicDataWrites[0] = pendingWrites[0]; - // mockedAvmOutput.accumulatedData.publicDataWrites[1] = pendingWrites[1]; - // mockedAvmOutput.accumulatedData.publicDataWrites[2] = pendingWrites[2]; - - // const tx = mockTxWithPublicCalls({ - // feePayer, - // }); - - // const [processed, failed] = await processor.process([tx], 1, handler); - - // expect(processed).toHaveLength(1); - // expect(processed[0].hash).toEqual(tx.getTxHash()); - // expect(processed[0].data.feePayer).toEqual(feePayer); - // expect(countAccumulatedItems(processed[0].txEffect.publicDataWrites)).toBe(3); - // expect(processed[0].txEffect.publicDataWrites.slice(0, 3)).toEqual([ - // pendingWrites[0], - // new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), pendingBalance.sub(txFee)), - // pendingWrites[2], - // ]); - // expect(failed).toEqual([]); - - // expect(worldStateDB.commit).toHaveBeenCalledTimes(1); - // expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(1); - - // expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); - // }); - - // it('rejects tx if fee payer has not enough balance', async function () { - // const txFee = initialBalance.add(new Fr(1)); - // mockedAvmOutput.transactionFee = txFee; - - // const tx = mockTxWithPublicCalls({ - // feePayer, - // }); - - // const [processed, failed] = await processor.process([tx], 1, handler); - - // expect(processed).toEqual([]); - // expect(failed).toHaveLength(1); - // expect(failed[0].error.message).toMatch(/Not enough balance/i); - - // expect(worldStateDB.commit).toHaveBeenCalledTimes(0); - // expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(0); - // }); + it('rejects tx if fee payer has not enough balance', async function () { + const tx = mockPrivateOnlyTx({ + feePayer, + }); + + const privateGasUsed = new Gas(initialBalance.toNumber(), initialBalance.toNumber()); + if (privateGasUsed.computeFee(gasFees) < initialBalance) { + throw new Error('Test setup error: gas fees are too low'); + } + tx.data.gasUsed = privateGasUsed; + + const [processed, failed] = await processor.process([tx], 1, handler); + + expect(processed).toEqual([]); + expect(failed).toHaveLength(1); + expect(failed[0].error.message).toMatch(/Not enough balance/i); + + expect(worldStateDB.commit).toHaveBeenCalledTimes(0); + expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(0); + }); }); }); diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index 19ea34b6818..f7b442c560d 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -188,16 +188,11 @@ export class PublicProcessor { } /** - * Creates the final set of data update requests for the transaction. This includes the - * set of public data update requests as returned by the public kernel, plus a data update - * request for updating fee balance. It also updates the local public state db. - * See build_or_patch_payment_update_request in base_rollup_inputs.nr for more details. + * Creates the public data write for paying the tx fee. + * This is used in private only txs, since for txs with public calls + * the avm handles the fee payment itself. */ - private async getFeePaymentPublicDataWrite( - publicDataWrites: PublicDataWrite[], - txFee: Fr, - feePayer: AztecAddress, - ): Promise { + private async getFeePaymentPublicDataWrite(txFee: Fr, feePayer: AztecAddress): Promise { if (feePayer.isZero()) { this.log.debug(`No one is paying the fee of ${txFee.toBigInt()}`); return; @@ -209,11 +204,7 @@ export class PublicProcessor { this.log.debug(`Deducting ${txFee.toBigInt()} balance in Fee Juice for ${feePayer}`); - const existingBalanceWrite = publicDataWrites.find(write => write.leafSlot.equals(leafSlot)); - - const balance = existingBalanceWrite - ? existingBalanceWrite.value - : await this.worldStateDB.storageRead(feeJuiceAddress, balanceSlot); + const balance = await this.worldStateDB.storageRead(feeJuiceAddress, balanceSlot); if (balance.lt(txFee)) { throw new Error( @@ -234,12 +225,7 @@ export class PublicProcessor { const gasFees = this.globalVariables.gasFees; const transactionFee = tx.data.gasUsed.computeFee(gasFees); - const accumulatedData = tx.data.forRollup!.end; - const feePaymentPublicDataWrite = await this.getFeePaymentPublicDataWrite( - accumulatedData.publicDataWrites, - transactionFee, - tx.data.feePayer, - ); + const feePaymentPublicDataWrite = await this.getFeePaymentPublicDataWrite(transactionFee, tx.data.feePayer); const processedTx = makeProcessedTxFromPrivateOnlyTx( tx, From d8baad8b60be6c818ee678e60099ff3362af70d8 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Wed, 4 Dec 2024 14:52:34 +0000 Subject: [PATCH 06/13] add tests for limit enforcing --- .../enqueued_call_side_effect_trace.test.ts | 52 +++++++++++++++++- .../src/public/side_effect_trace.test.ts | 53 ++++++++++++++++++- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts index eaf52dfe781..8e3483ccc11 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts @@ -174,7 +174,7 @@ describe('Enqueued-call Side Effect Trace', () => { ]); }); describe('Maximum accesses', () => { - it('Should enforce maximum number of public storage writes', () => { + it('Should enforce maximum number of user public storage writes', () => { for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; i++) { const lowLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i), new Fr(i), Fr.ZERO, 0n); const newLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i + 1), new Fr(i + 1), Fr.ZERO, 0n); @@ -194,6 +194,56 @@ describe('Enqueued-call Side Effect Trace', () => { [], ), ).toThrow(SideEffectLimitReachedError); + // Still allows protocol writes + expect(() => + trace.tracePublicStorageWrite( + AztecAddress.fromNumber(42), + new Fr(42), + value, + true, + leafPreimage, + Fr.ZERO, + [], + leafPreimage, + [], + ), + ).not.toThrow(); + }); + + it('Should enforce maximum number of protocol public storage writes', () => { + for (let i = 0; i < PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; i++) { + const lowLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i), new Fr(i), Fr.ZERO, 0n); + const newLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i + 1), new Fr(i + 1), Fr.ZERO, 0n); + trace.tracePublicStorageWrite(address, slot, value, true, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); + } + const leafPreimage = new PublicDataTreeLeafPreimage(new Fr(42), new Fr(42), Fr.ZERO, 0n); + expect(() => + trace.tracePublicStorageWrite( + AztecAddress.fromNumber(42), + new Fr(42), + value, + true, + leafPreimage, + Fr.ZERO, + [], + leafPreimage, + [], + ), + ).toThrow(SideEffectLimitReachedError); + // Still allows user writes + expect(() => + trace.tracePublicStorageWrite( + AztecAddress.fromNumber(42), + new Fr(42), + value, + false, + leafPreimage, + Fr.ZERO, + [], + leafPreimage, + [], + ), + ).not.toThrow(); }); it('Should enforce maximum number of new note hashes', () => { diff --git a/yarn-project/simulator/src/public/side_effect_trace.test.ts b/yarn-project/simulator/src/public/side_effect_trace.test.ts index 531580f3aba..905b0e078af 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.test.ts @@ -15,6 +15,7 @@ import { MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, NullifierLeafPreimage, + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataTreeLeafPreimage, SerializableContractInstance, } from '@aztec/circuits.js'; @@ -259,7 +260,7 @@ describe('Side Effect Trace', () => { ); }); - it('Should enforce maximum number of public storage writes', () => { + it('Should enforce maximum number of user public storage writes', () => { for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; i++) { const lowLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i), new Fr(i), Fr.ZERO, 0n); const newLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i + 1), new Fr(i + 1), Fr.ZERO, 0n); @@ -279,6 +280,56 @@ describe('Side Effect Trace', () => { [], ), ).toThrow(SideEffectLimitReachedError); + // Still allows protocol writes + expect(() => + trace.tracePublicStorageWrite( + AztecAddress.fromNumber(42), + new Fr(42), + value, + true, + leafPreimage, + Fr.ZERO, + [], + leafPreimage, + [], + ), + ).not.toThrow(); + }); + + it('Should enforce maximum number of protocol public storage writes', () => { + for (let i = 0; i < PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; i++) { + const lowLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i), new Fr(i), Fr.ZERO, 0n); + const newLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i + 1), new Fr(i + 1), Fr.ZERO, 0n); + trace.tracePublicStorageWrite(address, slot, value, true, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); + } + const leafPreimage = new PublicDataTreeLeafPreimage(new Fr(42), new Fr(42), Fr.ZERO, 0n); + expect(() => + trace.tracePublicStorageWrite( + AztecAddress.fromNumber(42), + new Fr(42), + value, + true, + leafPreimage, + Fr.ZERO, + [], + leafPreimage, + [], + ), + ).toThrow(SideEffectLimitReachedError); + // Still allows user writes + expect(() => + trace.tracePublicStorageWrite( + AztecAddress.fromNumber(42), + new Fr(42), + value, + false, + leafPreimage, + Fr.ZERO, + [], + leafPreimage, + [], + ), + ).not.toThrow(); }); it('Should enforce maximum number of note hash checks', () => { From c60e2662929bb72967e5623abfb16308a255080d Mon Sep 17 00:00:00 2001 From: sirasistant Date: Wed, 4 Dec 2024 15:06:56 +0000 Subject: [PATCH 07/13] better printing --- .../simulator/src/public/enqueued_call_side_effect_trace.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index 401b18a4525..da9b85e982a 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -271,7 +271,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI ); this.log.debug( - `Traced public data write (address=${contractAddress}, slot=${slot}, leafSlot=${leafSlot}): value=${value} (counter=${this.sideEffectCounter})`, + `Traced public data write (address=${contractAddress}, slot=${slot}, leafSlot=${leafSlot}): value=${value} (counter=${this.sideEffectCounter}, isProtocol:${protocolWrite})`, ); this.incrementSideEffectCounter(); } From 051624fd9ba97ae48e7777af0711622eb73df14d Mon Sep 17 00:00:00 2001 From: sirasistant Date: Wed, 4 Dec 2024 15:09:29 +0000 Subject: [PATCH 08/13] updated constants --- barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp | 4 ++-- l1-contracts/src/core/libraries/ConstantsGen.sol | 4 ++-- yarn-project/circuits.js/src/constants.gen.ts | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index d2fff918e9a..199f5a49a98 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -40,8 +40,8 @@ #define TOTAL_FEES_LENGTH 1 #define HEADER_LENGTH 25 #define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 867 -#define AVM_ACCUMULATED_DATA_LENGTH 318 -#define AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH 1006 +#define AVM_ACCUMULATED_DATA_LENGTH 320 +#define AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH 1008 #define AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS 86 #define AVM_PROOF_LENGTH_IN_FIELDS 4166 #define AVM_PUBLIC_COLUMN_MAX_SIZE 1024 diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index f76deaaf78c..987fa08c138 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -208,7 +208,7 @@ library Constants { uint256 internal constant SCOPED_READ_REQUEST_LEN = 3; uint256 internal constant PUBLIC_DATA_READ_LENGTH = 3; uint256 internal constant PRIVATE_VALIDATION_REQUESTS_LENGTH = 772; - uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 900; + uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 902; uint256 internal constant TX_CONSTANT_DATA_LENGTH = 35; uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = 44; uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1412; @@ -217,7 +217,7 @@ library Constants { uint256 internal constant PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH = 160; uint256 internal constant NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS = 3; uint256 internal constant PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1845; - uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 956; + uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 958; uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 13; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 31; uint256 internal constant BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 90; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 3168b6099f6..669aafde334 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -186,7 +186,7 @@ export const AGGREGATION_OBJECT_LENGTH = 16; export const SCOPED_READ_REQUEST_LEN = 3; export const PUBLIC_DATA_READ_LENGTH = 3; export const PRIVATE_VALIDATION_REQUESTS_LENGTH = 772; -export const COMBINED_ACCUMULATED_DATA_LENGTH = 900; +export const COMBINED_ACCUMULATED_DATA_LENGTH = 902; export const TX_CONSTANT_DATA_LENGTH = 35; export const COMBINED_CONSTANT_DATA_LENGTH = 44; export const PRIVATE_ACCUMULATED_DATA_LENGTH = 1412; @@ -194,10 +194,10 @@ export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2226; export const PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH = 900; export const PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH = 160; export const NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS = 3; -export const AVM_ACCUMULATED_DATA_LENGTH = 318; +export const AVM_ACCUMULATED_DATA_LENGTH = 320; export const PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1845; -export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 956; -export const AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1006; +export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 958; +export const AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1008; export const CONSTANT_ROLLUP_DATA_LENGTH = 13; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 31; export const BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 90; From 44218a3c567a347f08653732e6d885e6187e0b84 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Mon, 9 Dec 2024 19:16:39 +0000 Subject: [PATCH 09/13] witgen --- .../barretenberg/vm/avm/trace/execution.cpp | 9 ++- .../vm/avm/trace/public_inputs.hpp | 2 + .../src/barretenberg/vm/avm/trace/trace.cpp | 62 +++++++++++++++++++ .../src/barretenberg/vm/avm/trace/trace.hpp | 1 + .../src/barretenberg/vm/aztec_constants.hpp | 1 + .../src/core/libraries/ConstantsGen.sol | 1 + .../src/abis/avm_circuit_public_inputs.nr | 6 ++ .../crates/types/src/constants.nr | 3 + yarn-project/circuits.js/src/constants.gen.ts | 1 + .../circuits.js/src/scripts/constants.in.ts | 1 + .../structs/avm/avm_circuit_public_inputs.ts | 7 +++ .../circuits.js/src/tests/factories.ts | 1 + .../public/enqueued_call_side_effect_trace.ts | 3 + .../simulator/src/public/public_tx_context.ts | 1 + .../src/public/public_tx_simulator.ts | 3 +- .../src/public/transitional_adapters.ts | 3 + 16 files changed, 103 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index c6332a7c234..d7dc79ae8e0 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -377,10 +378,16 @@ std::vector Execution::gen_trace(AvmPublicInputs const& public_inputs, if (!is_ok(phase_error) && phase == TxExecutionPhase::SETUP) { // Stop processing phases. Halt TX. - info("A revert during SETUP phase halts the entire TX"); + info("A revert was encountered in the SETUP phase, killing the entire TX"); + throw std::runtime_error("A revert was encountered in the SETUP phase, killing the entire TX"); break; } } + + if (apply_e2e_assertions) { + trace_builder.pay_fee(); + } + auto trace = trace_builder.finalize(apply_e2e_assertions); returndata = trace_builder.get_all_returndata(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/public_inputs.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/public_inputs.hpp index c68d5e363fd..35b57c350f5 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/public_inputs.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/public_inputs.hpp @@ -306,6 +306,7 @@ class AvmPublicInputs { TreeSnapshots start_tree_snapshots; Gas start_gas_used; GasSettings gas_settings; + FF fee_payer; std::array public_setup_call_requests; std::array public_app_logic_call_requests; PublicCallRequest public_teardown_call_request; @@ -330,6 +331,7 @@ class AvmPublicInputs { read(it, public_inputs.start_tree_snapshots); read(it, public_inputs.start_gas_used); read(it, public_inputs.gas_settings); + read(it, public_inputs.fee_payer); read(it, public_inputs.public_setup_call_requests); read(it, public_inputs.public_app_logic_call_requests); read(it, public_inputs.public_teardown_call_request); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index c7247f64871..75701b10df1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,7 @@ #include "barretenberg/vm/avm/trace/gadgets/cmp.hpp" #include "barretenberg/vm/avm/trace/gadgets/keccak.hpp" #include "barretenberg/vm/avm/trace/gadgets/merkle_tree.hpp" +#include "barretenberg/vm/avm/trace/gadgets/poseidon2.hpp" #include "barretenberg/vm/avm/trace/gadgets/slice_trace.hpp" #include "barretenberg/vm/avm/trace/helper.hpp" #include "barretenberg/vm/avm/trace/opcode.hpp" @@ -225,6 +227,63 @@ void AvmTraceBuilder::insert_private_state(const std::vector& siloed_nullifi } } +void AvmTraceBuilder::pay_fee() +{ + auto clk = static_cast(main_trace.size()) + 1; + + auto tx_fee = (public_inputs.global_variables.gas_fees.fee_per_da_gas * public_inputs.end_gas_used.da_gas) + + (public_inputs.global_variables.gas_fees.fee_per_l2_gas * public_inputs.end_gas_used.l2_gas); + + if (public_inputs.fee_payer == 0) { + vinfo("No one is paying the fee of ", tx_fee); + return; + } + + // ** Compute the storage slot ** + // using the base slot of the balances map and the fee payer address (map key) + // TS equivalent: + // computeFeePayerBalanceStorageSlot(fee_payer); + std::vector slot_hash_inputs = { FEE_JUICE_BALANCES_SLOT, public_inputs.fee_payer }; + const auto balance_slot = poseidon2_trace_builder.poseidon2_hash(slot_hash_inputs, clk, Poseidon2Caller::SILO); + + // ** Read the balance before fee payment ** + // TS equivalent: + // current_balance = readStorage(FEE_JUICE_ADDRESS, balance_slot); + PublicDataReadTreeHint read_hint = execution_hints.storage_read_hints.at(storage_read_counter++); + FF computed_tree_slot = + merkle_tree_trace_builder.compute_public_tree_leaf_slot(clk, FEE_JUICE_ADDRESS, balance_slot); + // Sanity check that the computed slot using the value read from slot_offset should match the read hint + ASSERT(computed_tree_slot == read_hint.leaf_preimage.slot); + + // ** Write the updated balance after fee payment ** + // TS equivalent: + // Check that the leaf is a member of the public data tree + bool is_member = merkle_tree_trace_builder.perform_storage_read( + clk, read_hint.leaf_preimage, read_hint.leaf_index, read_hint.sibling_path); + ASSERT(is_member); + FF current_balance = read_hint.leaf_preimage.value; + + const auto updated_balance = current_balance - tx_fee; + if (current_balance < tx_fee) { + info("Not enough balance for fee payer to pay for transaction (got ", current_balance, " needs ", tx_fee); + throw std::runtime_error("Not enough balance for fee payer to pay for transaction"); + } + + // writeStorage(FEE_JUICE_ADDRESS, balance_slot, updated_balance); + PublicDataWriteTreeHint write_hint = execution_hints.storage_write_hints.at(storage_write_counter++); + ASSERT(write_hint.new_leaf_preimage.value == updated_balance); + merkle_tree_trace_builder.perform_storage_write(clk, + write_hint.low_leaf_membership.leaf_preimage, + write_hint.low_leaf_membership.leaf_index, + write_hint.low_leaf_membership.sibling_path, + write_hint.new_leaf_preimage.slot, + write_hint.new_leaf_preimage.value, + write_hint.insertion_path); + + debug("pay fee side-effect cnt: ", side_effect_counter); + side_effect_counter++; +} + /** * @brief Loads a value from memory into a given intermediate register at a specified clock cycle. * Handles both direct and indirect memory access. @@ -2677,6 +2736,9 @@ AvmError AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint3 auto clk = static_cast(main_trace.size()) + 1; if (storage_write_counter >= MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) { + // NOTE: the circuit constraint for this limit should only be applied + // for the storage writes performed by this opcode. An exception should before + // made for the fee juice storage write made after teardown. error = AvmError::SIDE_EFFECT_LIMIT_REACHED; auto row = Row{ .main_clk = clk, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index 68666f38419..b7da9588d83 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -235,6 +235,7 @@ class AvmTraceBuilder { std::vector get_bytecode(const FF contract_address, bool check_membership = false); std::unordered_set bytecode_membership_cache; void insert_private_state(const std::vector& siloed_nullifiers, const std::vector& siloed_note_hashes); + void pay_fee(); // These are used for testing only. AvmTraceBuilder& set_range_check_required(bool required) diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index db2306b11d9..9bb09e93c7c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -26,6 +26,7 @@ #define MULTI_CALL_ENTRYPOINT_ADDRESS 4 #define FEE_JUICE_ADDRESS 5 #define ROUTER_ADDRESS 6 +#define FEE_JUICE_BALANCES_SLOT 1 #define AZTEC_ADDRESS_LENGTH 1 #define GAS_FEES_LENGTH 2 #define GAS_LENGTH 2 diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 90f6ea5b98c..632544c44a4 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -138,6 +138,7 @@ library Constants { uint256 internal constant MULTI_CALL_ENTRYPOINT_ADDRESS = 4; uint256 internal constant FEE_JUICE_ADDRESS = 5; uint256 internal constant ROUTER_ADDRESS = 6; + uint256 internal constant FEE_JUICE_BALANCES_SLOT = 1; uint256 internal constant DEFAULT_NPK_M_X = 582240093077765400562621227108555700500271598878376310175765873770292988861; uint256 internal constant DEFAULT_NPK_M_Y = diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr index 3e6c59e0b24..ab26d2b8211 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr @@ -12,6 +12,7 @@ use crate::{ public_call_request::PublicCallRequest, tree_snapshots::TreeSnapshots, }, + address::{AztecAddress}, constants::{ AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, MAX_ENQUEUED_CALLS_PER_TX, @@ -30,6 +31,7 @@ pub struct AvmCircuitPublicInputs { pub start_tree_snapshots: TreeSnapshots, pub start_gas_used: Gas, pub gas_settings: GasSettings, + pub fee_payer: AztecAddress, pub public_setup_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], pub public_app_logic_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], pub public_teardown_call_request: PublicCallRequest, @@ -54,6 +56,7 @@ impl Empty for AvmCircuitPublicInputs { start_tree_snapshots: TreeSnapshots::empty(), start_gas_used: Gas::empty(), gas_settings: GasSettings::empty(), + fee_payer: AztecAddress::zero(), public_setup_call_requests: [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], public_app_logic_call_requests: [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], public_teardown_call_request: PublicCallRequest::empty(), @@ -76,6 +79,7 @@ impl Eq for AvmCircuitPublicInputs { & (self.start_tree_snapshots == other.start_tree_snapshots) & (self.start_gas_used == other.start_gas_used) & (self.gas_settings == other.gas_settings) + & (self.fee_payer == other.fee_payer) & (self.public_setup_call_requests == other.public_setup_call_requests) & (self.public_app_logic_call_requests == other.public_app_logic_call_requests) & (self.public_teardown_call_request == other.public_teardown_call_request) @@ -111,6 +115,7 @@ impl Serialize for AvmCircuitPublicInputs { fields.extend_from_array(self.start_tree_snapshots.serialize()); fields.extend_from_array(self.start_gas_used.serialize()); fields.extend_from_array(self.gas_settings.serialize()); + fields.push(self.fee_payer.to_field()); for i in 0..self.public_setup_call_requests.len() { fields.extend_from_array(self.public_setup_call_requests[i].serialize()); } @@ -144,6 +149,7 @@ impl Deserialize for AvmCircuitPublicInputs { start_tree_snapshots: reader.read_struct(TreeSnapshots::deserialize), start_gas_used: reader.read_struct(Gas::deserialize), gas_settings: reader.read_struct(GasSettings::deserialize), + fee_payer: AztecAddress::from_field(reader.read()), public_setup_call_requests: reader.read_struct_array( PublicCallRequest::deserialize, [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 5768cf768db..11a50d6f739 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -227,6 +227,9 @@ pub global MULTI_CALL_ENTRYPOINT_ADDRESS: AztecAddress = AztecAddress::from_fiel pub global FEE_JUICE_ADDRESS: AztecAddress = AztecAddress::from_field(5); pub global ROUTER_ADDRESS: AztecAddress = AztecAddress::from_field(6); +// Slot of the balances map to be hashed with an AztecAddress (map key) to get an actual storage slot. +pub global FEE_JUICE_BALANCES_SLOT: u32 = 1; + // CANONICAL DEFAULT KEYS // This below are: // "az_null_npk" diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index c51b5793f92..bc71f92c847 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -124,6 +124,7 @@ export const REGISTERER_CONTRACT_ADDRESS = 3; export const MULTI_CALL_ENTRYPOINT_ADDRESS = 4; export const FEE_JUICE_ADDRESS = 5; export const ROUTER_ADDRESS = 6; +export const FEE_JUICE_BALANCES_SLOT = 1; export const DEFAULT_NPK_M_X = 582240093077765400562621227108555700500271598878376310175765873770292988861n; export const DEFAULT_NPK_M_Y = 10422444662424639723529825114205836958711284159673861467999592572974769103684n; export const DEFAULT_IVPK_M_X = 339708709767762472786445938838804872781183545349360029270386718856175781484n; diff --git a/yarn-project/circuits.js/src/scripts/constants.in.ts b/yarn-project/circuits.js/src/scripts/constants.in.ts index 6ac65ef90ea..44fbfc546db 100644 --- a/yarn-project/circuits.js/src/scripts/constants.in.ts +++ b/yarn-project/circuits.js/src/scripts/constants.in.ts @@ -90,6 +90,7 @@ const CPP_CONSTANTS = [ 'MULTI_CALL_ENTRYPOINT_ADDRESS', 'FEE_JUICE_ADDRESS', 'ROUTER_ADDRESS', + 'FEE_JUICE_BALANCES_SLOT', ]; const CPP_GENERATORS: string[] = [ diff --git a/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts index 8877b4b8003..1a9c1abeb1a 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts @@ -1,4 +1,5 @@ import { makeTuple } from '@aztec/foundation/array'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; @@ -23,6 +24,7 @@ export class AvmCircuitPublicInputs { public startTreeSnapshots: TreeSnapshots, public startGasUsed: Gas, public gasSettings: GasSettings, + public feePayer: AztecAddress, public publicSetupCallRequests: Tuple, public publicAppLogicCallRequests: Tuple, public publicTeardownCallRequest: PublicCallRequest, @@ -44,6 +46,7 @@ export class AvmCircuitPublicInputs { reader.readObject(TreeSnapshots), reader.readObject(Gas), reader.readObject(GasSettings), + reader.readObject(AztecAddress), reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), reader.readObject(PublicCallRequest), @@ -65,6 +68,7 @@ export class AvmCircuitPublicInputs { this.startTreeSnapshots, this.startGasUsed, this.gasSettings, + this.feePayer, this.publicSetupCallRequests, this.publicAppLogicCallRequests, this.publicTeardownCallRequest, @@ -95,6 +99,7 @@ export class AvmCircuitPublicInputs { TreeSnapshots.fromFields(reader), Gas.fromFields(reader), GasSettings.fromFields(reader), + AztecAddress.fromFields(reader), reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), PublicCallRequest.fromFields(reader), @@ -116,6 +121,7 @@ export class AvmCircuitPublicInputs { TreeSnapshots.empty(), Gas.empty(), GasSettings.empty(), + AztecAddress.zero(), makeTuple(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest.empty), makeTuple(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest.empty), PublicCallRequest.empty(), @@ -137,6 +143,7 @@ export class AvmCircuitPublicInputs { startTreeSnapshots: ${inspect(this.startTreeSnapshots)}, startGasUsed: ${inspect(this.startGasUsed)}, gasSettings: ${inspect(this.gasSettings)}, + feePayer: ${inspect(this.feePayer)}, publicSetupCallRequests: [${this.publicSetupCallRequests .filter(x => !x.isEmpty()) .map(h => inspect(h)) diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 27ef02fa3ad..8913da5c27f 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -441,6 +441,7 @@ function makeAvmCircuitPublicInputs(seed = 1) { makeTreeSnapshots(seed + 0x10), makeGas(seed + 0x20), makeGasSettings(), + makeAztecAddress(seed + 0x40), makeTuple(MAX_ENQUEUED_CALLS_PER_TX, makePublicCallRequest, seed + 0x100), makeTuple(MAX_ENQUEUED_CALLS_PER_TX, makePublicCallRequest, seed + 0x200), makePublicCallRequest(seed + 0x300), diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index 347e9b95cab..81155a55151 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -546,6 +546,8 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI startGasUsed: Gas, /** How much gas was available for this public execution. */ gasLimits: GasSettings, + /** Address of the fee payer. */ + feePayer: AztecAddress, /** Call requests for setup phase. */ publicSetupCallRequests: PublicCallRequest[], /** Call requests for app logic phase. */ @@ -569,6 +571,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI startTreeSnapshots, startGasUsed, gasLimits, + feePayer, padArrayEnd(publicSetupCallRequests, PublicCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_TX), padArrayEnd(publicAppLogicCallRequests, PublicCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_TX), publicTeardownCallRequest, diff --git a/yarn-project/simulator/src/public/public_tx_context.ts b/yarn-project/simulator/src/public/public_tx_context.ts index 4dcbf7cb026..3690644f61e 100644 --- a/yarn-project/simulator/src/public/public_tx_context.ts +++ b/yarn-project/simulator/src/public/public_tx_context.ts @@ -330,6 +330,7 @@ export class PublicTxContext { this.startStateReference, this.startGasUsed, this.gasSettings, + this.feePayer, this.setupCallRequests, this.appLogicCallRequests, this.teardownCallRequests, diff --git a/yarn-project/simulator/src/public/public_tx_simulator.ts b/yarn-project/simulator/src/public/public_tx_simulator.ts index fcb2ec63cee..5d42c53dee1 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.ts @@ -20,7 +20,7 @@ import { } from '@aztec/circuits.js'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; -import { ProtocolContractAddress } from '@aztec/protocol-contracts'; +import { ProtocolContractAddress, ProtocolContractArtifact } from '@aztec/protocol-contracts'; import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec/telemetry-client'; import { strict as assert } from 'assert'; @@ -65,6 +65,7 @@ export class PublicTxSimulator { private doMerkleOperations: boolean = false, ) { this.log = createDebugLogger(`aztec:public_tx_simulator`); + this.log.info(`fee juice storage balances slot: ${ProtocolContractArtifact.FeeJuice.storageLayout.balances.slot}`); this.metrics = new ExecutorMetrics(telemetryClient, 'PublicTxSimulator'); } diff --git a/yarn-project/simulator/src/public/transitional_adapters.ts b/yarn-project/simulator/src/public/transitional_adapters.ts index 18f1c58cf1b..f701fd501cc 100644 --- a/yarn-project/simulator/src/public/transitional_adapters.ts +++ b/yarn-project/simulator/src/public/transitional_adapters.ts @@ -1,5 +1,6 @@ import { type AvmCircuitPublicInputs, + type AztecAddress, type Fr, type Gas, type GasSettings, @@ -30,6 +31,7 @@ export function generateAvmCircuitPublicInputs( startStateReference: StateReference, startGasUsed: Gas, gasSettings: GasSettings, + feePayer: AztecAddress, setupCallRequests: PublicCallRequest[], appLogicCallRequests: PublicCallRequest[], teardownCallRequests: PublicCallRequest[], @@ -52,6 +54,7 @@ export function generateAvmCircuitPublicInputs( startTreeSnapshots, startGasUsed, gasSettings, + feePayer, setupCallRequests, appLogicCallRequests, teardownCallRequests.length ? teardownCallRequests[0] : PublicCallRequest.empty(), From 2974dc784210943bcbf5b93e68abd33203e662ec Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Mon, 9 Dec 2024 20:46:04 +0000 Subject: [PATCH 10/13] fmt & fix --- .../crates/types/src/abis/avm_circuit_public_inputs.nr | 2 +- .../noir-protocol-circuits-types/src/type_conversion.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr index ab26d2b8211..3af68aeebec 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr @@ -12,7 +12,7 @@ use crate::{ public_call_request::PublicCallRequest, tree_snapshots::TreeSnapshots, }, - address::{AztecAddress}, + address::AztecAddress, constants::{ AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, MAX_ENQUEUED_CALLS_PER_TX, diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 58c7041999e..a5912d95589 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1606,6 +1606,7 @@ function mapAvmCircuitPublicInputsToNoir(inputs: AvmCircuitPublicInputs): AvmCir start_tree_snapshots: mapTreeSnapshotsToNoir(inputs.startTreeSnapshots), start_gas_used: mapGasToNoir(inputs.startGasUsed), gas_settings: mapGasSettingsToNoir(inputs.gasSettings), + fee_payer: mapAztecAddressToNoir(inputs.feePayer), public_setup_call_requests: mapTuple(inputs.publicSetupCallRequests, mapPublicCallRequestToNoir), public_app_logic_call_requests: mapTuple(inputs.publicAppLogicCallRequests, mapPublicCallRequestToNoir), public_teardown_call_request: mapPublicCallRequestToNoir(inputs.publicTeardownCallRequest), From de95db1e2ecaf2be033041ca6b38d5b80a056553 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Mon, 9 Dec 2024 20:54:50 +0000 Subject: [PATCH 11/13] fix --- yarn-project/simulator/src/public/transitional_adapters.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/public/transitional_adapters.ts b/yarn-project/simulator/src/public/transitional_adapters.ts index f701fd501cc..cdf0c0ab48c 100644 --- a/yarn-project/simulator/src/public/transitional_adapters.ts +++ b/yarn-project/simulator/src/public/transitional_adapters.ts @@ -1,7 +1,7 @@ import { type AvmCircuitPublicInputs, type AztecAddress, - type Fr, + Fr, type Gas, type GasSettings, type GlobalVariables, From b2f476d1f824ab2dfa6e2014459c8738ebf41442 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Mon, 9 Dec 2024 21:53:07 +0000 Subject: [PATCH 12/13] serialization size avm pub ins --- .../noir-protocol-circuits/crates/types/src/constants.nr | 1 + 1 file changed, 1 insertion(+) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 11a50d6f739..43c86da4885 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -434,6 +434,7 @@ pub global AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = GLOBAL_VARIABLES_LENGTH + TREE_SNAPSHOTS_LENGTH /* start_tree_snapshots */ + GAS_LENGTH /* start_gas_used */ + GAS_SETTINGS_LENGTH + + 1 /* fee_payer */ + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) /* public_setup_call_requests */ + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) /* public_app_logic_call_requests */ + PUBLIC_CALL_REQUEST_LENGTH /* public_teardown_call_request */ From 77f2910d993ddcef2837856579ead2a5e0e541cb Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Tue, 10 Dec 2024 19:00:58 +0000 Subject: [PATCH 13/13] fmt --- yarn-project/simulator/src/public/public_tx_simulator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/public/public_tx_simulator.ts b/yarn-project/simulator/src/public/public_tx_simulator.ts index cb7e2ecb7c7..4e14d76987a 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.ts @@ -20,7 +20,7 @@ import { } from '@aztec/circuits.js'; import { type Logger, createLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; -import { ProtocolContractAddress, ProtocolContractArtifact } from '@aztec/protocol-contracts'; +import { ProtocolContractAddress } from '@aztec/protocol-contracts'; import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec/telemetry-client'; import { strict as assert } from 'assert';