From f779eda466d2baecbe358d8e5652e5ea97959f23 Mon Sep 17 00:00:00 2001 From: Mitchell Tracy Date: Mon, 27 May 2024 13:33:35 +0200 Subject: [PATCH 1/9] [skip ci] --- .../structs/kernel/public_accumulated_data.ts | 5 ++++- .../src/public/abstract_phase_manager.ts | 20 ------------------- .../src/public/public_processor.test.ts | 6 +++--- 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts index 0bdf2481f70..8337cc01a48 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts @@ -54,7 +54,10 @@ export class PublicAccumulatedData { /** * All the public data update requests made in this transaction. */ - public publicDataUpdateRequests: Tuple, + public readonly publicDataUpdateRequests: Tuple< + PublicDataUpdateRequest, + typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + >, /** * Current public call stack. */ diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index 186e2ee560c..bf41d2691b8 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -61,7 +61,6 @@ import { type PublicExecutor, accumulateReturnValues, collectPublicDataReads, - collectPublicDataUpdateRequests, isPublicExecutionResult, } from '@aztec/simulator'; import { type MerkleTreeOperations } from '@aztec/world-state'; @@ -511,9 +510,6 @@ export abstract class AbstractPhaseManager { publicInputs: PublicKernelCircuitPublicInputs, execResult: PublicExecutionResult, ) { - const { publicDataUpdateRequests } = PhaseIsRevertible[this.phase] - ? publicInputs.end - : publicInputs.endNonRevertibleData; const { publicDataReads } = publicInputs.validationRequests; // Convert ContractStorage* objects to PublicData* objects and sort them in execution order. @@ -522,13 +518,9 @@ export abstract class AbstractPhaseManager { const simPublicDataReads = collectPublicDataReads(execResult); - const simPublicDataUpdateRequests = collectPublicDataUpdateRequests(execResult); - // We only want to reorder the items from the public inputs of the // most recently processed top/enqueued call. - const effectSet = PhaseIsRevertible[this.phase] ? 'end' : 'endNonRevertibleData'; - const numReadsInKernel = arrayNonEmptyLength(publicDataReads, f => f.isEmpty()); const numReadsBeforeThisEnqueuedCall = numReadsInKernel - simPublicDataReads.length; publicInputs.validationRequests.publicDataReads = padArrayEnd( @@ -540,18 +532,6 @@ export abstract class AbstractPhaseManager { PublicDataRead.empty(), MAX_PUBLIC_DATA_READS_PER_TX, ); - - const numUpdatesInKernel = arrayNonEmptyLength(publicDataUpdateRequests, f => f.isEmpty()); - const numUpdatesBeforeThisEnqueuedCall = numUpdatesInKernel - simPublicDataUpdateRequests.length; - - publicInputs[effectSet].publicDataUpdateRequests = padArrayEnd( - [ - ...publicInputs[effectSet].publicDataUpdateRequests.slice(0, numUpdatesBeforeThisEnqueuedCall), - ...simPublicDataUpdateRequests, - ], - PublicDataUpdateRequest.empty(), - 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 761f24b427e..02e411e2f7d 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -973,13 +973,13 @@ describe('public_processor', () => { const txEffect = toTxEffect(processed[0], GasFees.default()); expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toEqual(3); expect(txEffect.publicDataWrites[0]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotC), fr(0x201)), + new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotB), fr(0x152)), ); expect(txEffect.publicDataWrites[1]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x103)), + new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x102)), ); expect(txEffect.publicDataWrites[2]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotB), fr(0x152)), + new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotC), fr(0x201)), ); expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(0); expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(0); From 2165f0850893369e68635e901a9fcd3e4f51fa79 Mon Sep 17 00:00:00 2001 From: Mitchell Tracy Date: Mon, 27 May 2024 15:56:41 +0200 Subject: [PATCH 2/9] WIP [skip ci] --- .../src/core/libraries/ConstantsGen.sol | 4 +- .../src/public_kernel_tail.nr | 50 ++++++++++++++++--- .../src/reset/mutable_data_read_request.nr | 8 +-- .../rollup-lib/src/base/base_rollup_inputs.nr | 5 +- .../src/abis/public_data_update_request.nr | 19 +++++-- .../crates/types/src/constants.nr | 4 +- .../src/contrakt/storage_update_request.nr | 5 +- .../crates/types/src/tests/fixture_builder.nr | 2 +- .../src/tests/public_call_data_builder.nr | 3 +- yarn-project/circuits.js/src/constants.gen.ts | 4 +- .../src/hints/build_public_data_hints.test.ts | 5 +- ...ild_public_data_read_request_hints.test.ts | 4 +- .../contract_storage_update_request.ts | 16 +++--- .../src/structs/public_data_update_request.ts | 31 +++++++++--- .../circuits.js/src/tests/factories.ts | 6 +-- .../composed/integration_l1_publisher.test.ts | 8 +-- .../src/type_conversion.ts | 3 ++ .../prover-client/src/mocks/fixtures.ts | 4 +- .../src/public/abstract_phase_manager.ts | 10 +++- .../src/public/public_processor.test.ts | 4 ++ .../simulator/src/public/public_processor.ts | 2 +- yarn-project/simulator/src/public/utils.ts | 9 ++-- 22 files changed, 148 insertions(+), 58 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 7f4b29b5feb..8682d9a15a4 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -113,7 +113,7 @@ library Constants { uint256 internal constant CONTENT_COMMITMENT_LENGTH = 4; uint256 internal constant CONTRACT_INSTANCE_LENGTH = 5; uint256 internal constant CONTRACT_STORAGE_READ_LENGTH = 2; - uint256 internal constant CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2; + uint256 internal constant CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 3; uint256 internal constant ETH_ADDRESS_LENGTH = 1; uint256 internal constant FUNCTION_DATA_LENGTH = 2; uint256 internal constant FUNCTION_LEAF_PREIMAGE_LENGTH = 5; @@ -187,7 +187,7 @@ library Constants { + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + (SCOPED_KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); - uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 2; + uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 6 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index c37458ea749..89605eb8603 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -6,14 +6,20 @@ use dep::reset_kernel_lib::{ use dep::types::{ abis::{ accumulated_data::CombinedAccumulatedData, kernel_circuit_public_inputs::KernelCircuitPublicInputs, - public_kernel_data::PublicKernelData + public_kernel_data::PublicKernelData, public_data_update_request::PublicDataUpdateRequest, + side_effect::Ordered }, - constants::{MAX_PUBLIC_DATA_HINTS, MAX_NULLIFIER_READ_REQUESTS_PER_TX}, + constants::{MAX_PUBLIC_DATA_HINTS, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX}, data::public_data_hint::PublicDataHint, merkle_tree::{conditionally_assert_check_membership, MembershipWitness}, - partial_state_reference::PartialStateReference, utils::{arrays::array_length}, address::AztecAddress + partial_state_reference::PartialStateReference, + utils::{arrays::{array_length, assert_sorted_array}}, address::AztecAddress }; +fn asc_sort_by_counters(a: T, b: T) -> bool where T: Ordered { + a.counter() < b.counter() +} + struct PublicKernelTailCircuitPrivateInputs { previous_kernel: PublicKernelData, nullifier_read_request_hints: NullifierReadRequestHints, @@ -21,6 +27,8 @@ struct PublicKernelTailCircuitPrivateInputs { public_data_hints: [PublicDataHint; MAX_PUBLIC_DATA_HINTS], public_data_read_request_hints: PublicDataReadRequestHints, start_state: PartialStateReference, + sorted_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + sorted_public_data_update_requests_indexes: [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] } impl PublicKernelTailCircuitPrivateInputs { @@ -47,10 +55,21 @@ impl PublicKernelTailCircuitPrivateInputs { fn propagate_accumulated_data(self) -> CombinedAccumulatedData { let previous_public_inputs = self.previous_kernel.public_inputs; // TODO: Sort the combined data. - CombinedAccumulatedData::combine( + let mut data = CombinedAccumulatedData::combine( previous_public_inputs.end_non_revertible, previous_public_inputs.end - ) + ); + + assert_sorted_array( + data.public_data_update_requests, + self.sorted_public_data_update_requests, + self.sorted_public_data_update_requests_indexes, + asc_sort_by_counters + ); + + data.public_data_update_requests = self.sorted_public_data_update_requests; + + data } pub fn public_kernel_tail(self) -> KernelCircuitPublicInputs { @@ -98,7 +117,8 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData, - nullifier::ScopedNullifier, nullifier_leaf_preimage::NullifierLeafPreimage + nullifier::ScopedNullifier, nullifier_leaf_preimage::NullifierLeafPreimage, + accumulated_data::CombinedAccumulatedData, public_data_update_request::PublicDataUpdateRequest }, address::AztecAddress, constants::{ @@ -110,7 +130,7 @@ mod tests { }, hash::{silo_nullifier, sha256_to_field}, public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, - tests::{fixture_builder::FixtureBuilder, merkle_tree_utils::NonEmptyMerkleTree}, + tests::{fixture_builder::FixtureBuilder, merkle_tree_utils::NonEmptyMerkleTree, sort::sort_get_sorted_hints}, traits::is_empty, partial_state_reference::PartialStateReference, utils::arrays::array_merge, merkle_tree::MembershipWitness }; @@ -292,13 +312,27 @@ mod tests { let mut previous_kernel = self.previous_kernel.to_public_kernel_data(false); previous_kernel.public_inputs.end = self.previous_revertible.to_public_accumulated_data(); + let combined = CombinedAccumulatedData::combine( + previous_kernel.public_inputs.end_non_revertible, + previous_kernel.public_inputs.end + ); + + let sorted = sort_get_sorted_hints( + combined.public_data_update_requests, + |a: PublicDataUpdateRequest, b: PublicDataUpdateRequest| a.counter() < b.counter() + ); + let sorted_public_data_update_requests = sorted.sorted_array; + let sorted_public_data_update_requests_indexes = sorted.sorted_index_hints; + let kernel = PublicKernelTailCircuitPrivateInputs { previous_kernel, nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), nullifier_non_existent_read_request_hints: self.nullifier_non_existent_read_request_hints_builder.to_hints(), public_data_hints: self.public_data_hints.storage, public_data_read_request_hints: self.public_data_read_request_hints_builder.to_hints(), - start_state: self.start_state + start_state: self.start_state, + sorted_public_data_update_requests, + sorted_public_data_update_requests_indexes }; kernel.public_kernel_tail() diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/mutable_data_read_request.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/mutable_data_read_request.nr index 299970a6f13..f73536b4f1c 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/mutable_data_read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/mutable_data_read_request.nr @@ -138,10 +138,10 @@ mod tests { } global data_writes = [ - PublicDataUpdateRequest { leaf_slot: 22, new_value: 200 }, - PublicDataUpdateRequest { leaf_slot: 11, new_value: 100 }, - PublicDataUpdateRequest { leaf_slot: 33, new_value: 300 }, - PublicDataUpdateRequest { leaf_slot: 44, new_value: 400 } + PublicDataUpdateRequest { leaf_slot: 22, new_value: 200, counter: 0 }, + PublicDataUpdateRequest { leaf_slot: 11, new_value: 100, counter: 1 }, + PublicDataUpdateRequest { leaf_slot: 33, new_value: 300, counter: 2 }, + PublicDataUpdateRequest { leaf_slot: 44, new_value: 400, counter: 3 } ]; global leaf_data_hints = [ diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index 8cb43e345a3..04514890c11 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -273,7 +273,7 @@ impl BaseRollupInputs { ); let new_value = compute_public_data_tree_value(existing_update.new_value - tx_fee); - let protocol_update_request = PublicDataUpdateRequest { leaf_slot, new_value }; + let protocol_update_request = PublicDataUpdateRequest { leaf_slot, new_value, counter: 0 }; (protocol_update_request, existing_update_index as u64) } else { // Otherwise, build a new one to be inserted into the protocol update requests at the end of the array. @@ -284,7 +284,7 @@ impl BaseRollupInputs { assert(!balance.lt(tx_fee), "Not enough balance for fee payer to pay for transaction"); let new_value = compute_public_data_tree_value(balance - tx_fee); - let protocol_update_request = PublicDataUpdateRequest { leaf_slot, new_value }; + let protocol_update_request = PublicDataUpdateRequest { leaf_slot, new_value, counter: 0 }; (protocol_update_request, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) } } else { @@ -505,6 +505,7 @@ mod tests { kernel_data.public_inputs.end.public_data_update_requests[i] = PublicDataUpdateRequest { leaf_slot : leaf.slot, new_value : leaf.value, + counter : 0 }; } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr index 5543269aaf3..09779b0d812 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr @@ -5,10 +5,12 @@ use crate::public_data_tree_leaf::PublicDataTreeLeaf; use crate::address::AztecAddress; use crate::contrakt::storage_update_request::StorageUpdateRequest; use crate::data::hash::{compute_public_data_tree_value, compute_public_data_tree_index}; +use crate::abis::side_effect::Ordered; struct PublicDataUpdateRequest { leaf_slot : Field, - new_value : Field + new_value : Field, + counter: u32 } impl PublicDataUpdateRequest { @@ -18,11 +20,18 @@ impl PublicDataUpdateRequest { ) -> PublicDataUpdateRequest { PublicDataUpdateRequest { leaf_slot: compute_public_data_tree_index(contract_address, update_request.storage_slot), - new_value: compute_public_data_tree_value(update_request.new_value) + new_value: compute_public_data_tree_value(update_request.new_value), + counter: update_request.counter } } } +impl Ordered for PublicDataUpdateRequest { + fn counter(self)-> u32{ + self.counter + } +} + impl Eq for PublicDataUpdateRequest { fn eq(self, update_request: PublicDataUpdateRequest) -> bool { (update_request.leaf_slot == self.leaf_slot) @@ -34,7 +43,8 @@ impl Empty for PublicDataUpdateRequest { fn empty() -> Self { Self { leaf_slot : 0, - new_value : 0 + new_value : 0, + counter : 0 } } } @@ -66,7 +76,7 @@ impl PublicDataUpdateRequest { impl Serialize for PublicDataUpdateRequest { fn serialize(self) -> [Field; PUBLIC_DATA_UPDATE_REQUEST_LENGTH] { - [self.leaf_slot, self.new_value] + [self.leaf_slot, self.new_value, self.counter as Field] } } @@ -75,6 +85,7 @@ impl Deserialize for PublicDataUpdateRequest PublicDataUpdateRequest { leaf_slot: fields[0], new_value: fields[1], + counter: fields[2] as u32 } } } 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 4298295827f..4a51e9a2300 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -154,7 +154,7 @@ global CALL_CONTEXT_LENGTH: u64 = 6; global CONTENT_COMMITMENT_LENGTH: u64 = 4; global CONTRACT_INSTANCE_LENGTH: u64 = 5; global CONTRACT_STORAGE_READ_LENGTH: u64 = 2; -global CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: u64 = 2; +global CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: u64 = 3; global ETH_ADDRESS_LENGTH = 1; global FUNCTION_DATA_LENGTH: u64 = 2; global FUNCTION_LEAF_PREIMAGE_LENGTH: u64 = 5; @@ -199,7 +199,7 @@ global SCOPED_READ_REQUEST_LEN = READ_REQUEST_LENGTH + 1; global PUBLIC_DATA_READ_LENGTH = 2; global VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + (SCOPED_KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); -global PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 2; +global PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 6 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; global COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr index 5c9e244f937..01f0acf1eb1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr @@ -7,6 +7,7 @@ use dep::std::cmp::Eq; struct StorageUpdateRequest { storage_slot : Field, new_value : Field, + counter: u32 } impl Eq for StorageUpdateRequest { @@ -21,6 +22,7 @@ impl Empty for StorageUpdateRequest { StorageUpdateRequest { storage_slot: 0, new_value: 0, + counter: 0 } } } @@ -33,7 +35,7 @@ impl Hash for StorageUpdateRequest { impl Serialize for StorageUpdateRequest { fn serialize(self) -> [Field; CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH] { - [self.storage_slot, self.new_value] + [self.storage_slot, self.new_value, self.counter as Field] } } @@ -42,6 +44,7 @@ impl Deserialize for StorageUpdateReques StorageUpdateRequest { storage_slot: serialized[0], new_value: serialized[1], + counter: serialized[2] as u32 } } } 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 489df58716d..2f8d5516e12 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 @@ -344,7 +344,7 @@ impl FixtureBuilder { } pub fn add_public_data_update_request(&mut self, leaf_slot: Field, value: Field) { - let update_request = PublicDataUpdateRequest { leaf_slot, new_value: value }; + let update_request = PublicDataUpdateRequest { leaf_slot, new_value: value, counter: self.next_counter() }; self.public_data_update_requests.push(update_request); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr index 258c70f3145..ed3f4825ec6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr @@ -128,7 +128,8 @@ impl PublicCallDataBuilder { // The default storage slot is its index + 1. storage_slot: (value_offset + i + 1) as Field, // The default value is its index + 890. - new_value: (value_offset + i + 890) as Field + new_value: (value_offset + i + 890) as Field, + counter: i as u32 }; self.public_inputs.contract_storage_update_requests.push(update_request); } diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 7bbdd32cf05..3a11892a0a6 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -95,7 +95,7 @@ export const CALL_CONTEXT_LENGTH = 6; export const CONTENT_COMMITMENT_LENGTH = 4; export const CONTRACT_INSTANCE_LENGTH = 5; export const CONTRACT_STORAGE_READ_LENGTH = 2; -export const CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2; +export const CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 3; export const ETH_ADDRESS_LENGTH = 1; export const FUNCTION_DATA_LENGTH = 2; export const FUNCTION_LEAF_PREIMAGE_LENGTH = 5; @@ -186,7 +186,7 @@ export const VALIDATION_REQUESTS_LENGTH = SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX + SCOPED_KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_TX + PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX; -export const PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 2; +export const PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; export const COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + diff --git a/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts b/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts index 9c16f9c77d9..3e038e13c9d 100644 --- a/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts @@ -30,6 +30,9 @@ describe('buildPublicDataHints', () => { let publicDataReads: Tuple; let publicDataUpdateRequests: Tuple; let expectedHints: Tuple; + let sideEffectCounter = 0; + + const nextSideEffectCounter = () => sideEffectCounter++; const publicDataLeaves = [ new PublicDataTreeLeafPreimage(new Fr(22), new Fr(200), new Fr(33), 0n), @@ -39,7 +42,7 @@ describe('buildPublicDataHints', () => { const makePublicDataRead = (leafSlot: number, value: number) => new PublicDataRead(new Fr(leafSlot), new Fr(value)); const makePublicDataWrite = (leafSlot: number, value: number) => - new PublicDataUpdateRequest(new Fr(leafSlot), new Fr(value)); + new PublicDataUpdateRequest(new Fr(leafSlot), new Fr(value), nextSideEffectCounter()); const oracle = { getMatchOrLowPublicDataMembershipWitness: (leafSlot: bigint) => { diff --git a/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts index 164256ede3e..4afea4a13b9 100644 --- a/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts @@ -23,9 +23,11 @@ describe('buildPublicDataReadRequestHints', () => { let expectedStatuses: Tuple; let expectedPendingHints: Tuple; let expectedLeafDataHints: Tuple; + let counter = 0; + const nextCounter = () => counter++; const makePublicDataWrite = (leafSlot: number, value: number) => - new PublicDataUpdateRequest(new Fr(leafSlot), new Fr(value)); + new PublicDataUpdateRequest(new Fr(leafSlot), new Fr(value), nextCounter()); const makePublicDataHint = (slot: number, value: number) => { const hint = PublicDataHint.empty(); hint.leafSlot = new Fr(slot); diff --git a/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts b/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts index 378279d55bb..04be2dd24f9 100644 --- a/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts +++ b/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts @@ -24,17 +24,17 @@ export class ContractStorageUpdateRequest { /** * Optional side effect counter tracking position of this event in tx execution. */ - public readonly sideEffectCounter?: number, + public readonly sideEffectCounter: number, public contractAddress?: AztecAddress, // TODO: Should not be optional. This is a temporary hack to silo the storage slot with the correct address for nested executions. ) {} toBuffer() { - return serializeToBuffer(this.storageSlot, this.newValue); + return serializeToBuffer(this.storageSlot, this.newValue, this.sideEffectCounter); } static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new ContractStorageUpdateRequest(Fr.fromBuffer(reader), Fr.fromBuffer(reader)); + return new ContractStorageUpdateRequest(Fr.fromBuffer(reader), Fr.fromBuffer(reader), reader.readNumber()); } /** @@ -56,7 +56,7 @@ export class ContractStorageUpdateRequest { } static empty() { - return new ContractStorageUpdateRequest(Fr.ZERO, Fr.ZERO); + return new ContractStorageUpdateRequest(Fr.ZERO, Fr.ZERO, 0); } isEmpty() { @@ -64,11 +64,13 @@ export class ContractStorageUpdateRequest { } toFriendlyJSON() { - return `Slot=${this.storageSlot.toFriendlyJSON()}: ${this.newValue.toFriendlyJSON()}`; + return `Slot=${this.storageSlot.toFriendlyJSON()}: ${this.newValue.toFriendlyJSON()}, sideEffectCounter=${ + this.sideEffectCounter + }`; } toFields(): Fr[] { - const fields = [this.storageSlot, this.newValue]; + const fields = [this.storageSlot, this.newValue, new Fr(this.sideEffectCounter)]; if (fields.length !== CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH) { throw new Error( `Invalid number of fields for ContractStorageUpdateRequest. Expected ${CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH}, got ${fields.length}`, @@ -83,6 +85,6 @@ export class ContractStorageUpdateRequest { const storageSlot = reader.readField(); const newValue = reader.readField(); - return new ContractStorageUpdateRequest(storageSlot, newValue); + return new ContractStorageUpdateRequest(storageSlot, newValue, reader.readU32()); } } diff --git a/yarn-project/circuits.js/src/structs/public_data_update_request.ts b/yarn-project/circuits.js/src/structs/public_data_update_request.ts index c34bf44a58e..d396ebb1ffd 100644 --- a/yarn-project/circuits.js/src/structs/public_data_update_request.ts +++ b/yarn-project/circuits.js/src/structs/public_data_update_request.ts @@ -1,6 +1,8 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { inspect } from 'util'; + /** * Write operations on the public data tree including the previous value. */ @@ -15,9 +17,9 @@ export class PublicDataUpdateRequest { */ public readonly newValue: Fr, /** - * Optional side effect counter tracking position of this event in tx execution. + * Side effect counter tracking position of this event in tx execution. */ - public readonly sideEffectCounter?: number, + public readonly sideEffectCounter: number, ) {} static from(args: { @@ -29,12 +31,17 @@ export class PublicDataUpdateRequest { * New value of the leaf. */ newValue: Fr; + + /** + * Side effect counter tracking position of this event in tx execution. + */ + sideEffectCounter: number; }) { - return new PublicDataUpdateRequest(args.leafIndex, args.newValue); + return new PublicDataUpdateRequest(args.leafIndex, args.newValue, args.sideEffectCounter); } toBuffer() { - return serializeToBuffer(this.leafSlot, this.newValue); + return serializeToBuffer(this.leafSlot, this.newValue, this.sideEffectCounter); } isEmpty() { @@ -43,7 +50,7 @@ export class PublicDataUpdateRequest { static fromFields(fields: Fr[] | FieldReader) { const reader = FieldReader.asReader(fields); - return new PublicDataUpdateRequest(reader.readField(), reader.readField()); + return new PublicDataUpdateRequest(reader.readField(), reader.readField(), reader.readU32()); } static isEmpty(x: PublicDataUpdateRequest) { @@ -56,14 +63,22 @@ export class PublicDataUpdateRequest { static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new PublicDataUpdateRequest(Fr.fromBuffer(reader), Fr.fromBuffer(reader)); + return new PublicDataUpdateRequest(Fr.fromBuffer(reader), Fr.fromBuffer(reader), reader.readNumber()); } static empty() { - return new PublicDataUpdateRequest(Fr.ZERO, Fr.ZERO); + return new PublicDataUpdateRequest(Fr.ZERO, Fr.ZERO, 0); } toFriendlyJSON() { - return `Leaf=${this.leafSlot.toFriendlyJSON()}: ${this.newValue.toFriendlyJSON()}`; + return `Leaf=${this.leafSlot.toFriendlyJSON()}: ${this.newValue.toFriendlyJSON()}, SideEffectCounter=${ + this.sideEffectCounter + }`; + } + + [inspect.custom]() { + return `PublicDataUpdateRequest { leafSlot: ${this.leafSlot.toFriendlyJSON()}, newValue: ${this.newValue.toFriendlyJSON()}, sideEffectCounter: ${ + this.sideEffectCounter + } }`; } } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index cd429991dfe..59151988b05 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -249,7 +249,7 @@ function makeScopedKeyValidationRequestAndGenerators(seed: number): ScopedKeyVal * @returns A public data update request. */ export function makePublicDataUpdateRequest(seed = 1): PublicDataUpdateRequest { - return new PublicDataUpdateRequest(fr(seed), fr(seed + 1)); + return new PublicDataUpdateRequest(fr(seed), fr(seed + 1), seed + 2); } /** @@ -257,7 +257,7 @@ export function makePublicDataUpdateRequest(seed = 1): PublicDataUpdateRequest { * @returns An empty public data update request. */ export function makeEmptyPublicDataUpdateRequest(): PublicDataUpdateRequest { - return new PublicDataUpdateRequest(fr(0), fr(0)); + return new PublicDataUpdateRequest(fr(0), fr(0), 0); } /** @@ -283,7 +283,7 @@ export function makeEmptyPublicDataRead(): PublicDataRead { * @returns A contract storage update request. */ export function makeContractStorageUpdateRequest(seed = 1): ContractStorageUpdateRequest { - return new ContractStorageUpdateRequest(fr(seed), fr(seed + 1)); + return new ContractStorageUpdateRequest(fr(seed), fr(seed + 1), seed + 2); } /** diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 3fc6ee3d64a..9b4cd85a9a7 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -168,7 +168,7 @@ describe('L1Publisher integration', () => { return tx; }; - const makeBloatedProcessedTx = (seed = 0x1) => { + const makeBloatedProcessedTx = (seed = 0x1): ProcessedTx => { const tx = mockTx(seed); const kernelOutput = KernelCircuitPublicInputs.empty(); kernelOutput.constants.txContext.chainId = fr(chainId); @@ -176,7 +176,7 @@ describe('L1Publisher integration', () => { kernelOutput.constants.historicalHeader = prevHeader; kernelOutput.end.publicDataUpdateRequests = makeTuple( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - i => new PublicDataUpdateRequest(fr(i), fr(i + 10)), + i => new PublicDataUpdateRequest(fr(i), fr(i + 10), i + 20), seed + 0x500, ); @@ -192,7 +192,7 @@ describe('L1Publisher integration', () => { return processedTx; }; - const sendToL2 = async (content: Fr, recipientAddress: AztecAddress) => { + const sendToL2 = async (content: Fr, recipientAddress: AztecAddress): Promise => { // @todo @LHerskind version hardcoded here (update to bigint or field) const recipient = new L2Actor(recipientAddress, 1); // getting the 32 byte hex string representation of the content @@ -233,7 +233,7 @@ describe('L1Publisher integration', () => { l1ToL2Content: Fr[], recipientAddress: AztecAddress, deployerAddress: `0x${string}`, - ) => { + ): void => { if (!AZTEC_GENERATE_TEST_DATA) { return; } 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 ce4dfdcd75b..9fc7acbe1fb 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1041,6 +1041,7 @@ export function mapPublicDataUpdateRequestFromNoir( return new PublicDataUpdateRequest( mapFieldFromNoir(publicDataUpdateRequest.leaf_slot), mapFieldFromNoir(publicDataUpdateRequest.new_value), + mapNumberFromNoir(publicDataUpdateRequest.counter), ); } @@ -1055,6 +1056,7 @@ export function mapPublicDataUpdateRequestToNoir( return { leaf_slot: mapFieldToNoir(publicDataUpdateRequest.leafSlot), new_value: mapFieldToNoir(publicDataUpdateRequest.newValue), + counter: mapNumberToNoir(publicDataUpdateRequest.sideEffectCounter), }; } @@ -1792,6 +1794,7 @@ export function mapStorageUpdateRequestToNoir( return { storage_slot: mapFieldToNoir(storageUpdateRequest.storageSlot), new_value: mapFieldToNoir(storageUpdateRequest.newValue), + counter: mapNumberToNoir(storageUpdateRequest.sideEffectCounter), }; } /** diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index d8b144eeffb..81a1aff8a14 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -102,12 +102,12 @@ export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, se kernelOutput.constants.historicalHeader = await builderDb.buildInitialHeader(); kernelOutput.end.publicDataUpdateRequests = makeTuple( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - i => new PublicDataUpdateRequest(fr(i), fr(i + 10)), + i => new PublicDataUpdateRequest(fr(i), fr(i + 10), i + 20), seed + 0x500, ); kernelOutput.end.publicDataUpdateRequests = makeTuple( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - i => new PublicDataUpdateRequest(fr(i), fr(i + 10)), + i => new PublicDataUpdateRequest(fr(i), fr(i + 10), i + 20), seed + 0x600, ); diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index bf41d2691b8..87494431036 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -52,7 +52,7 @@ import { makeEmptyRecursiveProof, } from '@aztec/circuits.js'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; -import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection'; +import { arrayNonEmptyLength, padArrayEnd, removeArrayPaddingEnd } from '@aztec/foundation/collection'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { type Tuple } from '@aztec/foundation/serialize'; import { @@ -65,6 +65,8 @@ import { } from '@aztec/simulator'; import { type MerkleTreeOperations } from '@aztec/world-state'; +import { inspect } from 'util'; + import { HintsBuilder } from './hints_builder.js'; import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; import { lastSideEffectCounter } from './utils.js'; @@ -341,6 +343,7 @@ export abstract class AbstractPhaseManager { // HACK(#1622): Manually patches the ordering of public state actions // TODO(#757): Enforce proper ordering of public state actions this.patchPublicStorageActionOrdering(kernelOutput, enqueuedExecutionResult!); + this.debug(kernelOutput); } return [publicKernelInputs, kernelOutput, newUnencryptedFunctionLogs, undefined, enqueuedCallResults, gasUsed]; @@ -533,6 +536,11 @@ export abstract class AbstractPhaseManager { MAX_PUBLIC_DATA_READS_PER_TX, ); } + + private debug(publicInputs: PublicKernelCircuitPublicInputs) { + this.log.debug('CUSTOM DEBUG'); + this.log.debug(inspect(removeArrayPaddingEnd(publicInputs.end.publicDataUpdateRequests, x => x.isEmpty()))); + } } export function removeRedundantPublicDataWrites( diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 02e411e2f7d..d50495bd11f 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -1021,6 +1021,7 @@ describe('public_processor', () => { PublicDataUpdateRequest.from({ leafIndex: computeFeePayerBalanceLeafSlot(feePayer), newValue: new Fr(initialBalance - inclusionFee), + sideEffectCounter: 0, }), ); @@ -1071,6 +1072,7 @@ describe('public_processor', () => { PublicDataUpdateRequest.from({ leafIndex: computeFeePayerBalanceLeafSlot(feePayer), newValue: new Fr(initialBalance - inclusionFee), + sideEffectCounter: 0, }), ); @@ -1110,6 +1112,7 @@ describe('public_processor', () => { tx.data.publicInputs.end.publicDataUpdateRequests[0] = PublicDataUpdateRequest.from({ leafIndex: computeFeePayerBalanceLeafSlot(feePayer), newValue: new Fr(initialBalance), + sideEffectCounter: 0, }); const [processed, failed] = await processor.process([tx], 1, prover); @@ -1126,6 +1129,7 @@ describe('public_processor', () => { PublicDataUpdateRequest.from({ leafIndex: computeFeePayerBalanceLeafSlot(feePayer), newValue: new Fr(initialBalance - inclusionFee), + sideEffectCounter: 0, }), ); diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index a625fb47d14..80cb94211a9 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -207,7 +207,7 @@ export class PublicProcessor { finalPublicDataUpdateRequests[ existingBalanceWriteIndex > -1 ? existingBalanceWriteIndex : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX - ] = new PublicDataUpdateRequest(leafSlot, updatedBalance); + ] = new PublicDataUpdateRequest(leafSlot, updatedBalance, 0); return finalPublicDataUpdateRequests; } diff --git a/yarn-project/simulator/src/public/utils.ts b/yarn-project/simulator/src/public/utils.ts index f824cf9e92f..738aa4ed1e7 100644 --- a/yarn-project/simulator/src/public/utils.ts +++ b/yarn-project/simulator/src/public/utils.ts @@ -1,5 +1,4 @@ import { type Tx } from '@aztec/circuit-types'; -import { CallRequest } from '@aztec/circuits.js'; /** * Looks at the side effects of a transaction and returns the highest counter @@ -13,19 +12,23 @@ export function lastSideEffectCounter(tx: Tx): number { ...data.endNonRevertibleData.newNullifiers, ...data.endNonRevertibleData.unencryptedLogsHashes, ...data.endNonRevertibleData.publicCallStack, + ...data.endNonRevertibleData.publicDataUpdateRequests, ...data.end.newNoteHashes, ...data.end.newNullifiers, ...data.end.unencryptedLogsHashes, ...data.end.publicCallStack, + ...data.end.publicDataUpdateRequests, ]; let max = 0; for (const sideEffect of sideEffectCounters) { - if (sideEffect instanceof CallRequest) { + if ('startSideEffectCounter' in sideEffect) { // look at both start and end counters because for enqueued public calls start > 0 while end === 0 max = Math.max(max, sideEffect.startSideEffectCounter.toNumber(), sideEffect.endSideEffectCounter.toNumber()); - } else { + } else if ('counter' in sideEffect) { max = Math.max(max, sideEffect.counter); + } else if ('sideEffectCounter' in sideEffect) { + max = Math.max(max, sideEffect.sideEffectCounter); } } From 92fb2c93468a2f9fdd111afb77fb164cd0e7f947 Mon Sep 17 00:00:00 2001 From: Mitchell Tracy Date: Mon, 27 May 2024 17:00:14 +0200 Subject: [PATCH 3/9] sort the public data update requests in TS --- .../kernel/combined_accumulated_data.ts | 36 +++++---- .../public_kernel_circuit_public_inputs.ts | 78 ++++++++++++++++++- ...blic_kernel_tail_circuit_private_inputs.ts | 16 +++- .../src/structs/public_data_update_request.ts | 4 + .../circuits.js/src/tests/factories.ts | 2 + yarn-project/foundation/src/fields/fields.ts | 4 + .../src/type_conversion.ts | 5 ++ .../build_private_kernel_tail_hints.ts | 2 +- .../src/public/tail_phase_manager.ts | 10 +++ yarn-project/simulator/src/public/utils.ts | 4 +- 10 files changed, 140 insertions(+), 21 deletions(-) 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 302e0887a54..035c1999988 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 @@ -1,4 +1,4 @@ -import { makeTuple } from '@aztec/foundation/array'; +import { type FieldsOf, makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -67,20 +67,28 @@ export class CombinedAccumulatedData { public gasUsed: Gas, ) {} + static getFields(fields: FieldsOf) { + return [ + fields.newNoteHashes, + fields.newNullifiers, + fields.newL2ToL1Msgs, + fields.noteEncryptedLogsHash, + fields.encryptedLogsHash, + fields.unencryptedLogsHash, + fields.noteEncryptedLogPreimagesLength, + fields.encryptedLogPreimagesLength, + fields.unencryptedLogPreimagesLength, + fields.publicDataUpdateRequests, + fields.gasUsed, + ] as const; + } + + static from(fields: FieldsOf): CombinedAccumulatedData { + return new CombinedAccumulatedData(...CombinedAccumulatedData.getFields(fields)); + } + toBuffer() { - return serializeToBuffer( - this.newNoteHashes, - this.newNullifiers, - this.newL2ToL1Msgs, - this.noteEncryptedLogsHash, - this.encryptedLogsHash, - this.unencryptedLogsHash, - this.noteEncryptedLogPreimagesLength, - this.encryptedLogPreimagesLength, - this.unencryptedLogPreimagesLength, - this.publicDataUpdateRequests, - this.gasUsed, - ); + return serializeToBuffer(...CombinedAccumulatedData.getFields(this)); } toString() { diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts index f789606f5d0..4be538347a4 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts @@ -1,14 +1,24 @@ import { makeTuple } from '@aztec/foundation/array'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { type Fr } from '@aztec/foundation/fields'; -import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { arrayNonEmptyLength } from '@aztec/foundation/collection'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, type Tuple, mapTuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { inspect } from 'util'; -import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX } from '../../constants.gen.js'; +import { + MAX_ENCRYPTED_LOGS_PER_TX, + MAX_NEW_L2_TO_L1_MSGS_PER_TX, + MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, +} from '../../constants.gen.js'; +import { mergeAccumulatedData } from '../../utils/index.js'; import { CallRequest } from '../call_request.js'; import { RevertCode } from '../revert_code.js'; import { ValidationRequests } from '../validation_requests.js'; +import { CombinedAccumulatedData } from './combined_accumulated_data.js'; import { CombinedConstantData } from './combined_constant_data.js'; import { PublicAccumulatedData } from './public_accumulated_data.js'; @@ -84,6 +94,68 @@ export class PublicKernelCircuitPublicInputs { return !this.publicTeardownCallStack[0].isEmpty(); } + recombineAccumulatedData(): CombinedAccumulatedData { + const newNoteHashes: Tuple = mapTuple( + mergeAccumulatedData(this.endNonRevertibleData.newNoteHashes, this.end.newNoteHashes, MAX_NEW_NOTE_HASHES_PER_TX), + n => n.value, + ); + + const newNullifiers: Tuple = mapTuple( + mergeAccumulatedData(this.endNonRevertibleData.newNullifiers, this.end.newNullifiers, MAX_NEW_NOTE_HASHES_PER_TX), + n => n.value, + ); + + const newL2ToL1Msgs = mergeAccumulatedData( + this.endNonRevertibleData.newL2ToL1Msgs, + this.end.newL2ToL1Msgs, + MAX_NEW_L2_TO_L1_MSGS_PER_TX, + ); + + const noteEncryptedLogHashes = mergeAccumulatedData( + this.endNonRevertibleData.noteEncryptedLogsHashes, + this.end.noteEncryptedLogsHashes, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + ); + const noteEncryptedLogPreimagesLength = new Fr(arrayNonEmptyLength(noteEncryptedLogHashes, x => x.isEmpty())); + + const encryptedLogHashes = mergeAccumulatedData( + this.endNonRevertibleData.encryptedLogsHashes, + this.end.encryptedLogsHashes, + MAX_ENCRYPTED_LOGS_PER_TX, + ); + const encryptedLogPreimagesLength = new Fr(arrayNonEmptyLength(encryptedLogHashes, x => x.isEmpty())); + + const unencryptedLogHashes = mergeAccumulatedData( + this.endNonRevertibleData.unencryptedLogsHashes, + this.end.unencryptedLogsHashes, + MAX_ENCRYPTED_LOGS_PER_TX, + ); + + const unencryptedLogPreimagesLength = new Fr(arrayNonEmptyLength(unencryptedLogHashes, x => x.isEmpty())); + + const publicDataUpdateRequests = mergeAccumulatedData( + this.endNonRevertibleData.publicDataUpdateRequests, + this.end.publicDataUpdateRequests, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + + const gasUsed = this.endNonRevertibleData.gasUsed.add(this.end.gasUsed); + + return CombinedAccumulatedData.from({ + newNoteHashes, + newNullifiers, + newL2ToL1Msgs, + noteEncryptedLogsHash: noteEncryptedLogHashes[0].value, + noteEncryptedLogPreimagesLength, + encryptedLogsHash: encryptedLogHashes[0].value, + encryptedLogPreimagesLength, + unencryptedLogsHash: unencryptedLogHashes[0].value, + unencryptedLogPreimagesLength, + publicDataUpdateRequests: publicDataUpdateRequests, + gasUsed, + }); + } + /** * Deserializes from a buffer or reader, corresponding to a write in cpp. * @param buffer - Buffer or reader to read from. diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts index c6f22d4b536..84637a0e8f0 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts @@ -1,6 +1,10 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS } from '../../constants.gen.js'; +import { + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_PUBLIC_DATA_HINTS, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, +} from '../../constants.gen.js'; import { type NullifierNonExistentReadRequestHints, nullifierNonExistentReadRequestHintsFromBuffer, @@ -8,6 +12,7 @@ import { import { PartialStateReference } from '../partial_state_reference.js'; import { PublicDataHint } from '../public_data_hint.js'; import { PublicDataReadRequestHints } from '../public_data_read_request_hints.js'; +import { PublicDataUpdateRequest } from '../public_data_update_request.js'; import { type NullifierReadRequestHints, nullifierReadRequestHintsFromBuffer } from '../read_request_hints/index.js'; import { PublicKernelData } from './public_kernel_data.js'; @@ -31,6 +36,11 @@ export class PublicKernelTailCircuitPrivateInputs { public readonly publicDataHints: Tuple, public readonly publicDataReadRequestHints: PublicDataReadRequestHints, public readonly startState: PartialStateReference, + public readonly sortedPublicDataUpdateRequests: Tuple< + PublicDataUpdateRequest, + typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + >, + public readonly sortedPublicDataUpdateRequestsIndexes: Tuple, ) {} toBuffer() { @@ -41,6 +51,8 @@ export class PublicKernelTailCircuitPrivateInputs { this.publicDataHints, this.publicDataReadRequestHints, this.startState, + this.sortedPublicDataUpdateRequests, + this.sortedPublicDataUpdateRequestsIndexes, ); } @@ -65,6 +77,8 @@ export class PublicKernelTailCircuitPrivateInputs { reader.readArray(MAX_PUBLIC_DATA_HINTS, PublicDataHint), reader.readObject(PublicDataReadRequestHints), reader.readObject(PartialStateReference), + reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), + reader.readNumbers(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), ); } diff --git a/yarn-project/circuits.js/src/structs/public_data_update_request.ts b/yarn-project/circuits.js/src/structs/public_data_update_request.ts index d396ebb1ffd..a6b5d99a896 100644 --- a/yarn-project/circuits.js/src/structs/public_data_update_request.ts +++ b/yarn-project/circuits.js/src/structs/public_data_update_request.ts @@ -40,6 +40,10 @@ export class PublicDataUpdateRequest { return new PublicDataUpdateRequest(args.leafIndex, args.newValue, args.sideEffectCounter); } + get counter() { + return this.sideEffectCounter; + } + toBuffer() { return serializeToBuffer(this.leafSlot, this.newValue, this.sideEffectCounter); } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 59151988b05..8d0467e3738 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -682,6 +682,8 @@ export function makePublicKernelTailCircuitPrivateInputs(seed = 1): PublicKernel makeTuple(MAX_PUBLIC_DATA_HINTS, PublicDataHint.empty, seed + 0x100), PublicDataReadRequestHintsBuilder.empty(), makePartialStateReference(seed + 0x200), + makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataUpdateRequest, seed + 0x300), + makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, i => i, seed + 0x400), ); } diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 8aaa9345874..f8d31429f58 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -133,6 +133,10 @@ abstract class BaseField { return this.toBuffer().equals(ZERO_BUFFER); } + isEmpty(): boolean { + return this.isZero(); + } + toFriendlyJSON(): string { return this.toString(); } 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 9fc7acbe1fb..d4cdc71d210 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1766,6 +1766,11 @@ export function mapPublicKernelTailCircuitPrivateInputsToNoir( public_data_hints: mapTuple(inputs.publicDataHints, mapPublicDataHintToNoir), public_data_read_request_hints: mapPublicDataReadRequestHintsToNoir(inputs.publicDataReadRequestHints), start_state: mapPartialStateReferenceToNoir(inputs.startState), + sorted_public_data_update_requests: mapTuple( + inputs.sortedPublicDataUpdateRequests, + mapPublicDataUpdateRequestToNoir, + ), + sorted_public_data_update_requests_indexes: mapTuple(inputs.sortedPublicDataUpdateRequestsIndexes, mapNumberToNoir), }; } diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts index e4853eca8d4..4f16d0d3db6 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts @@ -10,7 +10,7 @@ import { sortByCounterGetSortedHints, } from '@aztec/circuits.js'; -export function buildPrivateKernelTailHints(publicInputs: PrivateKernelCircuitPublicInputs) { +export function buildPrivateKernelTailHints(publicInputs: PrivateKernelCircuitPublicInputs): PrivateKernelTailHints { const [sortedNoteHashes, sortedNoteHashesIndexes] = sortByCounterGetSortedHints( publicInputs.end.newNoteHashes, MAX_NEW_NOTE_HASHES_PER_TX, diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index 96ba9425ede..8e8c7f63aa1 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -14,6 +14,7 @@ import { PublicKernelTailCircuitPrivateInputs, mergeAccumulatedData, sortByCounter, + sortByCounterGetSortedHints, } from '@aztec/circuits.js'; import { type Tuple } from '@aztec/foundation/serialize'; import { type PublicExecutor, type PublicStateDB } from '@aztec/simulator'; @@ -136,6 +137,13 @@ export class TailPhaseManager extends AbstractPhaseManager { const currentState = await this.db.getStateReference(); + const combinedData = previousKernel.publicInputs.recombineAccumulatedData(); + + const [sortedPublicDataUpdateRequests, sortedPublicDataUpdateRequestsIndexes] = sortByCounterGetSortedHints( + combinedData.publicDataUpdateRequests, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + return new PublicKernelTailCircuitPrivateInputs( previousKernel, nullifierReadRequestHints, @@ -143,6 +151,8 @@ export class TailPhaseManager extends AbstractPhaseManager { publicDataHints, publicDataReadRequestHints, currentState.partial, + sortedPublicDataUpdateRequests, + sortedPublicDataUpdateRequestsIndexes, ); } diff --git a/yarn-project/simulator/src/public/utils.ts b/yarn-project/simulator/src/public/utils.ts index 738aa4ed1e7..d140e52bd47 100644 --- a/yarn-project/simulator/src/public/utils.ts +++ b/yarn-project/simulator/src/public/utils.ts @@ -27,8 +27,8 @@ export function lastSideEffectCounter(tx: Tx): number { max = Math.max(max, sideEffect.startSideEffectCounter.toNumber(), sideEffect.endSideEffectCounter.toNumber()); } else if ('counter' in sideEffect) { max = Math.max(max, sideEffect.counter); - } else if ('sideEffectCounter' in sideEffect) { - max = Math.max(max, sideEffect.sideEffectCounter); + } else { + throw new Error('Unknown side effect type'); } } From d6d96ee43427be40900532b89c2fbde52c67bba9 Mon Sep 17 00:00:00 2001 From: Mitchell Tracy Date: Tue, 28 May 2024 09:52:00 +0200 Subject: [PATCH 4/9] pass correct starting side effect counter to AVM --- .../types/src/abis/public_call_stack_item.nr | 4 +-- .../src/abis/public_circuit_public_inputs.nr | 2 +- .../public_call_stack_item.test.ts.snap | 8 ++--- .../public_circuit_public_inputs.test.ts.snap | 4 +-- .../simulator/src/avm/journal/journal.ts | 1 - .../src/public/abstract_phase_manager.ts | 15 ++-------- yarn-project/simulator/src/public/executor.ts | 4 +-- .../src/public/public_processor.test.ts | 14 ++++----- .../simulator/src/public/utils.test.ts | 24 +++++++-------- yarn-project/simulator/src/public/utils.ts | 29 ++++++++++--------- 10 files changed, 48 insertions(+), 57 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr index 6746118086d..40b6243801c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr @@ -69,7 +69,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test - let test_data_call_stack_item_request_hash = 0x11998b1d33b8ba1c8fa7a6c2f5bc76b31bbaa80400554465c335ba31559ac1f9; + let test_data_call_stack_item_request_hash = 0x09b460df8be10a6bd56588c93b478243fdf5cc92db59d9b1670ce2a044fab6d6; assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash); } @@ -87,7 +87,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item hash" test - let test_data_call_stack_item_hash = 0x2b7f8b68d96d0011ecc576459899e9451fbd880568ccc7a071d9cf04e59abb65; + let test_data_call_stack_item_hash = 0x0931a8de516f3f49dff48fbdea57f01b706dc67cbd1fd8bde97d26c4a53afd0a; assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index 157171f2648..3b9589d9ed2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -188,6 +188,6 @@ fn empty_hash() { let hash = inputs.hash(); // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x1e4351db0c9aa20836e7009bc3e6a4555c92622c5e9cb3b49e2ec0fbbf59d0bd; + let test_data_empty_hash = 0x05061edabeae1057b6f6216afc118e46ea0b77044d4c57ed12e5712dab01b8d4; assert_eq(hash, test_data_empty_hash); } diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap index 380fc1ae9c6..70445295be3 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x2b7f8b68d96d0011ecc576459899e9451fbd880568ccc7a071d9cf04e59abb65"`; +exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x0931a8de516f3f49dff48fbdea57f01b706dc67cbd1fd8bde97d26c4a53afd0a"`; -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x11998b1d33b8ba1c8fa7a6c2f5bc76b31bbaa80400554465c335ba31559ac1f9"`; +exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x09b460df8be10a6bd56588c93b478243fdf5cc92db59d9b1670ce2a044fab6d6"`; -exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x2e7cef26b4ef88a036f6f2bc5bd5d7457b7c2851c7357f1e6f79be9fdde4cf77>`; +exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x2baaf9d674eb8f64e18bca2f87a665fdbd43d8696c7a62d689d88bd0296175a4>`; -exports[`PublicCallStackItem computes hash 1`] = `Fr<0x1506520f17c103197070a8f5dec9c0665fefd4251d93ee52f32c07aad554fc78>`; +exports[`PublicCallStackItem computes hash 1`] = `Fr<0x17703e5a5555de5e97d3e6c991b489f4818e71931fd8ee958a00e2c18b806072>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index e666e2b7cbf..635a3f60030 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x1e4351db0c9aa20836e7009bc3e6a4555c92622c5e9cb3b49e2ec0fbbf59d0bd>`; +exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x05061edabeae1057b6f6216afc118e46ea0b77044d4c57ed12e5712dab01b8d4>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x099d3f1f21b3405cf1dffefd8dd045f4a628ecdd2a717ac7a41e4cc3d41ff79b>`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x14d9838268c0549fdbc4231fc36432f7ec6687157287117bf15b2fb5a39c9026>`; diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 24f682ecbce..2661d7242d7 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -138,7 +138,6 @@ export class AvmPersistableStateManager { * @param value - the value being written to the slot */ public writeStorage(storageAddress: Fr, slot: Fr, value: Fr) { - this.log.debug(`Storage write (address=${storageAddress}, slot=${slot}): value=${value}`); // Cache storage writes for later reference/reads this.publicStorage.write(storageAddress, slot, value); diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index 87494431036..39900a113f0 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -52,7 +52,7 @@ import { makeEmptyRecursiveProof, } from '@aztec/circuits.js'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; -import { arrayNonEmptyLength, padArrayEnd, removeArrayPaddingEnd } from '@aztec/foundation/collection'; +import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { type Tuple } from '@aztec/foundation/serialize'; import { @@ -65,8 +65,6 @@ import { } from '@aztec/simulator'; import { type MerkleTreeOperations } from '@aztec/world-state'; -import { inspect } from 'util'; - import { HintsBuilder } from './hints_builder.js'; import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; import { lastSideEffectCounter } from './utils.js'; @@ -228,7 +226,7 @@ export abstract class AbstractPhaseManager { Gas, ] > { - let kernelOutput = previousPublicKernelOutput; + let kernelOutput: PublicKernelCircuitPublicInputs = previousPublicKernelOutput; const publicKernelInputs: PublicKernelCircuitPrivateInputs[] = []; const enqueuedCalls = this.extractEnqueuedPublicCalls(tx); @@ -259,8 +257,7 @@ export abstract class AbstractPhaseManager { while (executionStack.length) { const current = executionStack.pop()!; const isExecutionRequest = !isPublicExecutionResult(current); - // TODO(6052): Extract correct new counter from nested calls - const sideEffectCounter = lastSideEffectCounter(tx) + 1; + const sideEffectCounter = lastSideEffectCounter(kernelOutput) + 1; const availableGas = this.getAvailableGas(tx, kernelOutput); const pendingNullifiers = this.getSiloedPendingNullifiers(kernelOutput); @@ -343,7 +340,6 @@ export abstract class AbstractPhaseManager { // HACK(#1622): Manually patches the ordering of public state actions // TODO(#757): Enforce proper ordering of public state actions this.patchPublicStorageActionOrdering(kernelOutput, enqueuedExecutionResult!); - this.debug(kernelOutput); } return [publicKernelInputs, kernelOutput, newUnencryptedFunctionLogs, undefined, enqueuedCallResults, gasUsed]; @@ -536,11 +532,6 @@ export abstract class AbstractPhaseManager { MAX_PUBLIC_DATA_READS_PER_TX, ); } - - private debug(publicInputs: PublicKernelCircuitPublicInputs) { - this.log.debug('CUSTOM DEBUG'); - this.log.debug(inspect(removeArrayPaddingEnd(publicInputs.end.publicDataUpdateRequests, x => x.isEmpty()))); - } } export function removeRedundantPublicDataWrites( diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 47d7e734a9b..2379ea9ec19 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -70,10 +70,8 @@ async function executeTopLevelPublicFunctionAvm( executionContext.commitmentsDb, ); - // TODO(6207): add sideEffectCounter to persistableState construction - // or modify the PersistableStateManager to manage rollbacks across enqueued-calls and transactions. + const startSideEffectCounter = executionContext.sideEffectCounter.current(); const worldStateJournal = new AvmPersistableStateManager(hostStorage); - const startSideEffectCounter = executionContext.execution.callContext.sideEffectCounter; for (const nullifier of executionContext.pendingNullifiers) { worldStateJournal.nullifiers.cache.appendSiloed(nullifier.value); } diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index d50495bd11f..d1a2a46e136 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -884,8 +884,8 @@ describe('public_processor', () => { PublicExecutionResultBuilder.fromPublicCallRequest({ request: publicCallRequests[1], contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 14, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 15, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 10, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 11, baseContractAddress), ], }).build({ startGasLeft: afterSetupGas, @@ -900,16 +900,16 @@ describe('public_processor', () => { from: teardown!.contractAddress, tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 11, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 12, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x103), 14, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 15, baseContractAddress), ], }).build({ startGasLeft: teardownGas, endGasLeft: teardownGas, transactionFee }), PublicExecutionResultBuilder.fromFunctionCall({ from: teardown!.contractAddress, tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x103), 13, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotB, fr(0x152), 15, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotB, fr(0x152), 13, baseContractAddress), ], }).build({ startGasLeft: teardownGas, endGasLeft: teardownGas, transactionFee }), ], @@ -976,7 +976,7 @@ describe('public_processor', () => { new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotB), fr(0x152)), ); expect(txEffect.publicDataWrites[1]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x102)), + new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x103)), ); expect(txEffect.publicDataWrites[2]).toEqual( new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotC), fr(0x201)), diff --git a/yarn-project/simulator/src/public/utils.test.ts b/yarn-project/simulator/src/public/utils.test.ts index 3f791162bcd..0ca629d7ce3 100644 --- a/yarn-project/simulator/src/public/utils.test.ts +++ b/yarn-project/simulator/src/public/utils.test.ts @@ -1,26 +1,26 @@ -import { mockTx } from '@aztec/circuit-types'; import { Fr } from '@aztec/circuits.js'; +import { makePublicKernelCircuitPublicInputs } from '@aztec/circuits.js/testing'; import { lastSideEffectCounter } from './utils.js'; describe('sequencer utils', () => { describe('lastSideEffectCounter', () => { it('correctly identifies the highest side effect counter in a transaction', () => { - const tx = mockTx(); - // mockTx creates a Tx with side effect counts of all 0 - expect(lastSideEffectCounter(tx)).toBe(0); + const inputs = makePublicKernelCircuitPublicInputs(); - tx.data.forPublic!.endNonRevertibleData.newNoteHashes.at(-1)!.counter = 8; - expect(lastSideEffectCounter(tx)).toBe(8); + const startingCounter = lastSideEffectCounter(inputs); - tx.data.forPublic!.endNonRevertibleData.publicCallStack.at(-1)!.startSideEffectCounter = new Fr(9); - expect(lastSideEffectCounter(tx)).toBe(9); + inputs.endNonRevertibleData.newNoteHashes.at(-1)!.counter = startingCounter + 1; + expect(lastSideEffectCounter(inputs)).toBe(startingCounter + 1); - tx.data.forPublic!.end.newNoteHashes.at(-1)!.counter = 10; - expect(lastSideEffectCounter(tx)).toBe(10); + inputs.endNonRevertibleData.publicCallStack.at(-1)!.startSideEffectCounter = new Fr(startingCounter + 2); + expect(lastSideEffectCounter(inputs)).toBe(startingCounter + 2); - tx.data.forPublic!.end.newNullifiers.at(-1)!.counter = 11; - expect(lastSideEffectCounter(tx)).toBe(11); + inputs.end.newNoteHashes.at(-1)!.counter = startingCounter + 3; + expect(lastSideEffectCounter(inputs)).toBe(startingCounter + 3); + + inputs.end.newNullifiers.at(-1)!.counter = startingCounter + 4; + expect(lastSideEffectCounter(inputs)).toBe(startingCounter + 4); }); }); }); diff --git a/yarn-project/simulator/src/public/utils.ts b/yarn-project/simulator/src/public/utils.ts index d140e52bd47..2ca86c7ddb6 100644 --- a/yarn-project/simulator/src/public/utils.ts +++ b/yarn-project/simulator/src/public/utils.ts @@ -1,23 +1,26 @@ -import { type Tx } from '@aztec/circuit-types'; +import { type PublicKernelCircuitPublicInputs } from '@aztec/circuits.js'; /** * Looks at the side effects of a transaction and returns the highest counter * @param tx - A transaction * @returns The highest side effect counter in the transaction so far */ -export function lastSideEffectCounter(tx: Tx): number { - const data = tx.data.forPublic!; +export function lastSideEffectCounter(inputs: PublicKernelCircuitPublicInputs): number { const sideEffectCounters = [ - ...data.endNonRevertibleData.newNoteHashes, - ...data.endNonRevertibleData.newNullifiers, - ...data.endNonRevertibleData.unencryptedLogsHashes, - ...data.endNonRevertibleData.publicCallStack, - ...data.endNonRevertibleData.publicDataUpdateRequests, - ...data.end.newNoteHashes, - ...data.end.newNullifiers, - ...data.end.unencryptedLogsHashes, - ...data.end.publicCallStack, - ...data.end.publicDataUpdateRequests, + ...inputs.endNonRevertibleData.newNoteHashes, + ...inputs.endNonRevertibleData.newNullifiers, + ...inputs.endNonRevertibleData.noteEncryptedLogsHashes, + ...inputs.endNonRevertibleData.encryptedLogsHashes, + ...inputs.endNonRevertibleData.unencryptedLogsHashes, + ...inputs.endNonRevertibleData.publicCallStack, + ...inputs.endNonRevertibleData.publicDataUpdateRequests, + ...inputs.end.newNoteHashes, + ...inputs.end.newNullifiers, + ...inputs.end.noteEncryptedLogsHashes, + ...inputs.end.encryptedLogsHashes, + ...inputs.end.unencryptedLogsHashes, + ...inputs.end.publicCallStack, + ...inputs.end.publicDataUpdateRequests, ]; let max = 0; From f8e5e1ed49b098d97f6d416b85db63773c7858b8 Mon Sep 17 00:00:00 2001 From: Mitchell Tracy Date: Tue, 28 May 2024 12:47:30 +0200 Subject: [PATCH 5/9] chore: add ability to plumb hints to public kernel tail --- .../src/public_kernel_tail.nr | 50 +++++++++++++---- .../src/public_kernel_teardown.nr | 11 +++- .../public_kernel_circuit_public_inputs.ts | 46 +++++++++++++--- ...blic_kernel_tail_circuit_private_inputs.ts | 54 +++++++++++++++---- .../circuits.js/src/tests/factories.ts | 17 +++++- .../src/type_conversion.ts | 25 +++++++-- .../simulator/src/avm/journal/journal.ts | 1 + .../src/public/tail_phase_manager.ts | 27 +--------- 8 files changed, 173 insertions(+), 58 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index 89605eb8603..cac175b6996 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -9,7 +9,10 @@ use dep::types::{ public_kernel_data::PublicKernelData, public_data_update_request::PublicDataUpdateRequest, side_effect::Ordered }, - constants::{MAX_PUBLIC_DATA_HINTS, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX}, + constants::{ + MAX_NEW_NOTE_HASHES_PER_TX, MAX_PUBLIC_DATA_HINTS, MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX +}, data::public_data_hint::PublicDataHint, merkle_tree::{conditionally_assert_check_membership, MembershipWitness}, partial_state_reference::PartialStateReference, @@ -20,6 +23,13 @@ fn asc_sort_by_counters(a: T, b: T) -> bool where T: Ordered { a.counter() < b.counter() } +struct PublicKernelTailCombineHints { + sorted_note_hashes: [Field; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + sorted_public_data_update_requests_indexes: [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], +} + struct PublicKernelTailCircuitPrivateInputs { previous_kernel: PublicKernelData, nullifier_read_request_hints: NullifierReadRequestHints, @@ -27,8 +37,7 @@ struct PublicKernelTailCircuitPrivateInputs { public_data_hints: [PublicDataHint; MAX_PUBLIC_DATA_HINTS], public_data_read_request_hints: PublicDataReadRequestHints, start_state: PartialStateReference, - sorted_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - sorted_public_data_update_requests_indexes: [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] + combine_hints: PublicKernelTailCombineHints } impl PublicKernelTailCircuitPrivateInputs { @@ -62,12 +71,12 @@ impl PublicKernelTailCircuitPrivateInputs { assert_sorted_array( data.public_data_update_requests, - self.sorted_public_data_update_requests, - self.sorted_public_data_update_requests_indexes, + self.combine_hints.sorted_public_data_update_requests, + self.combine_hints.sorted_public_data_update_requests_indexes, asc_sort_by_counters ); - data.public_data_update_requests = self.sorted_public_data_update_requests; + data.public_data_update_requests = self.combine_hints.sorted_public_data_update_requests; data } @@ -105,7 +114,7 @@ impl PublicKernelTailCircuitPrivateInputs { } mod tests { - use crate::public_kernel_tail::PublicKernelTailCircuitPrivateInputs; + use crate::public_kernel_tail::{PublicKernelTailCircuitPrivateInputs, PublicKernelTailCombineHints}; use dep::reset_kernel_lib::{ tests::{ nullifier_non_existent_read_request_hints_builder::NullifierNonExistentReadRequestHintsBuilder, @@ -118,7 +127,8 @@ mod tests { abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData, nullifier::ScopedNullifier, nullifier_leaf_preimage::NullifierLeafPreimage, - accumulated_data::CombinedAccumulatedData, public_data_update_request::PublicDataUpdateRequest + accumulated_data::CombinedAccumulatedData, public_data_update_request::PublicDataUpdateRequest, + note_hash::NoteHash }, address::AztecAddress, constants::{ @@ -312,6 +322,20 @@ mod tests { let mut previous_kernel = self.previous_kernel.to_public_kernel_data(false); previous_kernel.public_inputs.end = self.previous_revertible.to_public_accumulated_data(); + // Note: note hashes are a bit odd here: whereas we'd like to use `combined` and then + // sort the result, we cannot because we lose the side effect counters when we combine. + let new_note_hashes = array_merge( + previous_kernel.public_inputs.end_non_revertible.new_note_hashes, + previous_kernel.public_inputs.end.new_note_hashes + ); + let sorted = sort_get_sorted_hints( + new_note_hashes, + |a: NoteHash, b: NoteHash| a.counter() < b.counter() + ); + let sorted_note_hashes = sorted.sorted_array.map(|note_hash: NoteHash| note_hash.value); + let sorted_note_hashes_indexes = sorted.sorted_index_hints; + + // Proceed as normal let combined = CombinedAccumulatedData::combine( previous_kernel.public_inputs.end_non_revertible, previous_kernel.public_inputs.end @@ -324,6 +348,13 @@ mod tests { let sorted_public_data_update_requests = sorted.sorted_array; let sorted_public_data_update_requests_indexes = sorted.sorted_index_hints; + let combine_hints = PublicKernelTailCombineHints { + sorted_note_hashes, + sorted_note_hashes_indexes, + sorted_public_data_update_requests, + sorted_public_data_update_requests_indexes + }; + let kernel = PublicKernelTailCircuitPrivateInputs { previous_kernel, nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), @@ -331,8 +362,7 @@ mod tests { public_data_hints: self.public_data_hints.storage, public_data_read_request_hints: self.public_data_read_request_hints_builder.to_hints(), start_state: self.start_state, - sorted_public_data_update_requests, - sorted_public_data_update_requests_indexes + combine_hints }; kernel.public_kernel_tail() diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr index 951c70283ba..736b3f79047 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr @@ -548,23 +548,32 @@ mod tests { } #[test] - unconstrained fn correctly_updates_revert_code() { + unconstrained fn correctly_updates_revert_code_0() { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); let public_inputs = builder.execute(); assert_eq(public_inputs.revert_code, 0); + } + #[test] + unconstrained fn correctly_updates_revert_code_1() { // Case where we carry forward a revert code from app logic let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); builder.previous_kernel.revert_code = 1; let public_inputs = builder.execute(); assert_eq(public_inputs.revert_code, 1); + } + #[test] + unconstrained fn correctly_updates_revert_code_2() { // Case where there is a new error in teardown let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); builder.public_call.public_inputs.revert_code = 1; let public_inputs = builder.execute(); assert_eq(public_inputs.revert_code, 2); + } + #[test] + unconstrained fn correctly_updates_revert_code_3() { // Case where there is an error in both app logic and teardown let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); builder.previous_kernel.revert_code = 1; diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts index 4be538347a4..8ea7f8c7c62 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts @@ -14,13 +14,14 @@ import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, } from '../../constants.gen.js'; -import { mergeAccumulatedData } from '../../utils/index.js'; +import { mergeAccumulatedData, sortByCounterGetSortedHints } from '../../utils/index.js'; import { CallRequest } from '../call_request.js'; import { RevertCode } from '../revert_code.js'; import { ValidationRequests } from '../validation_requests.js'; import { CombinedAccumulatedData } from './combined_accumulated_data.js'; import { CombinedConstantData } from './combined_constant_data.js'; import { PublicAccumulatedData } from './public_accumulated_data.js'; +import { PublicKernelTailCombineHints } from './public_kernel_tail_circuit_private_inputs.js'; /** * Outputs from the public kernel circuits. @@ -94,9 +95,25 @@ export class PublicKernelCircuitPublicInputs { return !this.publicTeardownCallStack[0].isEmpty(); } - recombineAccumulatedData(): CombinedAccumulatedData { - const newNoteHashes: Tuple = mapTuple( - mergeAccumulatedData(this.endNonRevertibleData.newNoteHashes, this.end.newNoteHashes, MAX_NEW_NOTE_HASHES_PER_TX), + combineAndSortAccumulatedData(): { + data: CombinedAccumulatedData; + hints: PublicKernelTailCombineHints; + } { + const mergedNoteHashes = mergeAccumulatedData( + this.endNonRevertibleData.newNoteHashes, + this.end.newNoteHashes, + MAX_NEW_NOTE_HASHES_PER_TX, + ); + + const newNoteHashes = mapTuple(mergedNoteHashes, n => n.value); + + const [sortedNoteHashesObjects, sortedNoteHashesIndexes] = sortByCounterGetSortedHints( + mergedNoteHashes, + MAX_NEW_NOTE_HASHES_PER_TX, + ); + + const sortedNoteHashes: Tuple = mapTuple( + sortedNoteHashesObjects, n => n.value, ); @@ -139,9 +156,14 @@ export class PublicKernelCircuitPublicInputs { MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); + const [sortedPublicDataUpdateRequests, sortedPublicDataUpdateRequestsIndexes] = sortByCounterGetSortedHints( + publicDataUpdateRequests, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + const gasUsed = this.endNonRevertibleData.gasUsed.add(this.end.gasUsed); - return CombinedAccumulatedData.from({ + const data = CombinedAccumulatedData.from({ newNoteHashes, newNullifiers, newL2ToL1Msgs, @@ -151,9 +173,21 @@ export class PublicKernelCircuitPublicInputs { encryptedLogPreimagesLength, unencryptedLogsHash: unencryptedLogHashes[0].value, unencryptedLogPreimagesLength, - publicDataUpdateRequests: publicDataUpdateRequests, + publicDataUpdateRequests: sortedPublicDataUpdateRequests, gasUsed, }); + + const hints = PublicKernelTailCombineHints.from({ + sortedNoteHashes, + sortedNoteHashesIndexes, + sortedPublicDataUpdateRequests, + sortedPublicDataUpdateRequestsIndexes, + }); + + return { + data, + hints, + }; } /** diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts index 84637a0e8f0..e3560e4fc6c 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts @@ -1,6 +1,9 @@ +import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; import { + MAX_NEW_NOTE_HASHES_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -16,6 +19,45 @@ import { PublicDataUpdateRequest } from '../public_data_update_request.js'; import { type NullifierReadRequestHints, nullifierReadRequestHintsFromBuffer } from '../read_request_hints/index.js'; import { PublicKernelData } from './public_kernel_data.js'; +export class PublicKernelTailCombineHints { + constructor( + public readonly sortedNoteHashes: Tuple, + public readonly sortedNoteHashesIndexes: Tuple, + public readonly sortedPublicDataUpdateRequests: Tuple< + PublicDataUpdateRequest, + typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + >, + public readonly sortedPublicDataUpdateRequestsIndexes: Tuple, + ) {} + + static getFields(fields: FieldsOf) { + return [ + fields.sortedNoteHashes, + fields.sortedNoteHashesIndexes, + fields.sortedPublicDataUpdateRequests, + fields.sortedPublicDataUpdateRequestsIndexes, + ] as const; + } + + static from(fields: FieldsOf): PublicKernelTailCombineHints { + return new PublicKernelTailCombineHints(...PublicKernelTailCombineHints.getFields(fields)); + } + + toBuffer() { + return serializeToBuffer(...PublicKernelTailCombineHints.getFields(this)); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicKernelTailCombineHints( + reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, Fr), + reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), + reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), + reader.readNumbers(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), + ); + } +} + export class PublicKernelTailCircuitPrivateInputs { constructor( /** @@ -36,11 +78,7 @@ export class PublicKernelTailCircuitPrivateInputs { public readonly publicDataHints: Tuple, public readonly publicDataReadRequestHints: PublicDataReadRequestHints, public readonly startState: PartialStateReference, - public readonly sortedPublicDataUpdateRequests: Tuple< - PublicDataUpdateRequest, - typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX - >, - public readonly sortedPublicDataUpdateRequestsIndexes: Tuple, + public readonly combineHints: PublicKernelTailCombineHints, ) {} toBuffer() { @@ -51,8 +89,7 @@ export class PublicKernelTailCircuitPrivateInputs { this.publicDataHints, this.publicDataReadRequestHints, this.startState, - this.sortedPublicDataUpdateRequests, - this.sortedPublicDataUpdateRequestsIndexes, + this.combineHints, ); } @@ -77,8 +114,7 @@ export class PublicKernelTailCircuitPrivateInputs { reader.readArray(MAX_PUBLIC_DATA_HINTS, PublicDataHint), reader.readObject(PublicDataReadRequestHints), reader.readObject(PartialStateReference), - reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), - reader.readNumbers(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), + reader.readObject(PublicKernelTailCombineHints), ); } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 8d0467e3738..673d1265fc8 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -110,6 +110,7 @@ import { PublicKernelCircuitPublicInputs, PublicKernelData, PublicKernelTailCircuitPrivateInputs, + PublicKernelTailCombineHints, RECURSIVE_PROOF_LENGTH, ROLLUP_VK_TREE_HEIGHT, ReadRequest, @@ -669,6 +670,19 @@ export function makePublicKernelCircuitPrivateInputs(seed = 1): PublicKernelCirc return new PublicKernelCircuitPrivateInputs(makePublicKernelData(seed), makePublicCallData(seed + 0x1000)); } +export function makePublicKernelTailCombineHints(seed = 1): PublicKernelTailCombineHints { + return PublicKernelTailCombineHints.from({ + sortedNoteHashes: makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, fr, seed + 0x100), + sortedNoteHashesIndexes: makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, i => i, seed + 0x200), + sortedPublicDataUpdateRequests: makeTuple( + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + makePublicDataUpdateRequest, + seed + 0x300, + ), + sortedPublicDataUpdateRequestsIndexes: makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, i => i, seed + 0x400), + }); +} + /** * Makes arbitrary public kernel tail inputs. * @param seed - The seed to use for generating the public kernel inputs. @@ -682,8 +696,7 @@ export function makePublicKernelTailCircuitPrivateInputs(seed = 1): PublicKernel makeTuple(MAX_PUBLIC_DATA_HINTS, PublicDataHint.empty, seed + 0x100), PublicDataReadRequestHintsBuilder.empty(), makePartialStateReference(seed + 0x200), - makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataUpdateRequest, seed + 0x300), - makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, i => i, seed + 0x400), + makePublicKernelTailCombineHints(seed + 0x300), ); } 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 d4cdc71d210..b9b73ab6bb3 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -101,6 +101,7 @@ import { PublicKernelCircuitPublicInputs, type PublicKernelData, type PublicKernelTailCircuitPrivateInputs, + type PublicKernelTailCombineHints, type RECURSIVE_PROOF_LENGTH, ReadRequest, type ReadRequestStatus, @@ -216,6 +217,7 @@ import type { PublicKernelData as PublicKernelDataNoir, PublicKernelSetupCircuitPrivateInputs as PublicKernelSetupCircuitPrivateInputsNoir, PublicKernelTailCircuitPrivateInputs as PublicKernelTailCircuitPrivateInputsNoir, + PublicKernelTailCombineHints as PublicKernelTailCombineHintsNoir, ReadRequest as ReadRequestNoir, ReadRequestStatus as ReadRequestStatusNoir, RollupValidationRequests as RollupValidationRequestsNoir, @@ -1754,6 +1756,23 @@ export function mapPublicKernelCircuitPrivateInputsToNoir( }; } +export function mapPublicKernelTailCombineHintsToNoir( + combineHints: PublicKernelTailCombineHints, +): PublicKernelTailCombineHintsNoir { + return { + sorted_note_hashes: mapTuple(combineHints.sortedNoteHashes, mapFieldToNoir), + sorted_note_hashes_indexes: mapTuple(combineHints.sortedNoteHashesIndexes, mapNumberToNoir), + sorted_public_data_update_requests: mapTuple( + combineHints.sortedPublicDataUpdateRequests, + mapPublicDataUpdateRequestToNoir, + ), + sorted_public_data_update_requests_indexes: mapTuple( + combineHints.sortedPublicDataUpdateRequestsIndexes, + mapNumberToNoir, + ), + }; +} + export function mapPublicKernelTailCircuitPrivateInputsToNoir( inputs: PublicKernelTailCircuitPrivateInputs, ): PublicKernelTailCircuitPrivateInputsNoir { @@ -1766,11 +1785,7 @@ export function mapPublicKernelTailCircuitPrivateInputsToNoir( public_data_hints: mapTuple(inputs.publicDataHints, mapPublicDataHintToNoir), public_data_read_request_hints: mapPublicDataReadRequestHintsToNoir(inputs.publicDataReadRequestHints), start_state: mapPartialStateReferenceToNoir(inputs.startState), - sorted_public_data_update_requests: mapTuple( - inputs.sortedPublicDataUpdateRequests, - mapPublicDataUpdateRequestToNoir, - ), - sorted_public_data_update_requests_indexes: mapTuple(inputs.sortedPublicDataUpdateRequestsIndexes, mapNumberToNoir), + combine_hints: mapPublicKernelTailCombineHintsToNoir(inputs.combineHints), }; } diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 2661d7242d7..24f682ecbce 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -138,6 +138,7 @@ export class AvmPersistableStateManager { * @param value - the value being written to the slot */ public writeStorage(storageAddress: Fr, slot: Fr, value: Fr) { + this.log.debug(`Storage write (address=${storageAddress}, slot=${slot}): value=${value}`); // Cache storage writes for later reference/reads this.publicStorage.write(storageAddress, slot, value); diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index 8e8c7f63aa1..9fd0c217eec 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -1,20 +1,16 @@ import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types'; import { - type Fr, type GlobalVariables, type Header, type KernelCircuitPublicInputs, type LogHash, - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, type MAX_UNENCRYPTED_LOGS_PER_TX, - type NoteHash, type PublicKernelCircuitPublicInputs, PublicKernelTailCircuitPrivateInputs, mergeAccumulatedData, sortByCounter, - sortByCounterGetSortedHints, } from '@aztec/circuits.js'; import { type Tuple } from '@aztec/foundation/serialize'; import { type PublicExecutor, type PublicStateDB } from '@aztec/simulator'; @@ -78,14 +74,6 @@ export class TailPhaseManager extends AbstractPhaseManager { ); const [inputs, output] = await this.simulate(previousOutput); - // Temporary hack. Should sort them in the tail circuit. - const noteHashes = mergeAccumulatedData( - previousOutput.endNonRevertibleData.newNoteHashes, - previousOutput.end.newNoteHashes, - MAX_NEW_NOTE_HASHES_PER_TX, - ); - output.end.newNoteHashes = this.sortNoteHashes(noteHashes); - return [inputs, output]; } @@ -137,12 +125,7 @@ export class TailPhaseManager extends AbstractPhaseManager { const currentState = await this.db.getStateReference(); - const combinedData = previousKernel.publicInputs.recombineAccumulatedData(); - - const [sortedPublicDataUpdateRequests, sortedPublicDataUpdateRequestsIndexes] = sortByCounterGetSortedHints( - combinedData.publicDataUpdateRequests, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - ); + const { hints } = previousKernel.publicInputs.combineAndSortAccumulatedData(); return new PublicKernelTailCircuitPrivateInputs( previousKernel, @@ -151,17 +134,11 @@ export class TailPhaseManager extends AbstractPhaseManager { publicDataHints, publicDataReadRequestHints, currentState.partial, - sortedPublicDataUpdateRequests, - sortedPublicDataUpdateRequestsIndexes, + hints, ); } - private sortNoteHashes(noteHashes: Tuple): Tuple { - return sortByCounter(noteHashes).map(n => n.value) as Tuple; - } - private sortLogsHashes(unencryptedLogsHashes: Tuple): Tuple { - // TODO(6052): logs here may have duplicate counters from nested calls return sortByCounter(unencryptedLogsHashes); } } From 3aec50dc35d094f0be76b30045988f42f32d48d5 Mon Sep 17 00:00:00 2001 From: Mitchell Tracy Date: Tue, 28 May 2024 14:42:48 +0200 Subject: [PATCH 6/9] enforce note hash ordering in kernel --- .../src/public_kernel_tail.nr | 65 ++++++------------- .../crates/types/src/abis/accumulated_data.nr | 2 +- .../combined_accumulated_data.nr | 48 +++++++++++--- yarn-project/circuits.js/src/structs/index.ts | 1 + .../src/structs/kernel/combine_hints.ts | 45 +++++++++++++ .../structs/kernel/public_accumulated_data.ts | 2 +- .../public_kernel_circuit_public_inputs.ts | 13 ++-- ...blic_kernel_tail_circuit_private_inputs.ts | 54 ++------------- .../circuits.js/src/tests/factories.ts | 10 +-- .../src/type_conversion.ts | 12 ++-- 10 files changed, 125 insertions(+), 127 deletions(-) create mode 100644 yarn-project/circuits.js/src/structs/kernel/combine_hints.ts diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index cac175b6996..df3e2a9d43f 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -5,9 +5,9 @@ use dep::reset_kernel_lib::{ }; use dep::types::{ abis::{ - accumulated_data::CombinedAccumulatedData, kernel_circuit_public_inputs::KernelCircuitPublicInputs, - public_kernel_data::PublicKernelData, public_data_update_request::PublicDataUpdateRequest, - side_effect::Ordered + accumulated_data::{CombinedAccumulatedData, CombineHints}, + kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData, + public_data_update_request::PublicDataUpdateRequest, side_effect::Ordered }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_PUBLIC_DATA_HINTS, MAX_NULLIFIER_READ_REQUESTS_PER_TX, @@ -19,17 +19,6 @@ use dep::types::{ utils::{arrays::{array_length, assert_sorted_array}}, address::AztecAddress }; -fn asc_sort_by_counters(a: T, b: T) -> bool where T: Ordered { - a.counter() < b.counter() -} - -struct PublicKernelTailCombineHints { - sorted_note_hashes: [Field; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - sorted_public_data_update_requests_indexes: [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], -} - struct PublicKernelTailCircuitPrivateInputs { previous_kernel: PublicKernelData, nullifier_read_request_hints: NullifierReadRequestHints, @@ -37,7 +26,7 @@ struct PublicKernelTailCircuitPrivateInputs { public_data_hints: [PublicDataHint; MAX_PUBLIC_DATA_HINTS], public_data_read_request_hints: PublicDataReadRequestHints, start_state: PartialStateReference, - combine_hints: PublicKernelTailCombineHints + combine_hints: CombineHints } impl PublicKernelTailCircuitPrivateInputs { @@ -63,22 +52,11 @@ impl PublicKernelTailCircuitPrivateInputs { fn propagate_accumulated_data(self) -> CombinedAccumulatedData { let previous_public_inputs = self.previous_kernel.public_inputs; - // TODO: Sort the combined data. - let mut data = CombinedAccumulatedData::combine( + CombinedAccumulatedData::combine( previous_public_inputs.end_non_revertible, - previous_public_inputs.end - ); - - assert_sorted_array( - data.public_data_update_requests, - self.combine_hints.sorted_public_data_update_requests, - self.combine_hints.sorted_public_data_update_requests_indexes, - asc_sort_by_counters - ); - - data.public_data_update_requests = self.combine_hints.sorted_public_data_update_requests; - - data + previous_public_inputs.end, + self.combine_hints + ) } pub fn public_kernel_tail(self) -> KernelCircuitPublicInputs { @@ -114,7 +92,7 @@ impl PublicKernelTailCircuitPrivateInputs { } mod tests { - use crate::public_kernel_tail::{PublicKernelTailCircuitPrivateInputs, PublicKernelTailCombineHints}; + use crate::public_kernel_tail::PublicKernelTailCircuitPrivateInputs; use dep::reset_kernel_lib::{ tests::{ nullifier_non_existent_read_request_hints_builder::NullifierNonExistentReadRequestHintsBuilder, @@ -127,8 +105,8 @@ mod tests { abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData, nullifier::ScopedNullifier, nullifier_leaf_preimage::NullifierLeafPreimage, - accumulated_data::CombinedAccumulatedData, public_data_update_request::PublicDataUpdateRequest, - note_hash::NoteHash + accumulated_data::{CombinedAccumulatedData, CombineHints}, + public_data_update_request::PublicDataUpdateRequest, note_hash::NoteHash }, address::AztecAddress, constants::{ @@ -324,31 +302,26 @@ mod tests { // Note: note hashes are a bit odd here: whereas we'd like to use `combined` and then // sort the result, we cannot because we lose the side effect counters when we combine. - let new_note_hashes = array_merge( + let merged = array_merge( previous_kernel.public_inputs.end_non_revertible.new_note_hashes, previous_kernel.public_inputs.end.new_note_hashes ); - let sorted = sort_get_sorted_hints( - new_note_hashes, - |a: NoteHash, b: NoteHash| a.counter() < b.counter() - ); - let sorted_note_hashes = sorted.sorted_array.map(|note_hash: NoteHash| note_hash.value); + let sorted = sort_get_sorted_hints(merged, |a: NoteHash, b: NoteHash| a.counter() < b.counter()); + let sorted_note_hashes = sorted.sorted_array; let sorted_note_hashes_indexes = sorted.sorted_index_hints; - // Proceed as normal - let combined = CombinedAccumulatedData::combine( - previous_kernel.public_inputs.end_non_revertible, - previous_kernel.public_inputs.end + let merged = array_merge( + previous_kernel.public_inputs.end_non_revertible.public_data_update_requests, + previous_kernel.public_inputs.end.public_data_update_requests ); - let sorted = sort_get_sorted_hints( - combined.public_data_update_requests, + merged, |a: PublicDataUpdateRequest, b: PublicDataUpdateRequest| a.counter() < b.counter() ); let sorted_public_data_update_requests = sorted.sorted_array; let sorted_public_data_update_requests_indexes = sorted.sorted_index_hints; - let combine_hints = PublicKernelTailCombineHints { + let combine_hints = CombineHints { sorted_note_hashes, sorted_note_hashes_indexes, sorted_public_data_update_requests, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data.nr index 2e8ec3cef79..7159c14a363 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data.nr @@ -5,7 +5,7 @@ mod public_accumulated_data; mod public_accumulated_data_builder; use crate::abis::accumulated_data::{ - combined_accumulated_data::CombinedAccumulatedData, + combined_accumulated_data::CombinedAccumulatedData, combined_accumulated_data::CombineHints, private_accumulated_data::PrivateAccumulatedData, private_accumulated_data_builder::PrivateAccumulatedDataBuilder, public_accumulated_data::PublicAccumulatedData, 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 c8c869e53ce..f449f542c11 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,15 +3,23 @@ use crate::{ abis::{ accumulated_data::public_accumulated_data::PublicAccumulatedData, note_hash::NoteHash, nullifier::Nullifier, public_data_update_request::PublicDataUpdateRequest, - log_hash::{LogHash, NoteLogHash}, gas::Gas + log_hash::{LogHash, NoteLogHash}, gas::Gas, side_effect::Ordered }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, COMBINED_ACCUMULATED_DATA_LENGTH }, - utils::{arrays::array_merge, reader::Reader}, traits::{Empty, Serialize, Deserialize} + utils::{arrays::{array_merge, assert_sorted_array}, reader::Reader}, + traits::{Empty, Serialize, Deserialize} }; +struct CombineHints { + sorted_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + sorted_public_data_update_requests_indexes: [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], +} + struct CombinedAccumulatedData { new_note_hashes: [Field; MAX_NEW_NOTE_HASHES_PER_TX], new_nullifiers: [Field; MAX_NEW_NULLIFIERS_PER_TX], @@ -32,8 +40,35 @@ struct CombinedAccumulatedData { gas_used: Gas, } +fn asc_sort_by_counters(a: T, b: T) -> bool where T: Ordered { + a.counter() < b.counter() +} + impl CombinedAccumulatedData { - pub fn combine(non_revertible: PublicAccumulatedData, revertible: PublicAccumulatedData) -> Self { + pub fn combine( + non_revertible: PublicAccumulatedData, + revertible: PublicAccumulatedData, + combine_hints: CombineHints + ) -> Self { + let merged_note_hashes = array_merge(non_revertible.new_note_hashes, revertible.new_note_hashes); + assert_sorted_array( + merged_note_hashes, + combine_hints.sorted_note_hashes, + combine_hints.sorted_note_hashes_indexes, + asc_sort_by_counters + ); + + let merged_public_data_update_requests = array_merge( + non_revertible.public_data_update_requests, + revertible.public_data_update_requests + ); + assert_sorted_array( + merged_public_data_update_requests, + combine_hints.sorted_public_data_update_requests, + combine_hints.sorted_public_data_update_requests_indexes, + asc_sort_by_counters + ); + // TODO(Miranda): Hash here or elsewhere? let note_encrypted_logs_hash = compute_tx_note_logs_hash( array_merge( @@ -60,7 +95,7 @@ impl CombinedAccumulatedData { let unencrypted_log_preimages_length = non_revertible.unencrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length) + revertible.unencrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length); CombinedAccumulatedData { - new_note_hashes: array_merge(non_revertible.new_note_hashes, revertible.new_note_hashes).map(|n: NoteHash| n.value), + new_note_hashes: combine_hints.sorted_note_hashes.map(|n: NoteHash| n.value), new_nullifiers: array_merge(non_revertible.new_nullifiers, revertible.new_nullifiers).map(|n: Nullifier| n.value), new_l2_to_l1_msgs: array_merge( non_revertible.new_l2_to_l1_msgs, @@ -72,10 +107,7 @@ impl CombinedAccumulatedData { note_encrypted_log_preimages_length, encrypted_log_preimages_length, unencrypted_log_preimages_length, - public_data_update_requests: array_merge( - non_revertible.public_data_update_requests, - revertible.public_data_update_requests - ), + public_data_update_requests: combine_hints.sorted_public_data_update_requests, gas_used: revertible.gas_used + non_revertible.gas_used } } diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 96ca0032582..d30c2454a87 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -14,6 +14,7 @@ export * from './gas_fees.js'; export * from './gas_settings.js'; export * from './global_variables.js'; export * from './header.js'; +export * from './kernel/combine_hints.js'; export * from './kernel/combined_accumulated_data.js'; export * from './kernel/combined_constant_data.js'; export * from './kernel/kernel_circuit_public_inputs.js'; diff --git a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts new file mode 100644 index 00000000000..ea3a39c4d7d --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts @@ -0,0 +1,45 @@ +import { type FieldsOf } from '@aztec/foundation/array'; +import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX } from '../../constants.gen.js'; +import { NoteHash } from '../note_hash.js'; +import { PublicDataUpdateRequest } from '../public_data_update_request.js'; + +export class CombineHints { + constructor( + public readonly sortedNoteHashes: Tuple, + public readonly sortedNoteHashesIndexes: Tuple, + public readonly sortedPublicDataUpdateRequests: Tuple< + PublicDataUpdateRequest, + typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + >, + public readonly sortedPublicDataUpdateRequestsIndexes: Tuple, + ) {} + + static getFields(fields: FieldsOf) { + return [ + fields.sortedNoteHashes, + fields.sortedNoteHashesIndexes, + fields.sortedPublicDataUpdateRequests, + fields.sortedPublicDataUpdateRequestsIndexes, + ] as const; + } + + static from(fields: FieldsOf): CombineHints { + return new CombineHints(...CombineHints.getFields(fields)); + } + + toBuffer() { + return serializeToBuffer(...CombineHints.getFields(this)); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new CombineHints( + reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHash), + reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), + reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), + reader.readNumbers(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), + ); + } +} diff --git a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts index 8337cc01a48..ec4109cc211 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts @@ -27,7 +27,7 @@ export class PublicAccumulatedData { /** * The new note hashes made in this transaction. */ - public newNoteHashes: Tuple, + public readonly newNoteHashes: Tuple, /** * The new nullifiers made in this transaction. */ diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts index 8ea7f8c7c62..6973a4013f3 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts @@ -18,10 +18,10 @@ import { mergeAccumulatedData, sortByCounterGetSortedHints } from '../../utils/i import { CallRequest } from '../call_request.js'; import { RevertCode } from '../revert_code.js'; import { ValidationRequests } from '../validation_requests.js'; +import { CombineHints } from './combine_hints.js'; import { CombinedAccumulatedData } from './combined_accumulated_data.js'; import { CombinedConstantData } from './combined_constant_data.js'; import { PublicAccumulatedData } from './public_accumulated_data.js'; -import { PublicKernelTailCombineHints } from './public_kernel_tail_circuit_private_inputs.js'; /** * Outputs from the public kernel circuits. @@ -97,7 +97,7 @@ export class PublicKernelCircuitPublicInputs { combineAndSortAccumulatedData(): { data: CombinedAccumulatedData; - hints: PublicKernelTailCombineHints; + hints: CombineHints; } { const mergedNoteHashes = mergeAccumulatedData( this.endNonRevertibleData.newNoteHashes, @@ -107,16 +107,11 @@ export class PublicKernelCircuitPublicInputs { const newNoteHashes = mapTuple(mergedNoteHashes, n => n.value); - const [sortedNoteHashesObjects, sortedNoteHashesIndexes] = sortByCounterGetSortedHints( + const [sortedNoteHashes, sortedNoteHashesIndexes] = sortByCounterGetSortedHints( mergedNoteHashes, MAX_NEW_NOTE_HASHES_PER_TX, ); - const sortedNoteHashes: Tuple = mapTuple( - sortedNoteHashesObjects, - n => n.value, - ); - const newNullifiers: Tuple = mapTuple( mergeAccumulatedData(this.endNonRevertibleData.newNullifiers, this.end.newNullifiers, MAX_NEW_NOTE_HASHES_PER_TX), n => n.value, @@ -177,7 +172,7 @@ export class PublicKernelCircuitPublicInputs { gasUsed, }); - const hints = PublicKernelTailCombineHints.from({ + const hints = CombineHints.from({ sortedNoteHashes, sortedNoteHashesIndexes, sortedPublicDataUpdateRequests, diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts index e3560e4fc6c..639296898f1 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts @@ -1,13 +1,6 @@ -import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { type FieldsOf } from '@aztec/foundation/types'; -import { - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_HINTS, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, -} from '../../constants.gen.js'; +import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS } from '../../constants.gen.js'; import { type NullifierNonExistentReadRequestHints, nullifierNonExistentReadRequestHintsFromBuffer, @@ -15,49 +8,10 @@ import { import { PartialStateReference } from '../partial_state_reference.js'; import { PublicDataHint } from '../public_data_hint.js'; import { PublicDataReadRequestHints } from '../public_data_read_request_hints.js'; -import { PublicDataUpdateRequest } from '../public_data_update_request.js'; import { type NullifierReadRequestHints, nullifierReadRequestHintsFromBuffer } from '../read_request_hints/index.js'; +import { CombineHints } from './combine_hints.js'; import { PublicKernelData } from './public_kernel_data.js'; -export class PublicKernelTailCombineHints { - constructor( - public readonly sortedNoteHashes: Tuple, - public readonly sortedNoteHashesIndexes: Tuple, - public readonly sortedPublicDataUpdateRequests: Tuple< - PublicDataUpdateRequest, - typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX - >, - public readonly sortedPublicDataUpdateRequestsIndexes: Tuple, - ) {} - - static getFields(fields: FieldsOf) { - return [ - fields.sortedNoteHashes, - fields.sortedNoteHashesIndexes, - fields.sortedPublicDataUpdateRequests, - fields.sortedPublicDataUpdateRequestsIndexes, - ] as const; - } - - static from(fields: FieldsOf): PublicKernelTailCombineHints { - return new PublicKernelTailCombineHints(...PublicKernelTailCombineHints.getFields(fields)); - } - - toBuffer() { - return serializeToBuffer(...PublicKernelTailCombineHints.getFields(this)); - } - - static fromBuffer(buffer: Buffer | BufferReader) { - const reader = BufferReader.asReader(buffer); - return new PublicKernelTailCombineHints( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, Fr), - reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), - reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), - reader.readNumbers(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), - ); - } -} - export class PublicKernelTailCircuitPrivateInputs { constructor( /** @@ -78,7 +32,7 @@ export class PublicKernelTailCircuitPrivateInputs { public readonly publicDataHints: Tuple, public readonly publicDataReadRequestHints: PublicDataReadRequestHints, public readonly startState: PartialStateReference, - public readonly combineHints: PublicKernelTailCombineHints, + public readonly combineHints: CombineHints, ) {} toBuffer() { @@ -114,7 +68,7 @@ export class PublicKernelTailCircuitPrivateInputs { reader.readArray(MAX_PUBLIC_DATA_HINTS, PublicDataHint), reader.readObject(PublicDataReadRequestHints), reader.readObject(PartialStateReference), - reader.readObject(PublicKernelTailCombineHints), + reader.readObject(CombineHints), ); } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 673d1265fc8..64be423aa2b 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -21,6 +21,7 @@ import { CallContext, CallRequest, CallerContext, + CombineHints, CombinedAccumulatedData, CombinedConstantData, ConstantRollupData, @@ -110,7 +111,6 @@ import { PublicKernelCircuitPublicInputs, PublicKernelData, PublicKernelTailCircuitPrivateInputs, - PublicKernelTailCombineHints, RECURSIVE_PROOF_LENGTH, ROLLUP_VK_TREE_HEIGHT, ReadRequest, @@ -670,9 +670,9 @@ export function makePublicKernelCircuitPrivateInputs(seed = 1): PublicKernelCirc return new PublicKernelCircuitPrivateInputs(makePublicKernelData(seed), makePublicCallData(seed + 0x1000)); } -export function makePublicKernelTailCombineHints(seed = 1): PublicKernelTailCombineHints { - return PublicKernelTailCombineHints.from({ - sortedNoteHashes: makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, fr, seed + 0x100), +export function makeCombineHints(seed = 1): CombineHints { + return CombineHints.from({ + sortedNoteHashes: makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, makeNoteHash, seed + 0x100), sortedNoteHashesIndexes: makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, i => i, seed + 0x200), sortedPublicDataUpdateRequests: makeTuple( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -696,7 +696,7 @@ export function makePublicKernelTailCircuitPrivateInputs(seed = 1): PublicKernel makeTuple(MAX_PUBLIC_DATA_HINTS, PublicDataHint.empty, seed + 0x100), PublicDataReadRequestHintsBuilder.empty(), makePartialStateReference(seed + 0x200), - makePublicKernelTailCombineHints(seed + 0x300), + makeCombineHints(seed + 0x300), ); } 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 b9b73ab6bb3..1041a979a2f 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -7,6 +7,7 @@ import { CallContext, CallRequest, CallerContext, + type CombineHints, CombinedAccumulatedData, CombinedConstantData, ConstantRollupData, @@ -101,7 +102,6 @@ import { PublicKernelCircuitPublicInputs, type PublicKernelData, type PublicKernelTailCircuitPrivateInputs, - type PublicKernelTailCombineHints, type RECURSIVE_PROOF_LENGTH, ReadRequest, type ReadRequestStatus, @@ -139,6 +139,7 @@ import type { CallContext as CallContextNoir, CallRequest as CallRequestNoir, CallerContext as CallerContextNoir, + CombineHints as CombineHintsNoir, CombinedAccumulatedData as CombinedAccumulatedDataNoir, CombinedConstantData as CombinedConstantDataNoir, ConstantRollupData as ConstantRollupDataNoir, @@ -217,7 +218,6 @@ import type { PublicKernelData as PublicKernelDataNoir, PublicKernelSetupCircuitPrivateInputs as PublicKernelSetupCircuitPrivateInputsNoir, PublicKernelTailCircuitPrivateInputs as PublicKernelTailCircuitPrivateInputsNoir, - PublicKernelTailCombineHints as PublicKernelTailCombineHintsNoir, ReadRequest as ReadRequestNoir, ReadRequestStatus as ReadRequestStatusNoir, RollupValidationRequests as RollupValidationRequestsNoir, @@ -1756,11 +1756,9 @@ export function mapPublicKernelCircuitPrivateInputsToNoir( }; } -export function mapPublicKernelTailCombineHintsToNoir( - combineHints: PublicKernelTailCombineHints, -): PublicKernelTailCombineHintsNoir { +export function mapCombineHintsToNoir(combineHints: CombineHints): CombineHintsNoir { return { - sorted_note_hashes: mapTuple(combineHints.sortedNoteHashes, mapFieldToNoir), + sorted_note_hashes: mapTuple(combineHints.sortedNoteHashes, mapNoteHashToNoir), sorted_note_hashes_indexes: mapTuple(combineHints.sortedNoteHashesIndexes, mapNumberToNoir), sorted_public_data_update_requests: mapTuple( combineHints.sortedPublicDataUpdateRequests, @@ -1785,7 +1783,7 @@ export function mapPublicKernelTailCircuitPrivateInputsToNoir( public_data_hints: mapTuple(inputs.publicDataHints, mapPublicDataHintToNoir), public_data_read_request_hints: mapPublicDataReadRequestHintsToNoir(inputs.publicDataReadRequestHints), start_state: mapPartialStateReferenceToNoir(inputs.startState), - combine_hints: mapPublicKernelTailCombineHintsToNoir(inputs.combineHints), + combine_hints: mapCombineHintsToNoir(inputs.combineHints), }; } From dca09cefa9b6ec95b811a25e301b9f6b001cb9fc Mon Sep 17 00:00:00 2001 From: Mitchell Tracy Date: Tue, 28 May 2024 16:07:31 +0200 Subject: [PATCH 7/9] sort the unencrypted log hashes --- .../src/public_kernel_tail.nr | 12 +++++++++- .../combined_accumulated_data.nr | 22 ++++++++++++++----- .../src/structs/kernel/combine_hints.ts | 13 ++++++++++- .../structs/kernel/public_accumulated_data.ts | 2 +- .../public_kernel_circuit_public_inputs.ts | 7 ++++++ .../circuits.js/src/tests/factories.ts | 2 ++ .../src/type_conversion.ts | 2 ++ .../src/public/tail_phase_manager.ts | 22 +------------------ 8 files changed, 52 insertions(+), 30 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index df3e2a9d43f..4ac1172442d 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -106,7 +106,7 @@ mod tests { kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData, nullifier::ScopedNullifier, nullifier_leaf_preimage::NullifierLeafPreimage, accumulated_data::{CombinedAccumulatedData, CombineHints}, - public_data_update_request::PublicDataUpdateRequest, note_hash::NoteHash + public_data_update_request::PublicDataUpdateRequest, note_hash::NoteHash, log_hash::LogHash }, address::AztecAddress, constants::{ @@ -310,6 +310,14 @@ mod tests { let sorted_note_hashes = sorted.sorted_array; let sorted_note_hashes_indexes = sorted.sorted_index_hints; + let merged = array_merge( + previous_kernel.public_inputs.end_non_revertible.unencrypted_logs_hashes, + previous_kernel.public_inputs.end.unencrypted_logs_hashes + ); + let sorted = sort_get_sorted_hints(merged, |a: LogHash, b: LogHash| a.counter() < b.counter()); + let sorted_unencrypted_logs_hashes = sorted.sorted_array; + let sorted_unencrypted_logs_hashes_indexes = sorted.sorted_index_hints; + let merged = array_merge( previous_kernel.public_inputs.end_non_revertible.public_data_update_requests, previous_kernel.public_inputs.end.public_data_update_requests @@ -324,6 +332,8 @@ mod tests { let combine_hints = CombineHints { sorted_note_hashes, sorted_note_hashes_indexes, + sorted_unencrypted_logs_hashes, + sorted_unencrypted_logs_hashes_indexes, sorted_public_data_update_requests, sorted_public_data_update_requests_indexes }; 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 f449f542c11..a0caa79a82c 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 @@ -7,7 +7,8 @@ use crate::{ }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, COMBINED_ACCUMULATED_DATA_LENGTH + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, COMBINED_ACCUMULATED_DATA_LENGTH, + MAX_UNENCRYPTED_LOGS_PER_TX }, utils::{arrays::{array_merge, assert_sorted_array}, reader::Reader}, traits::{Empty, Serialize, Deserialize} @@ -16,6 +17,8 @@ use crate::{ struct CombineHints { sorted_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_TX], sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_logs_hashes_indexes: [u64; MAX_UNENCRYPTED_LOGS_PER_TX], sorted_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], sorted_public_data_update_requests_indexes: [u64; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], } @@ -82,12 +85,19 @@ impl CombinedAccumulatedData { revertible.encrypted_logs_hashes ) ); - let unencrypted_logs_hash = compute_tx_logs_hash( - array_merge( - non_revertible.unencrypted_logs_hashes, - revertible.unencrypted_logs_hashes - ) + + let merged_unencrypted_logs_hashes = array_merge( + non_revertible.unencrypted_logs_hashes, + revertible.unencrypted_logs_hashes ); + assert_sorted_array( + merged_unencrypted_logs_hashes, + combine_hints.sorted_unencrypted_logs_hashes, + combine_hints.sorted_unencrypted_logs_hashes_indexes, + asc_sort_by_counters + ); + let unencrypted_logs_hash = compute_tx_logs_hash(combine_hints.sorted_unencrypted_logs_hashes); + let note_encrypted_log_preimages_length = non_revertible.note_encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length) + revertible.note_encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length); let encrypted_log_preimages_length = non_revertible.encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length) diff --git a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts index ea3a39c4d7d..1c4e3fd9e68 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts @@ -1,7 +1,12 @@ import { type FieldsOf } from '@aztec/foundation/array'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX } from '../../constants.gen.js'; +import { + MAX_NEW_NOTE_HASHES_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, +} from '../../constants.gen.js'; +import { LogHash } from '../log_hash.js'; import { NoteHash } from '../note_hash.js'; import { PublicDataUpdateRequest } from '../public_data_update_request.js'; @@ -9,6 +14,8 @@ export class CombineHints { constructor( public readonly sortedNoteHashes: Tuple, public readonly sortedNoteHashesIndexes: Tuple, + public readonly sortedUnencryptedLogsHashes: Tuple, + public readonly sortedUnencryptedLogsHashesIndexes: Tuple, public readonly sortedPublicDataUpdateRequests: Tuple< PublicDataUpdateRequest, typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX @@ -20,6 +27,8 @@ export class CombineHints { return [ fields.sortedNoteHashes, fields.sortedNoteHashesIndexes, + fields.sortedUnencryptedLogsHashes, + fields.sortedUnencryptedLogsHashesIndexes, fields.sortedPublicDataUpdateRequests, fields.sortedPublicDataUpdateRequestsIndexes, ] as const; @@ -38,6 +47,8 @@ export class CombineHints { return new CombineHints( reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHash), reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), + reader.readNumbers(MAX_UNENCRYPTED_LOGS_PER_TX), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), reader.readNumbers(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), ); diff --git a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts index ec4109cc211..eb25838af82 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts @@ -50,7 +50,7 @@ export class PublicAccumulatedData { * Accumulated unencrypted logs hashes from all the previous kernel iterations. * Note: Truncated to 31 bytes to fit in Fr. */ - public unencryptedLogsHashes: Tuple, + public readonly unencryptedLogsHashes: Tuple, /** * All the public data update requests made in this transaction. */ diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts index 6973a4013f3..cbb0e1a6ea8 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts @@ -143,6 +143,11 @@ export class PublicKernelCircuitPublicInputs { MAX_ENCRYPTED_LOGS_PER_TX, ); + const [sortedUnencryptedLogsHashes, sortedUnencryptedLogsHashesIndexes] = sortByCounterGetSortedHints( + unencryptedLogHashes, + MAX_ENCRYPTED_LOGS_PER_TX, + ); + const unencryptedLogPreimagesLength = new Fr(arrayNonEmptyLength(unencryptedLogHashes, x => x.isEmpty())); const publicDataUpdateRequests = mergeAccumulatedData( @@ -175,6 +180,8 @@ export class PublicKernelCircuitPublicInputs { const hints = CombineHints.from({ sortedNoteHashes, sortedNoteHashesIndexes, + sortedUnencryptedLogsHashes, + sortedUnencryptedLogsHashesIndexes, sortedPublicDataUpdateRequests, sortedPublicDataUpdateRequestsIndexes, }); diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 64be423aa2b..4f250c417ad 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -674,6 +674,8 @@ export function makeCombineHints(seed = 1): CombineHints { return CombineHints.from({ sortedNoteHashes: makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, makeNoteHash, seed + 0x100), sortedNoteHashesIndexes: makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, i => i, seed + 0x200), + sortedUnencryptedLogsHashes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x300), + sortedUnencryptedLogsHashesIndexes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, i => i, seed + 0x400), sortedPublicDataUpdateRequests: makeTuple( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataUpdateRequest, 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 1041a979a2f..ead7212a1ca 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1760,6 +1760,8 @@ export function mapCombineHintsToNoir(combineHints: CombineHints): CombineHintsN return { sorted_note_hashes: mapTuple(combineHints.sortedNoteHashes, mapNoteHashToNoir), sorted_note_hashes_indexes: mapTuple(combineHints.sortedNoteHashesIndexes, mapNumberToNoir), + sorted_unencrypted_logs_hashes: mapTuple(combineHints.sortedUnencryptedLogsHashes, mapLogHashToNoir), + sorted_unencrypted_logs_hashes_indexes: mapTuple(combineHints.sortedUnencryptedLogsHashesIndexes, mapNumberToNoir), sorted_public_data_update_requests: mapTuple( combineHints.sortedPublicDataUpdateRequests, mapPublicDataUpdateRequestToNoir, diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index 9fd0c217eec..57d8b5de6a9 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -3,16 +3,12 @@ import { type GlobalVariables, type Header, type KernelCircuitPublicInputs, - type LogHash, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - type MAX_UNENCRYPTED_LOGS_PER_TX, type PublicKernelCircuitPublicInputs, PublicKernelTailCircuitPrivateInputs, mergeAccumulatedData, - sortByCounter, } from '@aztec/circuits.js'; -import { type Tuple } from '@aztec/foundation/serialize'; import { type PublicExecutor, type PublicStateDB } from '@aztec/simulator'; import { type MerkleTreeOperations } from '@aztec/world-state'; @@ -36,7 +32,7 @@ export class TailPhaseManager extends AbstractPhaseManager { override async handle(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs) { this.log.verbose(`Processing tx ${tx.getTxHash()}`); - const [inputs, finalKernelOutput] = await this.runTailKernelCircuit(previousPublicKernelOutput).catch( + const [inputs, finalKernelOutput] = await this.simulate(previousPublicKernelOutput).catch( // the abstract phase manager throws if simulation gives error in non-revertible phase async err => { await this.publicStateDB.rollbackToCommit(); @@ -65,18 +61,6 @@ export class TailPhaseManager extends AbstractPhaseManager { }; } - private async runTailKernelCircuit( - previousOutput: PublicKernelCircuitPublicInputs, - ): Promise<[PublicKernelTailCircuitPrivateInputs, KernelCircuitPublicInputs]> { - // Temporary hack. Should sort them in the tail circuit. - previousOutput.end.unencryptedLogsHashes = this.sortLogsHashes( - previousOutput.end.unencryptedLogsHashes, - ); - const [inputs, output] = await this.simulate(previousOutput); - - return [inputs, output]; - } - private async simulate( previousOutput: PublicKernelCircuitPublicInputs, ): Promise<[PublicKernelTailCircuitPrivateInputs, KernelCircuitPublicInputs]> { @@ -137,8 +121,4 @@ export class TailPhaseManager extends AbstractPhaseManager { hints, ); } - - private sortLogsHashes(unencryptedLogsHashes: Tuple): Tuple { - return sortByCounter(unencryptedLogsHashes); - } } From f34601a96e693b66b66ccb0bec82c3c88607c803 Mon Sep 17 00:00:00 2001 From: Mitchell Tracy Date: Tue, 28 May 2024 16:59:30 +0200 Subject: [PATCH 8/9] allow duplicate values in combine sorting. --- .../combined_accumulated_data.nr | 2 +- .../src/structs/kernel/combine_hints.ts | 64 ++++++++++ .../public_kernel_circuit_public_inputs.ts | 114 +----------------- .../circuits.js/src/structs/log_hash.ts | 6 + .../src/public/tail_phase_manager.ts | 3 +- 5 files changed, 76 insertions(+), 113 deletions(-) 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 a0caa79a82c..fb987377fdf 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 @@ -44,7 +44,7 @@ struct CombinedAccumulatedData { } fn asc_sort_by_counters(a: T, b: T) -> bool where T: Ordered { - a.counter() < b.counter() + a.counter() <= b.counter() } impl CombinedAccumulatedData { diff --git a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts index 1c4e3fd9e68..f5824e8dd0f 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts @@ -1,14 +1,20 @@ import { type FieldsOf } from '@aztec/foundation/array'; +import { removeArrayPaddingEnd } from '@aztec/foundation/collection'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { inspect } from 'util'; + import { + MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; +import { getNonEmptyItems, mergeAccumulatedData, sortByCounterGetSortedHints } from '../../utils/index.js'; import { LogHash } from '../log_hash.js'; import { NoteHash } from '../note_hash.js'; import { PublicDataUpdateRequest } from '../public_data_update_request.js'; +import { type PublicAccumulatedData } from './public_accumulated_data.js'; export class CombineHints { constructor( @@ -53,4 +59,62 @@ export class CombineHints { reader.readNumbers(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), ); } + + static fromPublicData(revertible: PublicAccumulatedData, nonRevertible: PublicAccumulatedData): CombineHints { + const mergedNoteHashes = mergeAccumulatedData( + nonRevertible.newNoteHashes, + revertible.newNoteHashes, + MAX_NEW_NOTE_HASHES_PER_TX, + ); + + const [sortedNoteHashes, sortedNoteHashesIndexes] = sortByCounterGetSortedHints( + mergedNoteHashes, + MAX_NEW_NOTE_HASHES_PER_TX, + ); + + const unencryptedLogHashes = mergeAccumulatedData( + nonRevertible.unencryptedLogsHashes, + revertible.unencryptedLogsHashes, + MAX_ENCRYPTED_LOGS_PER_TX, + ); + + const [sortedUnencryptedLogsHashes, sortedUnencryptedLogsHashesIndexes] = sortByCounterGetSortedHints( + unencryptedLogHashes, + MAX_ENCRYPTED_LOGS_PER_TX, + ); + + const publicDataUpdateRequests = mergeAccumulatedData( + nonRevertible.publicDataUpdateRequests, + revertible.publicDataUpdateRequests, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + + const [sortedPublicDataUpdateRequests, sortedPublicDataUpdateRequestsIndexes] = sortByCounterGetSortedHints( + publicDataUpdateRequests, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + + return CombineHints.from({ + sortedNoteHashes, + sortedNoteHashesIndexes, + sortedUnencryptedLogsHashes, + sortedUnencryptedLogsHashesIndexes, + sortedPublicDataUpdateRequests, + sortedPublicDataUpdateRequestsIndexes, + }); + } + + [inspect.custom](): string { + return `CombineHints { + sortedNoteHashes: ${getNonEmptyItems(this.sortedNoteHashes)}, + sortedNoteHashesIndexes: ${removeArrayPaddingEnd(this.sortedNoteHashesIndexes, n => n === 0)}, + sortedUnencryptedLogsHashes: ${getNonEmptyItems(this.sortedUnencryptedLogsHashes)}, + sortedUnencryptedLogsHashesIndexes: ${removeArrayPaddingEnd(this.sortedUnencryptedLogsHashesIndexes, n => n === 0)}, + sortedPublicDataUpdateRequests: ${getNonEmptyItems(this.sortedPublicDataUpdateRequests)}, + sortedPublicDataUpdateRequestsIndexes: ${removeArrayPaddingEnd( + this.sortedPublicDataUpdateRequestsIndexes, + n => n === 0, + )} +}`; + } } diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts index cbb0e1a6ea8..f789606f5d0 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts @@ -1,25 +1,14 @@ import { makeTuple } from '@aztec/foundation/array'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { arrayNonEmptyLength } from '@aztec/foundation/collection'; -import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, FieldReader, type Tuple, mapTuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { inspect } from 'util'; -import { - MAX_ENCRYPTED_LOGS_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, -} from '../../constants.gen.js'; -import { mergeAccumulatedData, sortByCounterGetSortedHints } from '../../utils/index.js'; +import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { RevertCode } from '../revert_code.js'; import { ValidationRequests } from '../validation_requests.js'; -import { CombineHints } from './combine_hints.js'; -import { CombinedAccumulatedData } from './combined_accumulated_data.js'; import { CombinedConstantData } from './combined_constant_data.js'; import { PublicAccumulatedData } from './public_accumulated_data.js'; @@ -95,103 +84,6 @@ export class PublicKernelCircuitPublicInputs { return !this.publicTeardownCallStack[0].isEmpty(); } - combineAndSortAccumulatedData(): { - data: CombinedAccumulatedData; - hints: CombineHints; - } { - const mergedNoteHashes = mergeAccumulatedData( - this.endNonRevertibleData.newNoteHashes, - this.end.newNoteHashes, - MAX_NEW_NOTE_HASHES_PER_TX, - ); - - const newNoteHashes = mapTuple(mergedNoteHashes, n => n.value); - - const [sortedNoteHashes, sortedNoteHashesIndexes] = sortByCounterGetSortedHints( - mergedNoteHashes, - MAX_NEW_NOTE_HASHES_PER_TX, - ); - - const newNullifiers: Tuple = mapTuple( - mergeAccumulatedData(this.endNonRevertibleData.newNullifiers, this.end.newNullifiers, MAX_NEW_NOTE_HASHES_PER_TX), - n => n.value, - ); - - const newL2ToL1Msgs = mergeAccumulatedData( - this.endNonRevertibleData.newL2ToL1Msgs, - this.end.newL2ToL1Msgs, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - ); - - const noteEncryptedLogHashes = mergeAccumulatedData( - this.endNonRevertibleData.noteEncryptedLogsHashes, - this.end.noteEncryptedLogsHashes, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - ); - const noteEncryptedLogPreimagesLength = new Fr(arrayNonEmptyLength(noteEncryptedLogHashes, x => x.isEmpty())); - - const encryptedLogHashes = mergeAccumulatedData( - this.endNonRevertibleData.encryptedLogsHashes, - this.end.encryptedLogsHashes, - MAX_ENCRYPTED_LOGS_PER_TX, - ); - const encryptedLogPreimagesLength = new Fr(arrayNonEmptyLength(encryptedLogHashes, x => x.isEmpty())); - - const unencryptedLogHashes = mergeAccumulatedData( - this.endNonRevertibleData.unencryptedLogsHashes, - this.end.unencryptedLogsHashes, - MAX_ENCRYPTED_LOGS_PER_TX, - ); - - const [sortedUnencryptedLogsHashes, sortedUnencryptedLogsHashesIndexes] = sortByCounterGetSortedHints( - unencryptedLogHashes, - MAX_ENCRYPTED_LOGS_PER_TX, - ); - - const unencryptedLogPreimagesLength = new Fr(arrayNonEmptyLength(unencryptedLogHashes, x => x.isEmpty())); - - const publicDataUpdateRequests = mergeAccumulatedData( - this.endNonRevertibleData.publicDataUpdateRequests, - this.end.publicDataUpdateRequests, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - ); - - const [sortedPublicDataUpdateRequests, sortedPublicDataUpdateRequestsIndexes] = sortByCounterGetSortedHints( - publicDataUpdateRequests, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - ); - - const gasUsed = this.endNonRevertibleData.gasUsed.add(this.end.gasUsed); - - const data = CombinedAccumulatedData.from({ - newNoteHashes, - newNullifiers, - newL2ToL1Msgs, - noteEncryptedLogsHash: noteEncryptedLogHashes[0].value, - noteEncryptedLogPreimagesLength, - encryptedLogsHash: encryptedLogHashes[0].value, - encryptedLogPreimagesLength, - unencryptedLogsHash: unencryptedLogHashes[0].value, - unencryptedLogPreimagesLength, - publicDataUpdateRequests: sortedPublicDataUpdateRequests, - gasUsed, - }); - - const hints = CombineHints.from({ - sortedNoteHashes, - sortedNoteHashesIndexes, - sortedUnencryptedLogsHashes, - sortedUnencryptedLogsHashesIndexes, - sortedPublicDataUpdateRequests, - sortedPublicDataUpdateRequestsIndexes, - }); - - return { - data, - hints, - }; - } - /** * Deserializes from a buffer or reader, corresponding to a write in cpp. * @param buffer - Buffer or reader to read from. diff --git a/yarn-project/circuits.js/src/structs/log_hash.ts b/yarn-project/circuits.js/src/structs/log_hash.ts index 7f845e69485..86105784e5c 100644 --- a/yarn-project/circuits.js/src/structs/log_hash.ts +++ b/yarn-project/circuits.js/src/structs/log_hash.ts @@ -2,6 +2,8 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { inspect } from 'util'; + import { type Ordered } from '../interfaces/index.js'; export class LogHash implements Ordered { @@ -36,6 +38,10 @@ export class LogHash implements Ordered { toString(): string { return `value=${this.value} counter=${this.counter} length=${this.length}`; } + + [inspect.custom](): string { + return `LogHash { ${this.toString()} }`; + } } export class ScopedLogHash implements Ordered { diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index 57d8b5de6a9..8f1398de0fa 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -1,5 +1,6 @@ import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types'; import { + CombineHints, type GlobalVariables, type Header, type KernelCircuitPublicInputs, @@ -109,7 +110,7 @@ export class TailPhaseManager extends AbstractPhaseManager { const currentState = await this.db.getStateReference(); - const { hints } = previousKernel.publicInputs.combineAndSortAccumulatedData(); + const hints = CombineHints.fromPublicData(endNonRevertibleData, end); return new PublicKernelTailCircuitPrivateInputs( previousKernel, From 62f78355596c99a66f18ce993ef2ec53e214aa4e Mon Sep 17 00:00:00 2001 From: Mitchell Tracy Date: Tue, 28 May 2024 21:54:55 +0200 Subject: [PATCH 9/9] force explicitness after fixing bug from mixing up non/revertible param locations --- .../src/structs/kernel/combine_hints.ts | 37 ++++++++++++------- .../src/public/tail_phase_manager.ts | 12 +++--- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts index f5824e8dd0f..6b4954f587d 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts @@ -60,10 +60,16 @@ export class CombineHints { ); } - static fromPublicData(revertible: PublicAccumulatedData, nonRevertible: PublicAccumulatedData): CombineHints { + static fromPublicData({ + revertibleData, + nonRevertibleData, + }: { + revertibleData: PublicAccumulatedData; + nonRevertibleData: PublicAccumulatedData; + }): CombineHints { const mergedNoteHashes = mergeAccumulatedData( - nonRevertible.newNoteHashes, - revertible.newNoteHashes, + nonRevertibleData.newNoteHashes, + revertibleData.newNoteHashes, MAX_NEW_NOTE_HASHES_PER_TX, ); @@ -73,8 +79,8 @@ export class CombineHints { ); const unencryptedLogHashes = mergeAccumulatedData( - nonRevertible.unencryptedLogsHashes, - revertible.unencryptedLogsHashes, + nonRevertibleData.unencryptedLogsHashes, + revertibleData.unencryptedLogsHashes, MAX_ENCRYPTED_LOGS_PER_TX, ); @@ -84,8 +90,8 @@ export class CombineHints { ); const publicDataUpdateRequests = mergeAccumulatedData( - nonRevertible.publicDataUpdateRequests, - revertible.publicDataUpdateRequests, + nonRevertibleData.publicDataUpdateRequests, + revertibleData.publicDataUpdateRequests, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); @@ -106,15 +112,18 @@ export class CombineHints { [inspect.custom](): string { return `CombineHints { - sortedNoteHashes: ${getNonEmptyItems(this.sortedNoteHashes)}, + sortedNoteHashes: ${getNonEmptyItems(this.sortedNoteHashes) + .map(h => inspect(h)) + .join(', ')}, sortedNoteHashesIndexes: ${removeArrayPaddingEnd(this.sortedNoteHashesIndexes, n => n === 0)}, - sortedUnencryptedLogsHashes: ${getNonEmptyItems(this.sortedUnencryptedLogsHashes)}, + sortedUnencryptedLogsHashes: ${getNonEmptyItems(this.sortedUnencryptedLogsHashes) + .map(h => inspect(h)) + .join(', ')}, sortedUnencryptedLogsHashesIndexes: ${removeArrayPaddingEnd(this.sortedUnencryptedLogsHashesIndexes, n => n === 0)}, - sortedPublicDataUpdateRequests: ${getNonEmptyItems(this.sortedPublicDataUpdateRequests)}, - sortedPublicDataUpdateRequestsIndexes: ${removeArrayPaddingEnd( - this.sortedPublicDataUpdateRequestsIndexes, - n => n === 0, - )} + sortedPublicDataUpdateRequests: ${getNonEmptyItems(this.sortedPublicDataUpdateRequests) + .map(h => inspect(h)) + .join(', ')}, + sortedPublicDataUpdateRequestsIndexes: ${this.sortedPublicDataUpdateRequestsIndexes} }`; } } diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index 8f1398de0fa..866c0da874f 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -73,11 +73,11 @@ export class TailPhaseManager extends AbstractPhaseManager { private async buildPrivateInputs(previousOutput: PublicKernelCircuitPublicInputs) { const previousKernel = this.getPreviousKernelData(previousOutput); - const { validationRequests, endNonRevertibleData, end } = previousOutput; + const { validationRequests, endNonRevertibleData: nonRevertibleData, end: revertibleData } = previousOutput; const pendingNullifiers = mergeAccumulatedData( - endNonRevertibleData.newNullifiers, - end.newNullifiers, + nonRevertibleData.newNullifiers, + revertibleData.newNullifiers, MAX_NEW_NULLIFIERS_PER_TX, ); @@ -92,8 +92,8 @@ export class TailPhaseManager extends AbstractPhaseManager { ); const pendingPublicDataWrites = mergeAccumulatedData( - endNonRevertibleData.publicDataUpdateRequests, - end.publicDataUpdateRequests, + nonRevertibleData.publicDataUpdateRequests, + revertibleData.publicDataUpdateRequests, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); @@ -110,7 +110,7 @@ export class TailPhaseManager extends AbstractPhaseManager { const currentState = await this.db.getStateReference(); - const hints = CombineHints.fromPublicData(endNonRevertibleData, end); + const hints = CombineHints.fromPublicData({ nonRevertibleData, revertibleData }); return new PublicKernelTailCircuitPrivateInputs( previousKernel,