diff --git a/barretenberg/cpp/pil/avm/constants_gen.pil b/barretenberg/cpp/pil/avm/constants_gen.pil index 6b2a6cb2ae5..0aa1c519355 100644 --- a/barretenberg/cpp/pil/avm/constants_gen.pil +++ b/barretenberg/cpp/pil/avm/constants_gen.pil @@ -2,7 +2,7 @@ namespace constants(256); pol MAX_NOTE_HASHES_PER_CALL = 16; pol MAX_NULLIFIERS_PER_CALL = 16; - pol MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 16; + pol MAX_ENQUEUED_CALLS_PER_CALL = 16; pol MAX_L2_TO_L1_MSGS_PER_CALL = 2; pol MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 64; pol MAX_PUBLIC_DATA_READS_PER_CALL = 64; diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index 7cee92f4f3a..d8ddcc2c605 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -3,7 +3,7 @@ #define MAX_NOTE_HASHES_PER_CALL 16 #define MAX_NULLIFIERS_PER_CALL 16 -#define MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL 16 +#define MAX_ENQUEUED_CALLS_PER_CALL 16 #define MAX_L2_TO_L1_MSGS_PER_CALL 2 #define MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL 64 #define MAX_PUBLIC_DATA_READS_PER_CALL 64 @@ -35,6 +35,7 @@ #define HEADER_LENGTH 24 #define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 866 #define PUBLIC_CONTEXT_INPUTS_LENGTH 41 +#define AVM_ACCUMULATED_DATA_LENGTH 318 #define AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS 86 #define AVM_PROOF_LENGTH_IN_FIELDS 4176 #define AVM_PUBLIC_COLUMN_MAX_SIZE 1024 diff --git a/barretenberg/cpp/src/barretenberg/vm/constants.hpp b/barretenberg/cpp/src/barretenberg/vm/constants.hpp index 7456b2ef924..fe1c0a83560 100644 --- a/barretenberg/cpp/src/barretenberg/vm/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/constants.hpp @@ -72,7 +72,7 @@ inline const uint32_t PUBLIC_CALLSTACK_PCPI_OFFSET = PUBLIC_DATA_READ_PCPI_OFFSET + (MAX_PUBLIC_DATA_READS_PER_CALL * CONTRACT_STORAGE_READ_LENGTH); inline const uint32_t NEW_NOTE_HASHES_PCPI_OFFSET = - PUBLIC_CALLSTACK_PCPI_OFFSET + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL * PUBLIC_INNER_CALL_REQUEST_LENGTH); + PUBLIC_CALLSTACK_PCPI_OFFSET + (MAX_ENQUEUED_CALLS_PER_CALL * PUBLIC_INNER_CALL_REQUEST_LENGTH); inline const uint32_t NEW_NULLIFIERS_PCPI_OFFSET = NEW_NOTE_HASHES_PCPI_OFFSET + (MAX_NOTE_HASHES_PER_CALL * NOTE_HASH_LENGTH); diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 1862d81b6b6..a717be49bca 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -19,7 +19,7 @@ library Constants { uint256 internal constant MAX_NOTE_HASHES_PER_CALL = 16; uint256 internal constant MAX_NULLIFIERS_PER_CALL = 16; uint256 internal constant MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL = 4; - uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 16; + uint256 internal constant MAX_ENQUEUED_CALLS_PER_CALL = 16; uint256 internal constant MAX_L2_TO_L1_MSGS_PER_CALL = 2; uint256 internal constant MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 64; uint256 internal constant MAX_PUBLIC_DATA_READS_PER_CALL = 64; @@ -56,7 +56,7 @@ library Constants { uint256 internal constant MAX_NOTE_HASHES_PER_TX = 64; uint256 internal constant MAX_NULLIFIERS_PER_TX = 64; uint256 internal constant MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8; - uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 32; + uint256 internal constant MAX_ENQUEUED_CALLS_PER_TX = 32; uint256 internal constant PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 1; uint256 internal constant MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 64; uint256 internal constant MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 63; @@ -194,17 +194,20 @@ library Constants { uint256 internal constant SCOPED_NOTE_HASH_LENGTH = 3; uint256 internal constant NULLIFIER_LENGTH = 3; uint256 internal constant SCOPED_NULLIFIER_LENGTH = 4; + uint256 internal constant PUBLIC_DATA_WRITE_LENGTH = 2; uint256 internal constant PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 12; uint256 internal constant PRIVATE_CALL_REQUEST_LENGTH = 8; - uint256 internal constant PUBLIC_CALL_REQUEST_LENGTH = 6; + uint256 internal constant PUBLIC_CALL_REQUEST_LENGTH = 5; + uint256 internal constant COUNTED_PUBLIC_CALL_REQUEST_LENGTH = 6; uint256 internal constant PUBLIC_INNER_CALL_REQUEST_LENGTH = 13; uint256 internal constant ROLLUP_VALIDATION_REQUESTS_LENGTH = 2; uint256 internal constant STATE_REFERENCE_LENGTH = 8; + uint256 internal constant TREE_SNAPSHOTS_LENGTH = 8; uint256 internal constant TX_CONTEXT_LENGTH = 9; uint256 internal constant TX_REQUEST_LENGTH = 13; uint256 internal constant TOTAL_FEES_LENGTH = 1; uint256 internal constant HEADER_LENGTH = 24; - uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 501; + uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 500; uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 866; uint256 internal constant PRIVATE_CONTEXT_INPUTS_LENGTH = 38; uint256 internal constant PUBLIC_CONTEXT_INPUTS_LENGTH = 41; @@ -216,15 +219,20 @@ library Constants { uint256 internal constant NUM_PUBLIC_VALIDATION_REQUEST_ARRAYS = 5; uint256 internal constant PUBLIC_VALIDATION_REQUESTS_LENGTH = 834; uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; - uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 610; + uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 547; + uint256 internal constant TX_CONSTANT_DATA_LENGTH = 35; uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = 44; uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1064; - uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1888; - uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 1055; + uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1878; + uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 1023; uint256 internal constant NUM_PUBLIC_ACCUMULATED_DATA_ARRAYS = 8; - uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2997; - uint256 internal constant VM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2374; - uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 664; + uint256 internal constant PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH = 578; + uint256 internal constant PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH = 160; + uint256 internal constant NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS = 3; + uint256 internal constant PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1199; + uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2932; + uint256 internal constant VM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2341; + uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 601; uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 13; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 30; uint256 internal constant BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 60; diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index b637afe6464..ee8c831d447 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -28,16 +28,17 @@ use dep::protocol_types::{ private_circuit_public_inputs::PrivateCircuitPublicInputs, public_call_request::PublicCallRequest, read_request::ReadRequest, + side_effect::Counted, validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator}, }, address::{AztecAddress, EthAddress}, constants::{ - MAX_ENCRYPTED_LOGS_PER_CALL, MAX_KEY_VALIDATION_REQUESTS_PER_CALL, - MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL, PUBLIC_DISPATCH_SELECTOR, + MAX_ENCRYPTED_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL, + MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, + MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL, + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, + PUBLIC_DISPATCH_SELECTOR, }, header::Header, messaging::l2_to_l1_message::L2ToL1Message, @@ -66,7 +67,7 @@ pub struct PrivateContext { nullifiers: BoundedVec, private_call_requests: BoundedVec, - public_call_requests: BoundedVec, + public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_CALL>, public_teardown_call_request: PublicCallRequest, l2_to_l1_msgs: BoundedVec, // docs:end:private-context @@ -503,15 +504,16 @@ impl PrivateContext { // Public calls are rerouted through the dispatch function. let function_selector = comptime { FunctionSelector::from_field(PUBLIC_DISPATCH_SELECTOR) }; - let call_context = CallContext { + + let call_request = PublicCallRequest { msg_sender: self.this_address(), contract_address, function_selector, is_static_call, + args_hash, }; - let call_request = PublicCallRequest { call_context, args_hash, counter }; - self.public_call_requests.push(call_request); + self.public_call_requests.push(Counted::new(call_request, counter)); } pub fn set_public_teardown_function( @@ -555,14 +557,14 @@ impl PrivateContext { ); let function_selector = comptime { FunctionSelector::from_field(PUBLIC_DISPATCH_SELECTOR) }; - let call_context = CallContext { + + self.public_teardown_call_request = PublicCallRequest { msg_sender: self.this_address(), contract_address, function_selector, is_static_call, + args_hash, }; - - self.public_teardown_call_request = PublicCallRequest { call_context, args_hash, counter }; } fn next_counter(&mut self) -> u32 { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr index 24eaeec2842..df372aa9751 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr @@ -15,6 +15,7 @@ use dep::types::{ private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputsArrayLengths, private_kernel::private_call_data::PrivateCallData, + public_call_request::PublicCallRequest, side_effect::{Ordered, RangeOrdered}, }, address::AztecAddress, @@ -23,17 +24,6 @@ use dep::types::{ utils::arrays::find_index_hint, }; -fn validate_call_context(target_context: CallContext, this_context: CallContext) { - assert_eq( - target_context.msg_sender, - this_context.contract_address, - "incorrect msg_sender for call request", - ); - if !target_context.is_static_call { - assert(this_context.is_static_call == false, "static call cannot make non-static calls"); - } -} - fn validate_incrementing_counters_within_range( counter_start: u32, counter_end: u32, @@ -111,7 +101,6 @@ impl PrivateCallDataValidator { self.validate_call(); self.validate_private_call_requests(); self.validate_public_call_requests(); - self.validate_teardown_call_request(); self.validate_counters(); self.validate_note_logs(accumulated_note_hashes); } @@ -244,7 +233,18 @@ impl PrivateCallDataValidator { for i in 0..call_requests.len() { should_check &= i != num_requests; if should_check { - validate_call_context(call_requests[i].call_context, public_inputs.call_context); + let call_request = call_requests[i]; + assert_eq( + call_request.call_context.msg_sender, + public_inputs.call_context.contract_address, + "incorrect msg_sender for call request", + ); + if !call_request.call_context.is_static_call { + assert( + public_inputs.call_context.is_static_call == false, + "static call cannot make non-static calls", + ); + } } } @@ -274,22 +274,34 @@ impl PrivateCallDataValidator { fn validate_public_call_requests(self) { let public_inputs = self.data.public_inputs; + let call_requests = public_inputs.public_call_requests; let num_requests = self.array_lengths.public_call_requests; let mut should_check = true; for i in 0..call_requests.len() { should_check &= i != num_requests; if should_check { - validate_call_context(call_requests[i].call_context, public_inputs.call_context); + self.validate_public_call_request(call_requests[i].inner); } } + + if !public_inputs.public_teardown_call_request.contract_address.is_zero() { + self.validate_public_call_request(public_inputs.public_teardown_call_request); + } } - fn validate_teardown_call_request(self) { - let public_inputs = self.data.public_inputs; - let request = public_inputs.public_teardown_call_request; - if request.counter != 0 { - validate_call_context(request.call_context, public_inputs.call_context); + fn validate_public_call_request(self, call_request: PublicCallRequest) { + let this_context = self.data.public_inputs.call_context; + assert_eq( + call_request.msg_sender, + this_context.contract_address, + "incorrect msg_sender for call request", + ); + if !call_request.is_static_call { + assert( + this_context.is_static_call == false, + "static call cannot make non-static calls", + ); } } @@ -356,20 +368,7 @@ impl PrivateCallDataValidator { public_inputs.public_call_requests, self.array_lengths.public_call_requests, ); - - let teardown_call_request_count = if public_inputs.public_teardown_call_request.counter == 0 - { - 0 - } else { - 1 - }; - validate_incrementing_counters_within_range( - counter_start, - counter_end, - [public_inputs.public_teardown_call_request], - teardown_call_request_count, - ); - } + } fn validate_note_logs(self, accumulated_note_hashes: [ScopedNoteHash; N]) { let note_logs = self.data.public_inputs.note_encrypted_logs_hashes; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr index 9784fefe4d0..ab4d9245ec0 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr @@ -85,10 +85,6 @@ impl PrivateKernelCircuitOutputValidator { private_call.historical_header, "mismatch historical_header", ); - assert( - is_empty(self.output.constants.global_variables), - "constants.global_variables must be empty", - ); assert_eq(self.output.constants.vk_tree_root, vk_tree_root, "mismatch vk_tree_root"); assert_eq( self.output.constants.protocol_contract_tree_root, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr index f0702793359..7e58f15693c 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr @@ -1,12 +1,12 @@ use dep::types::{ abis::{ - combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{ PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder, }, max_block_number::MaxBlockNumber, nullifier::{Nullifier, ScopedNullifier}, private_circuit_public_inputs::PrivateCircuitPublicInputs, + tx_constant_data::TxConstantData, }, address::AztecAddress, traits::is_empty, @@ -31,12 +31,12 @@ impl PrivateKernelCircuitPublicInputsComposer { ) -> Self { let mut public_inputs = PrivateKernelCircuitPublicInputsBuilder::empty(); - public_inputs.constants = CombinedConstantData::private( - private_call_public_inputs.historical_header, - tx_request.tx_context, + public_inputs.constants = TxConstantData { + historical_header: private_call_public_inputs.historical_header, + tx_context: tx_request.tx_context, vk_tree_root, protocol_contract_tree_root, - ); + }; // Since it's the first iteration, we need to push the tx hash nullifier into the `nullifiers` array public_inputs.end.nullifiers.push(create_first_nullifier(tx_request)); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr index 44eca05c0f6..8ed0ab04f1f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr @@ -7,6 +7,8 @@ use crate::components::{ use dep::types::{ abis::{ accumulated_data::combined_accumulated_data::CombinedAccumulatedData, + combined_constant_data::CombinedConstantData, + global_variables::GlobalVariables, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs}, log_hash::{NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash}, note_hash::ScopedNoteHash, @@ -33,7 +35,8 @@ impl TailOutputComposer { let mut output = KernelCircuitPublicInputs::empty(); output.rollup_validation_requests = source.validation_requests.for_rollup; output.end = self.build_combined_accumulated_data(); - output.constants = source.constants; + output.constants = + CombinedConstantData::combine(source.constants, GlobalVariables::empty()); output.fee_payer = source.fee_payer; output } @@ -62,10 +65,7 @@ impl TailOutputComposer { 0, |len, l: ScopedLogHash| len + l.log_hash.length, ); - data.gas_used = meter_gas_used( - data, - self.output_composer.public_inputs.constants.tx_context.gas_settings, - ); + data.gas_used = meter_gas_used(data); data } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr index 7ecd1b59a77..ca6a9575701 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr @@ -1,8 +1,5 @@ use dep::types::{ - abis::{ - accumulated_data::combined_accumulated_data::CombinedAccumulatedData, gas::Gas, - gas_settings::GasSettings, - }, + abis::{accumulated_data::combined_accumulated_data::CombinedAccumulatedData, gas::Gas}, constants::{ DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, L2_GAS_PER_LOG_BYTE, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, @@ -10,7 +7,7 @@ use dep::types::{ utils::arrays::array_length, }; -pub fn meter_gas_used(data: CombinedAccumulatedData, gas_settings: GasSettings) -> Gas { +pub fn meter_gas_used(data: CombinedAccumulatedData) -> Gas { let mut metered_da_bytes = 0; let mut metered_l2_gas = 0; @@ -34,6 +31,5 @@ pub fn meter_gas_used(data: CombinedAccumulatedData, gas_settings: GasSettings) metered_da_bytes += data.unencrypted_log_preimages_length as u32; metered_l2_gas += data.unencrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - let teardown_gas = gas_settings.teardown_gas_limits; - Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, metered_l2_gas) + Gas::tx_overhead() + teardown_gas + Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, metered_l2_gas) + Gas::tx_overhead() } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr index dbca9f64106..fee3e43e133 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr @@ -42,7 +42,27 @@ impl TailOutputValidator { } fn validate_propagated_values(self) { - assert_eq(self.output.constants, self.previous_kernel.constants, "mismatch constants"); + assert_eq( + self.output.constants.historical_header, + self.previous_kernel.constants.historical_header, + "mismatch historical_header", + ); + assert_eq( + self.output.constants.tx_context, + self.previous_kernel.constants.tx_context, + "mismatch tx_context", + ); + assert_eq( + self.output.constants.vk_tree_root, + self.previous_kernel.constants.vk_tree_root, + "mismatch vk_tree_root", + ); + assert_eq( + self.output.constants.protocol_contract_tree_root, + self.previous_kernel.constants.protocol_contract_tree_root, + "mismatch protocol_contract_tree_root", + ); + assert(is_empty(self.output.constants.global_variables), "global_variables must be empty"); assert_eq( self.output.rollup_validation_requests, @@ -106,10 +126,7 @@ impl TailOutputValidator { } fn validate_gas_used(self) { - let gas_used = meter_gas_used( - self.output.end, - self.output.constants.tx_context.gas_settings, - ); + let gas_used = meter_gas_used(self.output.end); assert(self.output.end.gas_used == gas_used, "incorrect metered gas used"); let limits = self.previous_kernel.constants.tx_context.gas_settings.gas_limits; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr index b32a7408dce..f5d48debad2 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr @@ -10,7 +10,7 @@ use crate::components::{ }; use dep::types::abis::{ kernel_circuit_public_inputs::{ - PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs, + PrivateKernelCircuitPublicInputs, PrivateToPublicKernelCircuitPublicInputs, }, validation_requests::PublicValidationRequests, }; @@ -28,26 +28,26 @@ impl TailToPublicOutputComposer { TailToPublicOutputComposer { output_composer } } - pub unconstrained fn finish(self) -> PublicKernelCircuitPublicInputs { + pub unconstrained fn finish(self) -> PrivateToPublicKernelCircuitPublicInputs { let source = self.output_composer.public_inputs; - let mut validation_requests = PublicValidationRequests::empty(); - validation_requests.for_rollup = source.validation_requests.for_rollup(); + let mut (non_revertible_accumulated_data, revertible_accumulated_data) = + split_to_public(source.end, source.min_revertible_side_effect_counter); - let mut output = PublicKernelCircuitPublicInputs::empty(); - output.validation_requests = validation_requests; - output.constants = source.constants; - output.public_teardown_call_request = - source.public_teardown_call_request.expose_to_public(); - output.fee_payer = source.fee_payer; + non_revertible_accumulated_data.gas_used = + meter_gas_used_non_revertible(non_revertible_accumulated_data); - let mut (end_non_revertible, end) = - split_to_public(source.end, source.min_revertible_side_effect_counter); - end_non_revertible.gas_used = meter_gas_used_non_revertible(end_non_revertible); - let teardown_gas = source.constants.tx_context.gas_settings.teardown_gas_limits; - end.gas_used = meter_gas_used_revertible(end, teardown_gas); - output.end_non_revertible = end_non_revertible; - output.end = end; + revertible_accumulated_data.gas_used = + meter_gas_used_revertible(revertible_accumulated_data); + + let mut output = PrivateToPublicKernelCircuitPublicInputs { + constants: source.constants, + rollup_validation_requests: source.validation_requests.for_rollup(), + non_revertible_accumulated_data, + revertible_accumulated_data, + public_teardown_call_request: source.public_teardown_call_request, + fee_payer: source.fee_payer, + }; output } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr index a338db8f439..16e11c7f4a9 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr @@ -1,5 +1,9 @@ use dep::types::{ - abis::{accumulated_data::PublicAccumulatedData, gas::Gas, log_hash::{LogHash, ScopedLogHash}}, + abis::{ + accumulated_data::PrivateToPublicAccumulatedData, + gas::Gas, + log_hash::{LogHash, ScopedLogHash}, + }, constants::{ DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS, L2_GAS_PER_LOG_BYTE, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, @@ -7,7 +11,7 @@ use dep::types::{ utils::arrays::array_length, }; -fn meter_gas_used(data: PublicAccumulatedData) -> Gas { +fn meter_gas_used(data: PrivateToPublicAccumulatedData) -> Gas { let mut metered_da_bytes = 0; let mut metered_l2_gas = 0; @@ -36,15 +40,15 @@ fn meter_gas_used(data: PublicAccumulatedData) -> Gas { metered_da_bytes += unencrypted_log_preimages_length as u32; metered_l2_gas += unencrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - metered_l2_gas += array_length(data.public_call_stack) * FIXED_AVM_STARTUP_L2_GAS; + metered_l2_gas += array_length(data.public_call_requests) * FIXED_AVM_STARTUP_L2_GAS; Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, metered_l2_gas) } -pub fn meter_gas_used_non_revertible(data: PublicAccumulatedData) -> Gas { +pub fn meter_gas_used_non_revertible(data: PrivateToPublicAccumulatedData) -> Gas { meter_gas_used(data) + Gas::tx_overhead() } -pub fn meter_gas_used_revertible(data: PublicAccumulatedData, teardown_gas: Gas) -> Gas { - meter_gas_used(data) + Gas::new(teardown_gas.da_gas, teardown_gas.l2_gas) +pub fn meter_gas_used_revertible(data: PrivateToPublicAccumulatedData) -> Gas { + meter_gas_used(data) } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr index 702e6a330da..ad944b4cd0b 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr @@ -1,25 +1,24 @@ use dep::types::abis::accumulated_data::{ private_accumulated_data_builder::PrivateAccumulatedDataBuilder, - public_accumulated_data::PublicAccumulatedData, - public_accumulated_data_builder::PublicAccumulatedDataBuilder, + private_to_public_accumulated_data::PrivateToPublicAccumulatedData, + private_to_public_accumulated_data_builder::PrivateToPublicAccumulatedDataBuilder, }; pub unconstrained fn split_to_public( data: PrivateAccumulatedDataBuilder, min_revertible_side_effect_counter: u32, -) -> (PublicAccumulatedData, PublicAccumulatedData) { - let mut non_revertible_builder = PublicAccumulatedDataBuilder::empty(); - let mut revertible_builder = PublicAccumulatedDataBuilder::empty(); +) -> (PrivateToPublicAccumulatedData, PrivateToPublicAccumulatedData) { + let mut non_revertible_builder = PrivateToPublicAccumulatedDataBuilder::empty(); + let mut revertible_builder = PrivateToPublicAccumulatedDataBuilder::empty(); let note_hashes = data.note_hashes; for i in 0..note_hashes.max_len() { if i < note_hashes.len() { let note_hash = note_hashes.get_unchecked(i); - let public_note_hash = note_hash.expose_to_public(); if note_hash.counter() < min_revertible_side_effect_counter { - non_revertible_builder.note_hashes.push(public_note_hash); + non_revertible_builder.note_hashes.push(note_hash.value()); } else { - revertible_builder.note_hashes.push(public_note_hash); + revertible_builder.note_hashes.push(note_hash.value()); } } } @@ -28,11 +27,10 @@ pub unconstrained fn split_to_public( for i in 0..nullifiers.max_len() { if i < nullifiers.len() { let nullifier = nullifiers.get_unchecked(i); - let public_nullifier = nullifier.expose_to_public(); if nullifier.counter() < min_revertible_side_effect_counter { - non_revertible_builder.nullifiers.push(public_nullifier); + non_revertible_builder.nullifiers.push(nullifier.value()); } else { - revertible_builder.nullifiers.push(public_nullifier); + revertible_builder.nullifiers.push(nullifier.value()); } } } @@ -92,11 +90,10 @@ pub unconstrained fn split_to_public( for i in 0..public_call_requests.max_len() { if i < public_call_requests.len() { let call_request = public_call_requests.get_unchecked(i); - let exposed_call_request = call_request.expose_to_public(); if call_request.counter < min_revertible_side_effect_counter { - non_revertible_builder.public_call_stack.push(exposed_call_request); + non_revertible_builder.public_call_requests.push(call_request.inner); } else { - revertible_builder.public_call_stack.push(exposed_call_request); + revertible_builder.public_call_requests.push(call_request.inner); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr index 7201736c70e..e768fbc3802 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr @@ -11,15 +11,15 @@ use crate::components::{ use dep::types::{ abis::{ kernel_circuit_public_inputs::{ - PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs, + PrivateKernelCircuitPublicInputs, PrivateToPublicKernelCircuitPublicInputs, }, log_hash::{LogHash, NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash}, note_hash::ScopedNoteHash, nullifier::{Nullifier, ScopedNullifier}, public_call_request::PublicCallRequest, + side_effect::Counted, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, - traits::is_empty_array, utils::arrays::{ assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc, assert_split_transformed_value_arrays, @@ -27,14 +27,14 @@ use dep::types::{ }; pub struct TailToPublicOutputValidator { - output: PublicKernelCircuitPublicInputs, + output: PrivateToPublicKernelCircuitPublicInputs, previous_kernel: PrivateKernelCircuitPublicInputs, hints: TailToPublicOutputHints, } impl TailToPublicOutputValidator { pub fn new( - output: PublicKernelCircuitPublicInputs, + output: PrivateToPublicKernelCircuitPublicInputs, previous_kernel: PrivateKernelCircuitPublicInputs, ) -> Self { let hints = unsafe { generate_tail_to_public_output_hints(previous_kernel) }; @@ -42,41 +42,17 @@ impl TailToPublicOutputValidator { } pub fn validate(self) { - self.validate_empty_values(); self.validate_propagated_values(); self.validate_propagated_split_values(); self.validate_propagated_sorted_values(); self.validate_gas_used(); } - fn validate_empty_values(self) { - assert_eq(self.output.revert_code, 0, "revert_code must be empty"); - - assert( - is_empty_array(self.output.end_non_revertible.public_data_update_requests), - "non-revertible public_data_update_requests must be empty", - ); - assert( - is_empty_array(self.output.end.public_data_update_requests), - "revertible public_data_update_requests must be empty", - ); - - // public_data_update_requests - assert( - is_empty_array(self.output.end_non_revertible.public_data_update_requests), - "unexpected non-revertible public_data_update_requests", - ); - assert( - is_empty_array(self.output.end.public_data_update_requests), - "unexpected revertible public_data_update_requests", - ); - } - fn validate_propagated_values(self) { assert_eq(self.output.constants, self.previous_kernel.constants, "mismatch constants"); assert_eq( - self.output.validation_requests.for_rollup, + self.output.rollup_validation_requests, self.previous_kernel.validation_requests.for_rollup, "mismatch rollup_validation_requests", ); @@ -85,7 +61,7 @@ impl TailToPublicOutputValidator { assert_eq( self.output.public_teardown_call_request, - self.previous_kernel.public_teardown_call_request.expose_to_public(), + self.previous_kernel.public_teardown_call_request, "mismatch public_teardown_call_request", ); } @@ -93,15 +69,15 @@ impl TailToPublicOutputValidator { fn validate_propagated_split_values(self) { let split_counter = self.previous_kernel.min_revertible_side_effect_counter; let prev_data = self.previous_kernel.end; - let output_non_revertible = self.output.end_non_revertible; - let output_revertible = self.output.end; + let output_non_revertible = self.output.non_revertible_accumulated_data; + let output_revertible = self.output.revertible_accumulated_data; // note_hashes assert_split_transformed_value_arrays( prev_data.note_hashes, output_non_revertible.note_hashes, output_revertible.note_hashes, - |prev: ScopedNoteHash, out: ScopedNoteHash| out == prev.expose_to_public(), + |prev: ScopedNoteHash, out: Field| out == prev.note_hash.value, split_counter, ); @@ -110,7 +86,7 @@ impl TailToPublicOutputValidator { prev_data.nullifiers, output_non_revertible.nullifiers, output_revertible.nullifiers, - |prev: ScopedNullifier, out: Nullifier| out == prev.expose_to_public(), + |prev: ScopedNullifier, out: Field| out == prev.nullifier.value, split_counter, ); @@ -136,8 +112,8 @@ impl TailToPublicOutputValidator { fn validate_propagated_sorted_values(self) { let split_counter = self.previous_kernel.min_revertible_side_effect_counter; let prev_data = self.previous_kernel.end; - let output_non_revertible = self.output.end_non_revertible; - let output_revertible = self.output.end; + let output_non_revertible = self.output.non_revertible_accumulated_data; + let output_revertible = self.output.revertible_accumulated_data; let hints = self.hints; // l2_to_l1_msgs @@ -163,29 +139,30 @@ impl TailToPublicOutputValidator { // public_call_requests assert_split_sorted_transformed_value_arrays_desc( prev_data.public_call_requests, - prev_data.public_call_requests.map(|cr: PublicCallRequest| cr.expose_to_public()), + prev_data.public_call_requests.map(|cr: Counted| cr.inner), split_counter, - output_non_revertible.public_call_stack, - output_revertible.public_call_stack, + output_non_revertible.public_call_requests, + output_revertible.public_call_requests, hints.sorted_public_call_request_hints, ) } fn validate_gas_used(self) { - let gas_used = meter_gas_used_non_revertible(self.output.end_non_revertible); + let gas_used = meter_gas_used_non_revertible(self.output.non_revertible_accumulated_data); assert( - self.output.end_non_revertible.gas_used == gas_used, + self.output.non_revertible_accumulated_data.gas_used == gas_used, "incorrect metered non-revertible gas used", ); - let gas_used = meter_gas_used_revertible( - self.output.end, - self.output.constants.tx_context.gas_settings.teardown_gas_limits, + let gas_used = meter_gas_used_revertible(self.output.revertible_accumulated_data); + assert( + self.output.revertible_accumulated_data.gas_used == gas_used, + "incorrect metered revertible gas used", ); - assert(self.output.end.gas_used == gas_used, "incorrect metered revertible gas used"); let limits = self.previous_kernel.constants.tx_context.gas_settings.gas_limits; - let total_gas_used = self.output.end_non_revertible.gas_used + self.output.end.gas_used; + let total_gas_used = self.output.non_revertible_accumulated_data.gas_used + + self.output.revertible_accumulated_data.gas_used; assert(total_gas_used.within(limits), "The gas used exceeds the gas limits"); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr index be4038a7515..0918eaa04b2 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr @@ -1,8 +1,6 @@ use dep::types::{ abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - constants::{ - MAX_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, - }, + constants::{MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX}, utils::arrays::{get_split_order_hints_asc, get_split_order_hints_desc, SplitOrderHints}, }; @@ -12,7 +10,7 @@ pub struct TailToPublicOutputHints { // Unencrypted log hashes. sorted_unencrypted_log_hash_hints: SplitOrderHints, // Public call requests. - sorted_public_call_request_hints: SplitOrderHints, + sorted_public_call_request_hints: SplitOrderHints, } pub unconstrained fn generate_tail_to_public_output_hints( diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index 946609fd82c..0aca41a778c 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -235,17 +235,15 @@ mod tests { } #[test] - fn empty_tx_consumes_teardown_limits_plus_fixed_gas() { + fn empty_tx_consumes_fixed_gas() { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = Gas::new(300, 300); let public_inputs = builder.execute(); // addition follows the form: - // teardown gas // tx overhead // tx nullifier (which has DA and L2 gas) - let expected_gas_consumed = Gas::new(300, 300) - + Gas::tx_overhead() + let expected_gas_consumed = Gas::tx_overhead() + Gas::new( DA_GAS_PER_BYTE * DA_BYTES_PER_FIELD * 1, L2_GAS_PER_NULLIFIER * 1, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr index 60bbb8bb959..0dbd3cd46f6 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr @@ -5,7 +5,7 @@ use crate::components::{ }; use dep::types::{ abis::{ - kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, + kernel_circuit_public_inputs::PrivateToPublicKernelCircuitPublicInputs, private_kernel_data::{PrivateKernelData, PrivateKernelDataWithoutPublicInputs}, }, constants::{PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX, PRIVATE_KERNEL_RESET_INDEX}, @@ -29,11 +29,11 @@ impl PrivateKernelTailToPublicCircuitPrivateInputs { } } - unconstrained fn generate_output(self) -> PublicKernelCircuitPublicInputs { + unconstrained fn generate_output(self) -> PrivateToPublicKernelCircuitPublicInputs { TailToPublicOutputComposer::new(self.previous_kernel.public_inputs).finish() } - pub fn execute(self) -> PublicKernelCircuitPublicInputs { + pub fn execute(self) -> PrivateToPublicKernelCircuitPublicInputs { // Generate output. let output = unsafe { self.generate_output() }; @@ -58,7 +58,7 @@ mod tests { use dep::types::{ abis::{ gas::Gas, - kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, + kernel_circuit_public_inputs::PrivateToPublicKernelCircuitPublicInputs, log_hash::{LogHash, NoteLogHash}, note_hash::ScopedNoteHash, nullifier::{Nullifier, ScopedNullifier}, @@ -89,44 +89,7 @@ mod tests { PrivateKernelTailToPublicInputsBuilder { previous_kernel } } - // A helper function that uses the first nullifer in the previous kernel to compute the unique siloed - // note_hashes for the given note_hashes. - pub fn compute_output_note_hashes( - _self: Self, - note_hashes: [ScopedNoteHash; N], - ) -> [ScopedNoteHash; N] { - let mut output = [ScopedNoteHash::empty(); N]; - for i in 0..N { - output[i].note_hash.value = note_hashes[i].value(); - } - output - } - - pub fn compute_output_nullifiers( - _self: Self, - nullifiers: [ScopedNullifier; N], - ) -> [Nullifier; N] { - let mut output = [Nullifier::empty(); N]; - for i in 0..N { - output[i].value = nullifiers[i].value(); - } - output - } - - pub fn compute_output_note_logs( - _self: Self, - logs: [NoteLogHash; N], - ) -> [LogHash; N] { - let mut output = [LogHash::empty(); N]; - for i in 0..N { - if logs[i].value != 0 { - output[i] = logs[i].expose_to_public(); // Counter is cleared so it's not exposed to the public. - } - } - output - } - - pub fn execute(&mut self) -> PublicKernelCircuitPublicInputs { + pub fn execute(&mut self) -> PrivateToPublicKernelCircuitPublicInputs { let kernel = PrivateKernelTailToPublicCircuitPrivateInputs { previous_kernel: self.previous_kernel.to_private_kernel_data(), }; @@ -192,30 +155,30 @@ mod tests { // expect 2 revertible nullifiers builder.previous_kernel.append_siloed_nullifiers(2); - let nullifiers = builder.previous_kernel.nullifiers.storage; let public_inputs = builder.execute(); - let output_nullifiers = builder.compute_output_nullifiers(nullifiers); + let output_nullifiers = + builder.previous_kernel.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value); assert_array_eq( - public_inputs.end_non_revertible.nullifiers, + public_inputs.non_revertible_accumulated_data.nullifiers, [output_nullifiers[0], output_nullifiers[1], output_nullifiers[2]], ); assert_array_eq( - public_inputs.end.nullifiers, + public_inputs.revertible_accumulated_data.nullifiers, [output_nullifiers[3], output_nullifiers[4]], ); assert_eq( - public_inputs.end.gas_used, + public_inputs.revertible_accumulated_data.gas_used, Gas::new( 2 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, 2 * L2_GAS_PER_NULLIFIER, ), ); assert_eq( - public_inputs.end_non_revertible.gas_used, + public_inputs.non_revertible_accumulated_data.gas_used, Gas::new( 3 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS + 3 * L2_GAS_PER_NULLIFIER, @@ -225,7 +188,7 @@ mod tests { } #[test] - fn split_note_hashes_into_non_revertible() { + unconstrained fn split_note_hashes_into_non_revertible() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); // expect 2 non-revertible note hashes @@ -235,30 +198,30 @@ mod tests { // expect 2 revertible note hashes builder.previous_kernel.append_siloed_note_hashes(2); - let note_hashes = builder.previous_kernel.note_hashes.storage; let public_inputs = builder.execute(); - let exposed_note_hashes = builder.compute_output_note_hashes(note_hashes); + let exposed_note_hashes = + builder.previous_kernel.note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value); assert_array_eq( - public_inputs.end_non_revertible.note_hashes, + public_inputs.non_revertible_accumulated_data.note_hashes, [exposed_note_hashes[0], exposed_note_hashes[1]], ); assert_array_eq( - public_inputs.end.note_hashes, + public_inputs.revertible_accumulated_data.note_hashes, [exposed_note_hashes[2], exposed_note_hashes[3]], ); assert_eq( - public_inputs.end.gas_used, + public_inputs.revertible_accumulated_data.gas_used, Gas::new( (2 * DA_BYTES_PER_FIELD) * DA_GAS_PER_BYTE, 2 * L2_GAS_PER_NOTE_HASH, ), ); assert_eq( - public_inputs.end_non_revertible.gas_used, + public_inputs.non_revertible_accumulated_data.gas_used, Gas::new( (3 * DA_BYTES_PER_FIELD) * DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS + L2_GAS_PER_NULLIFIER + 2 * L2_GAS_PER_NOTE_HASH, @@ -295,14 +258,13 @@ mod tests { } #[test] - fn empty_tx_consumes_teardown_limits_plus_fixed_gas() { + fn empty_tx_consumes_fixed_gas() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = Gas::new(300, 300); builder.previous_kernel.end_setup(); let public_inputs = builder.execute(); - let expected_revertible_gas_used = Gas::new(300, 300); - assert_eq(public_inputs.end.gas_used, expected_revertible_gas_used); + assert_eq(public_inputs.revertible_accumulated_data.gas_used, Gas::empty()); let expected_non_revertible_gas_used = Gas::tx_overhead() + Gas::new( @@ -310,7 +272,10 @@ mod tests { L2_GAS_PER_NULLIFIER * 1 + FIXED_AVM_STARTUP_L2_GAS, ); - assert_eq(public_inputs.end_non_revertible.gas_used, expected_non_revertible_gas_used); + assert_eq( + public_inputs.non_revertible_accumulated_data.gas_used, + expected_non_revertible_gas_used, + ); } #[test] @@ -324,7 +289,7 @@ mod tests { let public_inputs = builder.execute(); let expected_revertible_gas_used = Gas::new(0, 3 * FIXED_AVM_STARTUP_L2_GAS); - assert_eq(public_inputs.end.gas_used, expected_revertible_gas_used); + assert_eq(public_inputs.revertible_accumulated_data.gas_used, expected_revertible_gas_used); let expected_non_revertible_gas_used = Gas::tx_overhead() + Gas::new( @@ -332,7 +297,10 @@ mod tests { L2_GAS_PER_NULLIFIER * 1 + 2 * FIXED_AVM_STARTUP_L2_GAS, ); - assert_eq(public_inputs.end_non_revertible.gas_used, expected_non_revertible_gas_used); + assert_eq( + public_inputs.non_revertible_accumulated_data.gas_used, + expected_non_revertible_gas_used, + ); } #[test] @@ -348,7 +316,7 @@ mod tests { assert_eq( Gas::new(1 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, 0), - public_inputs.end.gas_used, + public_inputs.revertible_accumulated_data.gas_used, ); assert_eq( Gas::tx_overhead() @@ -356,7 +324,7 @@ mod tests { 3 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS + 1 * L2_GAS_PER_NULLIFIER, ), - public_inputs.end_non_revertible.gas_used, + public_inputs.non_revertible_accumulated_data.gas_used, ); } @@ -374,7 +342,7 @@ mod tests { assert_eq( Gas::new(13 * DA_GAS_PER_BYTE, 13 * L2_GAS_PER_LOG_BYTE), - public_inputs.end.gas_used, + public_inputs.revertible_accumulated_data.gas_used, ); assert_eq( @@ -383,7 +351,7 @@ mod tests { (1 * DA_BYTES_PER_FIELD + 12) * DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS + 1 * L2_GAS_PER_NULLIFIER + 12 * L2_GAS_PER_LOG_BYTE, ), - public_inputs.end_non_revertible.gas_used, + public_inputs.non_revertible_accumulated_data.gas_used, ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call_requests.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call_requests.nr index d1a6139eb49..b91bd56ef66 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call_requests.nr @@ -27,7 +27,7 @@ fn validate_public_call_requests_incorrect_msg_sender_for_regular_call_fails() { builder.private_call.append_public_call_requests(1); // Change the msg_sender to be the caller's msg_sender. - builder.private_call.public_call_requests.storage[0].call_context.msg_sender = + builder.private_call.public_call_requests.storage[0].inner.msg_sender = builder.private_call.msg_sender; builder.validate(); @@ -39,7 +39,7 @@ fn validate_public_call_requests_static_call_regular_call_fails() { builder.private_call.append_public_call_requests(1); // Tweak the request to be making a non-static call. - builder.private_call.public_call_requests.storage[0].call_context.is_static_call = false; + builder.private_call.public_call_requests.storage[0].inner.is_static_call = false; builder.validate(); } @@ -71,8 +71,7 @@ fn validate_teardown_call_request_incorrect_msg_sender_for_regular_call_fails() builder.private_call.set_public_teardown_call_request(); // Change the msg_sender to be the caller's msg_sender. - builder.private_call.public_teardown_call_request.call_context.msg_sender = - builder.private_call.msg_sender; + builder.private_call.public_teardown_call_request.msg_sender = builder.private_call.msg_sender; builder.validate(); } @@ -83,7 +82,7 @@ fn validate_teardown_call_request_static_call_regular_call_fails() { builder.private_call.set_public_teardown_call_request(); // Tweak the request to be making a non-static call. - builder.private_call.public_teardown_call_request.call_context.is_static_call = false; + builder.private_call.public_teardown_call_request.is_static_call = false; builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_initial_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_initial_values.nr index 98c59019fd2..3faeab0e8ab 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_initial_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_initial_values.nr @@ -28,15 +28,6 @@ fn validate_initial_values_constants_mismatch_txs_effects_hash_fails() { builder.validate_as_first_call(); } -#[test(should_fail_with = "constants.global_variables must be empty")] -fn validate_initial_values_constants_non_empty_global_variables_fails() { - let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - - builder.output.global_variables.block_number += 1; - - builder.validate_as_first_call(); -} - /** * First nullifier. */ diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr index 8ac4bb62749..dbc0b8e954c 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr @@ -28,10 +28,10 @@ fn validate_propagated_from_previous_kernel_constants_mismatch_txs_effects_hash_ } #[test(should_fail_with = "mismatch constants")] -fn validate_propagated_from_previous_kernel_constants_non_empty_global_variables_fails() { +fn validate_propagated_from_previous_kernel_constants_mismatch_protocol_contract_tree_root_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.output.global_variables.block_number += 1; + builder.output.protocol_contract_tree_root += 1; builder.validate_as_inner_call(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_tx_request.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_tx_request.nr index 16dcce34eae..b332fe9fb49 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_tx_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_tx_request.nr @@ -25,7 +25,6 @@ fn new_from_tx_request_succeeds() { // Check output constants. assert_eq(output.constants.tx_context, tx_request.tx_context); assert_eq(output.constants.historical_header, historical_header); - assert(is_empty(output.constants.global_variables)); // Check first nullifier is set. assert_eq(output.end.nullifiers[0], first_nullifier); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr index 3a04eb2c387..9759093dafa 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr @@ -10,7 +10,6 @@ use dep::types::{ fn new_builder() -> FixtureBuilder { let mut builder = FixtureBuilder::new(); - builder.tx_context.gas_settings.teardown_gas_limits = Gas::new(12, 345); builder } @@ -18,9 +17,8 @@ fn new_builder() -> FixtureBuilder { fn meter_gas_used_empty_succeeds() { let builder = new_builder(); let data = builder.to_combined_accumulated_data(); - let gas_settings = builder.tx_context.gas_settings; - let gas = meter_gas_used(data, gas_settings); - assert_eq(gas, Gas::tx_overhead() + gas_settings.teardown_gas_limits); + let gas = meter_gas_used(data); + assert_eq(gas, Gas::tx_overhead()); } #[test] @@ -65,13 +63,10 @@ fn meter_gas_used_everything_succeeds() { computed_l2_gas += 51 * L2_GAS_PER_LOG_BYTE; let data = builder.to_combined_accumulated_data(); - let gas_settings = builder.tx_context.gas_settings; - let gas = meter_gas_used(data, gas_settings); + let gas = meter_gas_used(data); assert_eq( gas, - Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, computed_l2_gas) - + Gas::tx_overhead() - + gas_settings.teardown_gas_limits, + Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, computed_l2_gas) + Gas::tx_overhead(), ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr index 7bc01c93661..89b81810ca1 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr @@ -40,7 +40,7 @@ impl TailOutputValidatorBuilder { pub fn export_output(self) -> KernelCircuitPublicInputs { let mut output = self.output.to_kernel_circuit_public_inputs(); - output.end.gas_used = meter_gas_used(output.end, output.constants.tx_context.gas_settings); + output.end.gas_used = meter_gas_used(output.end); output } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_values.nr index 7a4d23a0941..f9674389c67 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_values.nr @@ -14,8 +14,8 @@ fn validate_propagated_values_constants_succeeds() { builder.validate(); } -#[test(should_fail_with = "mismatch constants")] -fn validate_propagated_values_constants_mismatch_fails() { +#[test(should_fail_with = "mismatch historical_header")] +fn validate_propagated_values_total_fees_mismatch_fails() { let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.historical_header.total_fees = 123; @@ -25,6 +25,49 @@ fn validate_propagated_values_constants_mismatch_fails() { builder.validate(); } +#[test(should_fail_with = "mismatch tx_context")] +fn validate_propagated_values_chain_id_mismatch_fails() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.tx_context.chain_id = 123; + // Tweak the value in the output. + builder.output.tx_context.chain_id = 45; + + builder.validate(); +} + +#[test(should_fail_with = "mismatch vk_tree_root")] +fn validate_propagated_values_vk_tree_root_mismatch_fails() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.vk_tree_root = 123; + // Tweak the value in the output. + builder.output.vk_tree_root = 45; + + builder.validate(); +} + +#[test(should_fail_with = "mismatch protocol_contract_tree_root")] +fn validate_propagated_values_protocol_contract_tree_root_mismatch_fails() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.protocol_contract_tree_root = 123; + // Tweak the value in the output. + builder.output.protocol_contract_tree_root = 45; + + builder.validate(); +} + +#[test(should_fail_with = "global_variables must be empty")] +fn validate_propagated_values_global_variables_non_empty_fails() { + let mut builder = TailOutputValidatorBuilder::new(); + + // Tweak the value in the output. + builder.output.global_variables.chain_id = 1; + + builder.validate(); +} + /** * max_block_number */ diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr index f85e960474e..e684d244c33 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr @@ -13,7 +13,7 @@ use dep::types::{ #[test] fn meter_gas_used_non_revertible_empty_succeeds() { let builder = FixtureBuilder::new(); - let data = builder.to_public_accumulated_data(); + let data = builder.to_private_to_public_accumulated_data(); let gas = meter_gas_used_non_revertible(data); assert_eq(gas, Gas::tx_overhead()); } @@ -34,7 +34,7 @@ fn meter_gas_used_non_revertible_everything_succeeds() { builder.append_public_call_requests(2); builder.end_setup(); - let data = builder.to_public_accumulated_data(); + let data = builder.to_private_to_public_accumulated_data(); let gas = meter_gas_used_non_revertible(data); let total_num_side_effects = 4 + 3 + 1; @@ -57,10 +57,9 @@ fn meter_gas_used_non_revertible_everything_succeeds() { #[test] fn meter_gas_used_revertible_empty_succeeds() { let builder = FixtureBuilder::new(); - let data = builder.to_public_accumulated_data(); - let teardown_gas = Gas::new(42, 17); - let gas = meter_gas_used_revertible(data, teardown_gas); - assert_eq(gas, teardown_gas); + let data = builder.to_private_to_public_accumulated_data(); + let gas = meter_gas_used_revertible(data); + assert_eq(gas, Gas::empty()); } #[test] @@ -79,9 +78,8 @@ fn meter_gas_used_revertible_everything_succeeds() { builder.append_public_call_requests(2); builder.end_setup(); - let data = builder.to_public_accumulated_data(); - let teardown_gas = Gas::new(42, 17); - let gas = meter_gas_used_revertible(data, teardown_gas); + let data = builder.to_private_to_public_accumulated_data(); + let gas = meter_gas_used_revertible(data); let total_num_side_effects = 4 + 3 + 1; let total_log_length = 12 @@ -97,5 +95,5 @@ fn meter_gas_used_revertible_everything_succeeds() { + total_log_length * L2_GAS_PER_LOG_BYTE + 2 * FIXED_AVM_STARTUP_L2_GAS; - assert_eq(gas, Gas::new(computed_da_gas, computed_l2_gas) + teardown_gas); + assert_eq(gas, Gas::new(computed_da_gas, computed_l2_gas)); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr index c7daddc987e..9312710cc48 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr @@ -4,7 +4,7 @@ mod tail_to_public_output_composer; use crate::components::tail_to_public_output_composer::TailToPublicOutputComposer; use dep::types::{ - abis::kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, + abis::kernel_circuit_public_inputs::PrivateToPublicKernelCircuitPublicInputs, tests::fixture_builder::FixtureBuilder, }; @@ -19,7 +19,7 @@ impl TailToPublicOutputComposerBuilder { TailToPublicOutputComposerBuilder { previous_kernel } } - pub fn finish(self) -> PublicKernelCircuitPublicInputs { + pub fn finish(self) -> PrivateToPublicKernelCircuitPublicInputs { let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); unsafe { let composer = TailToPublicOutputComposer::new(previous_kernel); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr index f81f0ef541e..5faddeca1dc 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr @@ -23,7 +23,7 @@ fn split_to_public_succeeds() { builder.append_unencrypted_log_hashes(1); builder.append_public_call_requests(2); - let combined_data = builder.to_exposed_public_accumulated_data(); + let combined_data = builder.to_private_to_public_accumulated_data(); let (non_revertible, revertible) = unsafe { split_to_public( builder.to_private_accumulated_data_builder(), @@ -70,8 +70,11 @@ fn split_to_public_succeeds() { assert_array_eq(non_revertible.unencrypted_logs_hashes, [expected[0]]); assert_array_eq(revertible.unencrypted_logs_hashes, [expected[1]]); - // public_call_stack - let expected = combined_data.public_call_stack; - assert_array_eq(non_revertible.public_call_stack, [expected[0]]); - assert_array_eq(revertible.public_call_stack, [expected[1], expected[2]]); + // public_call_requests + let call_requests = combined_data.public_call_requests; + assert_array_eq(non_revertible.public_call_requests, [call_requests[0]]); + assert_array_eq( + revertible.public_call_requests, + [call_requests[1], call_requests[2]], + ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr index 02cea830552..7910d8f2000 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr @@ -51,7 +51,7 @@ fn tail_to_public_output_composer_succeeds() { builder.previous_kernel.append_public_call_requests(3); // Get ordered items before shuffling for verifying with the output later. - let data = builder.previous_kernel.to_exposed_public_accumulated_data(); + let data = builder.previous_kernel.to_private_to_public_accumulated_data(); // Shuffle ordered items. swap_items(&mut builder.previous_kernel.l2_to_l1_msgs, 0, 1); @@ -64,60 +64,76 @@ fn tail_to_public_output_composer_succeeds() { // note_hashes let note_hashes = data.note_hashes; assert_array_eq( - output.end_non_revertible.note_hashes, + output.non_revertible_accumulated_data.note_hashes, [note_hashes[0], note_hashes[1], note_hashes[2], note_hashes[3]], ); - assert_array_eq(output.end.note_hashes, [note_hashes[4], note_hashes[5]]); + assert_array_eq( + output.revertible_accumulated_data.note_hashes, + [note_hashes[4], note_hashes[5]], + ); // nullifiers let nullifiers = data.nullifiers; assert_array_eq( - output.end_non_revertible.nullifiers, + output.non_revertible_accumulated_data.nullifiers, [nullifiers[0], nullifiers[1], nullifiers[2]], ); - assert_array_eq(output.end.nullifiers, [nullifiers[3]]); + assert_array_eq( + output.revertible_accumulated_data.nullifiers, + [nullifiers[3]], + ); // l2_to_l1_msgs let msgs = data.l2_to_l1_msgs; - assert_array_eq(output.end_non_revertible.l2_to_l1_msgs, [msgs[0]]); - assert_array_eq(output.end.l2_to_l1_msgs, [msgs[1]]); + assert_array_eq( + output.non_revertible_accumulated_data.l2_to_l1_msgs, + [msgs[0]], + ); + assert_array_eq(output.revertible_accumulated_data.l2_to_l1_msgs, [msgs[1]]); // note_encrypted_logs_hashes let log_hashes = data.note_encrypted_logs_hashes; assert_array_eq( - output.end_non_revertible.note_encrypted_logs_hashes, + output.non_revertible_accumulated_data.note_encrypted_logs_hashes, [log_hashes[0], log_hashes[1]], ); - assert_array_eq(output.end.note_encrypted_logs_hashes, [log_hashes[2]]); + assert_array_eq( + output.revertible_accumulated_data.note_encrypted_logs_hashes, + [log_hashes[2]], + ); // encrypted_logs_hashes let log_hashes = data.encrypted_logs_hashes; assert_array_eq( - output.end_non_revertible.encrypted_logs_hashes, + output.non_revertible_accumulated_data.encrypted_logs_hashes, [log_hashes[0]], ); assert_array_eq( - output.end.encrypted_logs_hashes, + output.revertible_accumulated_data.encrypted_logs_hashes, [log_hashes[1], log_hashes[2]], ); // unencrypted_logs_hashes let log_hashes = data.unencrypted_logs_hashes; assert_array_eq( - output.end_non_revertible.unencrypted_logs_hashes, + output.non_revertible_accumulated_data.unencrypted_logs_hashes, [log_hashes[0], log_hashes[1]], ); - assert_array_eq(output.end.unencrypted_logs_hashes, [log_hashes[2]]); + assert_array_eq( + output.revertible_accumulated_data.unencrypted_logs_hashes, + [log_hashes[2]], + ); - // public_call_stack - let call_requests = data.public_call_stack; + // public_call_requests + let public_call_requests = data.public_call_requests; assert_array_eq( - output.end_non_revertible.public_call_stack, - [call_requests[1], call_requests[0]], + output.non_revertible_accumulated_data.public_call_requests, + [public_call_requests[1], public_call_requests[0]], ); + assert_array_eq( - output.end.public_call_stack, - [call_requests[4], call_requests[3], call_requests[2]], + output.revertible_accumulated_data.public_call_requests, + [public_call_requests[4], public_call_requests[3], public_call_requests[2]], ); // Gas: non-revertible @@ -134,7 +150,7 @@ fn tail_to_public_output_composer_succeeds() { + total_log_length * L2_GAS_PER_LOG_BYTE + 2 * FIXED_AVM_STARTUP_L2_GAS; assert_eq( - output.end_non_revertible.gas_used, + output.non_revertible_accumulated_data.gas_used, Gas::new(computed_da_gas, computed_l2_gas) + Gas::tx_overhead(), ); @@ -150,5 +166,8 @@ fn tail_to_public_output_composer_succeeds() { + 1 * L2_GAS_PER_NULLIFIER + total_log_length * L2_GAS_PER_LOG_BYTE + 3 * FIXED_AVM_STARTUP_L2_GAS; - assert_eq(output.end.gas_used, Gas::new(computed_da_gas, computed_l2_gas) + teardown_gas); + assert_eq( + output.revertible_accumulated_data.gas_used, + Gas::new(computed_da_gas, computed_l2_gas), + ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr index 45280bf52b7..ae18dddbf04 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr @@ -18,7 +18,7 @@ impl TailToPublicOutputValidatorBuilder { pub fn validate(self) { // TODO: Split the data using min_revertible_side_effect_counter in FixtureBuilder. let revertible = true; - let output = self.output.to_public_kernel_circuit_public_inputs(revertible); + let output = self.output.to_private_to_public_kernel_circuit_public_inputs(revertible); let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); TailToPublicOutputValidator::new(output, previous_kernel).validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-tail-to-public-simulated/src/main.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-tail-to-public-simulated/src/main.nr index 85f93ac33e3..efd9b3d036a 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-tail-to-public-simulated/src/main.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-tail-to-public-simulated/src/main.nr @@ -1,12 +1,13 @@ use dep::private_kernel_lib::PrivateKernelTailToPublicCircuitPrivateInputs; -use dep::types::PublicKernelCircuitPublicInputs; -use types::abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs; +use types::abis::kernel_circuit_public_inputs::{ + PrivateKernelCircuitPublicInputs, PrivateToPublicKernelCircuitPublicInputs, +}; use types::abis::private_kernel_data::PrivateKernelDataWithoutPublicInputs; unconstrained fn main( previous_kernel: PrivateKernelDataWithoutPublicInputs, previous_kernel_public_inputs: PrivateKernelCircuitPublicInputs, -) -> pub PublicKernelCircuitPublicInputs { +) -> pub PrivateToPublicKernelCircuitPublicInputs { let private_inputs = PrivateKernelTailToPublicCircuitPrivateInputs::new( previous_kernel, previous_kernel_public_inputs, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-tail-to-public/src/main.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-tail-to-public/src/main.nr index b3921692128..8554531407e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-tail-to-public/src/main.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-tail-to-public/src/main.nr @@ -1,12 +1,13 @@ use dep::private_kernel_lib::PrivateKernelTailToPublicCircuitPrivateInputs; -use dep::types::PublicKernelCircuitPublicInputs; -use types::abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs; +use types::abis::kernel_circuit_public_inputs::{ + PrivateKernelCircuitPublicInputs, PrivateToPublicKernelCircuitPublicInputs, +}; use types::abis::private_kernel_data::PrivateKernelDataWithoutPublicInputs; fn main( previous_kernel: PrivateKernelDataWithoutPublicInputs, previous_kernel_public_inputs: call_data(0) PrivateKernelCircuitPublicInputs, -) -> pub PublicKernelCircuitPublicInputs { +) -> pub PrivateToPublicKernelCircuitPublicInputs { let private_inputs = PrivateKernelTailToPublicCircuitPrivateInputs::new( previous_kernel, previous_kernel_public_inputs, diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr index 55c878de0eb..a760da90143 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr @@ -123,9 +123,11 @@ impl EnqueuedCallDataValidator { if self.phase != PublicKernelPhase.TEARDOWN { assert_eq(transaction_fee, 0, "Transaction fee must be zero on setup and app phases"); } else { - // Note that teardown_gas is already included in end.gas_used as it was injected by the private kernel - let total_gas_used = - previous_kernel.end.gas_used + previous_kernel.end_non_revertible.gas_used; + let teardown_gas = + previous_kernel.constants.tx_context.gas_settings.teardown_gas_limits; + let total_gas_used = previous_kernel.end.gas_used + + previous_kernel.end_non_revertible.gas_used + + teardown_gas; let block_gas_fees = self.enqueued_call.data.constants.global_variables.gas_fees; let inclusion_fee = previous_kernel.constants.tx_context.gas_settings.inclusion_fee; let computed_transaction_fee = diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/previous_kernel_validator.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/previous_kernel_validator.nr index 4d3bf25508f..5d6d9453d05 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/previous_kernel_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/previous_kernel_validator.nr @@ -21,23 +21,19 @@ impl PreviousKernelValidator { pub fn validate_phase(self, phase: u8) { let public_inputs = self.previous_kernel.public_inputs; - let needs_setup = !public_inputs.end_non_revertible.public_call_stack[0] - .call_context - .contract_address - .is_zero(); + let needs_setup = + !public_inputs.end_non_revertible.public_call_stack[0].contract_address.is_zero(); if phase == PublicKernelPhase.SETUP { assert_eq(needs_setup, true, "Cannot run unnecessary setup circuit"); } - let needs_app_logic = - !public_inputs.end.public_call_stack[0].call_context.contract_address.is_zero(); + let needs_app_logic = !public_inputs.end.public_call_stack[0].contract_address.is_zero(); if phase == PublicKernelPhase.APP_LOGIC { assert_eq(needs_setup, false, "Cannot run app logic circuit before setup circuit"); assert_eq(needs_app_logic, true, "Cannot run unnecessary app logic circuit"); } - let needs_teardown = - !public_inputs.public_teardown_call_request.call_context.contract_address.is_zero(); + let needs_teardown = !public_inputs.public_teardown_call_request.contract_address.is_zero(); if phase == PublicKernelPhase.TEARDOWN { assert_eq(needs_setup, false, "Cannot run teardown circuit before setup circuit"); assert_eq( diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/combine_data.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/combine_data.nr index e6362a42aa8..d4846909eeb 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/combine_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/combine_data.nr @@ -4,6 +4,8 @@ use dep::types::{ accumulated_data::{CombinedAccumulatedData, PublicAccumulatedData}, log_hash::{LogHash, ScopedLogHash}, nullifier::Nullifier, + public_data_update_request::PublicDataUpdateRequest, + public_data_write::PublicDataWrite, }, utils::arrays::{array_merge, dedupe_array, sort_by_counter_asc}, }; @@ -24,7 +26,11 @@ pub unconstrained fn combine_data( revertible.l2_to_l1_msgs, )); - let public_data_update_requests = dedupe_array(output_hints.public_data_writes); + let public_data_writes = dedupe_array(output_hints.public_data_writes).map( + |w: PublicDataUpdateRequest| { + PublicDataWrite { leaf_slot: w.leaf_slot, value: w.new_value } + }, + ); let note_encrypted_logs_hashes = sort_by_counter_asc(array_merge( non_revertible.note_encrypted_logs_hashes, @@ -57,7 +63,7 @@ pub unconstrained fn combine_data( note_encrypted_log_preimages_length, encrypted_log_preimages_length, unencrypted_log_preimages_length, - public_data_update_requests, + public_data_writes, gas_used: revertible.gas_used + non_revertible.gas_used, } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator.nr index 4b5da5a4d8f..a34e7b833ab 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator.nr @@ -17,15 +17,15 @@ use dep::types::{ note_hash::ScopedNoteHash, nullifier::Nullifier, public_data_update_request::PublicDataUpdateRequest, - public_data_write::OverridablePublicDataWrite, + public_data_write::{OverridablePublicDataWrite, PublicDataWrite}, }, data::PublicDataLeafHint, hash::silo_note_hash, messaging::l2_to_l1_message::ScopedL2ToL1Message, partial_state_reference::PartialStateReference, + traits::is_empty, utils::arrays::{ assert_combined_sorted_transformed_value_array_asc, assert_combined_transformed_array, - assert_deduped_array, }, }; @@ -214,10 +214,35 @@ impl PublicTailOutputValidator, + public_call_stack: BoundedVec, previous_validation_request_array_lengths: PublicValidationRequestArrayLengths, validation_requests: PublicValidationRequestsBuilder, previous_accumulated_data_array_lengths: PublicAccumulatedDataArrayLengths, diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_merge.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_merge.nr index 0d54460ec3d..094e33dc483 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_merge.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_merge.nr @@ -31,12 +31,9 @@ impl PublicKernelMergeCircuitPrivateInputs { fn get_phase(self) -> u8 { let public_inputs = self.previous_kernel.public_inputs; - let needs_setup = !public_inputs.end_non_revertible.public_call_stack[0] - .call_context - .contract_address - .is_zero(); - let needs_app_logic = - !public_inputs.end.public_call_stack[0].call_context.contract_address.is_zero(); + let needs_setup = + !public_inputs.end_non_revertible.public_call_stack[0].contract_address.is_zero(); + let needs_app_logic = !public_inputs.end.public_call_stack[0].contract_address.is_zero(); if needs_setup { PublicKernelPhase.SETUP } else if needs_app_logic { @@ -213,7 +210,7 @@ mod tests { assert_array_eq( public_inputs.end_non_revertible.public_call_stack, - [prev_calls[0]], // Public call requests can only be propagated from previous kernel. + [prev_calls[0].inner], // Public call requests can only be propagated from previous kernel. ); } 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 96e3f7c0022..2fafa38eb6e 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 @@ -107,8 +107,7 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, nullifier::ScopedNullifier, - nullifier_leaf_preimage::NullifierLeafPreimage, - public_data_update_request::PublicDataUpdateRequest, + nullifier_leaf_preimage::NullifierLeafPreimage, public_data_write::PublicDataWrite, }, address::AztecAddress, constants::{ @@ -593,23 +592,11 @@ mod tests { let public_inputs = builder.execute(); assert_array_eq( - public_inputs.end.public_data_update_requests, + public_inputs.end.public_data_writes, [ - PublicDataUpdateRequest { - leaf_slot: 3333, - new_value: 301, - counter: prev_writes[4].counter, - }, - PublicDataUpdateRequest { - leaf_slot: 11, - new_value: 500, - counter: prev_writes[1].counter, - }, - PublicDataUpdateRequest { - leaf_slot: 22, - new_value: 701, - counter: prev_writes[3].counter, - }, + PublicDataWrite { leaf_slot: 3333, value: 301 }, + PublicDataWrite { leaf_slot: 11, value: 500 }, + PublicDataWrite { leaf_slot: 22, value: 701 }, ], ); } 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 498924d2a6d..b63e3376986 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 @@ -10,8 +10,7 @@ use dep::types::{ abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, kernel_circuit_public_inputs::KernelCircuitPublicInputs, - nullifier_leaf_preimage::NullifierLeafPreimage, - public_data_update_request::PublicDataUpdateRequest, + nullifier_leaf_preimage::NullifierLeafPreimage, public_data_write::PublicDataWrite, }, address::AztecAddress, constants::{ @@ -36,7 +35,7 @@ use dep::types::{ partial_state_reference::PartialStateReference, storage::map::derive_storage_slot_in_map, traits::is_empty, - utils::field::{full_field_greater_than, full_field_less_than}, + utils::{arrays::find_index_hint, field::{full_field_greater_than, full_field_less_than}}, }; // Temporary struct to avoid changing all the references to kernel_data. Will remove it and just pass in the public_inputs. @@ -49,6 +48,7 @@ pub struct BaseRollupInputs { start: PartialStateReference, state_diff_hints: StateDiffHints, + transaction_fee: Field, fee_payer_fee_juice_balance_read_hint: PublicDataHint, // TODO: The following 6 values are eventually going to be nuked from here. See discussion: @@ -128,10 +128,8 @@ impl BaseRollupInputs { self.check_nullifier_tree_non_membership_and_insert_to_tree(); // Inject protocol update requests for deducting tx_fee from fee_payer's balance - let gas_fees = self.constants.global_variables.gas_fees; - let transaction_fee = self.kernel_data.public_inputs.compute_transaction_fee(gas_fees); let all_public_data_update_requests = - self.calculate_all_public_data_update_requests(transaction_fee); + self.calculate_all_public_data_update_requests(self.transaction_fee); // Validate public data update requests and update public data tree let end_public_data_tree_snapshot = @@ -149,7 +147,7 @@ impl BaseRollupInputs { let tx_effects_hash = compute_tx_effects_hash( self.kernel_data.public_inputs.end, self.kernel_data.public_inputs.revert_code, - transaction_fee, + self.transaction_fee, all_public_data_update_requests, out_hash, ); @@ -169,7 +167,7 @@ impl BaseRollupInputs { }, txs_effects_hash: tx_effects_hash, out_hash, - accumulated_fees: transaction_fee, + accumulated_fees: self.transaction_fee, } } @@ -252,11 +250,13 @@ impl BaseRollupInputs { fn validate_and_process_public_state( self, - all_update_requests: [PublicDataUpdateRequest; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + all_update_requests: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], ) -> AppendOnlyTreeSnapshot { let end_public_data_tree_snapshot = insert_public_data_update_requests( self.start.public_data_tree, - all_update_requests.map(PublicDataTreeLeaf::from), + all_update_requests.map(|w: PublicDataWrite| { + PublicDataTreeLeaf { slot: w.leaf_slot, value: w.value } + }), self.sorted_public_data_writes, self.sorted_public_data_writes_indexes, self.low_public_data_writes_preimages, @@ -273,12 +273,11 @@ impl BaseRollupInputs { fn calculate_all_public_data_update_requests( self, tx_fee: Field, - ) -> [PublicDataUpdateRequest; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] { - let mut all_update_requests: [PublicDataUpdateRequest; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] = - [PublicDataUpdateRequest::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; + ) -> [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] { + let mut all_update_requests: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] = + [PublicDataWrite::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { - all_update_requests[i] = - self.kernel_data.public_inputs.end.public_data_update_requests[i]; + all_update_requests[i] = self.kernel_data.public_inputs.end.public_data_writes[i]; } let (payment_update_request, payment_update_index) = @@ -294,61 +293,59 @@ impl BaseRollupInputs { // from the balance of the fee_payer, using the fee_payer_fee_juice_balance_read_hint to read the current balance. // Returns the data update request that subtracts the tx_fee from the fee_payer's balance, and the index where it // should be inserted in the public data update requests array. - fn build_or_patch_payment_update_request( - self, - tx_fee: Field, - ) -> (PublicDataUpdateRequest, u32) { + fn build_or_patch_payment_update_request(self, tx_fee: Field) -> (PublicDataWrite, u32) { let fee_payer = self.kernel_data.public_inputs.fee_payer; // TODO(@spalladino) Eventually remove the is_zero condition as we should always charge fees to every tx if !fee_payer.is_zero() { let read_hint = self.fee_payer_fee_juice_balance_read_hint; let leaf_slot = compute_fee_payer_fee_juice_balance_leaf_slot(fee_payer); + let existing_update_index = unsafe { + find_index_hint( + self.kernel_data.public_inputs.end.public_data_writes, + |w: PublicDataWrite| w.leaf_slot == leaf_slot, + ) + }; - if read_hint.leaf_slot == 0 { + if existing_update_index != MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { // Is there a balance update already in this tx? If so, update it and return its index. - let existing_update_index = - unsafe { self.find_fee_payer_fee_juice_update_index(leaf_slot) }; - let existing_update = self.kernel_data.public_inputs.end.public_data_update_requests - [existing_update_index]; - assert( - existing_update.leaf_slot == leaf_slot, - "Wrong leaf slot for Fee Juice balance update request", - ); - assert( - !existing_update.new_value.lt(tx_fee), - "Not enough balance for fee payer after claim to pay for transaction", - ); + let existing_update = + self.kernel_data.public_inputs.end.public_data_writes[existing_update_index]; + assert( + existing_update.leaf_slot == leaf_slot, + "Wrong leaf slot for Fee Juice balance update request", + ); + assert( + !existing_update.value.lt(tx_fee), + "Not enough balance for fee payer after claim to pay for transaction", + ); - let new_value = - compute_public_data_tree_value(existing_update.new_value - tx_fee); - let protocol_update_request = - PublicDataUpdateRequest { leaf_slot, new_value, counter: 0 }; - (protocol_update_request, existing_update_index as u32) - } else { - // Otherwise, build a new one to be inserted into the protocol update requests at the end of the array. - read_hint.validate(self.start.public_data_tree.root); + let value = compute_public_data_tree_value(existing_update.value - tx_fee); + let protocol_update_request = PublicDataWrite { leaf_slot, value }; + (protocol_update_request, existing_update_index as u32) + } else { + // Otherwise, build a new one to be inserted into the protocol update requests at the end of the array. + read_hint.validate(self.start.public_data_tree.root); - let balance = read_hint.value; - assert( - read_hint.leaf_slot == leaf_slot, - "Wrong leaf slot for Fee Juice balance read hint", - ); - assert( - !balance.lt(tx_fee), - "Not enough balance for fee payer to pay for transaction", - ); + let balance = read_hint.value; + assert( + read_hint.leaf_slot == leaf_slot, + "Wrong leaf slot for Fee Juice balance read hint", + ); + assert( + !balance.lt(tx_fee), + "Not enough balance for fee payer to pay for transaction", + ); - let new_value = compute_public_data_tree_value(balance - tx_fee); - let protocol_update_request = - PublicDataUpdateRequest { leaf_slot, new_value, counter: 0 }; - (protocol_update_request, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) - } - } else { - // Nothing to do, just place an empty update request at the end of the array - (PublicDataUpdateRequest::empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) + let value = compute_public_data_tree_value(balance - tx_fee); + let protocol_update_request = PublicDataWrite { leaf_slot, value }; + (protocol_update_request, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) } + } else { + // Nothing to do, just place an empty update request at the end of the array + (PublicDataWrite::empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) } + } // Check that the block header used by each kernel is a member of the blocks tree --> since the block header // contains roots of all the trees this is sufficient to verify that the tree roots used by kernels are correct @@ -371,21 +368,6 @@ impl BaseRollupInputs { archive_root, ); } - - unconstrained fn find_fee_payer_fee_juice_update_index(self, leaf_slot: Field) -> u32 { - let mut update_index = MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + 1; - for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { - if self.kernel_data.public_inputs.end.public_data_update_requests[i].leaf_slot - == leaf_slot { - update_index = i; - } - } - assert( - update_index < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - "Could not find fee payer Fee Juice update request", - ); - update_index - } } fn insert_public_data_update_requests( @@ -519,8 +501,7 @@ mod tests { use dep::types::{ abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, - nullifier_leaf_preimage::NullifierLeafPreimage, - public_data_update_request::PublicDataUpdateRequest, + nullifier_leaf_preimage::NullifierLeafPreimage, public_data_write::PublicDataWrite, }, address::{AztecAddress, EthAddress}, constants::{ @@ -578,11 +559,8 @@ mod tests { if i < (user_public_data_writes.len()) { let leaf = user_public_data_writes.get_unchecked(i).1; - kernel_data.public_inputs.end.public_data_update_requests[i] = PublicDataUpdateRequest { - leaf_slot: leaf.slot, - new_value: leaf.value, - counter: 0, - }; + kernel_data.public_inputs.end.public_data_writes[i] = + PublicDataWrite { leaf_slot: leaf.slot, value: leaf.value }; } } @@ -657,6 +635,7 @@ mod tests { struct BaseRollupInputsBuilder { kernel_data: FixtureBuilder, + transaction_fee: Field, pre_existing_notes: [Field; MAX_NOTE_HASHES_PER_TX], pre_existing_nullifiers: [NullifierLeafPreimage; MAX_NULLIFIERS_PER_TX], pre_existing_contracts: [Field; 2], @@ -905,6 +884,7 @@ mod tests { sibling_path: start_archive.get_sibling_path(0), }, constants: self.constants, + transaction_fee: self.transaction_fee, fee_payer_fee_juice_balance_read_hint, } } @@ -927,6 +907,7 @@ mod tests { fn empty() -> Self { BaseRollupInputsBuilder { kernel_data: FixtureBuilder::new(), + transaction_fee: 0, pre_existing_notes: [0; MAX_NOTE_HASHES_PER_TX], pre_existing_nullifiers: [NullifierLeafPreimage::empty(); MAX_NULLIFIERS_PER_TX], pre_existing_contracts: [0; 2], @@ -1318,7 +1299,7 @@ mod tests { builder.fee_payer_fee_juice_balance_pre_existing_public_data_index = Option::some(0); // Set values for computing exact tx_fee - builder.kernel_data.tx_context.gas_settings.inclusion_fee = tx_fee; + builder.transaction_fee = tx_fee; // Set expected protocol data update builder.protocol_public_data_writes.push(( @@ -1367,7 +1348,7 @@ mod tests { }; // Set values for computing exact tx_fee - builder.kernel_data.tx_context.gas_settings.inclusion_fee = tx_fee; + builder.transaction_fee = tx_fee; // Create an existing data update that corresponds to a claim builder.public_data_writes.push(( @@ -1422,7 +1403,7 @@ mod tests { builder.fee_payer_fee_juice_balance_pre_existing_public_data_index = Option::some(0); // Set values for computing exact tx_fee - builder.kernel_data.tx_context.gas_settings.inclusion_fee = tx_fee; + builder.transaction_fee = tx_fee; // Set expected protocol data update builder.protocol_public_data_writes.push(( diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/avm_proof_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/avm_proof_data.nr index 43bc6b18dfb..5a2aefbf616 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/avm_proof_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/avm_proof_data.nr @@ -1,11 +1,11 @@ use dep::types::{ - abis::kernel_circuit_public_inputs::vm_circuit_public_inputs::VMCircuitPublicInputs, + abis::avm_circuit_public_inputs::AvmCircuitPublicInputs, constants::AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, proof::{avm_proof::AvmProof, traits::Verifiable, vk_data::VkData}, }; pub struct AvmProofData { - public_inputs: VMCircuitPublicInputs, + public_inputs: AvmCircuitPublicInputs, proof: AvmProof, vk_data: VkData, } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/public_tube_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/public_tube_data.nr index cf0fe7d3300..3fe33cc8734 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/public_tube_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/public_tube_data.nr @@ -1,18 +1,18 @@ use dep::types::{ - abis::kernel_circuit_public_inputs::KernelCircuitPublicInputs, + abis::kernel_circuit_public_inputs::PrivateToPublicKernelCircuitPublicInputs, constants::HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS, proof::{traits::Verifiable, tube_proof::TubeProof, vk_data::VkData}, }; pub struct PublicTubeData { - public_inputs: KernelCircuitPublicInputs, // TODO: This should be the output of private-kernel-tail-to-public. + public_inputs: PrivateToPublicKernelCircuitPublicInputs, proof: TubeProof, vk_data: VkData, } impl Verifiable for PublicTubeData { fn verify(self) { - let inputs = KernelCircuitPublicInputs::serialize(self.public_inputs); + let inputs = PrivateToPublicKernelCircuitPublicInputs::serialize(self.public_inputs); std::verify_proof( self.vk_data.vk.key, self.proof.fields, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr index 07eb8498ff6..0d557a7cf9c 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr @@ -39,6 +39,13 @@ pub struct PrivateBaseRollupInputs { } impl PrivateBaseRollupInputs { + fn compute_transaction_fee(self) -> Field { + let gas_fees = self.constants.global_variables.gas_fees; + let data = self.tube_data.public_inputs; + let inclusion_fee = data.constants.tx_context.gas_settings.inclusion_fee; + inclusion_fee + data.end.gas_used.compute_fee(gas_fees) + } + pub fn execute(self) -> BaseOrMergeRollupPublicInputs { if !dep::std::runtime::is_unconstrained() { self.tube_data.verify(); @@ -46,10 +53,13 @@ impl PrivateBaseRollupInputs { // self.tube_data.vk_data.validate_in_vk_tree(self.tube_data.public_inputs.constants.vk_tree_root, ALLOWED_PREVIOUS_CIRCUITS); } + let transaction_fee = self.compute_transaction_fee(); + BaseRollupInputs { kernel_data: KernelData { public_inputs: self.tube_data.public_inputs }, start: self.start, state_diff_hints: self.state_diff_hints, + transaction_fee, fee_payer_fee_juice_balance_read_hint: self.fee_payer_fee_juice_balance_read_hint, sorted_public_data_writes: self.sorted_public_data_writes, sorted_public_data_writes_indexes: self.sorted_public_data_writes_indexes, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr index 08fc35076bf..8a8a9650bbc 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr @@ -10,13 +10,21 @@ use crate::{ }, }; use dep::types::{ + abis::{ + accumulated_data::CombinedAccumulatedData, + combined_constant_data::CombinedConstantData, + gas::Gas, + log_hash::{LogHash, ScopedLogHash}, + }, constants::{ ARCHIVE_HEIGHT, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, TUBE_VK_INDEX, }, data::{public_data_hint::PublicDataHint, PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, + KernelCircuitPublicInputs, merkle_tree::MembershipWitness, partial_state_reference::PartialStateReference, + utils::arrays::array_merge, }; pub struct PublicBaseRollupInputs { @@ -38,21 +46,93 @@ pub struct PublicBaseRollupInputs { } impl PublicBaseRollupInputs { + fn generate_kernel_circuit_public_inputs(self) -> KernelCircuitPublicInputs { + let from_private = self.tube_data.public_inputs; + let from_public = self.avm_proof_data.public_inputs; + let reverted = from_public.reverted; + + let note_encrypted_logs_hashes = if reverted { + from_private.non_revertible_accumulated_data.note_encrypted_logs_hashes + } else { + array_merge( + from_private.non_revertible_accumulated_data.note_encrypted_logs_hashes, + from_private.revertible_accumulated_data.note_encrypted_logs_hashes, + ) + }; + let encrypted_logs_hashes = if reverted { + from_private.non_revertible_accumulated_data.encrypted_logs_hashes + } else { + array_merge( + from_private.non_revertible_accumulated_data.encrypted_logs_hashes, + from_private.revertible_accumulated_data.encrypted_logs_hashes, + ) + }; + let note_encrypted_log_preimages_length = + note_encrypted_logs_hashes.fold(0, |len, l: LogHash| len + l.length); + let encrypted_log_preimages_length = + encrypted_logs_hashes.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); + let unencrypted_log_preimages_length = from_public + .accumulated_data + .unencrypted_logs_hashes + .fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); + let end = CombinedAccumulatedData { + note_hashes: from_public.accumulated_data.note_hashes, + nullifiers: from_public.accumulated_data.nullifiers, + l2_to_l1_msgs: from_public.accumulated_data.l2_to_l1_msgs, + note_encrypted_logs_hashes, + encrypted_logs_hashes, + unencrypted_logs_hashes: from_public.accumulated_data.unencrypted_logs_hashes, + note_encrypted_log_preimages_length, + encrypted_log_preimages_length, + unencrypted_log_preimages_length, + public_data_writes: from_public.accumulated_data.public_data_writes, + gas_used: Gas::empty(), // gas_used is not used in rollup circuits. + }; + + let constants = + CombinedConstantData::combine(from_private.constants, from_public.global_variables); + + let start_state = PartialStateReference { + note_hash_tree: from_public.start_tree_snapshots.note_hash_tree, + nullifier_tree: from_public.start_tree_snapshots.nullifier_tree, + public_data_tree: from_public.start_tree_snapshots.public_data_tree, + }; + + let revert_code = if from_public.reverted { 1 } else { 0 }; + + KernelCircuitPublicInputs { + constants, + rollup_validation_requests: from_private.rollup_validation_requests, + end, + start_state, + revert_code, + fee_payer: from_private.fee_payer, + } + } + pub fn execute(self) -> BaseOrMergeRollupPublicInputs { - // Skip it for now. As we currently swap the public inputs to be the output of public tail, so the proof won't be verfied. - // if !dep::std::runtime::is_unconstrained() { - // self.tube_data.verify(); - // self.tube_data.vk_data.validate_in_vk_tree([TUBE_VK_INDEX]); - // } + if !dep::std::runtime::is_unconstrained() { + self.tube_data.verify(); + // TODO(#7410) + // self.tube_data.vk_data.validate_in_vk_tree([TUBE_VK_INDEX]); + } + // TODO(#8470) // if !dep::std::runtime::is_unconstrained() { // self.avm_proof_data.verify(); // self.avm_proof_data.vk_data.validate_in_vk_tree([AVM_VK_INDEX]); // } + // TODO: Validate tube_data.public_inputs vs avm_proof_data.public_inputs + // TODO: Deprecate KernelData. + // Temporary workaround to create KernelCircuitPublicInputs from PublicKernelCircuitPublicInputs and AvmCircuitPublicInputs + // so that we don't have to modify base_rollup_inputs. + let public_inputs = self.generate_kernel_circuit_public_inputs(); + BaseRollupInputs { - kernel_data: KernelData { public_inputs: self.tube_data.public_inputs }, + kernel_data: KernelData { public_inputs }, start: self.start, state_diff_hints: self.state_diff_hints, + transaction_fee: self.avm_proof_data.public_inputs.transaction_fee, fee_payer_fee_juice_balance_read_hint: self.fee_payer_fee_juice_balance_read_hint, sorted_public_data_writes: self.sorted_public_data_writes, sorted_public_data_writes_indexes: self.sorted_public_data_writes_indexes, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index 68bdd43b3d8..3e1a1027d4e 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -9,7 +9,7 @@ use dep::types::{ abis::{ accumulated_data::CombinedAccumulatedData, log_hash::{LogHash, ScopedLogHash}, - public_data_update_request::PublicDataUpdateRequest, + public_data_write::PublicDataWrite, }, constants::{ AZTEC_EPOCH_DURATION, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, @@ -21,6 +21,7 @@ use dep::types::{ silo_unencrypted_log_hash, }, merkle_tree::VariableMerkleTree, + traits::is_empty, utils::arrays::{array_length, array_merge}, }; @@ -254,7 +255,7 @@ pub fn compute_tx_effects_hash( combined: CombinedAccumulatedData, revert_code: u8, transaction_fee: Field, - all_public_data_update_requests: [PublicDataUpdateRequest; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + all_public_data_update_requests: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], out_hash: Field, ) -> Field { let mut tx_effects_hash_input = [0; TX_EFFECTS_HASH_INPUT_FIELDS]; @@ -303,7 +304,7 @@ pub fn compute_tx_effects_hash( // PUBLIC DATA UPDATE REQUESTS for j in 0..MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { tx_effects_hash_input[offset + j * 2] = public_data_update_requests[j].leaf_slot; - tx_effects_hash_input[offset + j * 2 + 1] = public_data_update_requests[j].new_value; + tx_effects_hash_input[offset + j * 2 + 1] = public_data_update_requests[j].value; } offset += MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2; @@ -346,12 +347,12 @@ pub fn compute_tx_effects_hash( } fn get_all_update_requests_for_tx_effects( - all_public_data_update_requests: [PublicDataUpdateRequest; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], -) -> [PublicDataUpdateRequest; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] { - let mut all_update_requests: BoundedVec = + all_public_data_update_requests: [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], +) -> [PublicDataWrite; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] { + let mut all_update_requests: BoundedVec = BoundedVec::new(); for update_request in all_public_data_update_requests { - if !update_request.is_empty() { + if !is_empty(update_request) { all_update_requests.push(update_request); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr new file mode 100644 index 00000000000..a71e78b77cc --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/avm_accumulated_data.nr @@ -0,0 +1,109 @@ +use crate::{ + abis::{gas::Gas, log_hash::ScopedLogHash, public_data_write::PublicDataWrite}, + constants::{ + AVM_ACCUMULATED_DATA_LENGTH, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + }, + messaging::l2_to_l1_message::ScopedL2ToL1Message, + traits::{Deserialize, Empty, Serialize}, + utils::reader::Reader, +}; + +pub struct AvmAccumulatedData { + // The note hashes from private combining with those made in the AVM execution. + note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + // The nullifiers from private combining with those made in the AVM execution. + nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + // The L2 to L1 messages from private combining with those made in the AVM execution. + l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], + // TODO(#9589): This should only contain logs emitted from public. + // The unencrypted logs emitted from private combining with those made in the AVM execution. + unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + // The public data writes made in the AVM execution. + public_data_writes: [PublicDataWrite; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], +} + +impl Empty for AvmAccumulatedData { + fn empty() -> Self { + AvmAccumulatedData { + note_hashes: [0; MAX_NOTE_HASHES_PER_TX], + nullifiers: [0; MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], + unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + public_data_writes: [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + } + } +} + +impl Serialize for AvmAccumulatedData { + fn serialize(self) -> [Field; AVM_ACCUMULATED_DATA_LENGTH] { + let mut fields: BoundedVec = BoundedVec::new(); + + for i in 0..self.note_hashes.len() { + fields.extend_from_array(self.note_hashes[i].serialize()); + } + + for i in 0..self.nullifiers.len() { + fields.extend_from_array(self.nullifiers[i].serialize()); + } + + for i in 0..self.l2_to_l1_msgs.len() { + fields.extend_from_array(self.l2_to_l1_msgs[i].serialize()); + } + + for i in 0..self.unencrypted_logs_hashes.len() { + fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + } + + for i in 0..self.public_data_writes.len() { + fields.extend_from_array(self.public_data_writes[i].serialize()); + } + + assert_eq(fields.len(), AVM_ACCUMULATED_DATA_LENGTH); + + fields.storage + } +} + +impl Deserialize for AvmAccumulatedData { + fn deserialize(fields: [Field; AVM_ACCUMULATED_DATA_LENGTH]) -> AvmAccumulatedData { + let mut reader = Reader::new(fields); + + let item = AvmAccumulatedData { + note_hashes: reader.read_array(), + nullifiers: reader.read_array(), + l2_to_l1_msgs: reader.read_struct_array( + ScopedL2ToL1Message::deserialize, + [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], + ), + unencrypted_logs_hashes: reader.read_struct_array( + ScopedLogHash::deserialize, + [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + ), + public_data_writes: reader.read_struct_array( + PublicDataWrite::deserialize, + [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + ), + }; + reader.finish(); + item + } +} + +impl Eq for AvmAccumulatedData { + fn eq(self, other: Self) -> bool { + (self.note_hashes == other.note_hashes) + & (self.nullifiers == other.nullifiers) + & (self.l2_to_l1_msgs == other.l2_to_l1_msgs) + & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) + & (self.public_data_writes == other.public_data_writes) + } +} + +#[test] +fn serialization_of_empty_avm_accumulated_data() { + let item = AvmAccumulatedData::empty(); + let serialized = item.serialize(); + let deserialized = AvmAccumulatedData::deserialize(serialized); + assert(item.eq(deserialized)); +} 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 56116a56531..7b45a15dd0d 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 @@ -1,9 +1,5 @@ use crate::{ - abis::{ - gas::Gas, - log_hash::{LogHash, ScopedLogHash}, - public_data_update_request::PublicDataUpdateRequest, - }, + abis::{gas::Gas, log_hash::{LogHash, ScopedLogHash}, public_data_write::PublicDataWrite}, constants::{ COMBINED_ACCUMULATED_DATA_LENGTH, MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, @@ -29,7 +25,7 @@ pub struct CombinedAccumulatedData { encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, - public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + public_data_writes: [PublicDataWrite; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], gas_used: Gas, } @@ -46,9 +42,7 @@ impl Empty for CombinedAccumulatedData { note_encrypted_log_preimages_length: 0, encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, - public_data_update_requests: [ - PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX - ], + public_data_writes: [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], gas_used: Gas::empty(), } } @@ -77,7 +71,7 @@ impl Serialize for CombinedAccumulatedData { fields.push(self.unencrypted_log_preimages_length); for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { - fields.extend_from_array(self.public_data_update_requests[i].serialize()); + fields.extend_from_array(self.public_data_writes[i].serialize()); } fields.extend_from_array(self.gas_used.serialize()); @@ -93,8 +87,8 @@ impl Deserialize for CombinedAccumulatedData { let mut reader = Reader::new(fields); let item = CombinedAccumulatedData { - note_hashes: reader.read_array([0; MAX_NOTE_HASHES_PER_TX]), - nullifiers: reader.read_array([0; MAX_NULLIFIERS_PER_TX]), + note_hashes: reader.read_array(), + nullifiers: reader.read_array(), l2_to_l1_msgs: reader.read_struct_array( ScopedL2ToL1Message::deserialize, [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], @@ -114,9 +108,9 @@ impl Deserialize for CombinedAccumulatedData { note_encrypted_log_preimages_length: reader.read(), encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), - public_data_update_requests: reader.read_struct_array( - PublicDataUpdateRequest::deserialize, - [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + public_data_writes: reader.read_struct_array( + PublicDataWrite::deserialize, + [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], ), gas_used: reader.read_struct(Gas::deserialize), }; @@ -139,7 +133,7 @@ impl Eq for CombinedAccumulatedData { ) & (self.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & (self.unencrypted_log_preimages_length == other.unencrypted_log_preimages_length) - & (self.public_data_update_requests == other.public_data_update_requests) + & (self.public_data_writes == other.public_data_writes) & (self.gas_used == other.gas_used) } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/mod.nr index 5b1d9f59179..b3950385b1f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/mod.nr @@ -1,11 +1,19 @@ +mod avm_accumulated_data; mod combined_accumulated_data; mod private_accumulated_data; mod private_accumulated_data_builder; +mod private_to_avm_accumulated_data; +mod private_to_public_accumulated_data; +mod private_to_public_accumulated_data_builder; mod public_accumulated_data; mod public_accumulated_data_builder; +pub use avm_accumulated_data::AvmAccumulatedData; pub use combined_accumulated_data::CombinedAccumulatedData; pub use private_accumulated_data::PrivateAccumulatedData; pub use private_accumulated_data_builder::PrivateAccumulatedDataBuilder; +pub use private_to_avm_accumulated_data::PrivateToAvmAccumulatedData; +pub use private_to_public_accumulated_data::PrivateToPublicAccumulatedData; +pub use private_to_public_accumulated_data_builder::PrivateToPublicAccumulatedDataBuilder; pub use public_accumulated_data::{PublicAccumulatedData, PublicAccumulatedDataArrayLengths}; pub use public_accumulated_data_builder::PublicAccumulatedDataBuilder; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index b7aee6d64c6..18cc6edac75 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -5,15 +5,16 @@ use crate::{ nullifier::ScopedNullifier, private_call_request::PrivateCallRequest, public_call_request::PublicCallRequest, + side_effect::Counted, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Deserialize, Empty, Serialize}, utils::reader::Reader, }; use crate::constants::{ - MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, PRIVATE_ACCUMULATED_DATA_LENGTH, }; @@ -26,7 +27,7 @@ pub struct PrivateAccumulatedData { encrypted_logs_hashes: [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - public_call_requests: [PublicCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_requests: [Counted; MAX_ENQUEUED_CALLS_PER_TX], private_call_stack: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], } @@ -58,7 +59,7 @@ impl Serialize for PrivateAccumulatedData { fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); } - for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX { + for i in 0..MAX_ENQUEUED_CALLS_PER_TX { fields.extend_from_array(self.public_call_requests[i].serialize()); } @@ -102,8 +103,8 @@ impl Deserialize for PrivateAccumulatedData { [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], ), public_call_requests: reader.read_struct_array( - PublicCallRequest::deserialize, - [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + Counted::deserialize, + [Counted::empty(); MAX_ENQUEUED_CALLS_PER_TX], ), private_call_stack: reader.read_struct_array( PrivateCallRequest::deserialize, @@ -137,14 +138,14 @@ impl Empty for PrivateAccumulatedData { note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [ScopedEncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], - public_call_requests: [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_requests: [Counted::empty(); MAX_ENQUEUED_CALLS_PER_TX], private_call_stack: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], } } } #[test] -fn serialization_of_empty() { +fn serialization_of_empty_private_accumulated_data() { let item = PrivateAccumulatedData::empty(); let serialized = item.serialize(); let deserialized = PrivateAccumulatedData::deserialize(serialized); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index 3bd58cddbcf..fbf1d4fe2d8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -6,11 +6,12 @@ use crate::{ nullifier::ScopedNullifier, private_call_request::PrivateCallRequest, public_call_request::PublicCallRequest, + side_effect::Counted, }, constants::{ - MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::Empty, @@ -25,7 +26,7 @@ pub struct PrivateAccumulatedDataBuilder { encrypted_logs_hashes: BoundedVec, unencrypted_logs_hashes: BoundedVec, - public_call_requests: BoundedVec, + public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_TX>, private_call_stack: BoundedVec, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_avm_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_avm_accumulated_data.nr new file mode 100644 index 00000000000..da99c0f548e --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_avm_accumulated_data.nr @@ -0,0 +1,137 @@ +use crate::constants::{ + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS, PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH, +}; +use crate::{ + messaging::l2_to_l1_message::ScopedL2ToL1Message, + traits::{Deserialize, Empty, Serialize}, + utils::{arrays::array_length, reader::Reader}, +}; + +pub struct PrivateToAvmAccumulatedData { + note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], +} + +impl Empty for PrivateToAvmAccumulatedData { + fn empty() -> Self { + PrivateToAvmAccumulatedData { + note_hashes: [0; MAX_NOTE_HASHES_PER_TX], + nullifiers: [0; MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], + } + } +} + +impl Eq for PrivateToAvmAccumulatedData { + fn eq(self, other: Self) -> bool { + (self.note_hashes == other.note_hashes) + & (self.nullifiers == other.nullifiers) + & (self.l2_to_l1_msgs == other.l2_to_l1_msgs) + } +} + +impl Serialize for PrivateToAvmAccumulatedData { + fn serialize(self) -> [Field; PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH] { + let mut fields: BoundedVec = + BoundedVec::new(); + + fields.extend_from_array(self.note_hashes); + fields.extend_from_array(self.nullifiers); + for i in 0..self.l2_to_l1_msgs.len() { + fields.extend_from_array(self.l2_to_l1_msgs[i].serialize()); + } + + assert_eq(fields.len(), PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH); + + fields.storage + } +} + +impl Deserialize for PrivateToAvmAccumulatedData { + fn deserialize( + fields: [Field; PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH], + ) -> PrivateToAvmAccumulatedData { + let mut reader = Reader::new(fields); + + let item = PrivateToAvmAccumulatedData { + note_hashes: reader.read_array(), + nullifiers: reader.read_array(), + l2_to_l1_msgs: reader.read_struct_array( + ScopedL2ToL1Message::deserialize, + [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], + ), + }; + reader.finish(); + item + } +} + +pub struct PrivateToAvmAccumulatedDataArrayLengths { + note_hashes: u32, + nullifiers: u32, + l2_to_l1_msgs: u32, +} + +impl PrivateToAvmAccumulatedDataArrayLengths { + pub fn new(data: PrivateToAvmAccumulatedData) -> Self { + PrivateToAvmAccumulatedDataArrayLengths { + note_hashes: array_length(data.note_hashes), + nullifiers: array_length(data.nullifiers), + l2_to_l1_msgs: array_length(data.l2_to_l1_msgs), + } + } +} + +impl Empty for PrivateToAvmAccumulatedDataArrayLengths { + fn empty() -> Self { + PrivateToAvmAccumulatedDataArrayLengths { note_hashes: 0, nullifiers: 0, l2_to_l1_msgs: 0 } + } +} + +impl Eq for PrivateToAvmAccumulatedDataArrayLengths { + fn eq(self, other: Self) -> bool { + (self.note_hashes == other.note_hashes) + & (self.nullifiers == other.nullifiers) + & (self.l2_to_l1_msgs == other.l2_to_l1_msgs) + } +} + +impl Serialize for PrivateToAvmAccumulatedDataArrayLengths { + fn serialize(self) -> [Field; NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS] { + let mut fields: BoundedVec = + BoundedVec::new(); + + fields.push(self.note_hashes as Field); + fields.push(self.nullifiers as Field); + fields.push(self.l2_to_l1_msgs as Field); + + fields.storage + } +} + +impl Deserialize for PrivateToAvmAccumulatedDataArrayLengths { + fn deserialize( + fields: [Field; NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS], + ) -> PrivateToAvmAccumulatedDataArrayLengths { + let mut reader = Reader::new(fields); + + let item = Self { + note_hashes: reader.read_u32(), + nullifiers: reader.read_u32(), + l2_to_l1_msgs: reader.read_u32(), + }; + + reader.finish(); + item + } +} + +#[test] +fn serialization_of_empty_private_to_public_accumulated_data() { + let item = PrivateToAvmAccumulatedData::empty(); + let serialized = item.serialize(); + let deserialized = PrivateToAvmAccumulatedData::deserialize(serialized); + assert_eq(item, deserialized); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data.nr new file mode 100644 index 00000000000..2cc7e171d8c --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data.nr @@ -0,0 +1,124 @@ +use crate::{ + abis::{gas::Gas, log_hash::{LogHash, ScopedLogHash}, public_call_request::PublicCallRequest}, + messaging::l2_to_l1_message::ScopedL2ToL1Message, + traits::{Deserialize, Empty, Serialize}, + utils::{arrays::array_length, reader::Reader}, +}; +use crate::constants::{ + MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH, +}; + +pub struct PrivateToPublicAccumulatedData { + note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], + note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + encrypted_logs_hashes: [ScopedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], + unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + public_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], + gas_used: Gas, +} + +impl Empty for PrivateToPublicAccumulatedData { + fn empty() -> Self { + PrivateToPublicAccumulatedData { + note_hashes: [0; MAX_NOTE_HASHES_PER_TX], + nullifiers: [0; MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], + note_encrypted_logs_hashes: [LogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + encrypted_logs_hashes: [ScopedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], + unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + public_call_requests: [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], + gas_used: Gas::empty(), + } + } +} + +impl Eq for PrivateToPublicAccumulatedData { + fn eq(self, other: Self) -> bool { + (self.note_hashes == other.note_hashes) + & (self.nullifiers == other.nullifiers) + & (self.l2_to_l1_msgs == other.l2_to_l1_msgs) + & (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) + & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) + & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) + & (self.public_call_requests == other.public_call_requests) + & (self.gas_used == other.gas_used) + } +} + +impl Serialize for PrivateToPublicAccumulatedData { + fn serialize(self) -> [Field; PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH] { + let mut fields: BoundedVec = + BoundedVec::new(); + + fields.extend_from_array(self.note_hashes); + fields.extend_from_array(self.nullifiers); + for i in 0..self.l2_to_l1_msgs.len() { + fields.extend_from_array(self.l2_to_l1_msgs[i].serialize()); + } + for i in 0..self.note_encrypted_logs_hashes.len() { + fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize()); + } + for i in 0..self.encrypted_logs_hashes.len() { + fields.extend_from_array(self.encrypted_logs_hashes[i].serialize()); + } + for i in 0..self.unencrypted_logs_hashes.len() { + fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + } + for i in 0..self.public_call_requests.len() { + fields.extend_from_array(self.public_call_requests[i].serialize()); + } + fields.extend_from_array(self.gas_used.serialize()); + + assert_eq(fields.len(), PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH); + + fields.storage + } +} + +impl Deserialize for PrivateToPublicAccumulatedData { + fn deserialize( + fields: [Field; PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH], + ) -> PrivateToPublicAccumulatedData { + let mut reader = Reader::new(fields); + + let item = PrivateToPublicAccumulatedData { + note_hashes: reader.read_array(), + nullifiers: reader.read_array(), + l2_to_l1_msgs: reader.read_struct_array( + ScopedL2ToL1Message::deserialize, + [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], + ), + note_encrypted_logs_hashes: reader.read_struct_array( + LogHash::deserialize, + [LogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + ), + encrypted_logs_hashes: reader.read_struct_array( + ScopedLogHash::deserialize, + [ScopedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], + ), + unencrypted_logs_hashes: reader.read_struct_array( + ScopedLogHash::deserialize, + [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + ), + public_call_requests: reader.read_struct_array( + PublicCallRequest::deserialize, + [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], + ), + gas_used: reader.read_struct(Gas::deserialize), + }; + reader.finish(); + item + } +} + +#[test] +fn serialization_of_empty_private_to_public_accumulated_data() { + let item = PrivateToPublicAccumulatedData::empty(); + let serialized = item.serialize(); + let deserialized = PrivateToPublicAccumulatedData::deserialize(serialized); + assert_eq(item, deserialized); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data_builder.nr new file mode 100644 index 00000000000..e3516d4af94 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data_builder.nr @@ -0,0 +1,74 @@ +use crate::{ + abis::{ + accumulated_data::private_to_public_accumulated_data::PrivateToPublicAccumulatedData, + gas::Gas, + log_hash::{LogHash, ScopedLogHash}, + note_hash::ScopedNoteHash, + nullifier::Nullifier, + public_call_request::PublicCallRequest, + public_data_update_request::PublicDataUpdateRequest, + side_effect::Counted, + }, + constants::{ + MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, + }, + messaging::l2_to_l1_message::ScopedL2ToL1Message, + traits::Empty, + utils::arrays::array_to_bounded_vec, +}; + +pub struct PrivateToPublicAccumulatedDataBuilder { + note_hashes: BoundedVec, + nullifiers: BoundedVec, + l2_to_l1_msgs: BoundedVec, + note_encrypted_logs_hashes: BoundedVec, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, + public_call_requests: BoundedVec, + gas_used: Gas, +} + +impl PrivateToPublicAccumulatedDataBuilder { + pub fn new(data: PrivateToPublicAccumulatedData) -> Self { + PrivateToPublicAccumulatedDataBuilder { + note_hashes: array_to_bounded_vec(data.note_hashes), + nullifiers: array_to_bounded_vec(data.nullifiers), + l2_to_l1_msgs: array_to_bounded_vec(data.l2_to_l1_msgs), + note_encrypted_logs_hashes: array_to_bounded_vec(data.note_encrypted_logs_hashes), + encrypted_logs_hashes: array_to_bounded_vec(data.encrypted_logs_hashes), + unencrypted_logs_hashes: array_to_bounded_vec(data.unencrypted_logs_hashes), + public_call_requests: array_to_bounded_vec(data.public_call_requests), + gas_used: data.gas_used, + } + } + + pub fn finish(self) -> PrivateToPublicAccumulatedData { + PrivateToPublicAccumulatedData { + note_hashes: self.note_hashes.storage, + nullifiers: self.nullifiers.storage, + l2_to_l1_msgs: self.l2_to_l1_msgs.storage, + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, + encrypted_logs_hashes: self.encrypted_logs_hashes.storage, + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, + public_call_requests: self.public_call_requests.storage, + gas_used: self.gas_used, + } + } +} + +impl Empty for PrivateToPublicAccumulatedDataBuilder { + fn empty() -> Self { + PrivateToPublicAccumulatedDataBuilder { + note_hashes: BoundedVec::new(), + nullifiers: BoundedVec::new(), + l2_to_l1_msgs: BoundedVec::new(), + note_encrypted_logs_hashes: BoundedVec::new(), + encrypted_logs_hashes: BoundedVec::new(), + unencrypted_logs_hashes: BoundedVec::new(), + public_call_requests: BoundedVec::new(), + gas_used: Gas::empty(), + } + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr index 4c1ddda3649..3f185badfb6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr @@ -8,8 +8,8 @@ use crate::{ public_data_update_request::PublicDataUpdateRequest, }, constants::{ - MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, NUM_PUBLIC_ACCUMULATED_DATA_ARRAYS, PUBLIC_ACCUMULATED_DATA_LENGTH, }, @@ -18,6 +18,7 @@ use crate::{ utils::{arrays::array_length, reader::Reader}, }; +// TODO(#9594): To be deprecated. pub struct PublicAccumulatedData { note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], nullifiers: [Nullifier; MAX_NULLIFIERS_PER_TX], @@ -29,7 +30,7 @@ pub struct PublicAccumulatedData { public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - public_call_stack: [PublicCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_stack: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], gas_used: Gas, } @@ -46,7 +47,7 @@ impl Empty for PublicAccumulatedData { public_data_update_requests: [ PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX ], - public_call_stack: [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_stack: [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], gas_used: Gas::empty(), } } @@ -84,7 +85,7 @@ impl Serialize for PublicAccumulatedData { fields.extend_from_array(self.public_data_update_requests[i].serialize()); } - for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX { + for i in 0..MAX_ENQUEUED_CALLS_PER_TX { fields.extend_from_array(self.public_call_stack[i].serialize()); } @@ -131,7 +132,7 @@ impl Deserialize for PublicAccumulatedData { ), public_call_stack: reader.read_struct_array( PublicCallRequest::deserialize, - [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], ), gas_used: reader.read_struct(Gas::deserialize), }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr index 98b52060000..1e6a36766cb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr @@ -9,8 +9,8 @@ use crate::{ public_data_update_request::PublicDataUpdateRequest, }, constants::{ - MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, @@ -18,6 +18,7 @@ use crate::{ utils::arrays::array_to_bounded_vec, }; +// TODO(#9594): To be deprecated. pub struct PublicAccumulatedDataBuilder { note_hashes: BoundedVec, nullifiers: BoundedVec, @@ -29,7 +30,7 @@ pub struct PublicAccumulatedDataBuilder { public_data_update_requests: BoundedVec, - public_call_stack: BoundedVec, + public_call_stack: BoundedVec, gas_used: Gas, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr new file mode 100644 index 00000000000..614b25decb1 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr @@ -0,0 +1,168 @@ +use crate::{ + abis::{ + accumulated_data::{ + avm_accumulated_data::AvmAccumulatedData, + private_to_avm_accumulated_data::{ + PrivateToAvmAccumulatedData, PrivateToAvmAccumulatedDataArrayLengths, + }, + }, + gas_settings::GasSettings, + global_variables::GlobalVariables, + public_call_request::PublicCallRequest, + tree_snapshots::TreeSnapshots, + }, + constants::{AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_ENQUEUED_CALLS_PER_TX}, + traits::{Deserialize, Empty, Serialize}, + utils::reader::Reader, +}; + +pub struct AvmCircuitPublicInputs { + /////////////////////////////////// + // Inputs. + global_variables: GlobalVariables, + start_tree_snapshots: TreeSnapshots, + gas_settings: GasSettings, + public_setup_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], + public_app_logic_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], + public_teardown_call_request: PublicCallRequest, + previous_non_revertible_accumulated_data_array_lengths: PrivateToAvmAccumulatedDataArrayLengths, + previous_revertible_accumulated_data_array_lengths: PrivateToAvmAccumulatedDataArrayLengths, + previous_non_revertible_accumulated_data: PrivateToAvmAccumulatedData, + previous_revertible_accumulated_data: PrivateToAvmAccumulatedData, + + /////////////////////////////////// + // Outputs. + end_tree_snapshots: TreeSnapshots, + accumulated_data: AvmAccumulatedData, + transaction_fee: Field, + reverted: bool, +} + +impl Empty for AvmCircuitPublicInputs { + fn empty() -> Self { + AvmCircuitPublicInputs { + global_variables: GlobalVariables::empty(), + start_tree_snapshots: TreeSnapshots::empty(), + gas_settings: GasSettings::empty(), + public_setup_call_requests: [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], + public_app_logic_call_requests: [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], + public_teardown_call_request: PublicCallRequest::empty(), + previous_non_revertible_accumulated_data_array_lengths: PrivateToAvmAccumulatedDataArrayLengths::empty(), + previous_revertible_accumulated_data_array_lengths: PrivateToAvmAccumulatedDataArrayLengths::empty(), + previous_non_revertible_accumulated_data: PrivateToAvmAccumulatedData::empty(), + previous_revertible_accumulated_data: PrivateToAvmAccumulatedData::empty(), + end_tree_snapshots: TreeSnapshots::empty(), + accumulated_data: AvmAccumulatedData::empty(), + transaction_fee: 0, + reverted: false, + } + } +} + +impl Eq for AvmCircuitPublicInputs { + fn eq(self, other: Self) -> bool { + (self.global_variables == other.global_variables) + & (self.start_tree_snapshots == other.start_tree_snapshots) + & (self.gas_settings == other.gas_settings) + & (self.public_setup_call_requests == other.public_setup_call_requests) + & (self.public_app_logic_call_requests == other.public_app_logic_call_requests) + & (self.public_teardown_call_request == other.public_teardown_call_request) + & ( + self.previous_non_revertible_accumulated_data_array_lengths + == other.previous_non_revertible_accumulated_data_array_lengths + ) + & ( + self.previous_revertible_accumulated_data_array_lengths + == other.previous_revertible_accumulated_data_array_lengths + ) + & ( + self.previous_non_revertible_accumulated_data + == other.previous_non_revertible_accumulated_data + ) + & ( + self.previous_revertible_accumulated_data + == other.previous_revertible_accumulated_data + ) + & (self.end_tree_snapshots == other.end_tree_snapshots) + & (self.accumulated_data == other.accumulated_data) + & (self.transaction_fee == other.transaction_fee) + & (self.reverted == other.reverted) + } +} + +impl Serialize for AvmCircuitPublicInputs { + fn serialize(self) -> [Field; AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH] { + let mut fields: BoundedVec = BoundedVec::new(); + + fields.extend_from_array(self.global_variables.serialize()); + fields.extend_from_array(self.start_tree_snapshots.serialize()); + fields.extend_from_array(self.gas_settings.serialize()); + for i in 0..self.public_setup_call_requests.len() { + fields.extend_from_array(self.public_setup_call_requests[i].serialize()); + } + for i in 0..self.public_app_logic_call_requests.len() { + fields.extend_from_array(self.public_app_logic_call_requests[i].serialize()); + } + fields.extend_from_array(self.public_teardown_call_request.serialize()); + fields.extend_from_array(self + .previous_non_revertible_accumulated_data_array_lengths + .serialize()); + fields.extend_from_array(self.previous_revertible_accumulated_data_array_lengths.serialize()); + fields.extend_from_array(self.previous_non_revertible_accumulated_data.serialize()); + fields.extend_from_array(self.previous_revertible_accumulated_data.serialize()); + fields.extend_from_array(self.end_tree_snapshots.serialize()); + fields.extend_from_array(self.accumulated_data.serialize()); + fields.push(self.transaction_fee); + fields.push(self.reverted as Field); + + assert_eq(fields.len(), AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH); + + fields.storage + } +} + +impl Deserialize for AvmCircuitPublicInputs { + fn deserialize(fields: [Field; AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> AvmCircuitPublicInputs { + let mut reader = Reader::new(fields); + let item = AvmCircuitPublicInputs { + global_variables: reader.read_struct(GlobalVariables::deserialize), + start_tree_snapshots: reader.read_struct(TreeSnapshots::deserialize), + gas_settings: reader.read_struct(GasSettings::deserialize), + public_setup_call_requests: reader.read_struct_array( + PublicCallRequest::deserialize, + [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], + ), + public_app_logic_call_requests: reader.read_struct_array( + PublicCallRequest::deserialize, + [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], + ), + public_teardown_call_request: reader.read_struct(PublicCallRequest::deserialize), + previous_non_revertible_accumulated_data_array_lengths: reader.read_struct( + PrivateToAvmAccumulatedDataArrayLengths::deserialize, + ), + previous_revertible_accumulated_data_array_lengths: reader.read_struct( + PrivateToAvmAccumulatedDataArrayLengths::deserialize, + ), + previous_non_revertible_accumulated_data: reader.read_struct( + PrivateToAvmAccumulatedData::deserialize, + ), + previous_revertible_accumulated_data: reader.read_struct( + PrivateToAvmAccumulatedData::deserialize, + ), + end_tree_snapshots: reader.read_struct(TreeSnapshots::deserialize), + accumulated_data: reader.read_struct(AvmAccumulatedData::deserialize), + transaction_fee: reader.read(), + reverted: reader.read() as bool, + }; + reader.finish(); + item + } +} + +#[test] +fn serialization_of_empty_avm_circuit_public_inputs() { + let item = AvmCircuitPublicInputs::empty(); + let serialized = item.serialize(); + let deserialized = AvmCircuitPublicInputs::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr index 6998476def8..794b145e3b1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr @@ -1,4 +1,4 @@ -use crate::abis::global_variables::GlobalVariables; +use crate::abis::{global_variables::GlobalVariables, tx_constant_data::TxConstantData}; use crate::constants::COMBINED_CONSTANT_DATA_LENGTH; use crate::header::Header; use crate::traits::{Deserialize, Empty, Serialize}; @@ -12,27 +12,24 @@ pub struct CombinedConstantData { // a situation we could be using header from a block before the upgrade took place but be using the updated // protocol to execute and prove the transaction. tx_context: TxContext, - vk_tree_root: Field, protocol_contract_tree_root: Field, - // Must be empty in private, will be filled in by the public kernel + // Should be empty for private-only txs. This is filled in by the sequencer for txs with public calls. global_variables: GlobalVariables, } impl CombinedConstantData { - pub fn private( - historical_header: Header, - tx_context: TxContext, - vk_tree_root: Field, - protocol_contract_tree_root: Field, + pub fn combine( + tx_constant_data: TxConstantData, + global_variables: GlobalVariables, ) -> CombinedConstantData { CombinedConstantData { - historical_header, - tx_context, - vk_tree_root, - protocol_contract_tree_root, - global_variables: GlobalVariables::empty(), + historical_header: tx_constant_data.historical_header, + tx_context: tx_constant_data.tx_context, + vk_tree_root: tx_constant_data.vk_tree_root, + protocol_contract_tree_root: tx_constant_data.protocol_contract_tree_root, + global_variables, } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr index 5743fdb34a3..4c06de5e4d8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr @@ -1,7 +1,7 @@ use crate::{ abis::{ accumulated_data::CombinedAccumulatedData, combined_constant_data::CombinedConstantData, - gas_fees::GasFees, validation_requests::RollupValidationRequests, + validation_requests::RollupValidationRequests, }, address::AztecAddress, constants::KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH, @@ -10,6 +10,7 @@ use crate::{ utils::reader::Reader, }; +// TODO: Update it to be specifically for the private_kernel_tail once we remove public_kernel_tail, which also outputs this. pub struct KernelCircuitPublicInputs { rollup_validation_requests: RollupValidationRequests, end: CombinedAccumulatedData, @@ -19,13 +20,6 @@ pub struct KernelCircuitPublicInputs { fee_payer: AztecAddress, } -impl KernelCircuitPublicInputs { - pub fn compute_transaction_fee(self, gas_fees: GasFees) -> Field { - let inclusion_fee = self.constants.tx_context.gas_settings.inclusion_fee; - inclusion_fee + self.end.gas_used.compute_fee(gas_fees) - } -} - impl Empty for KernelCircuitPublicInputs { fn empty() -> Self { KernelCircuitPublicInputs { @@ -86,47 +80,10 @@ impl Deserialize for KernelCircuitPublicInp } } -mod tests { - use crate::abis::{ - accumulated_data::CombinedAccumulatedData, combined_constant_data::CombinedConstantData, - gas::Gas, gas_fees::GasFees, - kernel_circuit_public_inputs::kernel_circuit_public_inputs::KernelCircuitPublicInputs, - validation_requests::RollupValidationRequests, - }; - use crate::address::AztecAddress; - use crate::partial_state_reference::PartialStateReference; - - #[test] - unconstrained fn empty_has_zero_gas_and_fee() { - let empty = KernelCircuitPublicInputs::empty(); - assert_eq(empty.compute_transaction_fee(GasFees::empty()), 0); - } - - #[test] - unconstrained fn non_empty_gas_and_fee() { - let mut inputs = KernelCircuitPublicInputs { - rollup_validation_requests: RollupValidationRequests::empty(), - end: CombinedAccumulatedData::empty(), - constants: CombinedConstantData::empty(), - start_state: PartialStateReference::empty(), - revert_code: 0, - fee_payer: AztecAddress::empty(), - }; - - inputs.end.gas_used = Gas { da_gas: 10, l2_gas: 20 }; - - inputs.constants.tx_context.gas_settings.inclusion_fee = 42; - - let gas_fees = GasFees { fee_per_da_gas: 2, fee_per_l2_gas: 3 }; - let transaction_fee = inputs.compute_transaction_fee(gas_fees); - assert_eq(transaction_fee, 42 + 2 * 10 + 3 * 20); - } - - #[test] - fn serialization_of_empty() { - let item = KernelCircuitPublicInputs::empty(); - let serialized = item.serialize(); - let deserialized = KernelCircuitPublicInputs::deserialize(serialized); - assert(item.eq(deserialized)); - } +#[test] +fn serialization_of_empty_kernel_circuit_public_inputs() { + let item = KernelCircuitPublicInputs::empty(); + let serialized = item.serialize(); + let deserialized = KernelCircuitPublicInputs::deserialize(serialized); + assert(item.eq(deserialized)); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr index cc3ba303c15..d3f95abdae1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr @@ -1,6 +1,7 @@ mod kernel_circuit_public_inputs; mod private_kernel_circuit_public_inputs; mod private_kernel_circuit_public_inputs_builder; +mod private_to_public_kernel_circuit_public_inputs; mod public_kernel_circuit_public_inputs; mod public_kernel_circuit_public_inputs_builder; mod vm_circuit_public_inputs; @@ -10,6 +11,7 @@ pub use private_kernel_circuit_public_inputs::{ PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsArrayLengths, }; pub use private_kernel_circuit_public_inputs_builder::PrivateKernelCircuitPublicInputsBuilder; +pub use private_to_public_kernel_circuit_public_inputs::PrivateToPublicKernelCircuitPublicInputs; pub use public_kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs; pub use public_kernel_circuit_public_inputs_builder::PublicKernelCircuitPublicInputsBuilder; pub use vm_circuit_public_inputs::VMCircuitPublicInputs; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr index 647d8d6fc88..5694df6d704 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr @@ -1,7 +1,7 @@ use crate::{ abis::{ - accumulated_data::PrivateAccumulatedData, combined_constant_data::CombinedConstantData, - public_call_request::PublicCallRequest, validation_requests::PrivateValidationRequests, + accumulated_data::PrivateAccumulatedData, public_call_request::PublicCallRequest, + tx_constant_data::TxConstantData, validation_requests::PrivateValidationRequests, }, address::AztecAddress, constants::PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH, @@ -83,10 +83,10 @@ impl Eq for PrivateKernelCircuitPublicInputsArrayLengths { } pub struct PrivateKernelCircuitPublicInputs { + constants: TxConstantData, min_revertible_side_effect_counter: u32, validation_requests: PrivateValidationRequests, end: PrivateAccumulatedData, - constants: CombinedConstantData, public_teardown_call_request: PublicCallRequest, fee_payer: AztecAddress, } @@ -96,10 +96,10 @@ impl Serialize for PrivateKernelCir let mut fields: BoundedVec = BoundedVec::new(); + fields.extend_from_array(self.constants.serialize()); fields.push(self.min_revertible_side_effect_counter as Field); fields.extend_from_array(self.validation_requests.serialize()); fields.extend_from_array(self.end.serialize()); - fields.extend_from_array(self.constants.serialize()); fields.extend_from_array(self.public_teardown_call_request.serialize()); fields.extend_from_array(self.fee_payer.serialize()); @@ -115,10 +115,10 @@ impl Deserialize for PrivateKernelC ) -> PrivateKernelCircuitPublicInputs { let mut reader = Reader::new(fields); let item = Self { + constants: reader.read_struct(TxConstantData::deserialize), min_revertible_side_effect_counter: reader.read() as u32, validation_requests: reader.read_struct(PrivateValidationRequests::deserialize), end: reader.read_struct(PrivateAccumulatedData::deserialize), - constants: reader.read_struct(CombinedConstantData::deserialize), public_teardown_call_request: reader.read_struct(PublicCallRequest::deserialize), fee_payer: reader.read_struct(AztecAddress::deserialize), }; @@ -130,10 +130,10 @@ impl Deserialize for PrivateKernelC impl Eq for PrivateKernelCircuitPublicInputs { fn eq(self, other: Self) -> bool { - (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) + (self.constants.eq(other.constants)) + & (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) & (self.validation_requests.eq(other.validation_requests)) & (self.end.eq(other.end)) - & (self.constants.eq(other.constants)) & (self.public_teardown_call_request.eq(other.public_teardown_call_request)) } } @@ -141,10 +141,10 @@ impl Eq for PrivateKernelCircuitPublicInputs { impl Empty for PrivateKernelCircuitPublicInputs { fn empty() -> Self { Self { + constants: TxConstantData::empty(), min_revertible_side_effect_counter: 0, validation_requests: PrivateValidationRequests::empty(), end: PrivateAccumulatedData::empty(), - constants: CombinedConstantData::empty(), public_teardown_call_request: PublicCallRequest::empty(), fee_payer: AztecAddress::empty(), } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr index c602171f27d..1cee9d2d80b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr @@ -1,9 +1,8 @@ use crate::{ abis::{ accumulated_data::PrivateAccumulatedDataBuilder, - combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::private_kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - public_call_request::PublicCallRequest, + public_call_request::PublicCallRequest, tx_constant_data::TxConstantData, validation_requests::PrivateValidationRequestsBuilder, }, address::AztecAddress, @@ -11,10 +10,10 @@ use crate::{ }; pub struct PrivateKernelCircuitPublicInputsBuilder { + constants: TxConstantData, min_revertible_side_effect_counter: u32, validation_requests: PrivateValidationRequestsBuilder, end: PrivateAccumulatedDataBuilder, - constants: CombinedConstantData, public_teardown_call_request: PublicCallRequest, fee_payer: AztecAddress, } @@ -22,10 +21,10 @@ pub struct PrivateKernelCircuitPublicInputsBuilder { impl PrivateKernelCircuitPublicInputsBuilder { pub fn finish(self) -> PrivateKernelCircuitPublicInputs { PrivateKernelCircuitPublicInputs { + constants: self.constants, min_revertible_side_effect_counter: self.min_revertible_side_effect_counter, validation_requests: self.validation_requests.finish(), end: self.end.finish(), - constants: self.constants, public_teardown_call_request: self.public_teardown_call_request, fee_payer: self.fee_payer, } @@ -35,10 +34,10 @@ impl PrivateKernelCircuitPublicInputsBuilder { impl Empty for PrivateKernelCircuitPublicInputsBuilder { fn empty() -> Self { PrivateKernelCircuitPublicInputsBuilder { + constants: TxConstantData::empty(), min_revertible_side_effect_counter: 0, validation_requests: PrivateValidationRequestsBuilder::empty(), end: PrivateAccumulatedDataBuilder::empty(), - constants: CombinedConstantData::empty(), public_teardown_call_request: PublicCallRequest::empty(), fee_payer: AztecAddress::empty(), } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_to_public_kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_to_public_kernel_circuit_public_inputs.nr new file mode 100644 index 00000000000..cf3f7c35738 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_to_public_kernel_circuit_public_inputs.nr @@ -0,0 +1,92 @@ +use crate::{ + abis::{ + accumulated_data::PrivateToPublicAccumulatedData, public_call_request::PublicCallRequest, + tx_constant_data::TxConstantData, validation_requests::RollupValidationRequests, + }, + address::AztecAddress, + constants::PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH, + traits::{Deserialize, Empty, Serialize}, + utils::reader::Reader, +}; + +pub struct PrivateToPublicKernelCircuitPublicInputs { + constants: TxConstantData, + rollup_validation_requests: RollupValidationRequests, + non_revertible_accumulated_data: PrivateToPublicAccumulatedData, + revertible_accumulated_data: PrivateToPublicAccumulatedData, + public_teardown_call_request: PublicCallRequest, + fee_payer: AztecAddress, +} + +impl Empty for PrivateToPublicKernelCircuitPublicInputs { + fn empty() -> Self { + PrivateToPublicKernelCircuitPublicInputs { + constants: TxConstantData::empty(), + rollup_validation_requests: RollupValidationRequests::empty(), + non_revertible_accumulated_data: PrivateToPublicAccumulatedData::empty(), + revertible_accumulated_data: PrivateToPublicAccumulatedData::empty(), + public_teardown_call_request: PublicCallRequest::empty(), + fee_payer: AztecAddress::empty(), + } + } +} + +impl Eq for PrivateToPublicKernelCircuitPublicInputs { + fn eq(self, other: Self) -> bool { + (self.constants == other.constants) + & (self.rollup_validation_requests == other.rollup_validation_requests) + & (self.non_revertible_accumulated_data == other.non_revertible_accumulated_data) + & (self.revertible_accumulated_data == other.revertible_accumulated_data) + & (self.public_teardown_call_request == other.public_teardown_call_request) + & (self.fee_payer == other.fee_payer) + } +} + +impl Serialize for PrivateToPublicKernelCircuitPublicInputs { + fn serialize(self) -> [Field; PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH] { + let mut fields: BoundedVec = + BoundedVec::new(); + + fields.extend_from_array(self.constants.serialize()); + fields.extend_from_array(self.rollup_validation_requests.serialize()); + fields.extend_from_array(self.non_revertible_accumulated_data.serialize()); + fields.extend_from_array(self.revertible_accumulated_data.serialize()); + fields.extend_from_array(self.public_teardown_call_request.serialize()); + fields.extend_from_array(self.fee_payer.serialize()); + + assert_eq(fields.len(), PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH); + + fields.storage + } +} + +impl Deserialize for PrivateToPublicKernelCircuitPublicInputs { + fn deserialize( + fields: [Field; PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH], + ) -> PrivateToPublicKernelCircuitPublicInputs { + let mut reader = Reader::new(fields); + + let item = PrivateToPublicKernelCircuitPublicInputs { + constants: reader.read_struct(TxConstantData::deserialize), + rollup_validation_requests: reader.read_struct(RollupValidationRequests::deserialize), + non_revertible_accumulated_data: reader.read_struct( + PrivateToPublicAccumulatedData::deserialize, + ), + revertible_accumulated_data: reader.read_struct( + PrivateToPublicAccumulatedData::deserialize, + ), + public_teardown_call_request: reader.read_struct(PublicCallRequest::deserialize), + fee_payer: reader.read_struct(AztecAddress::deserialize), + }; + reader.finish(); + item + } +} + +#[test] +fn serialization_of_empty() { + let item = PrivateToPublicKernelCircuitPublicInputs::empty(); + let serialized = item.serialize(); + let deserialized = PrivateToPublicKernelCircuitPublicInputs::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/vm_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/vm_circuit_public_inputs.nr index 2bfd1cfe59d..7352c2d7f20 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/vm_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/vm_circuit_public_inputs.nr @@ -7,7 +7,7 @@ use crate::{ public_inner_call_request::PublicInnerCallRequest, validation_requests::{PublicValidationRequestArrayLengths, PublicValidationRequests}, }, - constants::{MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, VM_CIRCUIT_PUBLIC_INPUTS_LENGTH}, + constants::{MAX_ENQUEUED_CALLS_PER_TX, VM_CIRCUIT_PUBLIC_INPUTS_LENGTH}, traits::{Deserialize, Empty, Serialize}, utils::reader::Reader, }; @@ -17,7 +17,7 @@ pub struct VMCircuitPublicInputs { call_request: PublicCallRequest, // TODO(#7124): To be deprecated. - public_call_stack: [PublicInnerCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_stack: [PublicInnerCallRequest; MAX_ENQUEUED_CALLS_PER_TX], previous_validation_request_array_lengths: PublicValidationRequestArrayLengths, // Lengths of the validation requests before the enqueued call. validation_requests: PublicValidationRequests, // Validation requests emitted throughout the enqueued call. @@ -35,9 +35,7 @@ impl Empty for VMCircuitPublicInputs { VMCircuitPublicInputs { constants: CombinedConstantData::empty(), call_request: PublicCallRequest::empty(), - public_call_stack: [ - PublicInnerCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX - ], + public_call_stack: [PublicInnerCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], previous_validation_request_array_lengths: PublicValidationRequestArrayLengths::empty(), validation_requests: PublicValidationRequests::empty(), previous_accumulated_data_array_lengths: PublicAccumulatedDataArrayLengths::empty(), @@ -80,7 +78,7 @@ impl Serialize for VMCircuitPublicInputs { fields.extend_from_array(self.constants.serialize()); fields.extend_from_array(self.call_request.serialize()); - for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX { + for i in 0..MAX_ENQUEUED_CALLS_PER_TX { fields.extend_from_array(self.public_call_stack[i].serialize()); } fields.extend_from_array(self.previous_validation_request_array_lengths.serialize()); @@ -107,7 +105,7 @@ impl Deserialize for VMCircuitPublicInputs { call_request: reader.read_struct(PublicCallRequest::deserialize), public_call_stack: reader.read_struct_array( PublicInnerCallRequest::deserialize, - [PublicInnerCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + [PublicInnerCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], ), previous_validation_request_array_lengths: reader.read_struct( PublicValidationRequestArrayLengths::deserialize, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr index aa6e2fb940c..c91960814ac 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr @@ -1,4 +1,5 @@ mod append_only_tree_snapshot; +pub mod avm_circuit_public_inputs; mod contract_class_function_leaf_preimage; @@ -10,7 +11,8 @@ mod global_variables; mod note_hash_leaf_preimage; mod nullifier_leaf_preimage; -mod combined_constant_data; +pub mod tx_constant_data; +pub mod combined_constant_data; mod side_effect; mod read_request; @@ -20,7 +22,7 @@ mod note_hash; mod nullifier; mod public_data_read; mod public_data_update_request; -mod public_data_write; +pub mod public_data_write; mod accumulated_data; mod validation_requests; @@ -48,3 +50,5 @@ pub mod private_circuit_public_inputs; mod gas_fees; mod gas_settings; mod gas; + +mod tree_snapshots; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index cf1b9b4f8c8..9f0998e3da7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -8,15 +8,16 @@ use crate::{ private_call_request::PrivateCallRequest, public_call_request::PublicCallRequest, read_request::ReadRequest, + side_effect::Counted, validation_requests::KeyValidationRequestAndGenerator, }, constants::{ - MAX_ENCRYPTED_LOGS_PER_CALL, MAX_KEY_VALIDATION_REQUESTS_PER_CALL, - MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, + MAX_ENCRYPTED_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL, + MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, + MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL, + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, }, header::Header, messaging::l2_to_l1_message::L2ToL1Message, @@ -78,7 +79,7 @@ pub struct PrivateCircuitPublicInputs { note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_CALL], nullifiers: [Nullifier; MAX_NULLIFIERS_PER_CALL], private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL], - public_call_requests: [PublicCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + public_call_requests: [Counted; MAX_ENQUEUED_CALLS_PER_CALL], public_teardown_call_request: PublicCallRequest, l2_to_l1_msgs: [L2ToL1Message; MAX_L2_TO_L1_MSGS_PER_CALL], @@ -219,8 +220,8 @@ impl Deserialize for PrivateCircuitPublicI [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL], ), public_call_requests: reader.read_struct_array( - PublicCallRequest::deserialize, - [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + Counted::deserialize, + [Counted::empty(); MAX_ENQUEUED_CALLS_PER_CALL], ), public_teardown_call_request: reader.read_struct(PublicCallRequest::deserialize), l2_to_l1_msgs: reader.read_struct_array( @@ -269,9 +270,7 @@ impl Empty for PrivateCircuitPublicInputs { private_call_requests: [ PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL ], - public_call_requests: [ - PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL - ], + public_call_requests: [Counted::empty(); MAX_ENQUEUED_CALLS_PER_CALL], public_teardown_call_request: PublicCallRequest::empty(), l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter: 0 as u32, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr index d8aaf06f80c..04b133556dd 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr @@ -1,5 +1,5 @@ use crate::{ - abis::{call_context::CallContext, side_effect::Ordered}, + abis::{call_context::CallContext, function_selector::FunctionSelector, side_effect::Ordered}, address::AztecAddress, constants::PUBLIC_CALL_REQUEST_LENGTH, traits::{Deserialize, Empty, Serialize}, @@ -7,34 +7,36 @@ use crate::{ }; pub struct PublicCallRequest { - call_context: CallContext, - args_hash: Field, - counter: u32, -} + msg_sender: AztecAddress, + contract_address: AztecAddress, -impl Ordered for PublicCallRequest { - fn counter(self) -> u32 { - self.counter - } + // TODO: To be removed. + // Function selector is the first world of calldata. + function_selector: FunctionSelector, + + is_static_call: bool, + args_hash: Field, } impl Eq for PublicCallRequest { fn eq(self, other: PublicCallRequest) -> bool { - (self.call_context == other.call_context) + (self.msg_sender == other.msg_sender) + & (self.contract_address == other.contract_address) + & (self.function_selector == other.function_selector) + & (self.is_static_call == other.is_static_call) & (self.args_hash == other.args_hash) - & (self.counter == other.counter) } } impl Empty for PublicCallRequest { fn empty() -> Self { - PublicCallRequest { call_context: CallContext::empty(), args_hash: 0, counter: 0 } - } -} - -impl PublicCallRequest { - pub fn expose_to_public(self) -> Self { - PublicCallRequest { call_context: self.call_context, args_hash: self.args_hash, counter: 0 } + PublicCallRequest { + msg_sender: AztecAddress::empty(), + contract_address: AztecAddress::empty(), + function_selector: FunctionSelector::empty(), + is_static_call: false, + args_hash: 0, + } } } @@ -42,9 +44,11 @@ impl Serialize for PublicCallRequest { fn serialize(self) -> [Field; PUBLIC_CALL_REQUEST_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(); - fields.extend_from_array(self.call_context.serialize()); + fields.push(self.msg_sender.to_field()); + fields.push(self.contract_address.to_field()); + fields.push(self.function_selector.to_field()); + fields.push(self.is_static_call as Field); fields.push(self.args_hash); - fields.push(self.counter as Field); assert_eq(fields.len(), PUBLIC_CALL_REQUEST_LENGTH); @@ -57,9 +61,11 @@ impl Deserialize for PublicCallRequest { let mut reader = Reader::new(fields); let request = PublicCallRequest { - call_context: reader.read_struct(CallContext::deserialize), + msg_sender: AztecAddress::from_field(reader.read()), + contract_address: AztecAddress::from_field(reader.read()), + function_selector: FunctionSelector::from_field(reader.read()), + is_static_call: reader.read() as bool, args_hash: reader.read(), - counter: reader.read_u32(), }; reader.finish(); request @@ -67,7 +73,7 @@ impl Deserialize for PublicCallRequest { } #[test] -fn serialization_of_empty() { +fn serialization_of_empty_public_call_request() { let item = PublicCallRequest::empty(); let serialized = item.serialize(); let deserialized = PublicCallRequest::deserialize(serialized); 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 f1171176d09..dddd5d0a1aa 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 @@ -7,12 +7,12 @@ use crate::{ }, address::AztecAddress, constants::{ - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, + MAX_ENQUEUED_CALLS_PER_CALL, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, + MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_NULLIFIERS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL, PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, + MAX_NULLIFIERS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, header::Header, @@ -36,7 +36,7 @@ pub struct PublicCircuitPublicInputs { contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL], // todo: add sideeffect ranges for the input to these hashes - public_call_requests: [PublicInnerCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + public_call_requests: [PublicInnerCallRequest; MAX_ENQUEUED_CALLS_PER_CALL], note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_CALL], nullifiers: [Nullifier; MAX_NULLIFIERS_PER_CALL], l2_to_l1_msgs: [L2ToL1Message; MAX_L2_TO_L1_MSGS_PER_CALL], @@ -92,7 +92,7 @@ impl Serialize for PublicCircuitPublicInput for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { fields.extend_from_array(self.contract_storage_reads[i].serialize()); } - for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL { + for i in 0..MAX_ENQUEUED_CALLS_PER_CALL { fields.extend_from_array(self.public_call_requests[i].serialize()); } for i in 0..MAX_NOTE_HASHES_PER_CALL { @@ -156,7 +156,7 @@ impl Deserialize for PublicCircuitPublicInp ), public_call_requests: reader.read_struct_array( PublicInnerCallRequest::deserialize, - [PublicInnerCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + [PublicInnerCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_CALL], ), note_hashes: reader.read_struct_array( NoteHash::deserialize, @@ -210,9 +210,7 @@ impl Empty for PublicCircuitPublicInputs { StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL ], contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL], - public_call_requests: [ - PublicInnerCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL - ], + public_call_requests: [PublicInnerCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_CALL], note_hashes: [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL], nullifiers: [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL], l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_write.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_write.nr index 290c6ca6e31..1465aa16055 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_write.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_write.nr @@ -4,9 +4,40 @@ use crate::{ public_data_update_request::PublicDataUpdateRequest, side_effect::{Inner, Ordered, Overridable, Readable}, }, - traits::Empty, + constants::PUBLIC_DATA_WRITE_LENGTH, + traits::{Deserialize, Empty, Serialize}, }; +pub struct PublicDataWrite { + leaf_slot: Field, + value: Field, +} + +impl Eq for PublicDataWrite { + fn eq(self, other: Self) -> bool { + (self.leaf_slot == other.leaf_slot) & (self.value == other.value) + } +} + +impl Empty for PublicDataWrite { + fn empty() -> Self { + Self { leaf_slot: 0, value: 0 } + } +} + +impl Serialize for PublicDataWrite { + fn serialize(self) -> [Field; PUBLIC_DATA_WRITE_LENGTH] { + [self.leaf_slot, self.value] + } +} + +impl Deserialize for PublicDataWrite { + fn deserialize(fields: [Field; PUBLIC_DATA_WRITE_LENGTH]) -> PublicDataWrite { + PublicDataWrite { leaf_slot: fields[0], value: fields[1] } + } +} + +// TODO: To be deprecated. pub struct OverridablePublicDataWrite { write: PublicDataUpdateRequest, override_counter: u32, @@ -56,3 +87,11 @@ impl Inner for OverridablePublicDataWrite { self.write } } + +#[test] +fn serialization_of_empty_public_data_write() { + let item = PublicDataWrite::empty(); + let serialized = item.serialize(); + let deserialized = PublicDataWrite::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr index 67929ad3d89..a0ca4da6a8a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr @@ -1,4 +1,8 @@ -use crate::address::AztecAddress; +use crate::{ + address::AztecAddress, + traits::{Deserialize, Empty, Serialize}, + utils::{arrays::array_concat, reader::Reader}, +}; pub trait Ordered { fn counter(self) -> u32; @@ -37,3 +41,60 @@ pub trait Overridable { pub trait Inner { fn inner(self) -> T; } + +pub struct Counted { + pub inner: T, + pub counter: u32, +} + +impl Counted { + pub fn new(inner: T, counter: u32) -> Self { + Self { inner, counter } + } +} + +impl Eq for Counted +where + T: Eq, +{ + fn eq(self, other: Self) -> bool { + (self.inner == other.inner) & (self.counter == other.counter) + } +} + +impl Empty for Counted +where + T: Empty, +{ + fn empty() -> Self { + Self { inner: T::empty(), counter: 0 } + } +} + +impl Serialize for Counted +where + T: Serialize, +{ + fn serialize(self) -> [Field; N] { + array_concat(self.inner.serialize(), [self.counter as Field]) + } +} + +impl Deserialize for Counted +where + T: Deserialize, +{ + fn deserialize(fields: [Field; N]) -> Self { + let mut reader = Reader::new(fields); + let deserialized = + Self { inner: reader.read_struct(T::deserialize), counter: reader.read_u32() }; + reader.finish(); + deserialized + } +} + +impl Ordered for Counted { + fn counter(self) -> u32 { + self.counter + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_snapshots.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_snapshots.nr new file mode 100644 index 00000000000..59863026a5b --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_snapshots.nr @@ -0,0 +1,74 @@ +use crate::{ + abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, + constants::TREE_SNAPSHOTS_LENGTH, + traits::{Deserialize, Empty, Serialize}, +}; + +pub struct TreeSnapshots { + l1_to_l2_message_tree: AppendOnlyTreeSnapshot, + note_hash_tree: AppendOnlyTreeSnapshot, + nullifier_tree: AppendOnlyTreeSnapshot, + public_data_tree: AppendOnlyTreeSnapshot, +} + +impl Eq for TreeSnapshots { + fn eq(self, other: TreeSnapshots) -> bool { + self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) + & self.note_hash_tree.eq(other.note_hash_tree) + & self.nullifier_tree.eq(other.nullifier_tree) + & self.public_data_tree.eq(other.public_data_tree) + } +} + +impl Serialize for TreeSnapshots { + fn serialize(self) -> [Field; TREE_SNAPSHOTS_LENGTH] { + let serialized_l1_to_l2_message_tree = self.l1_to_l2_message_tree.serialize(); + let serialized_note_hash_tree = self.note_hash_tree.serialize(); + let serialized_nullifier_tree = self.nullifier_tree.serialize(); + let serialized_public_data_tree = self.public_data_tree.serialize(); + + [ + serialized_l1_to_l2_message_tree[0], + serialized_l1_to_l2_message_tree[1], + serialized_note_hash_tree[0], + serialized_note_hash_tree[1], + serialized_nullifier_tree[0], + serialized_nullifier_tree[1], + serialized_public_data_tree[0], + serialized_public_data_tree[1], + ] + } +} + +impl Deserialize for TreeSnapshots { + fn deserialize(serialized: [Field; TREE_SNAPSHOTS_LENGTH]) -> TreeSnapshots { + TreeSnapshots { + l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize([ + serialized[0], + serialized[1], + ]), + note_hash_tree: AppendOnlyTreeSnapshot::deserialize([serialized[2], serialized[3]]), + nullifier_tree: AppendOnlyTreeSnapshot::deserialize([serialized[4], serialized[5]]), + public_data_tree: AppendOnlyTreeSnapshot::deserialize([serialized[6], serialized[7]]), + } + } +} + +impl Empty for TreeSnapshots { + fn empty() -> Self { + Self { + l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(), + note_hash_tree: AppendOnlyTreeSnapshot::zero(), + nullifier_tree: AppendOnlyTreeSnapshot::zero(), + public_data_tree: AppendOnlyTreeSnapshot::zero(), + } + } +} + +#[test] +fn serialization_of_empty() { + let item = TreeSnapshots::empty(); + let serialized = item.serialize(); + let deserialized = TreeSnapshots::deserialize(serialized); + assert_eq(item, deserialized); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tx_constant_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tx_constant_data.nr new file mode 100644 index 00000000000..7ad0e0ab547 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tx_constant_data.nr @@ -0,0 +1,77 @@ +use crate::{ + constants::TX_CONSTANT_DATA_LENGTH, + header::Header, + traits::{Deserialize, Empty, Serialize}, + transaction::tx_context::TxContext, + utils::reader::Reader, +}; + +// Constants used throughout the executions of both private and public. +pub struct TxConstantData { + historical_header: Header, + // Note: `chain_id` and `version` in tx_context are not redundant to the values in + // self.historical_header.global_variables because they can be different in case of a protocol upgrade. In such + // a situation we could be using header from a block before the upgrade took place but be using the updated + // protocol to execute and prove the transaction. + tx_context: TxContext, + vk_tree_root: Field, + protocol_contract_tree_root: Field, +} + +impl Empty for TxConstantData { + fn empty() -> Self { + TxConstantData { + historical_header: Header::empty(), + tx_context: TxContext::empty(), + vk_tree_root: 0, + protocol_contract_tree_root: 0, + } + } +} + +impl Eq for TxConstantData { + fn eq(self, other: Self) -> bool { + (self.historical_header.eq(other.historical_header)) + & (self.tx_context.eq(other.tx_context)) + & (self.vk_tree_root.eq(other.vk_tree_root)) + & (self.protocol_contract_tree_root.eq(other.protocol_contract_tree_root)) + } +} + +impl Serialize for TxConstantData { + fn serialize(self) -> [Field; TX_CONSTANT_DATA_LENGTH] { + let mut fields: BoundedVec = BoundedVec::new(); + + fields.extend_from_array(self.historical_header.serialize()); + fields.extend_from_array(self.tx_context.serialize()); + fields.push(self.vk_tree_root); + fields.push(self.protocol_contract_tree_root); + + assert_eq(fields.len(), TX_CONSTANT_DATA_LENGTH); + + fields.storage + } +} + +impl Deserialize for TxConstantData { + fn deserialize(fields: [Field; TX_CONSTANT_DATA_LENGTH]) -> TxConstantData { + let mut reader = Reader::new(fields); + + let item = TxConstantData { + historical_header: reader.read_struct(Header::deserialize), + tx_context: reader.read_struct(TxContext::deserialize), + vk_tree_root: reader.read(), + protocol_contract_tree_root: reader.read(), + }; + reader.finish(); + item + } +} + +#[test] +fn serialization_of_empty_tx_constant_data() { + let item = TxConstantData::empty(); + let serialized = item.serialize(); + let deserialized = TxConstantData::deserialize(serialized); + assert(item.eq(deserialized)); +} 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 1793bf458b0..572a758adfa 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -29,7 +29,7 @@ global ARGS_LENGTH: u32 = 16; global MAX_NOTE_HASHES_PER_CALL: u32 = 16; global MAX_NULLIFIERS_PER_CALL: u32 = 16; global MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL: u32 = 4; -global MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL: u32 = 16; +global MAX_ENQUEUED_CALLS_PER_CALL: u32 = 16; global MAX_L2_TO_L1_MSGS_PER_CALL: u32 = 2; global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL: u32 = 64; global MAX_PUBLIC_DATA_READS_PER_CALL: u32 = 64; @@ -76,7 +76,7 @@ global L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH: u32 = global MAX_NOTE_HASHES_PER_TX: u32 = (1 as u8 << NOTE_HASH_SUBTREE_HEIGHT as u8) as u32; global MAX_NULLIFIERS_PER_TX: u32 = (1 as u8 << NULLIFIER_SUBTREE_HEIGHT as u8) as u32; global MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX: u32 = 8; -global MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX: u32 = 32; +global MAX_ENQUEUED_CALLS_PER_TX: u32 = 32; global PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u32 = 1; global MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u32 = (1 as u8 << PUBLIC_DATA_SUBTREE_HEIGHT as u8) as u32; @@ -289,15 +289,22 @@ global NOTE_HASH_LENGTH: u32 = 2; global SCOPED_NOTE_HASH_LENGTH: u32 = NOTE_HASH_LENGTH + 1; global NULLIFIER_LENGTH: u32 = 3; global SCOPED_NULLIFIER_LENGTH: u32 = NULLIFIER_LENGTH + 1; +global PUBLIC_DATA_WRITE_LENGTH: u32 = 2; global PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH: u32 = AZTEC_ADDRESS_LENGTH + CALL_CONTEXT_LENGTH + 3 + 2 * GAS_LENGTH; global PRIVATE_CALL_REQUEST_LENGTH: u32 = CALL_CONTEXT_LENGTH + 4; -global PUBLIC_CALL_REQUEST_LENGTH: u32 = CALL_CONTEXT_LENGTH + 1 /* args_hash */ + 1 /* counter */; +global PUBLIC_CALL_REQUEST_LENGTH: u32 = AZTEC_ADDRESS_LENGTH /* msg_sender */ + + AZTEC_ADDRESS_LENGTH /* contract_address */ + + 1 /* function_selector */ + + 1 /* is_static_call */ + + 1 /* args_hash */; +global COUNTED_PUBLIC_CALL_REQUEST_LENGTH = PUBLIC_CALL_REQUEST_LENGTH + 1; global PUBLIC_INNER_CALL_REQUEST_LENGTH: u32 = PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH + 1 /* counter */; global ROLLUP_VALIDATION_REQUESTS_LENGTH: u32 = MAX_BLOCK_NUMBER_LENGTH; global STATE_REFERENCE_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; +global TREE_SNAPSHOTS_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH * 4; global TX_CONTEXT_LENGTH: u32 = 2 + GAS_SETTINGS_LENGTH; global TX_REQUEST_LENGTH: u32 = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; global TOTAL_FEES_LENGTH: u32 = 1; @@ -315,7 +322,7 @@ global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + (NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_CALL) + (PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL) - + (PUBLIC_CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL) + + (COUNTED_PUBLIC_CALL_REQUEST_LENGTH * MAX_ENQUEUED_CALLS_PER_CALL) + PUBLIC_CALL_REQUEST_LENGTH + (L2_TO_L1_MESSAGE_LENGTH * MAX_L2_TO_L1_MSGS_PER_CALL) + 2 @@ -332,7 +339,7 @@ global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + (TREE_LEAF_READ_REQUEST_LENGTH * MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) - + (PUBLIC_INNER_CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL) + + (PUBLIC_INNER_CALL_REQUEST_LENGTH * MAX_ENQUEUED_CALLS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_L2_TO_L1_MSGS_PER_CALL) @@ -367,7 +374,7 @@ global PUBLIC_VALIDATION_REQUESTS_LENGTH: u32 = ROLLUP_VALIDATION_REQUESTS_LENGT + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX) + (TREE_LEAF_READ_REQUEST_LENGTH * MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX); -global PUBLIC_DATA_UPDATE_REQUEST_LENGTH: u32 = 3; +global PUBLIC_DATA_UPDATE_REQUEST_LENGTH: u32 = 3; // To be deprecated. global COMBINED_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) @@ -375,13 +382,13 @@ global COMBINED_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + (SCOPED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + 3 + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) - + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_WRITE_LENGTH) + GAS_LENGTH; -global COMBINED_CONSTANT_DATA_LENGTH: u32 = HEADER_LENGTH +global TX_CONSTANT_DATA_LENGTH: u32 = HEADER_LENGTH + TX_CONTEXT_LENGTH - + GLOBAL_VARIABLES_LENGTH + 1 /* vk_tree_root */ + 1 /* protocol_contract_tree_root */; +global COMBINED_CONSTANT_DATA_LENGTH: u32 = TX_CONSTANT_DATA_LENGTH + GLOBAL_VARIABLES_LENGTH; global PRIVATE_ACCUMULATED_DATA_LENGTH: u32 = (SCOPED_NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_TX) @@ -390,11 +397,11 @@ global PRIVATE_ACCUMULATED_DATA_LENGTH: u32 = (SCOPED_NOTE_HASH_LENGTH * MAX_NOT + (SCOPED_ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (SCOPED_LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + (PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) - + (PUBLIC_CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); -global PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = 1 + + (COUNTED_PUBLIC_CALL_REQUEST_LENGTH * MAX_ENQUEUED_CALLS_PER_TX); +global PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = TX_CONSTANT_DATA_LENGTH + + 1 /* min_revertible_side_effect_counter */ + PRIVATE_VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH - + COMBINED_CONSTANT_DATA_LENGTH + PUBLIC_CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH; @@ -405,9 +412,36 @@ global PUBLIC_ACCUMULATED_DATA_LENGTH: u32 = (MAX_NOTE_HASHES_PER_TX * SCOPED_NO + (MAX_ENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) - + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) + + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) + GAS_LENGTH; global NUM_PUBLIC_ACCUMULATED_DATA_ARRAYS: u32 = 8; + +global PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + + MAX_NULLIFIERS_PER_TX + + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + + (MAX_NOTE_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + + (MAX_ENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) + + GAS_LENGTH; + +global PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + + MAX_NULLIFIERS_PER_TX + + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH); +global NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS: u32 = 3; + +global AVM_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + + MAX_NULLIFIERS_PER_TX + + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_WRITE_LENGTH); + +global PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = TX_CONSTANT_DATA_LENGTH + + ROLLUP_VALIDATION_REQUESTS_LENGTH + + PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH /* non_revertible_accumulated_data */ + + PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH /* revertible_accumulated_data */ + + PUBLIC_CALL_REQUEST_LENGTH /* public_teardown_call_request */ + + AZTEC_ADDRESS_LENGTH /* fee_payer */; global PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = COMBINED_CONSTANT_DATA_LENGTH + PUBLIC_VALIDATION_REQUESTS_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH @@ -427,7 +461,7 @@ global VM_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = COMBINED_CONSTANT_DATA_LENGTH + GAS_LENGTH + 1 + 1 - + (PUBLIC_INNER_CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); + + (PUBLIC_INNER_CALL_REQUEST_LENGTH * MAX_ENQUEUED_CALLS_PER_TX); global KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = ROLLUP_VALIDATION_REQUESTS_LENGTH + COMBINED_ACCUMULATED_DATA_LENGTH @@ -436,6 +470,22 @@ global KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = ROLLUP_VALIDATION_REQUESTS_LEN + 1 + AZTEC_ADDRESS_LENGTH; +global AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = GLOBAL_VARIABLES_LENGTH + + TREE_SNAPSHOTS_LENGTH /* start_tree_snapshots */ + + GAS_SETTINGS_LENGTH + + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) /* public_setup_call_requests */ + + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) /* public_app_logic_call_requests */ + + PUBLIC_CALL_REQUEST_LENGTH /* public_teardown_call_request */ + + NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS /* previous_non_revertible_accumulated_data_array_lengths */ + + NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS /* previous_revertible_accumulated_data_array_lengths */ + + PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH /* previous_non_revertible_accumulated_data */ + + PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH /* previous_revertible_accumulated_data */ + + TREE_SNAPSHOTS_LENGTH /* end_tree_snapshots */ + + AVM_ACCUMULATED_DATA_LENGTH + + 1 /* transaction_fee */ + + 1 /* reverted */ +; + global CONSTANT_ROLLUP_DATA_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 1 /* vk_tree_root */ + 1 /* protocol_contract_tree_root */ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr index 855a74393cc..18d5662968f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr @@ -53,7 +53,7 @@ impl Eq for VerificationKey { pub type HonkVerificationKey = VerificationKey; pub type ClientIVCVerificationKey = VerificationKey; -pub type AVMVerificationKey = VerificationKey; +pub type AvmVerificationKey = VerificationKey; #[test] fn serialization_of_empty() { 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 9b90fff5998..ba8b509e250 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 @@ -2,7 +2,8 @@ use crate::{ abis::{ accumulated_data::{ CombinedAccumulatedData, PrivateAccumulatedData, PrivateAccumulatedDataBuilder, - PublicAccumulatedData, PublicAccumulatedDataArrayLengths, PublicAccumulatedDataBuilder, + PrivateToPublicAccumulatedData, PublicAccumulatedData, + PublicAccumulatedDataArrayLengths, PublicAccumulatedDataBuilder, }, call_context::CallContext, combined_constant_data::CombinedConstantData, @@ -14,7 +15,8 @@ use crate::{ global_variables::GlobalVariables, kernel_circuit_public_inputs::{ KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, - PublicKernelCircuitPublicInputs, VMCircuitPublicInputs, + PrivateToPublicKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs, + VMCircuitPublicInputs, }, log_hash::{EncryptedLogHash, LogHash, NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash}, max_block_number::MaxBlockNumber, @@ -29,10 +31,13 @@ use crate::{ public_circuit_public_inputs::PublicCircuitPublicInputs, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, + public_data_write::PublicDataWrite, public_inner_call_request::PublicInnerCallRequest, public_kernel_data::PublicKernelData, read_request::{ReadRequest, ScopedReadRequest}, + side_effect::Counted, tree_leaf_read_request::TreeLeafReadRequest, + tx_constant_data::TxConstantData, validation_requests::{ KeyValidationRequest, KeyValidationRequestAndGenerator, PrivateValidationRequests, PublicValidationRequestArrayLengths, PublicValidationRequests, RollupValidationRequests, @@ -42,12 +47,12 @@ use crate::{ address::{AztecAddress, EthAddress, SaltedInitializationHash}, constants::{ CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, FUNCTION_TREE_HEIGHT, - MAX_ENCRYPTED_LOGS_PER_TX, MAX_FIELD_VALUE, MAX_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_FIELD_VALUE, + MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_READS_PER_CALL, + MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, PRIVATE_CALL_REQUEST_LENGTH, PROTOCOL_CONTRACT_TREE_HEIGHT, PUBLIC_CALL_REQUEST_LENGTH, @@ -124,11 +129,12 @@ pub struct FixtureBuilder { note_encrypted_log_preimages_length: Field, encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, + public_data_writes: BoundedVec, public_data_update_requests: BoundedVec, contract_storage_update_requests: BoundedVec, private_call_requests: BoundedVec, - public_call_requests: BoundedVec, - public_inner_call_requests: BoundedVec, + public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_TX>, + public_inner_call_requests: BoundedVec, gas_used: Gas, revert_code: u8, @@ -293,6 +299,15 @@ impl FixtureBuilder { *self } + pub fn to_tx_constant_data(self) -> TxConstantData { + TxConstantData { + historical_header: self.historical_header, + tx_context: self.tx_context, + vk_tree_root: self.vk_tree_root, + protocol_contract_tree_root: self.protocol_contract_tree_root, + } + } + pub fn to_constant_data(self) -> CombinedConstantData { CombinedConstantData { historical_header: self.historical_header, @@ -409,9 +424,11 @@ impl FixtureBuilder { pub fn to_public_call_request(self) -> PublicCallRequest { PublicCallRequest { - call_context: self.build_call_context(), + msg_sender: self.msg_sender, + contract_address: self.contract_address, + function_selector: self.function_data.selector, + is_static_call: self.is_static_call, args_hash: self.args_hash, - counter: 0, } } @@ -448,7 +465,9 @@ impl FixtureBuilder { encrypted_logs_hashes, unencrypted_logs_hashes: self.unencrypted_logs_hashes, public_data_update_requests: self.public_data_update_requests, - public_call_stack: self.public_call_requests, + public_call_stack: self.public_call_requests.map(|r: Counted| { + r.inner + }), gas_used: self.gas_used, } } @@ -457,10 +476,10 @@ impl FixtureBuilder { self.to_public_accumulated_data_builder().finish() } - pub fn to_exposed_public_accumulated_data(self) -> PublicAccumulatedData { - PublicAccumulatedData { - note_hashes: self.note_hashes.storage.map(|n: ScopedNoteHash| n.expose_to_public()), - nullifiers: self.nullifiers.storage.map(|n: ScopedNullifier| n.expose_to_public()), + pub fn to_private_to_public_accumulated_data(self) -> PrivateToPublicAccumulatedData { + PrivateToPublicAccumulatedData { + note_hashes: self.note_hashes.storage.map(|n: ScopedNoteHash| n.value()), + nullifiers: self.nullifiers.storage.map(|n: ScopedNullifier| n.value()), l2_to_l1_msgs: self.l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| { m.expose_to_public() }), @@ -473,10 +492,9 @@ impl FixtureBuilder { unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| { l.expose_to_public() }), - public_data_update_requests: self.public_data_update_requests.storage, - public_call_stack: self.public_call_requests.storage.map(|cr: PublicCallRequest| { - cr.expose_to_public() - }), + public_call_requests: self.public_call_requests.storage.map( + |cr: Counted| cr.inner, + ), gas_used: self.gas_used, } } @@ -500,7 +518,7 @@ impl FixtureBuilder { note_encrypted_log_preimages_length: self.note_encrypted_log_preimages_length, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, - public_data_update_requests: self.public_data_update_requests.storage, + public_data_writes: self.public_data_writes.storage, gas_used: self.gas_used, } } @@ -518,16 +536,16 @@ impl FixtureBuilder { } pub fn to_private_kernel_circuit_public_inputs(self) -> PrivateKernelCircuitPublicInputs { + let constants = self.to_tx_constant_data(); let end = self.to_private_accumulated_data(); let validation_requests = self.to_private_validation_requests(); - let constants = self.to_constant_data(); let public_teardown_call_request = self.public_teardown_call_request; PrivateKernelCircuitPublicInputs { + constants, min_revertible_side_effect_counter: self.min_revertible_side_effect_counter, end, validation_requests, - constants, public_teardown_call_request, fee_payer: self.fee_payer, } @@ -543,6 +561,33 @@ impl FixtureBuilder { } } + pub fn to_private_to_public_kernel_circuit_public_inputs( + self, + revertible: bool, + ) -> PrivateToPublicKernelCircuitPublicInputs { + // TODO: Split the data using self.min_revertible_side_effect_counter. + let accumulated_data = self.to_private_to_public_accumulated_data(); + let non_revertible_accumulated_data = if revertible { + PrivateToPublicAccumulatedData::empty() + } else { + accumulated_data + }; + let revertible_accumulated_data = if revertible { + accumulated_data + } else { + PrivateToPublicAccumulatedData::empty() + }; + + PrivateToPublicKernelCircuitPublicInputs { + constants: self.to_tx_constant_data(), + rollup_validation_requests: self.to_rollup_validation_requests(), + non_revertible_accumulated_data, + revertible_accumulated_data, + public_teardown_call_request: self.public_teardown_call_request, + fee_payer: self.fee_payer, + } + } + pub fn to_public_circuit_public_inputs(self) -> PublicCircuitPublicInputs { PublicCircuitPublicInputs { call_context: self.build_call_context(), @@ -1137,15 +1182,14 @@ impl FixtureBuilder { } pub fn add_public_call_request(&mut self, request: PublicCallRequest) { - self.public_call_requests.push(request); + self.public_call_requests.push(Counted::new(request, self.next_counter())); } pub fn append_public_call_requests(&mut self, num: u32) { let index_offset = self.public_call_requests.len(); for i in 0..self.public_call_requests.max_len() { if i < num { - let mut request = self.mock_public_call_request(index_offset + i); - request.counter = self.next_counter(); + let request = self.mock_public_call_request(index_offset + i); self.add_public_call_request(request); } } @@ -1162,9 +1206,7 @@ impl FixtureBuilder { } pub fn set_public_teardown_call_request(&mut self) { - let mut request = self.mock_public_teardown_call_request(); - request.counter = self.next_counter(); - self.public_teardown_call_request = request; + self.public_teardown_call_request = self.mock_public_teardown_call_request(); } pub fn end_setup(&mut self) { @@ -1268,8 +1310,8 @@ impl FixtureBuilder { fields[i] = value_offset + i as Field; } let mut request = PublicCallRequest::deserialize(fields); - request.call_context.msg_sender = self.contract_address; - request.call_context.is_static_call = self.is_static_call; + request.msg_sender = self.contract_address; + request.is_static_call = self.is_static_call; request } @@ -1316,6 +1358,7 @@ impl Empty for FixtureBuilder { note_encrypted_log_preimages_length: 0, encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, + public_data_writes: BoundedVec::new(), public_data_update_requests: BoundedVec::new(), contract_storage_update_requests: BoundedVec::new(), private_call_requests: BoundedVec::new(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr index bde3ed335be..2dfa7dd1a51 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr @@ -22,7 +22,8 @@ impl Reader { self.read() as bool } - pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] { + pub fn read_array(&mut self) -> [Field; K] { + let mut result = [0; K]; for i in 0..K { result[i] = self.data[self.offset + i]; } @@ -30,9 +31,8 @@ impl Reader { result } - // TODO(#4394) pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T { - let result = deserialise(self.read_array([0; K])); + let result = deserialise(self.read_array()); result } diff --git a/yarn-project/aztec-node/src/aztec-node/server.test.ts b/yarn-project/aztec-node/src/aztec-node/server.test.ts index 81df0550a50..09b1a2e081a 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.test.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.test.ts @@ -135,13 +135,13 @@ describe('aztec node', () => { const invalidMaxBlockNumberMetadata = txs[1]; const validMaxBlockNumberMetadata = txs[2]; - invalidMaxBlockNumberMetadata.data.forRollup!.rollupValidationRequests = { + invalidMaxBlockNumberMetadata.data.rollupValidationRequests = { maxBlockNumber: new MaxBlockNumber(true, new Fr(1)), getSize: () => 1, toBuffer: () => Fr.ZERO.toBuffer(), }; - validMaxBlockNumberMetadata.data.forRollup!.rollupValidationRequests = { + validMaxBlockNumberMetadata.data.rollupValidationRequests = { maxBlockNumber: new MaxBlockNumber(true, new Fr(5)), getSize: () => 1, toBuffer: () => Fr.ZERO.toBuffer(), diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 9483f1d400b..2340fd6f2d4 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -745,11 +745,9 @@ export class AztecNodeService implements AztecNode { this.log.debug(`Simulated tx ${tx.getTxHash()} ${processedTx.revertReason ? 'Reverts' : 'Succeeds'}`); return new PublicSimulationOutput( - processedTx.encryptedLogs, - processedTx.unencryptedLogs, processedTx.revertReason, - processedTx.data.constants, - processedTx.data.end, + processedTx.constants, + processedTx.txEffect, returns, processedTx.gasUsed, ); diff --git a/yarn-project/aztec.js/src/contract/base_contract_interaction.ts b/yarn-project/aztec.js/src/contract/base_contract_interaction.ts index eb2bf9ed475..b62583c13ca 100644 --- a/yarn-project/aztec.js/src/contract/base_contract_interaction.ts +++ b/yarn-project/aztec.js/src/contract/base_contract_interaction.ts @@ -91,10 +91,7 @@ export abstract class BaseContractInteraction { ): Promise> { const txRequest = await this.create({ ...opts, estimateGas: false }); const simulationResult = await this.wallet.simulateTx(txRequest, true); - const { totalGas: gasLimits, teardownGas: teardownGasLimits } = getGasLimits( - simulationResult, - (opts?.fee?.gasSettings ?? GasSettings.default()).teardownGasLimits, - ); + const { totalGas: gasLimits, teardownGas: teardownGasLimits } = getGasLimits(simulationResult); return { gasLimits, teardownGasLimits }; } @@ -108,10 +105,7 @@ export abstract class BaseContractInteraction { if (fee) { const txRequest = await this.wallet.createTxExecutionRequest(request); const simulationResult = await this.wallet.simulateTx(txRequest, true); - const { totalGas: gasLimits, teardownGas: teardownGasLimits } = getGasLimits( - simulationResult, - fee.gasSettings.teardownGasLimits, - ); + const { totalGas: gasLimits, teardownGas: teardownGasLimits } = getGasLimits(simulationResult); this.log.debug( `Estimated gas limits for tx: DA=${gasLimits.daGas} L2=${gasLimits.l2Gas} teardownDA=${teardownGasLimits.daGas} teardownL2=${teardownGasLimits.l2Gas}`, ); diff --git a/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts b/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts index 98cdce70ee7..bd77479e8f0 100644 --- a/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts +++ b/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts @@ -1,54 +1,44 @@ -import { PublicKernelPhase, type TxSimulationResult, mockSimulatedTx } from '@aztec/circuit-types'; -import { Gas, type PartialPrivateTailPublicInputsForPublic } from '@aztec/circuits.js'; +import { type TxSimulationResult, mockSimulatedTx, mockTxForRollup } from '@aztec/circuit-types'; +import { Gas } from '@aztec/circuits.js'; import { getGasLimits } from './get_gas_limits.js'; describe('getGasLimits', () => { let txSimulationResult: TxSimulationResult; - let simulationTeardownGasLimits: Gas; beforeEach(() => { txSimulationResult = mockSimulatedTx(); - const data = txSimulationResult.publicInputs.forPublic?.end as any; - data.gasUsed = Gas.from({ daGas: 100, l2Gas: 200 }); - (txSimulationResult.publicInputs.forPublic as PartialPrivateTailPublicInputsForPublic).end = data; + const tx = mockTxForRollup(); + tx.data.forRollup!.end.gasUsed = Gas.from({ daGas: 100, l2Gas: 200 }); + txSimulationResult.publicInputs = tx.data; + txSimulationResult.publicOutput!.gasUsed = { - [PublicKernelPhase.SETUP]: Gas.from({ daGas: 10, l2Gas: 20 }), - [PublicKernelPhase.APP_LOGIC]: Gas.from({ daGas: 20, l2Gas: 40 }), - [PublicKernelPhase.TEARDOWN]: Gas.from({ daGas: 10, l2Gas: 20 }), + totalGas: Gas.from({ daGas: 140, l2Gas: 280 }), + teardownGas: Gas.from({ daGas: 10, l2Gas: 20 }), }; - simulationTeardownGasLimits = Gas.empty(); }); it('returns gas limits from private gas usage only', () => { txSimulationResult.publicOutput = undefined; // Should be 110 and 220 but oh floating point - expect(getGasLimits(txSimulationResult, simulationTeardownGasLimits)).toEqual({ + expect(getGasLimits(txSimulationResult)).toEqual({ totalGas: Gas.from({ daGas: 111, l2Gas: 221 }), teardownGas: Gas.empty(), }); }); it('returns gas limits for private and public', () => { - expect(getGasLimits(txSimulationResult, simulationTeardownGasLimits)).toEqual({ + expect(getGasLimits(txSimulationResult)).toEqual({ totalGas: Gas.from({ daGas: 154, l2Gas: 308 }), teardownGas: Gas.from({ daGas: 11, l2Gas: 22 }), }); }); it('pads gas limits', () => { - expect(getGasLimits(txSimulationResult, simulationTeardownGasLimits, 1)).toEqual({ + expect(getGasLimits(txSimulationResult, 1)).toEqual({ totalGas: Gas.from({ daGas: 280, l2Gas: 560 }), teardownGas: Gas.from({ daGas: 20, l2Gas: 40 }), }); }); - - it('subtracts input teardown gas limits', () => { - simulationTeardownGasLimits = Gas.from({ daGas: 80, l2Gas: 200 }); - expect(getGasLimits(txSimulationResult, simulationTeardownGasLimits)).toEqual({ - totalGas: Gas.from({ daGas: 66, l2Gas: 88 }), - teardownGas: Gas.from({ daGas: 11, l2Gas: 22 }), - }); - }); }); diff --git a/yarn-project/aztec.js/src/contract/get_gas_limits.ts b/yarn-project/aztec.js/src/contract/get_gas_limits.ts index 70d1dcae5ec..1d740c558bc 100644 --- a/yarn-project/aztec.js/src/contract/get_gas_limits.ts +++ b/yarn-project/aztec.js/src/contract/get_gas_limits.ts @@ -1,26 +1,13 @@ -import { PublicKernelPhase, type TxSimulationResult } from '@aztec/circuit-types'; -import { Gas } from '@aztec/circuits.js'; +import { type GasUsed, type TxSimulationResult } from '@aztec/circuit-types'; /** * Returns suggested total and teardown gas limits for a simulated tx. * Note that public gas usage is only accounted for if the publicOutput is present. * @param pad - Percentage to pad the suggested gas limits by, defaults to 10%. */ -export function getGasLimits(simulationResult: TxSimulationResult, simulationTeardownGasLimits: Gas, pad = 0.1) { - const simulatedTx = simulationResult.toSimulatedTx(); - const privateGasUsed = simulatedTx.data.publicInputs.end.gasUsed - .sub(simulationTeardownGasLimits) - .add(simulatedTx.data.forPublic?.endNonRevertibleData.gasUsed ?? Gas.empty()); - if (simulationResult.publicOutput) { - const publicGasUsed = Object.values(simulationResult.publicOutput.gasUsed) - .filter(Boolean) - .reduce((total, current) => total.add(current), Gas.empty()); - const teardownGas = simulationResult.publicOutput.gasUsed[PublicKernelPhase.TEARDOWN] ?? Gas.empty(); - - return { - totalGas: privateGasUsed.add(publicGasUsed).mul(1 + pad), - teardownGas: teardownGas.mul(1 + pad), - }; - } - return { totalGas: privateGasUsed.mul(1 + pad), teardownGas: Gas.empty() }; +export function getGasLimits(simulationResult: TxSimulationResult, pad = 0.1): GasUsed { + return { + totalGas: simulationResult.gasUsed.totalGas.mul(1 + pad), + teardownGas: simulationResult.gasUsed.teardownGas.mul(1 + pad), + }; } diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index 8f8677f2d53..4d437e565ba 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -1,5 +1,6 @@ import { AvmCircuitInputs, + AvmCircuitPublicInputs, Gas, GlobalVariables, type PublicFunction, @@ -150,6 +151,7 @@ const proveAndVerifyAvmTestContract = async ( /*calldata=*/ context.environment.calldata, /*publicInputs=*/ getPublicInputs(pxResult), /*avmHints=*/ pxResult.avmCircuitHints, + /*output*/ AvmCircuitPublicInputs.empty(), ); // Then we prove. diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 5e6031df2bb..72ce7b17bfe 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -393,20 +393,6 @@ export class BBNativeRollupProver implements ServerCircuitProver { return emptyPrivateKernelProof; } - public async getEmptyTubeProof( - inputs: PrivateKernelEmptyInputData, - ): Promise> { - const emptyNested = await this.getEmptyNestedProof(); - const emptyPrivateKernelProof = await this.getEmptyTubeProofFromEmptyNested( - PrivateKernelEmptyInputs.from({ - ...inputs, - emptyNested, - }), - ); - - return emptyPrivateKernelProof; - } - private async getEmptyNestedProof(): Promise { const inputs = new EmptyNestedCircuitInputs(); const { proof } = await this.createRecursiveProof( @@ -427,23 +413,6 @@ export class BBNativeRollupProver implements ServerCircuitProver { return new EmptyNestedData(proof, verificationKey.keyAsFields); } - private async getEmptyTubeProofFromEmptyNested( - inputs: PrivateKernelEmptyInputs, - ): Promise> { - const { circuitOutput, proof } = await this.createRecursiveProof( - inputs, - 'PrivateKernelEmptyArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, - convertPrivateKernelEmptyInputsToWitnessMap, - convertPrivateKernelEmptyOutputsFromWitnessMap, - ); - // info(`proof: ${proof.proof}`); - const verificationKey = await this.getVerificationKeyDataForCircuit('PrivateKernelEmptyArtifact'); - await this.verifyProof('PrivateKernelEmptyArtifact', proof.binaryProof); - - return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey); - } - private async getEmptyPrivateKernelProofFromEmptyNested( inputs: PrivateKernelEmptyInputs, ): Promise> { diff --git a/yarn-project/bb-prover/src/test/test_avm.ts b/yarn-project/bb-prover/src/test/test_avm.ts index d1b128f0c00..4cbac8bb1c4 100644 --- a/yarn-project/bb-prover/src/test/test_avm.ts +++ b/yarn-project/bb-prover/src/test/test_avm.ts @@ -7,6 +7,7 @@ import { Header, L2ToL1Message, LogHash, + MAX_ENQUEUED_CALLS_PER_CALL, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, @@ -14,7 +15,6 @@ import { MAX_NULLIFIERS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, @@ -72,7 +72,7 @@ export function getPublicInputs(result: PublicFunctionCallResult): PublicCircuit ContractStorageUpdateRequest.empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ), - publicCallRequests: padArrayEnd([], PublicInnerCallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL), + publicCallRequests: padArrayEnd([], PublicInnerCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_CALL), unencryptedLogsHashes: padArrayEnd(result.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_CALL), historicalHeader: Header.empty(), globalVariables: GlobalVariables.empty(), diff --git a/yarn-project/bb-prover/src/test/test_circuit_prover.ts b/yarn-project/bb-prover/src/test/test_circuit_prover.ts index 6deb323b502..7bc6e9ef655 100644 --- a/yarn-project/bb-prover/src/test/test_circuit_prover.ts +++ b/yarn-project/bb-prover/src/test/test_circuit_prover.ts @@ -55,7 +55,6 @@ import { convertMergeRollupInputsToWitnessMap, convertMergeRollupOutputsFromWitnessMap, convertPrivateKernelEmptyInputsToWitnessMap, - convertPrivateKernelEmptyOutputsFromWitnessMap, convertRootParityInputsToWitnessMap, convertRootParityOutputsFromWitnessMap, convertRootRollupInputsToWitnessMap, @@ -121,31 +120,6 @@ export class TestCircuitProver implements ServerCircuitProver { ); } - public async getEmptyTubeProof( - inputs: PrivateKernelEmptyInputData, - ): Promise> { - const emptyNested = new EmptyNestedData( - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - ProtocolCircuitVks['EmptyNestedArtifact'].keyAsFields, - ); - const kernelInputs = new PrivateKernelEmptyInputs( - emptyNested, - inputs.header, - inputs.chainId, - inputs.version, - inputs.vkTreeRoot, - inputs.protocolContractTreeRoot, - ); - - return await this.simulate( - kernelInputs, - 'EmptyNestedArtifact', - NESTED_RECURSIVE_PROOF_LENGTH, - convertPrivateKernelEmptyInputsToWitnessMap, - convertPrivateKernelEmptyOutputsFromWitnessMap, - ); - } - /** * Simulates the base parity circuit from its inputs. * @param inputs - Inputs to the circuit. diff --git a/yarn-project/circuit-types/src/index.ts b/yarn-project/circuit-types/src/index.ts index 12c74f0c8f8..ce3892157ac 100644 --- a/yarn-project/circuit-types/src/index.ts +++ b/yarn-project/circuit-types/src/index.ts @@ -17,7 +17,6 @@ export * from './p2p/index.js'; export * from './packed_values.js'; export * from './prover_coordination/index.js'; export * from './public_data_witness.js'; -export * from './public_data_write.js'; export * from './public_execution_request.js'; export * from './sibling_path/index.js'; export * from './simulation_error.js'; diff --git a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts index fd3578a1032..e150dddf0e5 100644 --- a/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts +++ b/yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts @@ -19,7 +19,6 @@ import { type RootParityInputs, type RootRollupInputs, type RootRollupPublicInputs, - type TUBE_PROOF_LENGTH, type TubeInputs, } from '@aztec/circuits.js'; @@ -132,12 +131,6 @@ export interface ServerCircuitProver { epochNumber?: number, ): Promise>; - getEmptyTubeProof( - inputs: PrivateKernelEmptyInputData, - signal?: AbortSignal, - epochNumber?: number, - ): Promise>; - /** * Create a proof for the AVM circuit. * @param inputs - Inputs to the AVM circuit. diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index c99a6af0a83..e89e8401267 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -7,15 +7,14 @@ import { GasSettings, LogHash, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_ENQUEUED_CALLS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_NULLIFIERS_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, Nullifier, PartialPrivateTailPublicInputsForPublic, PrivateCircuitPublicInputs, PrivateKernelTailCircuitPublicInputs, - PublicAccumulatedDataBuilder, + PrivateToPublicAccumulatedDataBuilder, ScopedLogHash, SerializableContractInstance, computeContractAddressFromInstance, @@ -23,11 +22,7 @@ import { getContractClassFromArtifact, } from '@aztec/circuits.js'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; -import { - makeCombinedAccumulatedData, - makeCombinedConstantData, - makePublicCallRequest, -} from '@aztec/circuits.js/testing'; +import { makeCombinedConstantData, makeGas, makePublicCallRequest } from '@aztec/circuits.js/testing'; import { type ContractArtifact, NoteSelector } from '@aztec/foundation/abi'; import { makeTuple } from '@aztec/foundation/array'; import { padArrayEnd, times } from '@aztec/foundation/collection'; @@ -42,14 +37,15 @@ import { EpochProofQuote } from './prover_coordination/epoch_proof_quote.js'; import { EpochProofQuotePayload } from './prover_coordination/epoch_proof_quote_payload.js'; import { PublicExecutionRequest } from './public_execution_request.js'; import { PublicSimulationOutput, Tx, TxHash, TxSimulationResult, accumulatePrivateReturnValues } from './tx/index.js'; +import { TxEffect } from './tx_effect.js'; export const randomTxHash = (): TxHash => new TxHash(randomBytes(32)); export const mockPrivateExecutionResult = ( seed = 1, hasLogs = false, - numberOfNonRevertiblePublicCallRequests = MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX / 2, - numberOfRevertiblePublicCallRequests = MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX / 2, + numberOfNonRevertiblePublicCallRequests = MAX_ENQUEUED_CALLS_PER_TX / 2, + numberOfRevertiblePublicCallRequests = MAX_ENQUEUED_CALLS_PER_TX / 2, hasPublicTeardownCallRequest = false, ) => { const totalPublicCallRequests = @@ -67,14 +63,11 @@ export const mockPrivateExecutionResult = ( if (hasPublicTeardownCallRequest) { const request = publicCallRequests.shift()!; const args = publicFunctionArgs.shift()!; - publicTeardownFunctionCall = new PublicExecutionRequest( - CallContext.fromFields(request.callContext.toFields()), - args, - ); + publicTeardownFunctionCall = new PublicExecutionRequest(CallContext.fromFields(request.toFields()), args); } enqueuedPublicFunctionCalls = publicCallRequests.map( - (r, i) => new PublicExecutionRequest(CallContext.fromFields(r.callContext.toFields()), publicFunctionArgs[i]), + (r, i) => new PublicExecutionRequest(CallContext.fromFields(r.toFields()), publicFunctionArgs[i]), ); } return new PrivateExecutionResult( @@ -107,8 +100,8 @@ export const mockTx = ( seed = 1, { hasLogs = false, - numberOfNonRevertiblePublicCallRequests = MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX / 2, - numberOfRevertiblePublicCallRequests = MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX / 2, + numberOfNonRevertiblePublicCallRequests = MAX_ENQUEUED_CALLS_PER_TX / 2, + numberOfRevertiblePublicCallRequests = MAX_ENQUEUED_CALLS_PER_TX / 2, hasPublicTeardownCallRequest = false, feePayer = AztecAddress.ZERO, }: { @@ -138,8 +131,8 @@ export const mockTx = ( data.forRollup = undefined; data.forPublic = PartialPrivateTailPublicInputsForPublic.empty(); - const revertibleBuilder = new PublicAccumulatedDataBuilder(); - const nonRevertibleBuilder = new PublicAccumulatedDataBuilder(); + const revertibleBuilder = new PrivateToPublicAccumulatedDataBuilder(); + const nonRevertibleBuilder = new PrivateToPublicAccumulatedDataBuilder(); const publicCallRequests = times(totalPublicCallRequests, i => makePublicCallRequest(seed + 0x102 + i)).reverse(); // Reverse it so that they are sorted by counters in descending order. const publicFunctionArgs = times(totalPublicCallRequests, i => [new Fr(seed + i * 100), new Fr(seed + i * 101)]); @@ -149,25 +142,19 @@ export const mockTx = ( const request = publicCallRequests.shift()!; data.forPublic.publicTeardownCallRequest = request; const args = publicFunctionArgs.shift()!; - publicTeardownFunctionCall = new PublicExecutionRequest( - CallContext.fromFields(request.callContext.toFields()), - args, - ); + publicTeardownFunctionCall = new PublicExecutionRequest(CallContext.fromFields(request.toFields()), args); } enqueuedPublicFunctionCalls = publicCallRequests.map( - (r, i) => new PublicExecutionRequest(CallContext.fromFields(r.callContext.toFields()), publicFunctionArgs[i]), + (r, i) => new PublicExecutionRequest(CallContext.fromFields(r.toFields()), publicFunctionArgs[i]), ); - const nonRevertibleNullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, Nullifier.empty); - nonRevertibleNullifiers[0] = firstNullifier; - - data.forPublic.endNonRevertibleData = nonRevertibleBuilder - .withNullifiers(nonRevertibleNullifiers) + data.forPublic.nonRevertibleAccumulatedData = nonRevertibleBuilder + .pushNullifier(firstNullifier.value) .withPublicCallStack(publicCallRequests.slice(numberOfRevertiblePublicCallRequests)) .build(); - data.forPublic.end = revertibleBuilder + data.forPublic.revertibleAccumulatedData = revertibleBuilder .withPublicCallStack(publicCallRequests.slice(0, numberOfRevertiblePublicCallRequests)) .build(); @@ -191,9 +178,9 @@ export const mockTx = ( ); // make the first log non-revertible if (functionCount === 0) { - data.forPublic.endNonRevertibleData.encryptedLogsHashes[nonRevertibleIndex++] = hash; + data.forPublic.nonRevertibleAccumulatedData.encryptedLogsHashes[nonRevertibleIndex++] = hash; } else { - data.forPublic.end.encryptedLogsHashes[revertibleIndex++] = hash; + data.forPublic.revertibleAccumulatedData.encryptedLogsHashes[revertibleIndex++] = hash; } } }); @@ -216,9 +203,9 @@ export const mockTx = ( ); // make the first log non-revertible if (functionCount === 0) { - data.forPublic.endNonRevertibleData.unencryptedLogsHashes[nonRevertibleIndex++] = hash; + data.forPublic.nonRevertibleAccumulatedData.unencryptedLogsHashes[nonRevertibleIndex++] = hash; } else { - data.forPublic.end.unencryptedLogsHashes[revertibleIndex++] = hash; + data.forPublic.revertibleAccumulatedData.unencryptedLogsHashes[revertibleIndex++] = hash; } } }); @@ -271,13 +258,14 @@ export const mockSimulatedTx = (seed = 1, hasLogs = true) => { const privateExecutionResult = mockPrivateExecutionResult(seed, hasLogs); const tx = mockTx(seed, { hasLogs }); const output = new PublicSimulationOutput( - tx.encryptedLogs, - tx.unencryptedLogs, undefined, makeCombinedConstantData(), - makeCombinedAccumulatedData(), + TxEffect.random(), [accumulatePrivateReturnValues(privateExecutionResult)], - {}, + { + totalGas: makeGas(), + teardownGas: makeGas(), + }, ); return new TxSimulationResult(privateExecutionResult, tx.data, output); }; diff --git a/yarn-project/circuit-types/src/public_data_write.ts b/yarn-project/circuit-types/src/public_data_write.ts deleted file mode 100644 index f15b8c29991..00000000000 --- a/yarn-project/circuit-types/src/public_data_write.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { STRING_ENCODING } from '@aztec/circuits.js'; -import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; - -/** - * Write operations on the public state tree. - */ -export class PublicDataWrite { - static SIZE_IN_BYTES = Fr.SIZE_IN_BYTES * 2; - - constructor( - /** - * Index of the updated leaf. - */ - public readonly leafIndex: Fr, - /** - * New value of the leaf. - */ - public readonly newValue: Fr, - ) {} - - /** - * Creates a new public data write operation from the given arguments. - * @param args - Arguments containing info used to create a new public data write operation. - * @returns A new public data write operation instance. - */ - static from(args: { - /** - * Index of the updated leaf. - */ - leafIndex: Fr; - /** - * New value of the leaf. - */ - newValue: Fr; - }) { - return new PublicDataWrite(args.leafIndex, args.newValue); - } - - /** - * Serializes the public data write operation to a buffer. - * @returns A buffer containing the serialized public data write operation. - */ - toBuffer(): Buffer { - return serializeToBuffer(this.leafIndex, this.newValue); - } - - /** - * Serializes the operation to a string. - * @returns A string representation of the operation. - */ - toString(): string { - return this.toBuffer().toString(STRING_ENCODING); - } - - /** - * Checks if the public data write operation is empty. - * @returns True if the public data write operation is empty, false otherwise. - */ - isEmpty(): boolean { - return this.leafIndex.isZero() && this.newValue.isZero(); - } - - /** - * Creates a new public data write operation from the given buffer. - * @param buffer - Buffer containing the serialized public data write operation. - * @returns A new public data write operation instance. - */ - static fromBuffer(buffer: Buffer | BufferReader): PublicDataWrite { - const reader = BufferReader.asReader(buffer); - return new PublicDataWrite(Fr.fromBuffer(reader), Fr.fromBuffer(reader)); - } - - /** - * Creates a new public data write operation from the given string. - * @param str - The serialized string - * @returns A new public data write operation instance. - */ - static fromString(str: string): PublicDataWrite { - return PublicDataWrite.fromBuffer(Buffer.from(str, STRING_ENCODING)); - } - - /** - * Creates an empty public data write operation. - * @returns A new public data write operation instance. - */ - static empty(): PublicDataWrite { - return new PublicDataWrite(Fr.ZERO, Fr.ZERO); - } - - /** - * Creates a random public data write operation. - * @returns A new public data write operation instance. - */ - static random(): PublicDataWrite { - return new PublicDataWrite(Fr.random(), Fr.random()); - } - - static isEmpty(data: PublicDataWrite): boolean { - return data.isEmpty(); - } -} diff --git a/yarn-project/circuit-types/src/public_execution_request.ts b/yarn-project/circuit-types/src/public_execution_request.ts index 2344054e7b6..8e7c8b5fa58 100644 --- a/yarn-project/circuit-types/src/public_execution_request.ts +++ b/yarn-project/circuit-types/src/public_execution_request.ts @@ -52,7 +52,11 @@ export class PublicExecutionRequest { isForCallRequest(callRequest: PublicCallRequest) { return ( - this.callContext.equals(callRequest.callContext) && computeVarArgsHash(this.args).equals(callRequest.argsHash) + this.callContext.msgSender.equals(callRequest.msgSender) && + this.callContext.contractAddress.equals(callRequest.contractAddress) && + this.callContext.functionSelector.equals(callRequest.functionSelector) && + this.callContext.isStaticCall == callRequest.isStaticCall && + computeVarArgsHash(this.args).equals(callRequest.argsHash) ); } diff --git a/yarn-project/circuit-types/src/test/factories.ts b/yarn-project/circuit-types/src/test/factories.ts index b0d5e8f71c8..e183779e0e7 100644 --- a/yarn-project/circuit-types/src/test/factories.ts +++ b/yarn-project/circuit-types/src/test/factories.ts @@ -1,65 +1,154 @@ -import { type MerkleTreeReadOperations, makeProcessedTx, mockTx } from '@aztec/circuit-types'; import { + type MerkleTreeReadOperations, + ProvingRequestType, + makeProcessedTxFromPrivateOnlyTx, + makeProcessedTxFromTxWithPublicCalls, + mockTx, +} from '@aztec/circuit-types'; +import { + AvmCircuitInputs, + AvmCircuitPublicInputs, + AvmExecutionHints, Fr, + Gas, GasSettings, + GlobalVariables, type Header, - KernelCircuitPublicInputs, LogHash, - MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - PublicDataUpdateRequest, + PublicCircuitPublicInputs, + PublicDataWrite, + RevertCode, ScopedLogHash, + TxConstantData, } from '@aztec/circuits.js'; -import { makeScopedL2ToL1Message } from '@aztec/circuits.js/testing'; +import { makeCombinedAccumulatedData, makeGas, makePrivateToPublicAccumulatedData } from '@aztec/circuits.js/testing'; import { makeTuple } from '@aztec/foundation/array'; +import { makeHeader } from '../l2_block_code_to_purge.js'; + /** Makes a bloated processed tx for testing purposes. */ -export function makeBloatedProcessedTx( - historicalHeaderOrDb: Header | MerkleTreeReadOperations, - vkRoot: Fr, - protocolContractTreeRoot: Fr, - seed = 0x1, - overrides: { inclusionFee?: Fr } = {}, -) { - seed *= MAX_NULLIFIERS_PER_TX; // Ensure no clashing given incremental seeds - const tx = mockTx(seed); - const kernelOutput = KernelCircuitPublicInputs.empty(); - kernelOutput.constants.vkTreeRoot = vkRoot; - kernelOutput.constants.protocolContractTreeRoot = protocolContractTreeRoot; - kernelOutput.constants.historicalHeader = - 'getInitialHeader' in historicalHeaderOrDb ? historicalHeaderOrDb.getInitialHeader() : historicalHeaderOrDb; - kernelOutput.end.publicDataUpdateRequests = makeTuple( - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - i => new PublicDataUpdateRequest(new Fr(i), new Fr(i + 10), i + 20), - seed + 0x500, - ); - kernelOutput.end.publicDataUpdateRequests = makeTuple( - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - i => new PublicDataUpdateRequest(new Fr(i), new Fr(i + 10), i + 20), - seed + 0x600, - ); - - kernelOutput.constants.txContext.gasSettings = GasSettings.default({ inclusionFee: overrides.inclusionFee }); - - const processedTx = makeProcessedTx(tx, kernelOutput); - - processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, i => new Fr(i), seed + 0x100); - processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, i => new Fr(i), seed + 0x100000); - - processedTx.data.end.nullifiers[tx.data.forPublic!.end.nullifiers.length - 1] = Fr.zero(); - - processedTx.data.end.l2ToL1Msgs = makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, makeScopedL2ToL1Message, seed + 0x300); - processedTx.noteEncryptedLogs.unrollLogs().forEach((log, i) => { - processedTx.data.end.noteEncryptedLogsHashes[i] = new LogHash(Fr.fromBuffer(log.hash()), 0, new Fr(log.length)); - }); - processedTx.encryptedLogs.unrollLogs().forEach((log, i) => { - processedTx.data.end.encryptedLogsHashes[i] = new ScopedLogHash( - new LogHash(Fr.fromBuffer(log.hash()), 0, new Fr(log.length)), - log.maskedContractAddress, +export function makeBloatedProcessedTx({ + seed = 1, + header, + db, + chainId = Fr.ZERO, + version = Fr.ZERO, + gasSettings = GasSettings.default(), + vkTreeRoot = Fr.ZERO, + protocolContractTreeRoot = Fr.ZERO, + globalVariables = GlobalVariables.empty(), + privateOnly = false, +}: { + seed?: number; + header?: Header; + db?: MerkleTreeReadOperations; + chainId?: Fr; + version?: Fr; + gasSettings?: GasSettings; + vkTreeRoot?: Fr; + globalVariables?: GlobalVariables; + protocolContractTreeRoot?: Fr; + privateOnly?: boolean; +} = {}) { + seed *= 0x1000; // Avoid clashing with the previous mock values if seed only increases by 1. + + if (!header) { + if (db) { + header = db.getInitialHeader(); + } else { + header = makeHeader(seed); + } + } + + const txConstantData = TxConstantData.empty(); + txConstantData.historicalHeader = header; + txConstantData.txContext.chainId = chainId; + txConstantData.txContext.version = version; + txConstantData.txContext.gasSettings = gasSettings; + txConstantData.vkTreeRoot = vkTreeRoot; + txConstantData.protocolContractTreeRoot = protocolContractTreeRoot; + + const tx = !privateOnly + ? mockTx(seed) + : mockTx(seed, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 0 }); + tx.data.constants = txConstantData; + + if (privateOnly) { + const data = makeCombinedAccumulatedData(seed + 0x1000); + + // Private-only tx has no public data writes. + data.publicDataWrites.forEach((_, i) => (data.publicDataWrites[i] = PublicDataWrite.empty())); + + // Make the gasUsed empty so that transaction fee is simply the inclusion fee. + data.gasUsed = Gas.empty(); + const transactionFee = gasSettings.inclusionFee; + + clearLogs(data); + + tx.data.forRollup!.end = data; + + return makeProcessedTxFromPrivateOnlyTx( + tx, + transactionFee, + undefined /* feePaymentPublicDataWrite */, + globalVariables, ); - }); + } else { + const revertibleData = makePrivateToPublicAccumulatedData(seed + 0x1000); + + revertibleData.nullifiers[MAX_NULLIFIERS_PER_TX - 1] = Fr.ZERO; // Leave one space for the tx hash nullifier in nonRevertibleAccumulatedData. + + clearLogs(revertibleData); + + tx.data.forPublic!.revertibleAccumulatedData = revertibleData; + + const avmOutput = AvmCircuitPublicInputs.empty(); + avmOutput.globalVariables = globalVariables; + avmOutput.accumulatedData.noteHashes = revertibleData.noteHashes; + avmOutput.accumulatedData.nullifiers = revertibleData.nullifiers; + avmOutput.accumulatedData.l2ToL1Msgs = revertibleData.l2ToL1Msgs; + avmOutput.accumulatedData.publicDataWrites = makeTuple( + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + i => new PublicDataWrite(new Fr(i), new Fr(i + 10)), + seed + 0x2000, + ); + + const avmCircuitInputs = new AvmCircuitInputs( + '', + [], + PublicCircuitPublicInputs.empty(), + AvmExecutionHints.empty(), + avmOutput, + ); + + const gasUsed = { + totalGas: makeGas(), + teardownGas: makeGas(), + }; + + return makeProcessedTxFromTxWithPublicCalls( + tx, + { + type: ProvingRequestType.PUBLIC_VM, + inputs: avmCircuitInputs, + }, + undefined /* feePaymentPublicDataWrite */, + gasUsed, + RevertCode.OK, + undefined /* revertReason */, + ); + } +} - return processedTx; +// Remove all logs as it's ugly to mock them at the moment and we are going to change it to have the preimages be part of the public inputs soon. +function clearLogs(data: { + noteEncryptedLogsHashes: LogHash[]; + encryptedLogsHashes: ScopedLogHash[]; + unencryptedLogsHashes: ScopedLogHash[]; +}) { + data.noteEncryptedLogsHashes.forEach((_, i) => (data.noteEncryptedLogsHashes[i] = LogHash.empty())); + data.encryptedLogsHashes.forEach((_, i) => (data.encryptedLogsHashes[i] = ScopedLogHash.empty())); + data.unencryptedLogsHashes.forEach((_, i) => (data.unencryptedLogsHashes[i] = ScopedLogHash.empty())); } diff --git a/yarn-project/circuit-types/src/tx/gas_used.ts b/yarn-project/circuit-types/src/tx/gas_used.ts new file mode 100644 index 00000000000..2522b74b863 --- /dev/null +++ b/yarn-project/circuit-types/src/tx/gas_used.ts @@ -0,0 +1,14 @@ +import { type Gas } from '@aztec/circuits.js'; + +export interface GasUsed { + /** + * Total gas used across both private and public executions. + * Note that this does not determine the transaction fee. The fee is calculated using `teardownGasLimits` from + * `GasSettings`, rather than actual teardown gas. + */ + totalGas: Gas; + /** + * The actual gas used in the teardown phase. + */ + teardownGas: Gas; +} diff --git a/yarn-project/circuit-types/src/tx/index.ts b/yarn-project/circuit-types/src/tx/index.ts index abe8d867574..bc94339f36b 100644 --- a/yarn-project/circuit-types/src/tx/index.ts +++ b/yarn-project/circuit-types/src/tx/index.ts @@ -1,3 +1,4 @@ +export * from './gas_used.js'; export * from './processed_tx.js'; export * from './public_simulation_output.js'; export * from './simulated_tx.js'; diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index 63345772338..80c9cb665c9 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -1,31 +1,20 @@ -import { - type AvmProvingRequest, - EncryptedNoteTxL2Logs, - EncryptedTxL2Logs, - PublicDataWrite, - type PublicInputsAndRecursiveProof, - type SimulationError, - type Tx, - TxEffect, - TxHash, - UnencryptedTxL2Logs, -} from '@aztec/circuit-types'; +import { type AvmProvingRequest, type SimulationError, type Tx, TxEffect, TxHash } from '@aztec/circuit-types'; import { ClientIvcProof, + CombinedConstantData, Fr, - type Gas, - type GasFees, + Gas, + type GlobalVariables, type Header, - KernelCircuitPublicInputs, - type NESTED_RECURSIVE_PROOF_LENGTH, - type PublicDataUpdateRequest, + PrivateKernelTailCircuitPublicInputs, + type PublicDataWrite, type PublicKernelCircuitPublicInputs, - type RecursiveProof, - type TUBE_PROOF_LENGTH, - type VerificationKeyData, + RevertCode, } from '@aztec/circuits.js'; import { siloL2ToL1Message } from '@aztec/circuits.js/hash'; +import { type GasUsed } from './gas_used.js'; + export enum PublicKernelPhase { SETUP, APP_LOGIC, @@ -36,37 +25,43 @@ export enum PublicKernelPhase { * Represents a tx that has been processed by the sequencer public processor, * so its kernel circuit public inputs are filled in. */ -export type ProcessedTx = Pick & { - /** - * Output of the private tail or public tail kernel circuit for this tx. - */ - data: KernelCircuitPublicInputs; +export type ProcessedTx = { /** * Hash of the transaction. */ hash: TxHash; /** - * Flag indicating the tx is 'empty' meaning it's a padding tx to take us to a power of 2. + * Tx.data. The output of the private kernel tail or tail_to_public. */ - isEmpty: boolean; + data: PrivateKernelTailCircuitPublicInputs; /** - * Reason the tx was reverted. + * Proof for the private execution. */ - revertReason: SimulationError | undefined; + clientIvcProof: ClientIvcProof; /** * The request for AVM proving. */ avmProvingRequest: AvmProvingRequest | undefined; /** - * Gas usage per public execution phase. - * Doesn't account for any base costs nor DA gas used in private execution. + * Combining `TxConstantData` specified by the user, and `GlobalVariables` injected by the sequencer. + */ + constants: CombinedConstantData; + /** + * Output data of the tx. + */ + txEffect: TxEffect; + /* + * Gas used by the entire transaction. + */ + gasUsed: GasUsed; + /** + * Reason the tx was reverted. */ - gasUsed: Partial>; + revertReason: SimulationError | undefined; /** - * All public data updates for this transaction, including those created - * or updated by the protocol, such as balance updates from fee payments. + * Flag indicating the tx is 'empty' meaning it's a padding tx to take us to a power of 2. */ - finalPublicDataUpdateRequests: PublicDataUpdateRequest[]; + isEmpty: boolean; }; export type RevertedTx = ProcessedTx & { @@ -78,7 +73,7 @@ export type RevertedTx = ProcessedTx & { }; export function isRevertedTx(tx: ProcessedTx): tx is RevertedTx { - return !tx.data.revertCode.isOK(); + return !tx.txEffect.revertCode.isOK(); } export function partitionReverts(txs: ProcessedTx[]): { reverted: RevertedTx[]; nonReverted: ProcessedTx[] } { @@ -109,103 +104,6 @@ export type FailedTx = { error: Error; }; -/** - * Makes a processed tx out of source tx. - * @param tx - Source tx. - * @param kernelOutput - Output of the kernel circuit simulation for this tx. - * @param proof - Proof of the kernel circuit for this tx. - */ -export function makeProcessedTx( - tx: Tx, - kernelOutput: KernelCircuitPublicInputs, - { - revertReason, - gasUsed = {}, - avmProvingRequest, - finalPublicDataUpdateRequests, - }: { - revertReason?: SimulationError; - gasUsed?: ProcessedTx['gasUsed']; - avmProvingRequest?: AvmProvingRequest; - finalPublicDataUpdateRequests?: PublicDataUpdateRequest[]; - } = {}, -): ProcessedTx { - return { - hash: tx.getTxHash(), - data: kernelOutput, - clientIvcProof: tx.clientIvcProof, - // TODO(4712): deal with non-revertible logs here - noteEncryptedLogs: tx.noteEncryptedLogs, - encryptedLogs: tx.encryptedLogs, - unencryptedLogs: tx.unencryptedLogs, - isEmpty: false, - revertReason, - avmProvingRequest, - gasUsed, - finalPublicDataUpdateRequests: finalPublicDataUpdateRequests ?? kernelOutput.end.publicDataUpdateRequests, - }; -} - -export type PaddingProcessedTx = ProcessedTx & { - verificationKey: VerificationKeyData; - recursiveProof: RecursiveProof; -}; - -export type PaddingProcessedTxFromTube = ProcessedTx & { - verificationKey: VerificationKeyData; - recursiveProof: RecursiveProof; -}; - -/** - * Makes a padding empty tx with a valid proof. - * @returns A valid padding processed tx. - */ -export function makePaddingProcessedTx( - kernelOutput: PublicInputsAndRecursiveProof, -): PaddingProcessedTx { - const hash = new TxHash(Fr.ZERO.toBuffer()); - return { - hash, - noteEncryptedLogs: EncryptedNoteTxL2Logs.empty(), - encryptedLogs: EncryptedTxL2Logs.empty(), - unencryptedLogs: UnencryptedTxL2Logs.empty(), - data: kernelOutput.inputs, - clientIvcProof: ClientIvcProof.empty(), - isEmpty: true, - revertReason: undefined, - avmProvingRequest: undefined, - gasUsed: {}, - finalPublicDataUpdateRequests: [], - verificationKey: kernelOutput.verificationKey, - recursiveProof: kernelOutput.proof, - }; -} - -/** - * Makes a padding empty tx with a valid proof. - * @returns A valid padding processed tx. - */ -export function makePaddingProcessedTxFromTubeProof( - kernelOutput: PublicInputsAndRecursiveProof, -): PaddingProcessedTxFromTube { - const hash = new TxHash(Fr.ZERO.toBuffer()); - return { - hash, - noteEncryptedLogs: EncryptedNoteTxL2Logs.empty(), - encryptedLogs: EncryptedTxL2Logs.empty(), - unencryptedLogs: UnencryptedTxL2Logs.empty(), - data: kernelOutput.inputs, - clientIvcProof: ClientIvcProof.empty(), - isEmpty: true, - revertReason: undefined, - avmProvingRequest: undefined, - gasUsed: {}, - finalPublicDataUpdateRequests: [], - verificationKey: kernelOutput.verificationKey, - recursiveProof: kernelOutput.proof, - }; -} - /** * Makes an empty tx from an empty kernel circuit public inputs. * @returns A processed empty tx. @@ -217,118 +115,131 @@ export function makeEmptyProcessedTx( vkTreeRoot: Fr, protocolContractTreeRoot: Fr, ): ProcessedTx { - const emptyKernelOutput = KernelCircuitPublicInputs.empty(); - emptyKernelOutput.constants.historicalHeader = header; - emptyKernelOutput.constants.txContext.chainId = chainId; - emptyKernelOutput.constants.txContext.version = version; - emptyKernelOutput.constants.vkTreeRoot = vkTreeRoot; - emptyKernelOutput.constants.protocolContractTreeRoot = protocolContractTreeRoot; + const constants = CombinedConstantData.empty(); + constants.historicalHeader = header; + constants.txContext.chainId = chainId; + constants.txContext.version = version; + constants.vkTreeRoot = vkTreeRoot; + constants.protocolContractTreeRoot = protocolContractTreeRoot; + + const clientProofOutput = PrivateKernelTailCircuitPublicInputs.empty(); + clientProofOutput.constants = constants; - const hash = new TxHash(Fr.ZERO.toBuffer()); return { - hash, - noteEncryptedLogs: EncryptedNoteTxL2Logs.empty(), - encryptedLogs: EncryptedTxL2Logs.empty(), - unencryptedLogs: UnencryptedTxL2Logs.empty(), - data: emptyKernelOutput, + hash: new TxHash(Fr.ZERO.toBuffer()), + data: clientProofOutput, clientIvcProof: ClientIvcProof.empty(), - isEmpty: true, - revertReason: undefined, avmProvingRequest: undefined, - gasUsed: {}, - finalPublicDataUpdateRequests: [], + constants, + txEffect: TxEffect.empty(), + gasUsed: { + totalGas: Gas.empty(), + teardownGas: Gas.empty(), + }, + revertReason: undefined, + isEmpty: true, }; } -export function toTxEffect(tx: ProcessedTx, gasFees: GasFees): TxEffect { - return new TxEffect( - tx.data.revertCode, - tx.data.getTransactionFee(gasFees), - tx.data.end.noteHashes.filter(h => !h.isZero()), - tx.data.end.nullifiers.filter(h => !h.isZero()), - tx.data.end.l2ToL1Msgs - .map(message => - siloL2ToL1Message(message, tx.data.constants.txContext.version, tx.data.constants.txContext.chainId), - ) +export function makeProcessedTxFromPrivateOnlyTx( + tx: Tx, + transactionFee: Fr, + feePaymentPublicDataWrite: PublicDataWrite | undefined, + globalVariables: GlobalVariables, +): ProcessedTx { + const constants = CombinedConstantData.combine(tx.data.constants, globalVariables); + + const publicDataWrites = feePaymentPublicDataWrite ? [feePaymentPublicDataWrite] : []; + + const data = tx.data.forRollup!; + const txEffect = new TxEffect( + RevertCode.OK, + transactionFee, + data.end.noteHashes.filter(h => !h.isZero()), + data.end.nullifiers.filter(h => !h.isZero()), + data.end.l2ToL1Msgs + .map(message => siloL2ToL1Message(message, constants.txContext.version, constants.txContext.chainId)) .filter(h => !h.isZero()), - tx.finalPublicDataUpdateRequests.map(t => new PublicDataWrite(t.leafSlot, t.newValue)).filter(h => !h.isEmpty()), - tx.data.end.noteEncryptedLogPreimagesLength, - tx.data.end.encryptedLogPreimagesLength, - tx.data.end.unencryptedLogPreimagesLength, - tx.noteEncryptedLogs || EncryptedNoteTxL2Logs.empty(), - tx.encryptedLogs || EncryptedTxL2Logs.empty(), - tx.unencryptedLogs || UnencryptedTxL2Logs.empty(), + publicDataWrites, + data.end.noteEncryptedLogPreimagesLength, + data.end.encryptedLogPreimagesLength, + data.end.unencryptedLogPreimagesLength, + tx.noteEncryptedLogs, + tx.encryptedLogs, + tx.unencryptedLogs, ); + + const gasUsed = { + totalGas: tx.data.forRollup!.end.gasUsed, + teardownGas: Gas.empty(), + }; + + return { + hash: tx.getTxHash(), + data: tx.data, + clientIvcProof: tx.clientIvcProof, + avmProvingRequest: undefined, + constants, + txEffect, + gasUsed, + revertReason: undefined, + isEmpty: false, + }; } -function validateProcessedTxLogs(tx: ProcessedTx): void { - const noteEncryptedLogs = tx.noteEncryptedLogs || EncryptedNoteTxL2Logs.empty(); - let kernelHash = Fr.fromBuffer( - EncryptedNoteTxL2Logs.hashNoteLogs( - tx.data.end.noteEncryptedLogsHashes.filter(hash => !hash.isEmpty()).map(h => h.value.toBuffer()), - ), - ); - let referenceHash = Fr.fromBuffer(noteEncryptedLogs.hash()); - if (!referenceHash.equals(kernelHash)) { - throw new Error( - `Note encrypted logs hash mismatch. Expected ${referenceHash.toString()}, got ${kernelHash.toString()}. - Processed: ${JSON.stringify(noteEncryptedLogs.toJSON())}`, - ); - } - const encryptedLogs = tx.encryptedLogs || EncryptedTxL2Logs.empty(); - kernelHash = kernelHash = Fr.fromBuffer( - EncryptedTxL2Logs.hashSiloedLogs( - tx.data.end.encryptedLogsHashes.filter(hash => !hash.isEmpty()).map(h => h.getSiloedHash()), - ), - ); - referenceHash = Fr.fromBuffer(encryptedLogs.hash()); - if (!referenceHash.equals(kernelHash)) { - throw new Error( - `Encrypted logs hash mismatch. Expected ${referenceHash.toString()}, got ${kernelHash.toString()}. - Processed: ${JSON.stringify(encryptedLogs.toJSON())}`, - ); +export function makeProcessedTxFromTxWithPublicCalls( + tx: Tx, + avmProvingRequest: AvmProvingRequest, + feePaymentPublicDataWrite: PublicDataWrite | undefined, + gasUsed: GasUsed, + revertCode: RevertCode, + revertReason: SimulationError | undefined, +): ProcessedTx { + const avmOutput = avmProvingRequest.inputs.output; + + const constants = CombinedConstantData.combine(tx.data.constants, avmOutput.globalVariables); + + const publicDataWrites = avmOutput.accumulatedData.publicDataWrites.filter(w => !w.isEmpty()); + if (feePaymentPublicDataWrite) { + const existingIndex = publicDataWrites.findIndex(w => w.leafSlot.equals(feePaymentPublicDataWrite.leafSlot)); + if (existingIndex >= 0) { + publicDataWrites[existingIndex] = feePaymentPublicDataWrite; + } else { + publicDataWrites.push(feePaymentPublicDataWrite); + } } - const unencryptedLogs = tx.unencryptedLogs || UnencryptedTxL2Logs.empty(); - kernelHash = Fr.fromBuffer( - UnencryptedTxL2Logs.hashSiloedLogs( - tx.data.end.unencryptedLogsHashes.filter(hash => !hash.isEmpty()).map(h => h.getSiloedHash()), - ), + + const noteEncryptedLogPreimagesLength = tx.noteEncryptedLogs.getKernelLength(); + const encryptedLogPreimagesLength = tx.encryptedLogs.getKernelLength(); + // Unencrypted logs emitted from public functions are inserted to tx.unencryptedLogs directly :( + const unencryptedLogPreimagesLength = tx.unencryptedLogs.getKernelLength(); + + const txEffect = new TxEffect( + revertCode, + avmOutput.transactionFee, + avmOutput.accumulatedData.noteHashes.filter(h => !h.isZero()), + avmOutput.accumulatedData.nullifiers.filter(h => !h.isZero()), + avmOutput.accumulatedData.l2ToL1Msgs + .map(message => siloL2ToL1Message(message, constants.txContext.version, constants.txContext.chainId)) + .filter(h => !h.isZero()), + publicDataWrites, + new Fr(noteEncryptedLogPreimagesLength), + new Fr(encryptedLogPreimagesLength), + new Fr(unencryptedLogPreimagesLength), + tx.noteEncryptedLogs, + tx.encryptedLogs, + tx.unencryptedLogs, ); - referenceHash = Fr.fromBuffer(unencryptedLogs.hash()); - if (!referenceHash.equals(kernelHash)) { - throw new Error( - `Unencrypted logs hash mismatch. Expected ${referenceHash.toString()}, got ${kernelHash.toString()}. - Processed: ${JSON.stringify(unencryptedLogs.toJSON())} - Kernel Length: ${tx.data.end.unencryptedLogPreimagesLength}`, - ); - } - let referenceLength = new Fr(noteEncryptedLogs.getKernelLength()); - let kernelLength = tx.data.end.noteEncryptedLogPreimagesLength; - if (!referenceLength.equals(kernelLength)) { - throw new Error( - `Note encrypted logs length mismatch. Expected ${referenceLength.toString()}, got ${kernelLength.toString()}. - Processed: ${JSON.stringify(noteEncryptedLogs.toJSON())}`, - ); - } - referenceLength = new Fr(encryptedLogs.getKernelLength()); - kernelLength = tx.data.end.encryptedLogPreimagesLength; - if (!referenceLength.equals(kernelLength)) { - throw new Error( - `Encrypted logs length mismatch. Expected ${referenceLength.toString()}, got ${kernelLength.toString()}. - Processed: ${JSON.stringify(encryptedLogs.toJSON())}`, - ); - } - referenceLength = new Fr(unencryptedLogs.getKernelLength()); - kernelLength = tx.data.end.unencryptedLogPreimagesLength; - if (!referenceLength.equals(kernelLength)) { - throw new Error( - `Unencrypted logs length mismatch. Expected ${referenceLength.toString()}, got ${kernelLength.toString()}. - Processed: ${JSON.stringify(unencryptedLogs.toJSON())}`, - ); - } -} -export function validateProcessedTx(tx: ProcessedTx): void { - validateProcessedTxLogs(tx); - // TODO: validate other fields + return { + hash: tx.getTxHash(), + data: tx.data, + clientIvcProof: tx.clientIvcProof, + avmProvingRequest, + constants, + txEffect, + gasUsed, + revertReason, + isEmpty: false, + }; } diff --git a/yarn-project/circuit-types/src/tx/public_simulation_output.ts b/yarn-project/circuit-types/src/tx/public_simulation_output.ts index 8b497b40467..4e75381ce6c 100644 --- a/yarn-project/circuit-types/src/tx/public_simulation_output.ts +++ b/yarn-project/circuit-types/src/tx/public_simulation_output.ts @@ -1,9 +1,9 @@ -import { CombinedAccumulatedData, CombinedConstantData, Fr, Gas } from '@aztec/circuits.js'; +import { CombinedConstantData, Fr, Gas } from '@aztec/circuits.js'; import { mapValues } from '@aztec/foundation/collection'; -import { EncryptedTxL2Logs, UnencryptedTxL2Logs } from '../logs/tx_l2_logs.js'; import { type SimulationError } from '../simulation_error.js'; -import { type PublicKernelPhase } from './processed_tx.js'; +import { TxEffect } from '../tx_effect.js'; +import { type GasUsed } from './gas_used.js'; /** Return values of simulating a circuit. */ export type ProcessReturnValues = Fr[] | undefined; @@ -42,22 +42,18 @@ export class NestedProcessReturnValues { */ export class PublicSimulationOutput { constructor( - public encryptedLogs: EncryptedTxL2Logs, - public unencryptedLogs: UnencryptedTxL2Logs, public revertReason: SimulationError | undefined, public constants: CombinedConstantData, - public end: CombinedAccumulatedData, + public txEffect: TxEffect, public publicReturnValues: NestedProcessReturnValues[], - public gasUsed: Partial>, + public gasUsed: GasUsed, ) {} toJSON() { return { - encryptedLogs: this.encryptedLogs.toJSON(), - unencryptedLogs: this.unencryptedLogs.toJSON(), revertReason: this.revertReason, constants: this.constants.toBuffer().toString('hex'), - end: this.end.toBuffer().toString('hex'), + txEffect: this.txEffect.toBuffer().toString('hex'), publicReturnValues: this.publicReturnValues.map(returns => returns?.toJSON()), gasUsed: mapValues(this.gasUsed, gas => gas?.toJSON()), }; @@ -65,15 +61,13 @@ export class PublicSimulationOutput { static fromJSON(json: any): PublicSimulationOutput { return new PublicSimulationOutput( - EncryptedTxL2Logs.fromJSON(json.encryptedLogs), - UnencryptedTxL2Logs.fromJSON(json.unencryptedLogs), json.revertReason, CombinedConstantData.fromBuffer(Buffer.from(json.constants, 'hex')), - CombinedAccumulatedData.fromBuffer(Buffer.from(json.end, 'hex')), + TxEffect.fromBuffer(Buffer.from(json.txEffect, 'hex')), Array.isArray(json.publicReturnValues) ? json.publicReturnValues.map((returns: any) => NestedProcessReturnValues.fromJSON(returns)) : [], - mapValues(json.gasUsed, gas => (gas ? Gas.fromJSON(gas) : undefined)), + mapValues(json.gasUsed, gas => Gas.fromJSON(gas)), ); } } diff --git a/yarn-project/circuit-types/src/tx/simulated_tx.ts b/yarn-project/circuit-types/src/tx/simulated_tx.ts index 0b360401e82..40fb969e7e8 100644 --- a/yarn-project/circuit-types/src/tx/simulated_tx.ts +++ b/yarn-project/circuit-types/src/tx/simulated_tx.ts @@ -1,8 +1,9 @@ -import { ClientIvcProof, PrivateKernelTailCircuitPublicInputs } from '@aztec/circuits.js'; +import { ClientIvcProof, Gas, PrivateKernelTailCircuitPublicInputs } from '@aztec/circuits.js'; import { EncryptedNoteTxL2Logs, EncryptedTxL2Logs, + type GasUsed, type PrivateKernelProverProfileResult, UnencryptedTxL2Logs, } from '../index.js'; @@ -70,6 +71,15 @@ export class TxSimulationResult extends PrivateSimulationResult { super(privateExecutionResult, publicInputs); } + get gasUsed(): GasUsed { + return ( + this.publicOutput?.gasUsed ?? { + totalGas: this.publicInputs.forRollup!.end.gasUsed, + teardownGas: Gas.empty(), + } + ); + } + getPublicReturnValues() { return this.publicOutput ? this.publicOutput.publicReturnValues : []; } diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index 6b3954af752..1bb78cf82f8 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -210,11 +210,8 @@ export class Tx extends Gossipable { ? // needsSetup? then we pay through a fee payment contract this.data.forPublic?.needsSetup ? // if the first call is to `approve_public_authwit`, then it's a public payment - this.data - .getNonRevertiblePublicCallRequests() - .at(-1)! - .callContext.functionSelector.toField() - .toBigInt() === 0x43417bb1n + this.data.getNonRevertiblePublicCallRequests().at(-1)!.functionSelector.toField().toBigInt() === + 0x43417bb1n ? 'fpc_public' : 'fpc_private' : 'fee_juice' diff --git a/yarn-project/circuit-types/src/tx/tx_receipt.ts b/yarn-project/circuit-types/src/tx/tx_receipt.ts index e784e938c9c..30b44e06f96 100644 --- a/yarn-project/circuit-types/src/tx/tx_receipt.ts +++ b/yarn-project/circuit-types/src/tx/tx_receipt.ts @@ -1,8 +1,7 @@ -import { RevertCode } from '@aztec/circuits.js'; +import { type PublicDataWrite, RevertCode } from '@aztec/circuits.js'; import { type Fr } from '@aztec/foundation/fields'; import { type UniqueNote } from '../notes/extended_note.js'; -import { type PublicDataWrite } from '../public_data_write.js'; import { TxHash } from './tx_hash.js'; /** diff --git a/yarn-project/circuit-types/src/tx_effect.ts b/yarn-project/circuit-types/src/tx_effect.ts index 1e327bd42a8..17a53abc2f8 100644 --- a/yarn-project/circuit-types/src/tx_effect.ts +++ b/yarn-project/circuit-types/src/tx_effect.ts @@ -1,16 +1,11 @@ -import { - EncryptedNoteTxL2Logs, - EncryptedTxL2Logs, - PublicDataWrite, - TxHash, - UnencryptedTxL2Logs, -} from '@aztec/circuit-types'; +import { EncryptedNoteTxL2Logs, EncryptedTxL2Logs, TxHash, UnencryptedTxL2Logs } from '@aztec/circuit-types'; import { Fr, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + PublicDataWrite, RevertCode, } from '@aztec/circuits.js'; import { makeTuple } from '@aztec/foundation/array'; @@ -220,7 +215,7 @@ export class TxEffect { makeTuple(MAX_NOTE_HASHES_PER_TX, Fr.random), makeTuple(MAX_NULLIFIERS_PER_TX, Fr.random), makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, Fr.random), - makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.random), + makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, () => new PublicDataWrite(Fr.random(), Fr.random())), new Fr(noteEncryptedLogs.getKernelLength()), new Fr(encryptedLogs.getKernelLength()), new Fr(unencryptedLogs.getKernelLength()), diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 653202d0799..a0c8f2558cd 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -5,7 +5,7 @@ export const ARGS_LENGTH = 16; export const MAX_NOTE_HASHES_PER_CALL = 16; export const MAX_NULLIFIERS_PER_CALL = 16; export const MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL = 4; -export const MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 16; +export const MAX_ENQUEUED_CALLS_PER_CALL = 16; export const MAX_L2_TO_L1_MSGS_PER_CALL = 2; export const MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 64; export const MAX_PUBLIC_DATA_READS_PER_CALL = 64; @@ -42,7 +42,7 @@ export const L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH = 12; export const MAX_NOTE_HASHES_PER_TX = 64; export const MAX_NULLIFIERS_PER_TX = 64; export const MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8; -export const MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 32; +export const MAX_ENQUEUED_CALLS_PER_TX = 32; export const PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 1; export const MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 64; export const MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 63; @@ -172,17 +172,20 @@ export const NOTE_HASH_LENGTH = 2; export const SCOPED_NOTE_HASH_LENGTH = 3; export const NULLIFIER_LENGTH = 3; export const SCOPED_NULLIFIER_LENGTH = 4; +export const PUBLIC_DATA_WRITE_LENGTH = 2; export const PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 12; export const PRIVATE_CALL_REQUEST_LENGTH = 8; -export const PUBLIC_CALL_REQUEST_LENGTH = 6; +export const PUBLIC_CALL_REQUEST_LENGTH = 5; +export const COUNTED_PUBLIC_CALL_REQUEST_LENGTH = 6; export const PUBLIC_INNER_CALL_REQUEST_LENGTH = 13; export const ROLLUP_VALIDATION_REQUESTS_LENGTH = 2; export const STATE_REFERENCE_LENGTH = 8; +export const TREE_SNAPSHOTS_LENGTH = 8; export const TX_CONTEXT_LENGTH = 9; export const TX_REQUEST_LENGTH = 13; export const TOTAL_FEES_LENGTH = 1; export const HEADER_LENGTH = 24; -export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 501; +export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 500; export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 866; export const PRIVATE_CONTEXT_INPUTS_LENGTH = 38; export const PUBLIC_CONTEXT_INPUTS_LENGTH = 41; @@ -194,15 +197,21 @@ export const PRIVATE_VALIDATION_REQUESTS_LENGTH = 772; export const NUM_PUBLIC_VALIDATION_REQUEST_ARRAYS = 5; export const PUBLIC_VALIDATION_REQUESTS_LENGTH = 834; export const PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; -export const COMBINED_ACCUMULATED_DATA_LENGTH = 610; +export const COMBINED_ACCUMULATED_DATA_LENGTH = 547; +export const TX_CONSTANT_DATA_LENGTH = 35; export const COMBINED_CONSTANT_DATA_LENGTH = 44; export const PRIVATE_ACCUMULATED_DATA_LENGTH = 1064; -export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1888; -export const PUBLIC_ACCUMULATED_DATA_LENGTH = 1055; +export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1878; +export const PUBLIC_ACCUMULATED_DATA_LENGTH = 1023; export const NUM_PUBLIC_ACCUMULATED_DATA_ARRAYS = 8; -export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2997; -export const VM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2374; -export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 664; +export const PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH = 578; +export const PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH = 160; +export const NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS = 3; +export const AVM_ACCUMULATED_DATA_LENGTH = 318; +export const PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1199; +export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2932; +export const VM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2341; +export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 601; export const CONSTANT_ROLLUP_DATA_LENGTH = 13; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 30; export const BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 60; diff --git a/yarn-project/circuits.js/src/scripts/constants.in.ts b/yarn-project/circuits.js/src/scripts/constants.in.ts index 6ed045614f8..369a9c94ae9 100644 --- a/yarn-project/circuits.js/src/scripts/constants.in.ts +++ b/yarn-project/circuits.js/src/scripts/constants.in.ts @@ -33,7 +33,7 @@ const CPP_CONSTANTS = [ 'CONTRACT_STORAGE_READ_LENGTH', 'PUBLIC_INNER_CALL_REQUEST_LENGTH', 'MAX_PUBLIC_DATA_READS_PER_CALL', - 'MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL', + 'MAX_ENQUEUED_CALLS_PER_CALL', 'NOTE_HASH_LENGTH', 'MAX_NOTE_HASHES_PER_CALL', 'NULLIFIER_LENGTH', @@ -90,7 +90,7 @@ const PIL_CONSTANTS = [ 'MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL', 'MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL', 'MAX_PUBLIC_DATA_READS_PER_CALL', - 'MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL', + 'MAX_ENQUEUED_CALLS_PER_CALL', 'MAX_NOTE_HASHES_PER_CALL', 'MAX_NULLIFIERS_PER_CALL', 'MAX_L2_TO_L1_MSGS_PER_CALL', diff --git a/yarn-project/circuits.js/src/structs/avm/avm.test.ts b/yarn-project/circuits.js/src/structs/avm/avm.test.ts index 6773232e478..3b6f765e013 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.test.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.test.ts @@ -9,6 +9,5 @@ describe('Avm circuit inputs', () => { const buffer = avmCircuitInputs.toBuffer(); const res = AvmCircuitInputs.fromBuffer(buffer); expect(res).toEqual(avmCircuitInputs); - expect(res.isEmpty()).toBe(false); }); }); diff --git a/yarn-project/circuits.js/src/structs/avm/avm.ts b/yarn-project/circuits.js/src/structs/avm/avm.ts index 8931f5c2bd5..aa11b038dff 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.ts @@ -8,6 +8,7 @@ import { PublicKeys } from '../../types/public_keys.js'; import { Gas } from '../gas.js'; import { PublicCircuitPublicInputs } from '../public_circuit_public_inputs.js'; import { Vector } from '../shared.js'; +import { AvmCircuitPublicInputs } from './avm_circuit_public_inputs.js'; export class AvmEnqueuedCallHint { public readonly contractAddress: Fr; @@ -587,6 +588,7 @@ export class AvmCircuitInputs { public readonly calldata: Fr[], public readonly publicInputs: PublicCircuitPublicInputs, public readonly avmHints: AvmExecutionHints, + public output: AvmCircuitPublicInputs, // This should replace the above `publicInputs` eventually. ) {} /** @@ -602,6 +604,7 @@ export class AvmCircuitInputs { this.calldata, this.publicInputs.toBuffer(), this.avmHints.toBuffer(), + this.output, ); } @@ -613,21 +616,14 @@ export class AvmCircuitInputs { return this.toBuffer().toString('hex'); } - /** - * Is the struct empty? - * @returns whether all members are empty. - */ - isEmpty(): boolean { - return ( - this.functionName.length == 0 && - this.calldata.length == 0 && - this.publicInputs.isEmpty() && - this.avmHints.isEmpty() - ); - } - static empty(): AvmCircuitInputs { - return new AvmCircuitInputs('', [], PublicCircuitPublicInputs.empty(), AvmExecutionHints.empty()); + return new AvmCircuitInputs( + '', + [], + PublicCircuitPublicInputs.empty(), + AvmExecutionHints.empty(), + AvmCircuitPublicInputs.empty(), + ); } /** @@ -645,7 +641,7 @@ export class AvmCircuitInputs { * @returns An array of fields. */ static getFields(fields: FieldsOf) { - return [fields.functionName, fields.calldata, fields.publicInputs, fields.avmHints] as const; + return [fields.functionName, fields.calldata, fields.publicInputs, fields.avmHints, fields.output] as const; } /** @@ -660,6 +656,7 @@ export class AvmCircuitInputs { /*calldata=*/ reader.readVector(Fr), PublicCircuitPublicInputs.fromBuffer(reader), AvmExecutionHints.fromBuffer(reader), + AvmCircuitPublicInputs.fromBuffer(reader), ); } diff --git a/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts b/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts new file mode 100644 index 00000000000..2e01efc6ee2 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts @@ -0,0 +1,138 @@ +import { makeTuple } from '@aztec/foundation/array'; +import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { inspect } from 'util'; + +import { + MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, +} from '../../constants.gen.js'; +import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; +import { ScopedLogHash } from '../log_hash.js'; +import { PublicDataWrite } from '../public_data_write.js'; + +export class AvmAccumulatedData { + constructor( + /** + * The note hashes from private combining with those made in the AVM execution. + */ + public noteHashes: Tuple, + /** + * The nullifiers from private combining with those made in the AVM execution. + */ + public nullifiers: Tuple, + /** + * The L2 to L1 messages from private combining with those made in the AVM execution. + */ + public l2ToL1Msgs: Tuple, + /** + * The unencrypted logs emitted from the AVM execution. + */ + public unencryptedLogsHashes: Tuple, + /** + * The public data writes made in the AVM execution. + */ + public publicDataWrites: Tuple, + ) {} + + getSize() { + return ( + arraySerializedSizeOfNonEmpty(this.noteHashes) + + arraySerializedSizeOfNonEmpty(this.nullifiers) + + arraySerializedSizeOfNonEmpty(this.l2ToL1Msgs) + + arraySerializedSizeOfNonEmpty(this.unencryptedLogsHashes) + + arraySerializedSizeOfNonEmpty(this.publicDataWrites) + ); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new this( + reader.readArray(MAX_NOTE_HASHES_PER_TX, Fr), + reader.readArray(MAX_NULLIFIERS_PER_TX, Fr), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), + reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), + ); + } + + toBuffer() { + return serializeToBuffer( + this.noteHashes, + this.nullifiers, + this.l2ToL1Msgs, + this.unencryptedLogsHashes, + this.publicDataWrites, + ); + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new this( + reader.readFieldArray(MAX_NOTE_HASHES_PER_TX), + reader.readFieldArray(MAX_NULLIFIERS_PER_TX), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), + reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), + ); + } + + static fromString(str: string) { + return this.fromBuffer(Buffer.from(str, 'hex')); + } + + toString() { + return this.toBuffer().toString('hex'); + } + + static empty() { + return new this( + makeTuple(MAX_NOTE_HASHES_PER_TX, Fr.zero), + makeTuple(MAX_NULLIFIERS_PER_TX, Fr.zero), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), + makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.empty), + ); + } + + isEmpty(): boolean { + return ( + this.noteHashes.every(x => x.isZero()) && + this.nullifiers.every(x => x.isZero()) && + this.l2ToL1Msgs.every(x => x.isEmpty()) && + this.unencryptedLogsHashes.every(x => x.isEmpty()) && + this.publicDataWrites.every(x => x.isEmpty()) + ); + } + + [inspect.custom]() { + // print out the non-empty fields + return `AvmAccumulatedData { + noteHashes: [${this.noteHashes + .filter(x => !x.isZero()) + .map(h => inspect(h)) + .join(', ')}], + nullifiers: [${this.nullifiers + .filter(x => !x.isZero()) + .map(h => inspect(h)) + .join(', ')}], + l2ToL1Msgs: [${this.l2ToL1Msgs + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], + unencryptedLogsHashes: [${this.unencryptedLogsHashes + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], + publicDataWrites: [${this.publicDataWrites + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], +}`; + } +} diff --git a/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts new file mode 100644 index 00000000000..b01f1d40a84 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts @@ -0,0 +1,148 @@ +import { makeTuple } from '@aztec/foundation/array'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { inspect } from 'util'; + +import { MAX_ENQUEUED_CALLS_PER_TX } from '../../constants.gen.js'; +import { GasSettings } from '../gas_settings.js'; +import { GlobalVariables } from '../global_variables.js'; +import { + PrivateToAvmAccumulatedData, + PrivateToAvmAccumulatedDataArrayLengths, +} from '../kernel/private_to_avm_accumulated_data.js'; +import { PublicCallRequest } from '../public_call_request.js'; +import { TreeSnapshots } from '../tree_snapshots.js'; +import { AvmAccumulatedData } from './avm_accumulated_data.js'; + +export class AvmCircuitPublicInputs { + constructor( + public globalVariables: GlobalVariables, + public startTreeSnapshots: TreeSnapshots, + public gasSettings: GasSettings, + public publicSetupCallRequests: Tuple, + public publicAppLogicCallRequests: Tuple, + public publicTeardownCallRequest: PublicCallRequest, + public previousNonRevertibleAccumulatedDataArrayLengths: PrivateToAvmAccumulatedDataArrayLengths, + public previousRevertibleAccumulatedDataArrayLengths: PrivateToAvmAccumulatedDataArrayLengths, + public previousNonRevertibleAccumulatedData: PrivateToAvmAccumulatedData, + public previousRevertibleAccumulatedData: PrivateToAvmAccumulatedData, + public endTreeSnapshots: TreeSnapshots, + public accumulatedData: AvmAccumulatedData, + public transactionFee: Fr, + public reverted: boolean, + ) {} + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new AvmCircuitPublicInputs( + reader.readObject(GlobalVariables), + reader.readObject(TreeSnapshots), + reader.readObject(GasSettings), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), + reader.readObject(PublicCallRequest), + reader.readObject(PrivateToAvmAccumulatedDataArrayLengths), + reader.readObject(PrivateToAvmAccumulatedDataArrayLengths), + reader.readObject(PrivateToAvmAccumulatedData), + reader.readObject(PrivateToAvmAccumulatedData), + reader.readObject(TreeSnapshots), + reader.readObject(AvmAccumulatedData), + reader.readObject(Fr), + reader.readBoolean(), + ); + } + + toBuffer() { + return serializeToBuffer( + this.globalVariables, + this.startTreeSnapshots, + this.gasSettings, + this.publicSetupCallRequests, + this.publicAppLogicCallRequests, + this.publicTeardownCallRequest, + this.previousNonRevertibleAccumulatedDataArrayLengths, + this.previousRevertibleAccumulatedDataArrayLengths, + this.previousNonRevertibleAccumulatedData, + this.previousRevertibleAccumulatedData, + this.endTreeSnapshots, + this.accumulatedData, + this.transactionFee, + this.reverted, + ); + } + + static fromString(str: string) { + return AvmCircuitPublicInputs.fromBuffer(Buffer.from(str, 'hex')); + } + + toString() { + return this.toBuffer().toString('hex'); + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new AvmCircuitPublicInputs( + GlobalVariables.fromFields(reader), + TreeSnapshots.fromFields(reader), + GasSettings.fromFields(reader), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), + PublicCallRequest.fromFields(reader), + PrivateToAvmAccumulatedDataArrayLengths.fromFields(reader), + PrivateToAvmAccumulatedDataArrayLengths.fromFields(reader), + PrivateToAvmAccumulatedData.fromFields(reader), + PrivateToAvmAccumulatedData.fromFields(reader), + TreeSnapshots.fromFields(reader), + AvmAccumulatedData.fromFields(reader), + reader.readField(), + reader.readBoolean(), + ); + } + + static empty() { + return new AvmCircuitPublicInputs( + GlobalVariables.empty(), + TreeSnapshots.empty(), + GasSettings.empty(), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest.empty), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest.empty), + PublicCallRequest.empty(), + PrivateToAvmAccumulatedDataArrayLengths.empty(), + PrivateToAvmAccumulatedDataArrayLengths.empty(), + PrivateToAvmAccumulatedData.empty(), + PrivateToAvmAccumulatedData.empty(), + TreeSnapshots.empty(), + AvmAccumulatedData.empty(), + Fr.zero(), + false, + ); + } + + [inspect.custom]() { + return `AvmCircuitPublicInputs { + globalVariables: ${inspect(this.globalVariables)}, + startTreeSnapshots: ${inspect(this.startTreeSnapshots)}, + gasSettings: ${inspect(this.gasSettings)}, + publicSetupCallRequests: [${this.publicSetupCallRequests + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}]}, + publicAppLogicCallRequests: [${this.publicAppLogicCallRequests + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}]}, + publicTeardownCallRequest: ${inspect(this.publicTeardownCallRequest)}, + previousNonRevertibleAccumulatedDataArrayLengths: ${inspect( + this.previousNonRevertibleAccumulatedDataArrayLengths, + )}, + previousRevertibleAccumulatedDataArrayLengths: ${inspect(this.previousRevertibleAccumulatedDataArrayLengths)}, + previousNonRevertibleAccumulatedData: ${inspect(this.previousNonRevertibleAccumulatedData)}, + previousRevertibleAccumulatedData: ${inspect(this.previousRevertibleAccumulatedData)}, + endTreeSnapshots: ${inspect(this.endTreeSnapshots)}, + accumulatedData: ${inspect(this.accumulatedData)}, + transactionFee: ${inspect(this.transactionFee)}, + reverted: ${this.reverted}, + }`; + } +} diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 7bc2702e0a5..72a416afb67 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -1,5 +1,7 @@ export * from '@aztec/foundation/eth-address'; export * from './avm/avm.js'; +export * from './avm/avm_accumulated_data.js'; +export * from './avm/avm_circuit_public_inputs.js'; export * from './call_context.js'; export * from './client_ivc_proof.js'; export * from './complete_address.js'; @@ -30,8 +32,11 @@ export * from './kernel/private_kernel_reset_dimensions.js'; export * from './kernel/private_kernel_reset_hints.js'; export * from './kernel/private_kernel_tail_circuit_private_inputs.js'; export * from './kernel/private_kernel_tail_circuit_public_inputs.js'; +export * from './kernel/private_to_avm_accumulated_data.js'; +export * from './kernel/private_to_public_accumulated_data.js'; +export * from './kernel/private_to_public_accumulated_data_builder.js'; +export * from './kernel/private_to_public_kernel_circuit_public_inputs.js'; export * from './kernel/public_accumulated_data.js'; -export * from './kernel/public_accumulated_data_builder.js'; export * from './kernel/public_call_data.js'; export * from './kernel/public_kernel_circuit_private_inputs.js'; export * from './kernel/public_kernel_circuit_public_inputs.js'; @@ -39,6 +44,7 @@ export * from './kernel/public_kernel_data.js'; export * from './kernel/public_kernel_inner_data.js'; export * from './kernel/public_kernel_inner_circuit_private_inputs.js'; export * from './kernel/public_kernel_tail_circuit_private_inputs.js'; +export * from './kernel/tx_constant_data.js'; export * from './kernel/vm_circuit_public_inputs.js'; export * from './key_validation_request.js'; export * from './key_validation_request_and_generator.js'; @@ -66,6 +72,7 @@ export * from './public_data_hint.js'; export * from './public_data_leaf_hint.js'; export * from './public_data_read.js'; export * from './public_data_update_request.js'; +export * from './public_data_write.js'; export * from './public_inner_call_request.js'; export * from './public_validation_requests.js'; export * from './read_request.js'; @@ -94,10 +101,10 @@ export * from './rollup/tube_inputs.js'; export * from './rollup_validation_requests.js'; export * from './scoped_key_validation_request_and_generator.js'; export * from './shared.js'; -export * from './side_effects.js'; export * from './state_reference.js'; export * from './tree_leaf_read_request.js'; export * from './tree_leaf_read_request_hint.js'; +export * from './tree_snapshots.js'; export * from './trees/index.js'; export * from './tx_context.js'; export * from './tx_request.js'; 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 88ba4af36d3..b79ba6a5d73 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 @@ -17,7 +17,7 @@ import { import { Gas } from '../gas.js'; import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; import { LogHash, ScopedLogHash } from '../log_hash.js'; -import { PublicDataUpdateRequest } from '../public_data_update_request.js'; +import { PublicDataWrite } from '../public_data_write.js'; /** * Data that is accumulated during the execution of the transaction. @@ -64,7 +64,7 @@ export class CombinedAccumulatedData { /** * All the public data update requests made in this transaction. */ - public publicDataUpdateRequests: Tuple, + public publicDataWrites: Tuple, /** Gas used during this transaction */ public gasUsed: Gas, @@ -81,7 +81,7 @@ export class CombinedAccumulatedData { this.noteEncryptedLogPreimagesLength.size + this.encryptedLogPreimagesLength.size + this.unencryptedLogPreimagesLength.size + - arraySerializedSizeOfNonEmpty(this.publicDataUpdateRequests) + + arraySerializedSizeOfNonEmpty(this.publicDataWrites) + this.gasUsed.toBuffer().length ); } @@ -97,7 +97,7 @@ export class CombinedAccumulatedData { fields.noteEncryptedLogPreimagesLength, fields.encryptedLogPreimagesLength, fields.unencryptedLogPreimagesLength, - fields.publicDataUpdateRequests, + fields.publicDataWrites, fields.gasUsed, ] as const; } @@ -131,7 +131,7 @@ export class CombinedAccumulatedData { Fr.fromBuffer(reader), Fr.fromBuffer(reader), Fr.fromBuffer(reader), - reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), + reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite), reader.readObject(Gas), ); } @@ -156,7 +156,7 @@ export class CombinedAccumulatedData { Fr.zero(), Fr.zero(), Fr.zero(), - makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty), + makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.empty), Gas.empty(), ); } @@ -190,7 +190,7 @@ export class CombinedAccumulatedData { noteEncryptedLogPreimagesLength: ${this.noteEncryptedLogPreimagesLength.toString()}, encryptedLogPreimagesLength: ${this.encryptedLogPreimagesLength.toString()}, unencryptedLogPreimagesLength: ${this.unencryptedLogPreimagesLength.toString()}, - publicDataUpdateRequests: [${this.publicDataUpdateRequests + publicDataWrites: [${this.publicDataWrites .filter(x => !x.isEmpty()) .map(x => inspect(x)) .join(', ')}], diff --git a/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts b/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts index f2196acdbe2..1de159aefbc 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts @@ -5,6 +5,7 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { GlobalVariables } from '../global_variables.js'; import { Header } from '../header.js'; import { TxContext } from '../tx_context.js'; +import { type TxConstantData } from './tx_constant_data.js'; /** * Data that is constant/not modified by neither of the kernels. @@ -34,6 +35,16 @@ export class CombinedConstantData { public globalVariables: GlobalVariables, ) {} + static combine(TxConstantData: TxConstantData, globalVariables: GlobalVariables) { + return new CombinedConstantData( + TxConstantData.historicalHeader, + TxConstantData.txContext, + TxConstantData.vkTreeRoot, + TxConstantData.protocolContractTreeRoot, + globalVariables, + ); + } + toBuffer() { return serializeToBuffer( this.historicalHeader, diff --git a/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.test.ts b/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.test.ts deleted file mode 100644 index a12f605179f..00000000000 --- a/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr } from '@aztec/foundation/fields'; - -import { Gas } from '../gas.js'; -import { GasFees } from '../gas_fees.js'; -import { GasSettings } from '../gas_settings.js'; -import { GlobalVariables } from '../global_variables.js'; -import { Header } from '../header.js'; -import { PartialStateReference } from '../partial_state_reference.js'; -import { RevertCode } from '../revert_code.js'; -import { RollupValidationRequests } from '../rollup_validation_requests.js'; -import { TxContext } from '../tx_context.js'; -import { CombinedAccumulatedData } from './combined_accumulated_data.js'; -import { CombinedConstantData } from './combined_constant_data.js'; -import { KernelCircuitPublicInputs } from './kernel_circuit_public_inputs.js'; - -describe('KernelCircuitPublicInputs', () => { - describe('Gas and Fees', () => { - it('empty is empty', () => { - const i = KernelCircuitPublicInputs.empty(); - expect(i.getTransactionFee(GasFees.empty())).toEqual(Fr.ZERO); - }); - - it('non-empty is correct', () => { - const i = new KernelCircuitPublicInputs( - RollupValidationRequests.empty(), - CombinedAccumulatedData.empty(), - new CombinedConstantData( - Header.empty(), - new TxContext( - 0, - 0, - GasSettings.from({ - // teardown limits are incorporated into end.gasUsed by the private kernel - teardownGasLimits: { daGas: 0, l2Gas: 0 }, - gasLimits: { daGas: 100, l2Gas: 200 }, - maxFeesPerGas: { feePerL2Gas: new Fr(20), feePerDaGas: new Fr(30) }, - inclusionFee: new Fr(42), - }), - ), - new Fr(0), - new Fr(1), - GlobalVariables.empty(), - ), - PartialStateReference.empty(), - RevertCode.OK, - AztecAddress.ZERO, - ); - - i.end.gasUsed = Gas.from({ daGas: 10, l2Gas: 20 }); - const gasFees = GasFees.from({ feePerDaGas: new Fr(2), feePerL2Gas: new Fr(3) }); - - expect(i.getTransactionFee(gasFees)).toEqual(new Fr(42 + 2 * 10 + 3 * 20)); - }); - }); -}); diff --git a/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts index 3c001d19860..ff3e0e7dbe7 100644 --- a/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts @@ -1,8 +1,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; -import type { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { type GasFees } from '../gas_fees.js'; import { PartialStateReference } from '../partial_state_reference.js'; import { RevertCode } from '../revert_code.js'; import { RollupValidationRequests } from '../rollup_validation_requests.js'; @@ -42,19 +40,6 @@ export class KernelCircuitPublicInputs { return this.end.nullifiers.filter(n => !n.isZero()); } - /** - * Computes the transaction fee for the transaction. - * @param gasFees - Gas fees for the block. We cannot source this from the constants - * since they may be unset if this comes from a private kernel directly. - * @returns The amount in Fee Juice to pay for this tx. - * @remarks It is safe to compute this method in typescript because we compute the - * transaction_fee ourselves in the base rollup. This value must match the value - * computed in the base rollup, otherwise the content commitment of the block will be invalid. - */ - getTransactionFee(gasFees: GasFees): Fr { - return this.end.gasUsed.computeFee(gasFees).add(this.constants.txContext.gasSettings.inclusionFee); - } - toBuffer() { return serializeToBuffer( this.rollupValidationRequests, diff --git a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts index 156e8a6a6ee..cc9a5aeab5f 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts @@ -3,12 +3,12 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/s import { MAX_ENCRYPTED_LOGS_PER_TX, + MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; @@ -16,7 +16,7 @@ import { NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash } from '../log_hash. import { ScopedNoteHash } from '../note_hash.js'; import { ScopedNullifier } from '../nullifier.js'; import { PrivateCallRequest } from '../private_call_request.js'; -import { PublicCallRequest } from '../public_call_request.js'; +import { CountedPublicCallRequest } from '../public_call_request.js'; /** * Specific accumulated data structure for the final ordering private kernel circuit. It is included @@ -54,7 +54,7 @@ export class PrivateAccumulatedData { /** * Accumulated public call requests from all the previous kernel iterations. */ - public publicCallRequests: Tuple, + public publicCallRequests: Tuple, /** * Current private call stack. */ @@ -92,7 +92,7 @@ export class PrivateAccumulatedData { reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, ScopedEncryptedLogHash), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, CountedPublicCallRequest), reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, PrivateCallRequest), ); } @@ -114,7 +114,7 @@ export class PrivateAccumulatedData { makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash.empty), makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, ScopedEncryptedLogHash.empty), makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest.empty), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, CountedPublicCallRequest.empty), makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, PrivateCallRequest.empty), ); } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts index d6c521f317a..9cb069f2ef7 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts @@ -4,14 +4,18 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { PrivateValidationRequests } from '../private_validation_requests.js'; import { PublicCallRequest } from '../public_call_request.js'; -import { CombinedConstantData } from './combined_constant_data.js'; import { PrivateAccumulatedData } from './private_accumulated_data.js'; +import { TxConstantData } from './tx_constant_data.js'; /** * Public inputs to the inner private kernel circuit */ export class PrivateKernelCircuitPublicInputs { constructor( + /** + * Data which is not modified by the circuits. + */ + public constants: TxConstantData, /** * The side effect counter that non-revertible side effects are all beneath. */ @@ -24,10 +28,6 @@ export class PrivateKernelCircuitPublicInputs { * Data accumulated from both public and private circuits. */ public end: PrivateAccumulatedData, - /** - * Data which is not modified by the circuits. - */ - public constants: CombinedConstantData, /** * The call request for the public teardown function */ @@ -40,10 +40,10 @@ export class PrivateKernelCircuitPublicInputs { toBuffer() { return serializeToBuffer( + this.constants, this.minRevertibleSideEffectCounter, this.validationRequests, this.end, - this.constants, this.publicTeardownCallRequest, this.feePayer, ); @@ -57,10 +57,10 @@ export class PrivateKernelCircuitPublicInputs { static fromBuffer(buffer: Buffer | BufferReader): PrivateKernelCircuitPublicInputs { const reader = BufferReader.asReader(buffer); return new PrivateKernelCircuitPublicInputs( + reader.readObject(TxConstantData), reader.readObject(Fr), reader.readObject(PrivateValidationRequests), reader.readObject(PrivateAccumulatedData), - reader.readObject(CombinedConstantData), reader.readObject(PublicCallRequest), reader.readObject(AztecAddress), ); @@ -68,10 +68,10 @@ export class PrivateKernelCircuitPublicInputs { static empty() { return new PrivateKernelCircuitPublicInputs( + TxConstantData.empty(), Fr.zero(), PrivateValidationRequests.empty(), PrivateAccumulatedData.empty(), - CombinedConstantData.empty(), PublicCallRequest.empty(), AztecAddress.ZERO, ); diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts index 0185cc3d377..69609a6c801 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts @@ -2,31 +2,28 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { countAccumulatedItems, mergeAccumulatedData } from '../../utils/index.js'; +import { GlobalVariables } from '../global_variables.js'; import { PartialStateReference } from '../partial_state_reference.js'; import { PublicCallRequest } from '../public_call_request.js'; -import { PublicValidationRequests } from '../public_validation_requests.js'; import { RevertCode } from '../revert_code.js'; import { RollupValidationRequests } from '../rollup_validation_requests.js'; import { CombinedAccumulatedData } from './combined_accumulated_data.js'; import { CombinedConstantData } from './combined_constant_data.js'; import { KernelCircuitPublicInputs } from './kernel_circuit_public_inputs.js'; -import { PublicAccumulatedData } from './public_accumulated_data.js'; -import { PublicKernelCircuitPublicInputs } from './public_kernel_circuit_public_inputs.js'; +import { PrivateToPublicAccumulatedData } from './private_to_public_accumulated_data.js'; +import { PrivateToPublicKernelCircuitPublicInputs } from './private_to_public_kernel_circuit_public_inputs.js'; +import { TxConstantData } from './tx_constant_data.js'; export class PartialPrivateTailPublicInputsForPublic { constructor( - /** - * Validation requests accumulated from public functions. - */ - public validationRequests: PublicValidationRequests, /** * Accumulated side effects and enqueued calls that are not revertible. */ - public endNonRevertibleData: PublicAccumulatedData, + public nonRevertibleAccumulatedData: PrivateToPublicAccumulatedData, /** * Data accumulated from both public and private circuits. */ - public end: PublicAccumulatedData, + public revertibleAccumulatedData: PrivateToPublicAccumulatedData, /** * Call request for the public teardown function. */ @@ -35,19 +32,18 @@ export class PartialPrivateTailPublicInputsForPublic { getSize() { return ( - this.validationRequests.getSize() + - this.endNonRevertibleData.getSize() + - this.end.getSize() + + this.nonRevertibleAccumulatedData.getSize() + + this.revertibleAccumulatedData.getSize() + this.publicTeardownCallRequest.getSize() ); } get needsSetup() { - return !this.endNonRevertibleData.publicCallStack[0].isEmpty(); + return !this.nonRevertibleAccumulatedData.publicCallRequests[0].isEmpty(); } get needsAppLogic() { - return !this.end.publicCallStack[0].isEmpty(); + return !this.revertibleAccumulatedData.publicCallRequests[0].isEmpty(); } get needsTeardown() { @@ -57,56 +53,47 @@ export class PartialPrivateTailPublicInputsForPublic { static fromBuffer(buffer: Buffer | BufferReader): PartialPrivateTailPublicInputsForPublic { const reader = BufferReader.asReader(buffer); return new PartialPrivateTailPublicInputsForPublic( - reader.readObject(PublicValidationRequests), - reader.readObject(PublicAccumulatedData), - reader.readObject(PublicAccumulatedData), + reader.readObject(PrivateToPublicAccumulatedData), + reader.readObject(PrivateToPublicAccumulatedData), reader.readObject(PublicCallRequest), ); } toBuffer() { return serializeToBuffer( - this.validationRequests, - this.endNonRevertibleData, - this.end, + this.nonRevertibleAccumulatedData, + this.revertibleAccumulatedData, this.publicTeardownCallRequest, ); } static empty() { return new PartialPrivateTailPublicInputsForPublic( - PublicValidationRequests.empty(), - PublicAccumulatedData.empty(), - PublicAccumulatedData.empty(), + PrivateToPublicAccumulatedData.empty(), + PrivateToPublicAccumulatedData.empty(), PublicCallRequest.empty(), ); } } export class PartialPrivateTailPublicInputsForRollup { - constructor(public rollupValidationRequests: RollupValidationRequests, public end: CombinedAccumulatedData) {} + constructor(public end: CombinedAccumulatedData) {} static fromBuffer(buffer: Buffer | BufferReader): PartialPrivateTailPublicInputsForRollup { const reader = BufferReader.asReader(buffer); - return new PartialPrivateTailPublicInputsForRollup( - reader.readObject(RollupValidationRequests), - reader.readObject(CombinedAccumulatedData), - ); + return new PartialPrivateTailPublicInputsForRollup(reader.readObject(CombinedAccumulatedData)); } getSize() { - return this.rollupValidationRequests.getSize() + this.end.getSize(); + return this.end.getSize(); } toBuffer() { - return serializeToBuffer(this.rollupValidationRequests, this.end); + return serializeToBuffer(this.end); } static empty() { - return new PartialPrivateTailPublicInputsForRollup( - RollupValidationRequests.empty(), - CombinedAccumulatedData.empty(), - ); + return new PartialPrivateTailPublicInputsForRollup(CombinedAccumulatedData.empty()); } } @@ -115,11 +102,8 @@ export class PrivateKernelTailCircuitPublicInputs { /** * Data which is not modified by the circuits. */ - public constants: CombinedConstantData, - /** - * Indicates whether execution of the public circuit reverted. - */ - public revertCode: RevertCode, + public constants: TxConstantData, + public rollupValidationRequests: RollupValidationRequests, /** * The address of the fee payer for the transaction. */ @@ -138,16 +122,12 @@ export class PrivateKernelTailCircuitPublicInputs { } } - get publicInputs(): PartialPrivateTailPublicInputsForPublic | PartialPrivateTailPublicInputsForRollup { - return (this.forPublic ?? this.forRollup)!; - } - getSize() { return ( (this.forPublic?.getSize() ?? 0) + (this.forRollup?.getSize() ?? 0) + this.constants.getSize() + - this.revertCode.getSerializedLength() + + this.rollupValidationRequests.getSize() + this.feePayer.size ); } @@ -156,15 +136,13 @@ export class PrivateKernelTailCircuitPublicInputs { if (!this.forPublic) { throw new Error('Private tail public inputs is not for public circuit.'); } - return new PublicKernelCircuitPublicInputs( + return new PrivateToPublicKernelCircuitPublicInputs( this.constants, - this.forPublic.validationRequests, - this.forPublic.endNonRevertibleData, - this.forPublic.end, - 0, // endSideEffectCounter + this.rollupValidationRequests, + this.forPublic.nonRevertibleAccumulatedData, + this.forPublic.revertibleAccumulatedData, this.forPublic.publicTeardownCallRequest, this.feePayer, - this.revertCode, ); } @@ -172,12 +150,19 @@ export class PrivateKernelTailCircuitPublicInputs { if (!this.forRollup) { throw new Error('Private tail public inputs is not for rollup circuit.'); } + const constants = new CombinedConstantData( + this.constants.historicalHeader, + this.constants.txContext, + this.constants.vkTreeRoot, + this.constants.protocolContractTreeRoot, + GlobalVariables.empty(), + ); return new KernelCircuitPublicInputs( - this.forRollup.rollupValidationRequests, + this.rollupValidationRequests, this.forRollup.end, - this.constants, + constants, PartialStateReference.empty(), - this.revertCode, + RevertCode.OK, this.feePayer, ); } @@ -191,11 +176,11 @@ export class PrivateKernelTailCircuitPublicInputs { } numberOfNonRevertiblePublicCallRequests() { - return this.forPublic ? countAccumulatedItems(this.forPublic.endNonRevertibleData.publicCallStack) : 0; + return this.forPublic ? countAccumulatedItems(this.forPublic.nonRevertibleAccumulatedData.publicCallRequests) : 0; } numberOfRevertiblePublicCallRequests() { - return this.forPublic ? countAccumulatedItems(this.forPublic.end.publicCallStack) : 0; + return this.forPublic ? countAccumulatedItems(this.forPublic.revertibleAccumulatedData.publicCallRequests) : 0; } hasTeardownPublicCallRequest() { @@ -203,11 +188,13 @@ export class PrivateKernelTailCircuitPublicInputs { } getNonRevertiblePublicCallRequests() { - return this.forPublic ? this.forPublic.endNonRevertibleData.publicCallStack.filter(r => !r.isEmpty()) : []; + return this.forPublic + ? this.forPublic.nonRevertibleAccumulatedData.publicCallRequests.filter(r => !r.isEmpty()) + : []; } getRevertiblePublicCallRequests() { - return this.forPublic ? this.forPublic.end.publicCallStack.filter(r => !r.isEmpty()) : []; + return this.forPublic ? this.forPublic.revertibleAccumulatedData.publicCallRequests.filter(r => !r.isEmpty()) : []; } getTeardownPublicCallRequest() { @@ -217,8 +204,9 @@ export class PrivateKernelTailCircuitPublicInputs { getNonEmptyNoteHashes() { const noteHashes = this.forPublic - ? mergeAccumulatedData(this.forPublic.endNonRevertibleData.noteHashes, this.forPublic.end.noteHashes).map( - n => n.value, + ? mergeAccumulatedData( + this.forPublic.nonRevertibleAccumulatedData.noteHashes, + this.forPublic.revertibleAccumulatedData.noteHashes, ) : this.forRollup!.end.noteHashes; return noteHashes.filter(n => !n.isZero()); @@ -226,8 +214,9 @@ export class PrivateKernelTailCircuitPublicInputs { getNonEmptyNullifiers() { const nullifiers = this.forPublic - ? mergeAccumulatedData(this.forPublic.endNonRevertibleData.nullifiers, this.forPublic.end.nullifiers).map( - n => n.value, + ? mergeAccumulatedData( + this.forPublic.nonRevertibleAccumulatedData.nullifiers, + this.forPublic.revertibleAccumulatedData.nullifiers, ) : this.forRollup!.end.nullifiers; return nullifiers.filter(n => !n.isZero()); @@ -237,8 +226,8 @@ export class PrivateKernelTailCircuitPublicInputs { const reader = BufferReader.asReader(buffer); const isForPublic = reader.readBoolean(); return new PrivateKernelTailCircuitPublicInputs( - reader.readObject(CombinedConstantData), - reader.readObject(RevertCode), + reader.readObject(TxConstantData), + reader.readObject(RollupValidationRequests), reader.readObject(AztecAddress), isForPublic ? reader.readObject(PartialPrivateTailPublicInputsForPublic) : undefined, !isForPublic ? reader.readObject(PartialPrivateTailPublicInputsForRollup) : undefined, @@ -250,7 +239,7 @@ export class PrivateKernelTailCircuitPublicInputs { return serializeToBuffer( isForPublic, this.constants, - this.revertCode, + this.rollupValidationRequests, this.feePayer, isForPublic ? this.forPublic!.toBuffer() : this.forRollup!.toBuffer(), ); @@ -258,8 +247,8 @@ export class PrivateKernelTailCircuitPublicInputs { static empty() { return new PrivateKernelTailCircuitPublicInputs( - CombinedConstantData.empty(), - RevertCode.OK, + TxConstantData.empty(), + RollupValidationRequests.empty(), AztecAddress.ZERO, undefined, PartialPrivateTailPublicInputsForRollup.empty(), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_to_avm_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_to_avm_accumulated_data.ts new file mode 100644 index 00000000000..75026cd5371 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/private_to_avm_accumulated_data.ts @@ -0,0 +1,123 @@ +import { type FieldsOf, makeTuple } from '@aztec/foundation/array'; +import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { inspect } from 'util'; + +import { MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX } from '../../constants.gen.js'; +import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; +import { type UInt32 } from '../shared.js'; + +export class PrivateToAvmAccumulatedData { + constructor( + public noteHashes: Tuple, + public nullifiers: Tuple, + public l2ToL1Msgs: Tuple, + ) {} + + getSize() { + return ( + arraySerializedSizeOfNonEmpty(this.noteHashes) + + arraySerializedSizeOfNonEmpty(this.nullifiers) + + arraySerializedSizeOfNonEmpty(this.l2ToL1Msgs) + ); + } + + static getFields(fields: FieldsOf) { + return [fields.noteHashes, fields.nullifiers, fields.l2ToL1Msgs] as const; + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new this( + reader.readFieldArray(MAX_NOTE_HASHES_PER_TX), + reader.readFieldArray(MAX_NULLIFIERS_PER_TX), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), + ); + } + + static from(fields: FieldsOf) { + return new PrivateToAvmAccumulatedData(...PrivateToAvmAccumulatedData.getFields(fields)); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PrivateToAvmAccumulatedData( + reader.readArray(MAX_NOTE_HASHES_PER_TX, Fr), + reader.readArray(MAX_NULLIFIERS_PER_TX, Fr), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), + ); + } + + toBuffer() { + return serializeToBuffer(...PrivateToAvmAccumulatedData.getFields(this)); + } + + static empty() { + return new PrivateToAvmAccumulatedData( + makeTuple(MAX_NOTE_HASHES_PER_TX, Fr.zero), + makeTuple(MAX_NULLIFIERS_PER_TX, Fr.zero), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), + ); + } + + [inspect.custom]() { + return `PrivateToAvmAccumulatedData { + noteHashes: [${this.noteHashes + .filter(x => !x.isZero()) + .map(x => inspect(x)) + .join(', ')}], + nullifiers: [${this.nullifiers + .filter(x => !x.isZero()) + .map(x => inspect(x)) + .join(', ')}], + l2ToL1Msgs: [${this.l2ToL1Msgs + .filter(x => !x.isEmpty()) + .map(x => inspect(x)) + .join(', ')}], + }`; + } +} + +export class PrivateToAvmAccumulatedDataArrayLengths { + constructor(public noteHashes: UInt32, public nullifiers: UInt32, public l2ToL1Msgs: UInt32) {} + + getSize() { + return 4 * 3; + } + + static getFields(fields: FieldsOf) { + return [fields.noteHashes, fields.nullifiers, fields.l2ToL1Msgs] as const; + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new this(reader.readU32(), reader.readU32(), reader.readU32()); + } + + static from(fields: FieldsOf) { + return new PrivateToAvmAccumulatedDataArrayLengths(...PrivateToAvmAccumulatedDataArrayLengths.getFields(fields)); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PrivateToAvmAccumulatedDataArrayLengths(reader.readNumber(), reader.readNumber(), reader.readNumber()); + } + + toBuffer() { + return serializeToBuffer(...PrivateToAvmAccumulatedDataArrayLengths.getFields(this)); + } + + static empty() { + return new PrivateToAvmAccumulatedDataArrayLengths(0, 0, 0); + } + + [inspect.custom]() { + return `PrivateToAvmAccumulatedDataArrayLengths { + noteHashes: ${this.noteHashes}, + nullifiers: ${this.nullifiers}, + l2ToL1Msgs: ${this.l2ToL1Msgs}, + }`; + } +} diff --git a/yarn-project/circuits.js/src/structs/kernel/private_to_public_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_to_public_accumulated_data.ts new file mode 100644 index 00000000000..0573ec8d875 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/private_to_public_accumulated_data.ts @@ -0,0 +1,142 @@ +import { type FieldsOf, makeTuple } from '@aztec/foundation/array'; +import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; +import { 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_ENQUEUED_CALLS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, +} from '../../constants.gen.js'; +import { Gas } from '../gas.js'; +import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; +import { LogHash, ScopedLogHash } from '../log_hash.js'; +import { PublicCallRequest } from '../public_call_request.js'; + +export class PrivateToPublicAccumulatedData { + constructor( + public readonly noteHashes: Tuple, + public readonly nullifiers: Tuple, + public readonly l2ToL1Msgs: Tuple, + public readonly noteEncryptedLogsHashes: Tuple, + public readonly encryptedLogsHashes: Tuple, + public readonly unencryptedLogsHashes: Tuple, + public readonly publicCallRequests: Tuple, + public readonly gasUsed: Gas, + ) {} + + getSize() { + return ( + arraySerializedSizeOfNonEmpty(this.noteHashes) + + arraySerializedSizeOfNonEmpty(this.nullifiers) + + arraySerializedSizeOfNonEmpty(this.l2ToL1Msgs) + + arraySerializedSizeOfNonEmpty(this.noteEncryptedLogsHashes) + + arraySerializedSizeOfNonEmpty(this.encryptedLogsHashes) + + arraySerializedSizeOfNonEmpty(this.unencryptedLogsHashes) + + arraySerializedSizeOfNonEmpty(this.publicCallRequests) + + this.gasUsed.toBuffer().length + ); + } + + static getFields(fields: FieldsOf) { + return [ + fields.noteHashes, + fields.nullifiers, + fields.l2ToL1Msgs, + fields.noteEncryptedLogsHashes, + fields.encryptedLogsHashes, + fields.unencryptedLogsHashes, + fields.publicCallRequests, + fields.gasUsed, + ] as const; + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new this( + reader.readFieldArray(MAX_NOTE_HASHES_PER_TX), + reader.readFieldArray(MAX_NULLIFIERS_PER_TX), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), + reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), + reader.readObject(Gas), + ); + } + + static from(fields: FieldsOf) { + return new PrivateToPublicAccumulatedData(...PrivateToPublicAccumulatedData.getFields(fields)); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PrivateToPublicAccumulatedData( + reader.readArray(MAX_NOTE_HASHES_PER_TX, Fr), + reader.readArray(MAX_NULLIFIERS_PER_TX, Fr), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), + reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), + reader.readObject(Gas), + ); + } + + toBuffer() { + return serializeToBuffer(...PrivateToPublicAccumulatedData.getFields(this)); + } + + static empty() { + return new PrivateToPublicAccumulatedData( + makeTuple(MAX_NOTE_HASHES_PER_TX, Fr.zero), + makeTuple(MAX_NULLIFIERS_PER_TX, Fr.zero), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), + makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash.empty), + makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest.empty), + Gas.empty(), + ); + } + + [inspect.custom]() { + return `PrivateToPublicAccumulatedData { + noteHashes: [${this.noteHashes + .filter(x => !x.isZero()) + .map(x => inspect(x)) + .join(', ')}], + nullifiers: [${this.nullifiers + .filter(x => !x.isZero()) + .map(x => inspect(x)) + .join(', ')}], + l2ToL1Msgs: [${this.l2ToL1Msgs + .filter(x => !x.isEmpty()) + .map(x => inspect(x)) + .join(', ')}], + noteEncryptedLogsHashes: [${this.noteEncryptedLogsHashes + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], + encryptedLogsHashes: [${this.encryptedLogsHashes + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], + unencryptedLogsHashes: [${this.unencryptedLogsHashes + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], + publicCallRequests: [${this.publicCallRequests + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], + gasUsed: [${inspect(this.gasUsed)}] + }`; + } +} diff --git a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts b/yarn-project/circuits.js/src/structs/kernel/private_to_public_accumulated_data_builder.ts similarity index 66% rename from yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts rename to yarn-project/circuits.js/src/structs/kernel/private_to_public_accumulated_data_builder.ts index b652345abd2..802e541d16c 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_to_public_accumulated_data_builder.ts @@ -1,23 +1,20 @@ import { padArrayEnd } from '@aztec/foundation/collection'; +import { Fr } from '@aztec/foundation/fields'; import { MAX_ENCRYPTED_LOGS_PER_TX, + MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { Gas } from '../gas.js'; import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; import { LogHash, ScopedLogHash } from '../log_hash.js'; -import { ScopedNoteHash } from '../note_hash.js'; -import { Nullifier } from '../nullifier.js'; import { PublicCallRequest } from '../public_call_request.js'; -import { PublicDataUpdateRequest } from '../public_data_update_request.js'; -import { PublicAccumulatedData } from './public_accumulated_data.js'; +import { PrivateToPublicAccumulatedData } from './private_to_public_accumulated_data.js'; /** * TESTS-ONLY CLASS @@ -25,33 +22,32 @@ import { PublicAccumulatedData } from './public_accumulated_data.js'; * as PublicAccumulatedData is (or will shortly be) immutable. * */ -export class PublicAccumulatedDataBuilder { - private noteHashes: ScopedNoteHash[] = []; - private nullifiers: Nullifier[] = []; +export class PrivateToPublicAccumulatedDataBuilder { + private noteHashes: Fr[] = []; + private nullifiers: Fr[] = []; private l2ToL1Msgs: ScopedL2ToL1Message[] = []; private noteEncryptedLogsHashes: LogHash[] = []; private encryptedLogsHashes: ScopedLogHash[] = []; private unencryptedLogsHashes: ScopedLogHash[] = []; - private publicDataUpdateRequests: PublicDataUpdateRequest[] = []; private publicCallStack: PublicCallRequest[] = []; private gasUsed: Gas = Gas.empty(); - pushNoteHash(newNoteHash: ScopedNoteHash) { + pushNoteHash(newNoteHash: Fr) { this.noteHashes.push(newNoteHash); return this; } - withNoteHashes(noteHashes: ScopedNoteHash[]) { + withNoteHashes(noteHashes: Fr[]) { this.noteHashes = noteHashes; return this; } - pushNullifier(newNullifier: Nullifier) { + pushNullifier(newNullifier: Fr) { this.nullifiers.push(newNullifier); return this; } - withNullifiers(nullifiers: Nullifier[]) { + withNullifiers(nullifiers: Fr[]) { this.nullifiers = nullifiers; return this; } @@ -96,16 +92,6 @@ export class PublicAccumulatedDataBuilder { return this; } - pushPublicDataUpdateRequest(publicDataUpdateRequest: PublicDataUpdateRequest) { - this.publicDataUpdateRequests.push(publicDataUpdateRequest); - return this; - } - - withPublicDataUpdateRequests(publicDataUpdateRequests: PublicDataUpdateRequest[]) { - this.publicDataUpdateRequests = publicDataUpdateRequests; - return this; - } - pushPublicCall(publicCall: PublicCallRequest) { this.publicCallStack.push(publicCall); return this; @@ -121,34 +107,28 @@ export class PublicAccumulatedDataBuilder { return this; } - build(): PublicAccumulatedData { - return new PublicAccumulatedData( - padArrayEnd(this.noteHashes, ScopedNoteHash.empty(), MAX_NOTE_HASHES_PER_TX), - padArrayEnd(this.nullifiers, Nullifier.empty(), MAX_NULLIFIERS_PER_TX), + build() { + return new PrivateToPublicAccumulatedData( + padArrayEnd(this.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX), + padArrayEnd(this.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX), padArrayEnd(this.l2ToL1Msgs, ScopedL2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_TX), padArrayEnd(this.noteEncryptedLogsHashes, LogHash.empty(), MAX_NOTE_ENCRYPTED_LOGS_PER_TX), padArrayEnd(this.encryptedLogsHashes, ScopedLogHash.empty(), MAX_ENCRYPTED_LOGS_PER_TX), padArrayEnd(this.unencryptedLogsHashes, ScopedLogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_TX), - padArrayEnd( - this.publicDataUpdateRequests, - PublicDataUpdateRequest.empty(), - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - ), - padArrayEnd(this.publicCallStack, PublicCallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX), + padArrayEnd(this.publicCallStack, PublicCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_TX), this.gasUsed, ); } - static fromPublicAccumulatedData(publicAccumulatedData: PublicAccumulatedData): PublicAccumulatedDataBuilder { - return new PublicAccumulatedDataBuilder() + static fromPublicAccumulatedData(publicAccumulatedData: PrivateToPublicAccumulatedData) { + return new PrivateToPublicAccumulatedDataBuilder() .withNoteHashes(publicAccumulatedData.noteHashes) .withNullifiers(publicAccumulatedData.nullifiers) .withL2ToL1Msgs(publicAccumulatedData.l2ToL1Msgs) .withNoteEncryptedLogsHashes(publicAccumulatedData.noteEncryptedLogsHashes) .withEncryptedLogsHashes(publicAccumulatedData.encryptedLogsHashes) .withUnencryptedLogsHashes(publicAccumulatedData.unencryptedLogsHashes) - .withPublicDataUpdateRequests(publicAccumulatedData.publicDataUpdateRequests) - .withPublicCallStack(publicAccumulatedData.publicCallStack) + .withPublicCallStack(publicAccumulatedData.publicCallRequests) .withGasUsed(publicAccumulatedData.gasUsed); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_to_public_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_to_public_kernel_circuit_public_inputs.ts new file mode 100644 index 00000000000..7e1e45f176d --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/private_to_public_kernel_circuit_public_inputs.ts @@ -0,0 +1,60 @@ +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { PublicCallRequest } from '../public_call_request.js'; +import { RollupValidationRequests } from '../rollup_validation_requests.js'; +import { PrivateToPublicAccumulatedData } from './private_to_public_accumulated_data.js'; +import { TxConstantData } from './tx_constant_data.js'; + +export class PrivateToPublicKernelCircuitPublicInputs { + constructor( + public constants: TxConstantData, + public rollupValidationRequests: RollupValidationRequests, + public nonRevertibleAccumulatedData: PrivateToPublicAccumulatedData, + public revertibleAccumulatedData: PrivateToPublicAccumulatedData, + public publicTeardownCallRequest: PublicCallRequest, + public feePayer: AztecAddress, + ) {} + + toBuffer() { + return serializeToBuffer( + this.constants, + this.rollupValidationRequests, + this.nonRevertibleAccumulatedData, + this.revertibleAccumulatedData, + this.publicTeardownCallRequest, + this.feePayer, + ); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PrivateToPublicKernelCircuitPublicInputs( + reader.readObject(TxConstantData), + reader.readObject(RollupValidationRequests), + reader.readObject(PrivateToPublicAccumulatedData), + reader.readObject(PrivateToPublicAccumulatedData), + reader.readObject(PublicCallRequest), + reader.readObject(AztecAddress), + ); + } + + static empty() { + return new PrivateToPublicKernelCircuitPublicInputs( + TxConstantData.empty(), + RollupValidationRequests.empty(), + PrivateToPublicAccumulatedData.empty(), + PrivateToPublicAccumulatedData.empty(), + PublicCallRequest.empty(), + AztecAddress.ZERO, + ); + } + + static fromString(str: string) { + return PrivateToPublicKernelCircuitPublicInputs.fromBuffer(Buffer.from(str, 'hex')); + } + + toString() { + return this.toBuffer().toString('hex'); + } +} 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 1dd6f2beb56..4a366853ebf 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 @@ -7,11 +7,11 @@ import { inspect } from 'util'; import { MAX_ENCRYPTED_LOGS_PER_TX, + MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, NUM_PUBLIC_ACCUMULATED_DATA_ARRAYS, @@ -64,7 +64,7 @@ export class PublicAccumulatedData { /** * Current public call stack. */ - public readonly publicCallStack: Tuple, + public readonly publicCallStack: Tuple, /** Gas used so far by the transaction. */ public readonly gasUsed: Gas, @@ -170,7 +170,7 @@ export class PublicAccumulatedData { reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), reader.readObject(Gas), ); } @@ -185,7 +185,7 @@ export class PublicAccumulatedData { reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest), reader.readObject(Gas), ); } @@ -208,7 +208,7 @@ export class PublicAccumulatedData { makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty), - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest.empty), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest.empty), Gas.empty(), ); } diff --git a/yarn-project/circuits.js/src/structs/kernel/tx_constant_data.ts b/yarn-project/circuits.js/src/structs/kernel/tx_constant_data.ts new file mode 100644 index 00000000000..84e852be92c --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/tx_constant_data.ts @@ -0,0 +1,82 @@ +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; + +import { Header } from '../header.js'; +import { TxContext } from '../tx_context.js'; + +/** + * Data that is constant/not modified by neither of the kernels. + */ +export class TxConstantData { + constructor( + /** Header of a block whose state is used during execution (not the block the transaction is included in). */ + public historicalHeader: Header, + /** + * Context of the transaction. + * + * Note: `chainId` and `version` in txContext are not redundant to the values in + * self.historical_header.global_variables because they can be different in case of a protocol upgrade. In such + * a situation we could be using header from a block before the upgrade took place but be using the updated + * protocol to execute and prove the transaction. + */ + public txContext: TxContext, + /** + * Root of the vk tree for the protocol circuits. + */ + public vkTreeRoot: Fr, + /** + * Root of the tree for the protocol contracts. + */ + public protocolContractTreeRoot: Fr, + ) {} + + static from(fields: FieldsOf) { + return new TxConstantData(...TxConstantData.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.historicalHeader, fields.txContext, fields.vkTreeRoot, fields.protocolContractTreeRoot] as const; + } + + static fromFields(fields: Fr[] | FieldReader): TxConstantData { + const reader = FieldReader.asReader(fields); + return new TxConstantData( + reader.readObject(Header), + reader.readObject(TxContext), + reader.readField(), + reader.readField(), + ); + } + + static fromBuffer(buffer: Buffer | BufferReader): TxConstantData { + const reader = BufferReader.asReader(buffer); + return new TxConstantData( + reader.readObject(Header), + reader.readObject(TxContext), + Fr.fromBuffer(reader), + Fr.fromBuffer(reader), + ); + } + + toBuffer() { + return serializeToBuffer(...TxConstantData.getFields(this)); + } + + static empty() { + return new TxConstantData(Header.empty(), TxContext.empty(), Fr.ZERO, Fr.ZERO); + } + + getSize() { + return ( + this.historicalHeader.getSize() + + this.txContext.getSize() + + this.vkTreeRoot.size + + this.protocolContractTreeRoot.size + ); + } + + clone(): TxConstantData { + return TxConstantData.fromBuffer(this.toBuffer()); + } +} diff --git a/yarn-project/circuits.js/src/structs/kernel/vm_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/vm_circuit_public_inputs.ts index fc4200a344c..7182981a3cb 100644 --- a/yarn-project/circuits.js/src/structs/kernel/vm_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/vm_circuit_public_inputs.ts @@ -4,7 +4,7 @@ import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec import { inspect } from 'util'; -import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX } from '../../constants.gen.js'; +import { MAX_ENQUEUED_CALLS_PER_TX } from '../../constants.gen.js'; import { Gas } from '../gas.js'; import { PublicCallRequest } from '../public_call_request.js'; import { PublicInnerCallRequest } from '../public_inner_call_request.js'; @@ -19,7 +19,7 @@ export class VMCircuitPublicInputs { constructor( public constants: CombinedConstantData, public callRequest: PublicCallRequest, - public publicCallStack: Tuple, + public publicCallStack: Tuple, public previousValidationRequestArrayLengths: PublicValidationRequestArrayLengths, public validationRequests: PublicValidationRequests, public previousAccumulatedDataArrayLengths: PublicAccumulatedDataArrayLengths, @@ -65,7 +65,7 @@ export class VMCircuitPublicInputs { return new VMCircuitPublicInputs( reader.readObject(CombinedConstantData), reader.readObject(PublicCallRequest), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicInnerCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicInnerCallRequest), reader.readObject(PublicValidationRequestArrayLengths), reader.readObject(PublicValidationRequests), reader.readObject(PublicAccumulatedDataArrayLengths), @@ -82,7 +82,7 @@ export class VMCircuitPublicInputs { return new VMCircuitPublicInputs( CombinedConstantData.empty(), PublicCallRequest.empty(), - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicInnerCallRequest.empty), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, PublicInnerCallRequest.empty), PublicValidationRequestArrayLengths.empty(), PublicValidationRequests.empty(), PublicAccumulatedDataArrayLengths.empty(), @@ -100,7 +100,7 @@ export class VMCircuitPublicInputs { return new VMCircuitPublicInputs( CombinedConstantData.fromFields(reader), PublicCallRequest.fromFields(reader), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicInnerCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_TX, PublicInnerCallRequest), PublicValidationRequestArrayLengths.fromFields(reader), PublicValidationRequests.fromFields(reader), PublicAccumulatedDataArrayLengths.fromFields(reader), diff --git a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts index 108ca3ff850..484dc9fc915 100644 --- a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts @@ -11,6 +11,7 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { MAX_ENCRYPTED_LOGS_PER_CALL, + MAX_ENQUEUED_CALLS_PER_CALL, MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, @@ -19,7 +20,6 @@ import { MAX_NULLIFIERS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, } from '../constants.gen.js'; @@ -33,7 +33,7 @@ import { MaxBlockNumber } from './max_block_number.js'; import { NoteHash } from './note_hash.js'; import { Nullifier } from './nullifier.js'; import { PrivateCallRequest } from './private_call_request.js'; -import { PublicCallRequest } from './public_call_request.js'; +import { CountedPublicCallRequest, PublicCallRequest } from './public_call_request.js'; import { ReadRequest } from './read_request.js'; import { TxContext } from './tx_context.js'; @@ -96,7 +96,7 @@ export class PrivateCircuitPublicInputs { /** * Public call stack at the current kernel iteration. */ - public publicCallRequests: Tuple, + public publicCallRequests: Tuple, /** * Hash of the public teardown function. */ @@ -171,7 +171,7 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NOTE_HASHES_PER_CALL, NoteHash), reader.readArray(MAX_NULLIFIERS_PER_CALL, Nullifier), reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, PrivateCallRequest), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_CALL, CountedPublicCallRequest), reader.readObject(PublicCallRequest), reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), @@ -199,7 +199,7 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NOTE_HASHES_PER_CALL, NoteHash), reader.readArray(MAX_NULLIFIERS_PER_CALL, Nullifier), reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, PrivateCallRequest), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_CALL, CountedPublicCallRequest), reader.readObject(PublicCallRequest), reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), @@ -230,7 +230,7 @@ export class PrivateCircuitPublicInputs { makeTuple(MAX_NOTE_HASHES_PER_CALL, NoteHash.empty), makeTuple(MAX_NULLIFIERS_PER_CALL, Nullifier.empty), makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, PrivateCallRequest.empty), - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicCallRequest.empty), + makeTuple(MAX_ENQUEUED_CALLS_PER_CALL, CountedPublicCallRequest.empty), PublicCallRequest.empty(), makeTuple(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, diff --git a/yarn-project/circuits.js/src/structs/public_call_request.ts b/yarn-project/circuits.js/src/structs/public_call_request.ts index c11e4975556..67987838cce 100644 --- a/yarn-project/circuits.js/src/structs/public_call_request.ts +++ b/yarn-project/circuits.js/src/structs/public_call_request.ts @@ -1,79 +1,157 @@ +import { FunctionSelector } from '@aztec/foundation/abi'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; import { inspect } from 'util'; -import { CallContext } from './call_context.js'; +import { COUNTED_PUBLIC_CALL_REQUEST_LENGTH, PUBLIC_CALL_REQUEST_LENGTH } from '../constants.gen.js'; +import { type UInt32 } from './shared.js'; /** * Represents a request to call a public function. */ export class PublicCallRequest { - constructor(public callContext: CallContext, public argsHash: Fr, public counter: number) {} + constructor( + /** + * Address of the account which represents the entity who invoked the call. + */ + public msgSender: AztecAddress, + /** + * The contract address being called. + */ + public contractAddress: AztecAddress, + /** + * Function selector of the function being called. + */ + public functionSelector: FunctionSelector, + /** + * Determines whether the call is modifying state. + */ + public isStaticCall: boolean, + public argsHash: Fr, + ) {} getSize() { return this.isEmpty() ? 0 : this.toBuffer().length; } - /** - * Serialize this as a buffer. - * @returns The buffer. - */ - toBuffer() { - return serializeToBuffer(this.callContext, this.argsHash, this.counter); - } - - /** - * Deserialize this from a buffer. - * @param buffer - The bufferable type from which to deserialize. - * @returns The deserialized instance of PublicCallRequest. - */ - static fromBuffer(buffer: Buffer | BufferReader) { - const reader = BufferReader.asReader(buffer); - return new PublicCallRequest(reader.readObject(CallContext), reader.readObject(Fr), reader.readNumber()); - } - - /** - * Create PublicCallRequest from a fields dictionary. - * @param fields - The dictionary. - * @returns A PublicCallRequest object. - */ static from(fields: FieldsOf): PublicCallRequest { return new PublicCallRequest(...PublicCallRequest.getFields(fields)); } - /** - * Serialize into a field array. Low-level utility. - * @param fields - Object with fields. - * @returns The array. - */ static getFields(fields: FieldsOf) { - return [fields.callContext, fields.argsHash, fields.counter] as const; + return [ + fields.msgSender, + fields.contractAddress, + fields.functionSelector, + fields.isStaticCall, + fields.argsHash, + ] as const; + } + + static fromFields(fields: Fr[] | FieldReader): PublicCallRequest { + const reader = FieldReader.asReader(fields); + return new PublicCallRequest( + reader.readObject(AztecAddress), + reader.readObject(AztecAddress), + reader.readObject(FunctionSelector), + reader.readBoolean(), + reader.readField(), + ); } toFields(): Fr[] { - return serializeToFields([this.callContext, this.argsHash, this.counter]); + const fields = serializeToFields(...PublicCallRequest.getFields(this)); + if (fields.length !== PUBLIC_CALL_REQUEST_LENGTH) { + throw new Error( + `Invalid number of fields for PublicCallRequest. Expected ${PUBLIC_CALL_REQUEST_LENGTH}, got ${fields.length}`, + ); + } + return fields; } - static fromFields(fields: Fr[] | FieldReader): PublicCallRequest { - const reader = FieldReader.asReader(fields); - return new PublicCallRequest(CallContext.fromFields(reader), reader.readField(), reader.readU32()); + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicCallRequest( + reader.readObject(AztecAddress), + reader.readObject(AztecAddress), + reader.readObject(FunctionSelector), + reader.readBoolean(), + reader.readObject(Fr), + ); + } + + toBuffer() { + return serializeToBuffer(...PublicCallRequest.getFields(this)); } static empty() { - return new PublicCallRequest(CallContext.empty(), Fr.ZERO, 0); + return new PublicCallRequest(AztecAddress.ZERO, AztecAddress.ZERO, FunctionSelector.empty(), false, Fr.ZERO); } isEmpty(): boolean { - return this.callContext.isEmpty() && this.argsHash.isEmpty() && this.counter == 0; + return ( + this.msgSender.isZero() && + this.contractAddress.isZero() && + this.functionSelector.isEmpty() && + !this.isStaticCall && + this.argsHash.isEmpty() + ); } [inspect.custom]() { return `PublicCallRequest { - callContext: ${this.callContext} + msgSender: ${this.msgSender} + contractAddress: ${this.contractAddress} + functionSelector: ${this.functionSelector} + isStaticCall: ${this.isStaticCall} argsHash: ${this.argsHash} - counter: ${this.counter} }`; } } + +export class CountedPublicCallRequest { + constructor(public inner: PublicCallRequest, public counter: UInt32) {} + + getSize() { + return this.isEmpty() ? 0 : this.toBuffer().length; + } + + static getFields(fields: FieldsOf) { + return [fields.inner, fields.counter] as const; + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new CountedPublicCallRequest(reader.readObject(PublicCallRequest), reader.readU32()); + } + + toFields(): Fr[] { + const fields = serializeToFields(...CountedPublicCallRequest.getFields(this)); + if (fields.length !== COUNTED_PUBLIC_CALL_REQUEST_LENGTH) { + throw new Error( + `Invalid number of fields for CountedPublicCallRequest. Expected ${COUNTED_PUBLIC_CALL_REQUEST_LENGTH}, got ${fields.length}`, + ); + } + return fields; + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new CountedPublicCallRequest(reader.readObject(PublicCallRequest), reader.readNumber()); + } + + toBuffer() { + return serializeToBuffer(...CountedPublicCallRequest.getFields(this)); + } + + static empty() { + return new CountedPublicCallRequest(PublicCallRequest.empty(), 0); + } + + isEmpty(): boolean { + return this.inner.isEmpty() && this.counter == 0; + } +} diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts index feb8d0382ba..b307b33f2a9 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts @@ -11,6 +11,7 @@ import { import { type FieldsOf } from '@aztec/foundation/types'; import { + MAX_ENQUEUED_CALLS_PER_CALL, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, @@ -18,7 +19,6 @@ import { MAX_NULLIFIERS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, @@ -90,7 +90,7 @@ export class PublicCircuitPublicInputs { /** * Public call stack of the current kernel iteration. */ - public publicCallRequests: Tuple, + public publicCallRequests: Tuple, /** * New note hashes created within a public execution call */ @@ -167,7 +167,7 @@ export class PublicCircuitPublicInputs { makeTuple(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, TreeLeafReadRequest.empty), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest.empty), makeTuple(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead.empty), - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicInnerCallRequest.empty), + makeTuple(MAX_ENQUEUED_CALLS_PER_CALL, PublicInnerCallRequest.empty), makeTuple(MAX_NOTE_HASHES_PER_CALL, NoteHash.empty), makeTuple(MAX_NULLIFIERS_PER_CALL, Nullifier.empty), makeTuple(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), @@ -279,7 +279,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, TreeLeafReadRequest), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest), reader.readArray(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicInnerCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_CALL, PublicInnerCallRequest), reader.readArray(MAX_NOTE_HASHES_PER_CALL, NoteHash), reader.readArray(MAX_NULLIFIERS_PER_CALL, Nullifier), reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), @@ -309,7 +309,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, TreeLeafReadRequest), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest), reader.readArray(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicInnerCallRequest), + reader.readArray(MAX_ENQUEUED_CALLS_PER_CALL, PublicInnerCallRequest), reader.readArray(MAX_NOTE_HASHES_PER_CALL, NoteHash), reader.readArray(MAX_NULLIFIERS_PER_CALL, Nullifier), reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), diff --git a/yarn-project/circuits.js/src/structs/public_data_write.ts b/yarn-project/circuits.js/src/structs/public_data_write.ts new file mode 100644 index 00000000000..571410573f0 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/public_data_write.ts @@ -0,0 +1,65 @@ +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; + +import { STRING_ENCODING } from './shared.js'; + +/** + * Write operations on the public state tree. + */ +export class PublicDataWrite { + static SIZE_IN_BYTES = Fr.SIZE_IN_BYTES * 2; + + constructor( + /** + * The updated leaf. + */ + public readonly leafSlot: Fr, + /** + * New value of the leaf. + */ + public readonly value: Fr, + ) {} + + static from(fields: FieldsOf) { + return new PublicDataWrite(...PublicDataWrite.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.leafSlot, fields.value] as const; + } + + static fromFields(fields: Fr[] | FieldReader): PublicDataWrite { + const reader = FieldReader.asReader(fields); + return new PublicDataWrite(reader.readField(), reader.readField()); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicDataWrite(Fr.fromBuffer(reader), Fr.fromBuffer(reader)); + } + + toBuffer() { + return serializeToBuffer(...PublicDataWrite.getFields(this)); + } + + static fromString(str: string) { + return PublicDataWrite.fromBuffer(Buffer.from(str, STRING_ENCODING)); + } + + toString() { + return this.toBuffer().toString(STRING_ENCODING); + } + + static empty() { + return new PublicDataWrite(Fr.ZERO, Fr.ZERO); + } + + static isEmpty(data: PublicDataWrite): boolean { + return data.isEmpty(); + } + + isEmpty() { + return this.leafSlot.isZero() && this.value.isZero(); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/avm_proof_data.ts b/yarn-project/circuits.js/src/structs/rollup/avm_proof_data.ts index 11b8dd553fd..72c843c89e7 100644 --- a/yarn-project/circuits.js/src/structs/rollup/avm_proof_data.ts +++ b/yarn-project/circuits.js/src/structs/rollup/avm_proof_data.ts @@ -1,13 +1,13 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { AVM_PROOF_LENGTH_IN_FIELDS } from '../../constants.gen.js'; -import { VMCircuitPublicInputs } from '../kernel/vm_circuit_public_inputs.js'; +import { AvmCircuitPublicInputs } from '../avm/avm_circuit_public_inputs.js'; import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; import { VkWitnessData } from '../vk_witness_data.js'; export class AvmProofData { constructor( - public publicInputs: VMCircuitPublicInputs, + public publicInputs: AvmCircuitPublicInputs, public proof: RecursiveProof, public vkData: VkWitnessData, ) {} @@ -15,7 +15,7 @@ export class AvmProofData { static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); return new AvmProofData( - reader.readObject(VMCircuitPublicInputs), + reader.readObject(AvmCircuitPublicInputs), RecursiveProof.fromBuffer(reader), reader.readObject(VkWitnessData), ); @@ -27,7 +27,7 @@ export class AvmProofData { static empty() { return new AvmProofData( - VMCircuitPublicInputs.empty(), + AvmCircuitPublicInputs.empty(), makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS), VkWitnessData.empty(), ); diff --git a/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.test.ts b/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.test.ts new file mode 100644 index 00000000000..9d3280e89b4 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.test.ts @@ -0,0 +1,11 @@ +import { makePublicBaseRollupInputs } from '../../tests/factories.js'; +import { PublicBaseRollupInputs } from './public_base_rollup_inputs.js'; + +describe('PublicBaseRollupInputs', () => { + it('serializes to buffer and deserializes it back', () => { + const expected = makePublicBaseRollupInputs(); + const buffer = expected.toBuffer(); + const res = PublicBaseRollupInputs.fromBuffer(buffer); + expect(res).toEqual(expected); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts b/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts index a71d0261c57..7ca444204a7 100644 --- a/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts +++ b/yarn-project/circuits.js/src/structs/rollup/public_tube_data.ts @@ -1,20 +1,20 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { RECURSIVE_PROOF_LENGTH } from '../../constants.gen.js'; -import { KernelCircuitPublicInputs } from '../kernel/kernel_circuit_public_inputs.js'; +import { PrivateToPublicKernelCircuitPublicInputs } from '../kernel/private_to_public_kernel_circuit_public_inputs.js'; import { RecursiveProof, makeEmptyRecursiveProof } from '../recursive_proof.js'; import { VkWitnessData } from '../vk_witness_data.js'; export class PublicTubeData { constructor( - public publicInputs: KernelCircuitPublicInputs, + public publicInputs: PrivateToPublicKernelCircuitPublicInputs, public proof: RecursiveProof, public vkData: VkWitnessData, ) {} static empty() { return new PublicTubeData( - KernelCircuitPublicInputs.empty(), + PrivateToPublicKernelCircuitPublicInputs.empty(), makeEmptyRecursiveProof(RECURSIVE_PROOF_LENGTH), VkWitnessData.empty(), ); @@ -23,7 +23,7 @@ export class PublicTubeData { static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); return new PublicTubeData( - reader.readObject(KernelCircuitPublicInputs), + reader.readObject(PrivateToPublicKernelCircuitPublicInputs), RecursiveProof.fromBuffer(reader, RECURSIVE_PROOF_LENGTH), reader.readObject(VkWitnessData), ); diff --git a/yarn-project/circuits.js/src/structs/side_effects.ts b/yarn-project/circuits.js/src/structs/side_effects.ts deleted file mode 100644 index 1bbe54ce470..00000000000 --- a/yarn-project/circuits.js/src/structs/side_effects.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; - -/** - * Essential members and functions of all SideEffect variants - */ -export interface SideEffectType { - /** The actual value associated with the SideEffect */ - value: Fr; - /** The counter associated with the SideEffect */ - counter: Fr; - /** Convert to a buffer */ - toBuffer(): Buffer; - /** Convert to a field array */ - toFields(): Fr[]; - /** Are all of the fields of the SideEffect zero? */ - isEmpty(): boolean; -} - -/** - * Side-effect object consisting of a value and a counter. - * cpp/src/aztec3/circuits/abis/side_effects.hpp. - */ -export class SideEffect implements SideEffectType { - constructor( - /** - * The value of the side-effect object. - */ - public value: Fr, - /** - * The side-effect counter. - */ - public counter: Fr, - ) {} - - toString(): string { - return `value=${this.value.toString()} counter=${this.counter.toString()}`; - } - - /** - * Serialize this as a buffer. - * @returns The buffer. - */ - toBuffer(): Buffer { - return serializeToBuffer(this.value, this.counter); - } - - /** - * Convert to an array of fields. - * @returns The array of fields. - */ - toFields(): Fr[] { - return [this.value, this.counter]; - } - - static fromFields(fields: Fr[] | FieldReader): SideEffect { - const reader = FieldReader.asReader(fields); - return new SideEffect(reader.readField(), reader.readField()); - } - - /** - * Returns whether this instance of side-effect is empty. - * @returns True if the value and counter both are zero. - */ - isEmpty() { - return SideEffect.isEmpty(this); - } - - /** - * Checks whether this instance of side-effect is empty. - * @returns True if the value and counter both are zero. - */ - static isEmpty(sideEffect: SideEffect) { - return sideEffect.value.isZero() && sideEffect.counter.isZero(); - } - - /** - * Returns an empty instance of side-effect. - * @returns Side-effect with both value and counter being zero. - */ - static empty(): SideEffect { - return new SideEffect(Fr.zero(), Fr.zero()); - } - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param buffer - Buffer or reader to read from. - * @returns A new instance of SideEffect. - */ - static fromBuffer(buffer: Buffer | BufferReader): SideEffect { - const reader = BufferReader.asReader(buffer); - return new SideEffect(Fr.fromBuffer(reader), Fr.fromBuffer(reader)); - } -} diff --git a/yarn-project/circuits.js/src/structs/tree_snapshots.ts b/yarn-project/circuits.js/src/structs/tree_snapshots.ts new file mode 100644 index 00000000000..c55e24be1b5 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/tree_snapshots.ts @@ -0,0 +1,96 @@ +import { type Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { inspect } from 'util'; + +import { TREE_SNAPSHOTS_LENGTH } from '../constants.gen.js'; +import { AppendOnlyTreeSnapshot } from './rollup/append_only_tree_snapshot.js'; + +/** + * Stores snapshots of all the trees but archive. + */ +export class TreeSnapshots { + constructor( + public readonly l1ToL2MessageTree: AppendOnlyTreeSnapshot, + public readonly noteHashTree: AppendOnlyTreeSnapshot, + public readonly nullifierTree: AppendOnlyTreeSnapshot, + public readonly publicDataTree: AppendOnlyTreeSnapshot, + ) {} + + getSize() { + return ( + this.l1ToL2MessageTree.getSize() + + this.noteHashTree.getSize() + + this.nullifierTree.getSize() + + this.publicDataTree.getSize() + ); + } + + static fromBuffer(buffer: Buffer | BufferReader): TreeSnapshots { + const reader = BufferReader.asReader(buffer); + return new TreeSnapshots( + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + ); + } + + toBuffer() { + // Note: The order here must match the order in the HeaderLib solidity library. + return serializeToBuffer(this.l1ToL2MessageTree, this.noteHashTree, this.nullifierTree, this.publicDataTree); + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + + const l1ToL2MessageTree = AppendOnlyTreeSnapshot.fromFields(reader); + const noteHashTree = AppendOnlyTreeSnapshot.fromFields(reader); + const nullifierTree = AppendOnlyTreeSnapshot.fromFields(reader); + const publicDataTree = AppendOnlyTreeSnapshot.fromFields(reader); + + return new TreeSnapshots(l1ToL2MessageTree, noteHashTree, nullifierTree, publicDataTree); + } + + toFields(): Fr[] { + const fields = [ + ...this.l1ToL2MessageTree.toFields(), + ...this.noteHashTree.toFields(), + ...this.nullifierTree.toFields(), + ...this.publicDataTree.toFields(), + ]; + if (fields.length !== TREE_SNAPSHOTS_LENGTH) { + throw new Error( + `Invalid number of fields for TreeSnapshots. Expected ${TREE_SNAPSHOTS_LENGTH}, got ${fields.length}`, + ); + } + return fields; + } + + static empty(): TreeSnapshots { + return new TreeSnapshots( + AppendOnlyTreeSnapshot.zero(), + AppendOnlyTreeSnapshot.zero(), + AppendOnlyTreeSnapshot.zero(), + AppendOnlyTreeSnapshot.zero(), + ); + } + + isEmpty(): boolean { + return ( + this.l1ToL2MessageTree.isZero() && + this.noteHashTree.isZero() && + this.nullifierTree.isZero() && + this.publicDataTree.isZero() + ); + } + + [inspect.custom]() { + return `TreeSnapshots { + l1ToL2MessageTree: ${inspect(this.l1ToL2MessageTree)}, + noteHashTree: ${inspect(this.noteHashTree)}, + nullifierTree: ${inspect(this.nullifierTree)}, + publicDataTree: ${inspect(this.publicDataTree)}, +}`; + } +} diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index cfd4a469b2d..99851fe4554 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -48,6 +48,8 @@ import { LogHash, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_ENQUEUED_CALLS_PER_CALL, + MAX_ENQUEUED_CALLS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, @@ -66,8 +68,6 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_HINTS, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_TX, @@ -151,16 +151,24 @@ import { GasSettings } from '../structs/gas_settings.js'; import { GlobalVariables } from '../structs/global_variables.js'; import { Header } from '../structs/header.js'; import { + AvmAccumulatedData, + AvmCircuitPublicInputs, AvmContractBytecodeHints, AvmEnqueuedCallHint, AvmProofData, BaseRollupHints, + CountedPublicCallRequest, EnqueuedCallData, PrivateBaseRollupInputs, + PrivateToAvmAccumulatedData, + PrivateToAvmAccumulatedDataArrayLengths, + PrivateToPublicAccumulatedData, + PrivateToPublicKernelCircuitPublicInputs, PrivateTubeData, PublicAccumulatedDataArrayLengths, PublicBaseRollupInputs, PublicDataLeafHint, + PublicDataWrite, PublicInnerCallRequest, PublicKernelCircuitPrivateInputs, PublicKernelInnerCircuitPrivateInputs, @@ -172,6 +180,8 @@ import { ScopedNoteHash, TreeLeafReadRequest, TreeLeafReadRequestHint, + TreeSnapshots, + TxConstantData, VMCircuitPublicInputs, VkWitnessData, } from '../structs/index.js'; @@ -296,6 +306,10 @@ export function makeEmptyPublicDataUpdateRequest(): PublicDataUpdateRequest { return new PublicDataUpdateRequest(fr(0), fr(0), 0); } +function makePublicDataWrite(seed = 1) { + return new PublicDataWrite(fr(seed), fr(seed + 1)); +} + /** * Creates arbitrary public data read. * @param seed - The seed to use for generating the public data read. @@ -350,6 +364,10 @@ export function makeRollupValidationRequests(seed = 1) { return new RollupValidationRequests(new MaxBlockNumber(true, new Fr(seed + 0x31415))); } +function makeTxConstantData(seed = 1) { + return new TxConstantData(makeHeader(seed), makeTxContext(seed + 0x100), new Fr(seed + 0x200), new Fr(seed + 0x201)); +} + export function makeCombinedConstantData(seed = 1): CombinedConstantData { return new CombinedConstantData( makeHeader(seed), @@ -378,16 +396,46 @@ export function makeCombinedAccumulatedData(seed = 1, full = false): CombinedAcc fr(seed + 0xa00), // note_encrypted_log_preimages_length fr(seed + 0xb00), // encrypted_log_preimages_length fr(seed + 0xc00), // unencrypted_log_preimages_length - tupleGenerator( - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - makePublicDataUpdateRequest, - seed + 0xd00, - PublicDataUpdateRequest.empty, - ), + tupleGenerator(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataWrite, seed + 0xd00, PublicDataWrite.empty), makeGas(seed + 0xe00), ); } +export function makePrivateToPublicAccumulatedData(seed = 1) { + return new PrivateToPublicAccumulatedData( + makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed), + makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x100), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, makeScopedL2ToL1Message, seed + 0x200), + makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x700), + makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, makeScopedLogHash, seed + 0x800), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, makeScopedLogHash, seed + 0x900), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, makePublicCallRequest, seed + 0x500), + makeGas(seed + 0x600), + ); +} + +function makePrivateToAvmAccumulatedData(seed = 1) { + return new PrivateToAvmAccumulatedData( + makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed), + makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x100), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, makeScopedL2ToL1Message, seed + 0x200), + ); +} + +function makePrivateToAvmAccumulatedDataArrayLengths(seed = 1) { + return new PrivateToAvmAccumulatedDataArrayLengths(seed, seed + 1, seed + 2); +} + +function makeAvmAccumulatedData(seed = 1) { + return new AvmAccumulatedData( + makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed), + makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x100), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, makeScopedL2ToL1Message, seed + 0x200), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, makeScopedLogHash, seed + 0x300), + makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataWrite, seed + 0x400), + ); +} + export function makeGas(seed = 1) { return new Gas(seed, seed + 1); } @@ -413,7 +461,7 @@ function makePublicAccumulatedData(seed = 1, full = false): PublicAccumulatedDat seed + 0xd00, PublicDataUpdateRequest.empty, ), - tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makePublicCallRequest, seed + 0x500, PublicCallRequest.empty), + tupleGenerator(MAX_ENQUEUED_CALLS_PER_TX, makePublicCallRequest, seed + 0x500, PublicCallRequest.empty), makeGas(seed + 0x600), ); } @@ -484,12 +532,7 @@ export function makePublicCircuitPublicInputs( ContractStorageUpdateRequest.empty, ), tupleGenerator(MAX_PUBLIC_DATA_READS_PER_CALL, makeContractStorageRead, seed + 0x500, ContractStorageRead.empty), - tupleGenerator( - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - makePublicInnerCallRequest, - seed + 0x600, - PublicInnerCallRequest.empty, - ), + tupleGenerator(MAX_ENQUEUED_CALLS_PER_CALL, makePublicInnerCallRequest, seed + 0x600, PublicInnerCallRequest.empty), tupleGenerator(MAX_NOTE_HASHES_PER_CALL, makeNoteHash, seed + 0x700, NoteHash.empty), tupleGenerator(MAX_NULLIFIERS_PER_CALL, makeNullifier, seed + 0x800, Nullifier.empty), tupleGenerator(MAX_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x900, L2ToL1Message.empty), @@ -538,27 +581,34 @@ export function makePrivateKernelTailCircuitPublicInputs( ): PrivateKernelTailCircuitPublicInputs { const forPublic = isForPublic ? new PartialPrivateTailPublicInputsForPublic( - PublicValidationRequests.empty(), - makePublicAccumulatedData(seed + 0x100, false), - makePublicAccumulatedData(seed + 0x200, false), + makePrivateToPublicAccumulatedData(seed + 0x100), + makePrivateToPublicAccumulatedData(seed + 0x200), makePublicCallRequest(seed + 0x400), ) : undefined; const forRollup = !isForPublic - ? new PartialPrivateTailPublicInputsForRollup( - makeRollupValidationRequests(seed), - makeCombinedAccumulatedData(seed + 0x100), - ) + ? new PartialPrivateTailPublicInputsForRollup(makeCombinedAccumulatedData(seed + 0x100)) : undefined; return new PrivateKernelTailCircuitPublicInputs( - makeCombinedConstantData(seed + 0x300), - RevertCode.OK, + makeTxConstantData(seed + 0x300), + makeRollupValidationRequests(seed + 0x500), makeAztecAddress(seed + 0x700), forPublic, forRollup, ); } +function makePrivateToPublicKernelCircuitPublicInputs(seed = 1) { + return new PrivateToPublicKernelCircuitPublicInputs( + makeTxConstantData(seed), + makeRollupValidationRequests(seed + 0x100), + makePrivateToPublicAccumulatedData(seed + 0x200), + makePrivateToPublicAccumulatedData(seed + 0x300), + makePublicCallRequest(seed + 0x400), + makeAztecAddress(seed + 0x500), + ); +} + /** * Creates arbitrary public kernel circuit public inputs. * @param seed - The seed to use for generating the kernel circuit public inputs. @@ -579,7 +629,7 @@ export function makeVMCircuitPublicInputs(seed = 1) { return new VMCircuitPublicInputs( makeCombinedConstantData(seed), makePublicCallRequest(seed + 0x100), - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makePublicInnerCallRequest, seed + 0x200), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, makePublicInnerCallRequest, seed + 0x200), makePublicValidationRequestArrayLengths(seed + 0x300), makePublicValidationRequests(seed + 0x310), makePublicAccumulatedDataArrayLengths(seed + 0x400), @@ -592,6 +642,25 @@ export function makeVMCircuitPublicInputs(seed = 1) { ); } +function makeAvmCircuitPublicInputs(seed = 1) { + return new AvmCircuitPublicInputs( + makeGlobalVariables(seed), + makeTreeSnapshots(seed + 0x10), + makeGasSettings(), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, makePublicCallRequest, seed + 0x100), + makeTuple(MAX_ENQUEUED_CALLS_PER_TX, makePublicCallRequest, seed + 0x200), + makePublicCallRequest(seed + 0x300), + makePrivateToAvmAccumulatedDataArrayLengths(seed + 0x400), + makePrivateToAvmAccumulatedDataArrayLengths(seed + 0x410), + makePrivateToAvmAccumulatedData(seed + 0x500), + makePrivateToAvmAccumulatedData(seed + 0x600), + makeTreeSnapshots(seed + 0x700), + makeAvmAccumulatedData(seed + 0x800), + fr(seed + 0x700), + false, + ); +} + function makeSiblingPath(seed: number, size: N) { return makeTuple(size, fr, seed); } @@ -682,9 +751,18 @@ function makePublicCallStackItemCompressed(seed = 1): PublicCallStackItemCompres ); } -export function makePublicCallRequest(seed = 1): PublicCallRequest { - const callContext = makeCallContext(seed); - return new PublicCallRequest(callContext, fr(seed + 0x20), seed + 0x60); +export function makePublicCallRequest(seed = 1) { + return new PublicCallRequest( + makeAztecAddress(seed), + makeAztecAddress(seed + 1), + makeSelector(seed + 2), + false, + fr(seed + 0x3), + ); +} + +function makeCountedPublicCallRequest(seed = 1) { + return new CountedPublicCallRequest(makePublicCallRequest(seed), seed + 0x100); } function makePublicInnerCallRequest(seed = 1): PublicInnerCallRequest { @@ -792,7 +870,7 @@ export function makePrivateCircuitPublicInputs(seed = 0): PrivateCircuitPublicIn noteHashes: makeTuple(MAX_NOTE_HASHES_PER_CALL, makeNoteHash, seed + 0x400), nullifiers: makeTuple(MAX_NULLIFIERS_PER_CALL, makeNullifier, seed + 0x500), privateCallRequests: makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, makePrivateCallRequest, seed + 0x600), - publicCallRequests: makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, makePublicCallRequest, seed + 0x700), + publicCallRequests: makeTuple(MAX_ENQUEUED_CALLS_PER_CALL, makeCountedPublicCallRequest, seed + 0x700), publicTeardownCallRequest: makePublicCallRequest(seed + 0x800), l2ToL1Msgs: makeTuple(MAX_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x800), startSideEffectCounter: fr(seed + 0x849), @@ -1130,6 +1208,15 @@ export function makeStateReference(seed = 0): StateReference { return new StateReference(makeAppendOnlyTreeSnapshot(seed), makePartialStateReference(seed + 1)); } +function makeTreeSnapshots(seed = 0) { + return new TreeSnapshots( + makeAppendOnlyTreeSnapshot(seed), + makeAppendOnlyTreeSnapshot(seed + 0x10), + makeAppendOnlyTreeSnapshot(seed + 0x20), + makeAppendOnlyTreeSnapshot(seed + 0x30), + ); +} + /** * Makes arbitrary L2 to L1 message. * @param seed - The seed to use for generating the state reference. @@ -1296,9 +1383,9 @@ export function makePrivateBaseRollupInputs(seed = 0) { }); } -function makePublicTubeData(seed = 1, kernelPublicInputs?: KernelCircuitPublicInputs) { +function makePublicTubeData(seed = 1) { return new PublicTubeData( - kernelPublicInputs ?? makeKernelCircuitPublicInputs(seed, true), + makePrivateToPublicKernelCircuitPublicInputs(seed), makeRecursiveProof(TUBE_PROOF_LENGTH, seed + 0x100), makeVkWitnessData(seed + 0x200), ); @@ -1306,7 +1393,7 @@ function makePublicTubeData(seed = 1, kernelPublicInputs?: KernelCircuitPublicIn function makeAvmProofData(seed = 1) { return new AvmProofData( - makeVMCircuitPublicInputs(seed), + makeAvmCircuitPublicInputs(seed), makeRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS, seed + 0x100), makeVkWitnessData(seed + 0x200), ); @@ -1535,6 +1622,7 @@ export function makeAvmCircuitInputs(seed = 0, overrides: Partial new Fr(i), seed + 0x1000), publicInputs: makePublicCircuitPublicInputs(seed + 0x2000), avmHints: makeAvmExecutionHints(seed + 0x3000), + output: makeAvmCircuitPublicInputs(seed + 0x4000), ...overrides, }); } diff --git a/yarn-project/cli/src/utils/inspect.ts b/yarn-project/cli/src/utils/inspect.ts index 88479a30578..d1f635ae514 100644 --- a/yarn-project/cli/src/utils/inspect.ts +++ b/yarn-project/cli/src/utils/inspect.ts @@ -78,7 +78,7 @@ export async function inspectTx( if (writes.length > 0) { log(' Public data writes:'); for (const write of writes) { - log(` Leaf ${write.leafIndex.toString()} = ${write.newValue.toString()}`); + log(` Leaf ${write.leafSlot.toString()} = ${write.value.toString()}`); } } 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 bb2ad9bb0af..5f7c23936b6 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 @@ -1,41 +1,26 @@ import { type ArchiveSource } from '@aztec/archiver'; import { getConfigEnvVars } from '@aztec/aztec-node'; -import { - AztecAddress, - EthCheatCodes, - Fr, - GlobalVariables, - type L2Block, - createDebugLogger, - mockTx, -} from '@aztec/aztec.js'; +import { AztecAddress, EthCheatCodes, Fr, GlobalVariables, type L2Block, createDebugLogger } from '@aztec/aztec.js'; // eslint-disable-next-line no-restricted-imports import { type BlockBuilder, type MerkleTreeWriteOperations, type ProcessedTx, makeEmptyProcessedTx as makeEmptyProcessedTxFromHistoricalTreeRoots, - makeProcessedTx, } from '@aztec/circuit-types'; +import { makeBloatedProcessedTx } from '@aztec/circuit-types/test'; import { ETHEREUM_SLOT_DURATION, EthAddress, GENESIS_ARCHIVE_ROOT, GasFees, type Header, - KernelCircuitPublicInputs, - LogHash, - MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, - PublicDataUpdateRequest, - ScopedLogHash, } from '@aztec/circuits.js'; -import { fr, makeScopedL2ToL1Message } from '@aztec/circuits.js/testing'; +import { fr } from '@aztec/circuits.js/testing'; import { type L1ContractAddresses, createEthereumChain } from '@aztec/ethereum'; -import { makeTuple, range } from '@aztec/foundation/array'; +import { range } from '@aztec/foundation/array'; import { openTmpStore } from '@aztec/kv-store/utils'; import { OutboxAbi, RollupAbi } from '@aztec/l1-artifacts'; import { SHA256Trunc, StandardTree } from '@aztec/merkle-tree'; @@ -203,36 +188,16 @@ describe('L1Publisher integration', () => { protocolContractTreeRoot, ); - const makeBloatedProcessedTx = (seed = 0x1): ProcessedTx => { - const tx = mockTx(seed); - const kernelOutput = KernelCircuitPublicInputs.empty(); - kernelOutput.constants.txContext.chainId = fr(chainId); - kernelOutput.constants.txContext.version = fr(config.version); - kernelOutput.constants.vkTreeRoot = getVKTreeRoot(); - kernelOutput.constants.protocolContractTreeRoot = protocolContractTreeRoot; - kernelOutput.constants.historicalHeader = prevHeader; - kernelOutput.end.publicDataUpdateRequests = makeTuple( - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - i => new PublicDataUpdateRequest(fr(i), fr(i + 10), i + 20), - seed + 0x500, - ); - - const processedTx = makeProcessedTx(tx, kernelOutput); - - processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed + 0x100); - processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x200); - processedTx.data.end.nullifiers[processedTx.data.end.nullifiers.length - 1] = Fr.ZERO; - processedTx.data.end.l2ToL1Msgs = makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, makeScopedL2ToL1Message, seed + 0x300); - processedTx.encryptedLogs.unrollLogs().forEach((log, i) => { - processedTx.data.end.encryptedLogsHashes[i] = new ScopedLogHash( - new LogHash(Fr.fromBuffer(log.hash()), 0, new Fr(log.length)), - log.maskedContractAddress, - ); + const makeProcessedTx = (seed = 0x1): ProcessedTx => + makeBloatedProcessedTx({ + header: prevHeader, + chainId: fr(chainId), + version: fr(config.version), + vkTreeRoot: getVKTreeRoot(), + protocolContractTreeRoot, + seed, }); - return processedTx; - }; - const sendToL2 = (content: Fr, recipient: AztecAddress): Promise => { return sendL1ToL2Message( { content, secretHash: Fr.ZERO, recipient }, @@ -368,10 +333,10 @@ describe('L1Publisher integration', () => { // Ensure that each transaction has unique (non-intersecting nullifier values) const totalNullifiersPerBlock = 4 * MAX_NULLIFIERS_PER_TX; const txs = [ - makeBloatedProcessedTx(totalNullifiersPerBlock * i + 1 * MAX_NULLIFIERS_PER_TX), - makeBloatedProcessedTx(totalNullifiersPerBlock * i + 2 * MAX_NULLIFIERS_PER_TX), - makeBloatedProcessedTx(totalNullifiersPerBlock * i + 3 * MAX_NULLIFIERS_PER_TX), - makeBloatedProcessedTx(totalNullifiersPerBlock * i + 4 * MAX_NULLIFIERS_PER_TX), + makeProcessedTx(totalNullifiersPerBlock * i + 1 * MAX_NULLIFIERS_PER_TX), + makeProcessedTx(totalNullifiersPerBlock * i + 2 * MAX_NULLIFIERS_PER_TX), + makeProcessedTx(totalNullifiersPerBlock * i + 3 * MAX_NULLIFIERS_PER_TX), + makeProcessedTx(totalNullifiersPerBlock * i + 4 * MAX_NULLIFIERS_PER_TX), ]; const ts = (await publicClient.getBlock()).timestamp; diff --git a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts index 026a2e8602f..00a1c15d585 100644 --- a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts +++ b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts @@ -1,5 +1,4 @@ import { type AccountWallet, AztecAddress, BatchCall, Fr, TxStatus } from '@aztec/aztec.js'; -import { GasSettings } from '@aztec/circuits.js'; import { AvmInitializerTestContract, AvmTestContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -72,9 +71,9 @@ describe('e2e_avm_simulator', () => { it('Tracks L2 gas usage on simulation', async () => { const request = await avmContract.methods.add_args_return(20n, 30n).create(); const simulation = await wallet.simulateTx(request, true); - // Subtract the teardown gas allocation from the gas used to figure out the gas used by the contract logic. - const l2TeardownAllocation = GasSettings.simulation().getTeardownLimits().l2Gas; - const l2GasUsed = simulation.publicOutput!.end.gasUsed.l2Gas! - l2TeardownAllocation; + // Subtract the teardown gas from the total gas to figure out the gas used by the contract logic. + const l2TeardownGas = simulation.publicOutput!.gasUsed.teardownGas.l2Gas; + const l2GasUsed = simulation.publicOutput!.gasUsed.totalGas.l2Gas - l2TeardownGas; // L2 gas used will vary a lot depending on codegen and other factors, // so we just set a wide range for it, and check it's not a suspiciously round number. expect(l2GasUsed).toBeGreaterThan(150); diff --git a/yarn-project/end-to-end/src/e2e_max_block_number.test.ts b/yarn-project/end-to-end/src/e2e_max_block_number.test.ts index 16758ffc7ea..0c05164a2c1 100644 --- a/yarn-project/end-to-end/src/e2e_max_block_number.test.ts +++ b/yarn-project/end-to-end/src/e2e_max_block_number.test.ts @@ -29,8 +29,8 @@ describe('e2e_max_block_number', () => { it('sets the max block number', async () => { const tx = await contract.methods.set_tx_max_block_number(maxBlockNumber, enqueuePublicCall).prove(); - expect(tx.data.forRollup!.rollupValidationRequests.maxBlockNumber.isSome).toEqual(true); - expect(tx.data.forRollup!.rollupValidationRequests.maxBlockNumber.value).toEqual(new Fr(maxBlockNumber)); + expect(tx.data.rollupValidationRequests.maxBlockNumber.isSome).toEqual(true); + expect(tx.data.rollupValidationRequests.maxBlockNumber.value).toEqual(new Fr(maxBlockNumber)); }); it('does not invalidate the transaction', async () => { @@ -43,8 +43,8 @@ describe('e2e_max_block_number', () => { it('sets the max block number', async () => { const tx = await contract.methods.set_tx_max_block_number(maxBlockNumber, enqueuePublicCall).prove(); - expect(tx.data.forPublic!.validationRequests.forRollup.maxBlockNumber.isSome).toEqual(true); - expect(tx.data.forPublic!.validationRequests.forRollup.maxBlockNumber.value).toEqual(new Fr(maxBlockNumber)); + expect(tx.data.rollupValidationRequests.maxBlockNumber.isSome).toEqual(true); + expect(tx.data.rollupValidationRequests.maxBlockNumber.value).toEqual(new Fr(maxBlockNumber)); }); it('does not invalidate the transaction', async () => { @@ -65,8 +65,8 @@ describe('e2e_max_block_number', () => { it('sets the max block number', async () => { const tx = await contract.methods.set_tx_max_block_number(maxBlockNumber, enqueuePublicCall).prove(); - expect(tx.data.forRollup!.rollupValidationRequests.maxBlockNumber.isSome).toEqual(true); - expect(tx.data.forRollup!.rollupValidationRequests.maxBlockNumber.value).toEqual(new Fr(maxBlockNumber)); + expect(tx.data.rollupValidationRequests.maxBlockNumber.isSome).toEqual(true); + expect(tx.data.rollupValidationRequests.maxBlockNumber.value).toEqual(new Fr(maxBlockNumber)); }); it('invalidates the transaction', async () => { @@ -81,8 +81,8 @@ describe('e2e_max_block_number', () => { it('sets the max block number', async () => { const tx = await contract.methods.set_tx_max_block_number(maxBlockNumber, enqueuePublicCall).prove(); - expect(tx.data.forPublic!.validationRequests.forRollup.maxBlockNumber.isSome).toEqual(true); - expect(tx.data.forPublic!.validationRequests.forRollup.maxBlockNumber.value).toEqual(new Fr(maxBlockNumber)); + expect(tx.data.rollupValidationRequests.maxBlockNumber.isSome).toEqual(true); + expect(tx.data.rollupValidationRequests.maxBlockNumber.value).toEqual(new Fr(maxBlockNumber)); }); it('invalidates the transaction', async () => { diff --git a/yarn-project/end-to-end/src/e2e_ordering.test.ts b/yarn-project/end-to-end/src/e2e_ordering.test.ts index 4f7694256df..f87a10f6e9a 100644 --- a/yarn-project/end-to-end/src/e2e_ordering.test.ts +++ b/yarn-project/end-to-end/src/e2e_ordering.test.ts @@ -70,7 +70,7 @@ describe('e2e_ordering', () => { // The call stack items in the output of the kernel proof match the tx enqueuedPublicFunctionCalls enqueuedPublicCalls.forEach((c, i) => { - expect(c.isForCallRequest(tx.data.forPublic!.end.publicCallStack[i])).toBe(true); + expect(c.isForCallRequest(tx.data.forPublic!.revertibleAccumulatedData.publicCallRequests[i])).toBe(true); }); // The enqueued public calls are in the expected order based on the argument they set (stack is reversed!) diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index 90d89404194..c3130166f2c 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -265,10 +265,8 @@ describe('e2e_state_vars', () => { const tx = await authContract.methods.get_authorized_in_private().prove(); // The validity of our SharedMutable read request should be limited to 2 blocks - expect(tx.data.forRollup!.rollupValidationRequests.maxBlockNumber.isSome).toEqual(true); - expect(tx.data.forRollup!.rollupValidationRequests.maxBlockNumber.value).toEqual( - new Fr(expectedModifiedMaxBlockNumber), - ); + expect(tx.data.rollupValidationRequests.maxBlockNumber.isSome).toEqual(true); + expect(tx.data.rollupValidationRequests.maxBlockNumber.value).toEqual(new Fr(expectedModifiedMaxBlockNumber)); }); }); }); diff --git a/yarn-project/ivc-integration/src/avm_integration.test.ts b/yarn-project/ivc-integration/src/avm_integration.test.ts index e99bd685b08..400f4b5965d 100644 --- a/yarn-project/ivc-integration/src/avm_integration.test.ts +++ b/yarn-project/ivc-integration/src/avm_integration.test.ts @@ -8,6 +8,7 @@ import { } from '@aztec/bb-prover'; import { AvmCircuitInputs, + AvmCircuitPublicInputs, Gas, GlobalVariables, type PublicFunction, @@ -241,6 +242,7 @@ const proveAvmTestContract = async ( /*calldata=*/ context.environment.calldata, /*publicInputs=*/ getPublicInputs(pxResult), /*avmHints=*/ pxResult.avmCircuitHints, + AvmCircuitPublicInputs.empty(), ); // Then we prove. 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 0d1d9fd8037..d67d6ade8f6 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -3,6 +3,8 @@ import { AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, AZTEC_EPOCH_DURATION, AppendOnlyTreeSnapshot, + type AvmAccumulatedData, + type AvmCircuitPublicInputs, type AvmProofData, AztecAddress, BaseOrMergeRollupPublicInputs, @@ -18,6 +20,7 @@ import { ContentCommitment, type ContractStorageRead, type ContractStorageUpdateRequest, + CountedPublicCallRequest, type EmptyBlockRootRollupInputs, type EmptyNestedData, EncryptedLogHash, @@ -42,6 +45,7 @@ import { L2ToL1Message, LogHash, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_ENQUEUED_CALLS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, @@ -52,7 +56,6 @@ import { MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, @@ -91,6 +94,10 @@ import { type PrivateKernelEmptyInputs, type PrivateKernelResetHints, PrivateKernelTailCircuitPublicInputs, + type PrivateToAvmAccumulatedData, + type PrivateToAvmAccumulatedDataArrayLengths, + PrivateToPublicAccumulatedData, + type PrivateToPublicKernelCircuitPublicInputs, type PrivateTubeData, PrivateValidationRequests, PublicAccumulatedData, @@ -106,6 +113,7 @@ import { type PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, PublicDataUpdateRequest, + PublicDataWrite, PublicInnerCallRequest, type PublicKernelCircuitPrivateInputs, PublicKernelCircuitPublicInputs, @@ -141,6 +149,8 @@ import { type TransientDataIndexHint, TreeLeafReadRequest, type TreeLeafReadRequestHint, + type TreeSnapshots, + TxConstantData, TxContext, type TxRequest, VMCircuitPublicInputs, @@ -152,6 +162,8 @@ import { type Tuple, mapTuple, toTruncField } from '@aztec/foundation/serialize' import type { AppendOnlyTreeSnapshot as AppendOnlyTreeSnapshotNoir, + AvmAccumulatedData as AvmAccumulatedDataNoir, + AvmCircuitPublicInputs as AvmCircuitPublicInputsNoir, AvmProofData as AvmProofDataNoir, BaseOrMergeRollupPublicInputs as BaseOrMergeRollupPublicInputsNoir, BaseParityInputs as BaseParityInputsNoir, @@ -163,6 +175,7 @@ import type { CombinedConstantData as CombinedConstantDataNoir, ConstantRollupData as ConstantRollupDataNoir, ContentCommitment as ContentCommitmentNoir, + Counted as CountedPublicCallRequestNoir, EmptyBlockRootRollupInputs as EmptyBlockRootRollupInputsNoir, EmptyNestedCircuitPublicInputs as EmptyNestedDataNoir, EncryptedLogHash as EncryptedLogHashNoir, @@ -218,6 +231,10 @@ import type { PrivateKernelDataWithoutPublicInputs as PrivateKernelDataWithoutPublicInputsNoir, PrivateKernelEmptyPrivateInputs as PrivateKernelEmptyPrivateInputsNoir, PrivateKernelResetHints as PrivateKernelResetHintsNoir, + PrivateToAvmAccumulatedDataArrayLengths as PrivateToAvmAccumulatedDataArrayLengthsNoir, + PrivateToAvmAccumulatedData as PrivateToAvmAccumulatedDataNoir, + PrivateToPublicAccumulatedData as PrivateToPublicAccumulatedDataNoir, + PrivateToPublicKernelCircuitPublicInputs as PrivateToPublicKernelCircuitPublicInputsNoir, PrivateTubeData as PrivateTubeDataNoir, PrivateValidationRequests as PrivateValidationRequestsNoir, PublicAccumulatedDataArrayLengths as PublicAccumulatedDataArrayLengthsNoir, @@ -233,6 +250,7 @@ import type { PublicDataTreeLeaf as PublicDataTreeLeafNoir, PublicDataTreeLeafPreimage as PublicDataTreeLeafPreimageNoir, PublicDataUpdateRequest as PublicDataUpdateRequestNoir, + PublicDataWrite as PublicDataWriteNoir, PublicInnerCallRequest as PublicInnerCallRequestNoir, PublicKernelCircuitPublicInputs as PublicKernelCircuitPublicInputsNoir, PublicKernelData as PublicKernelDataNoir, @@ -265,6 +283,8 @@ import type { TransientDataIndexHint as TransientDataIndexHintNoir, TreeLeafReadRequestHint as TreeLeafReadRequestHintNoir, TreeLeafReadRequest as TreeLeafReadRequestNoir, + TreeSnapshots as TreeSnapshotsNoir, + TxConstantData as TxConstantDataNoir, TxContext as TxContextNoir, TxRequest as TxRequestNoir, VMCircuitPublicInputs as VMCircuitPublicInputsNoir, @@ -585,16 +605,31 @@ function mapPublicCallStackItemCompressedToNoir( function mapPublicCallRequestFromNoir(request: PublicCallRequestNoir) { return new PublicCallRequest( - mapCallContextFromNoir(request.call_context), + mapAztecAddressFromNoir(request.msg_sender), + mapAztecAddressFromNoir(request.contract_address), + mapFunctionSelectorFromNoir(request.function_selector), + request.is_static_call, mapFieldFromNoir(request.args_hash), - mapNumberFromNoir(request.counter), ); } function mapPublicCallRequestToNoir(request: PublicCallRequest): PublicCallRequestNoir { return { - call_context: mapCallContextToNoir(request.callContext), + msg_sender: mapAztecAddressToNoir(request.msgSender), + contract_address: mapAztecAddressToNoir(request.contractAddress), + function_selector: mapFunctionSelectorToNoir(request.functionSelector), + is_static_call: request.isStaticCall, args_hash: mapFieldToNoir(request.argsHash), + }; +} + +function mapCountedPublicCallRequestFromNoir(request: CountedPublicCallRequestNoir) { + return new CountedPublicCallRequest(mapPublicCallRequestFromNoir(request.inner), mapNumberFromNoir(request.counter)); +} + +function mapCountedPublicCallRequestToNoir(request: CountedPublicCallRequest): CountedPublicCallRequestNoir { + return { + inner: mapPublicCallRequestToNoir(request.inner), counter: mapNumberToNoir(request.counter), }; } @@ -963,7 +998,7 @@ export function mapPrivateCircuitPublicInputsToNoir( note_hashes: mapTuple(privateCircuitPublicInputs.noteHashes, mapNoteHashToNoir), nullifiers: mapTuple(privateCircuitPublicInputs.nullifiers, mapNullifierToNoir), private_call_requests: mapTuple(privateCircuitPublicInputs.privateCallRequests, mapPrivateCallRequestToNoir), - public_call_requests: mapTuple(privateCircuitPublicInputs.publicCallRequests, mapPublicCallRequestToNoir), + public_call_requests: mapTuple(privateCircuitPublicInputs.publicCallRequests, mapCountedPublicCallRequestToNoir), public_teardown_call_request: mapPublicCallRequestToNoir(privateCircuitPublicInputs.publicTeardownCallRequest), l2_to_l1_msgs: mapTuple(privateCircuitPublicInputs.l2ToL1Msgs, mapL2ToL1MessageToNoir), start_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.startSideEffectCounter), @@ -1087,6 +1122,17 @@ export function mapPublicDataUpdateRequestToNoir( }; } +function mapPublicDataWriteFromNoir(write: PublicDataWriteNoir) { + return new PublicDataWrite(mapFieldFromNoir(write.leaf_slot), mapFieldFromNoir(write.value)); +} + +function mapPublicDataWriteToNoir(write: PublicDataWrite): PublicDataWriteNoir { + return { + leaf_slot: mapFieldToNoir(write.leafSlot), + value: mapFieldToNoir(write.value), + }; +} + /** * Maps public data read from noir to the parsed type. * @param publicDataRead - The noir public data read. @@ -1358,8 +1404,8 @@ export function mapPrivateAccumulatedDataFromNoir( ), mapTupleFromNoir( privateAccumulatedData.public_call_requests, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - mapPublicCallRequestFromNoir, + MAX_ENQUEUED_CALLS_PER_TX, + mapCountedPublicCallRequestFromNoir, ), mapTupleFromNoir( privateAccumulatedData.private_call_stack, @@ -1377,7 +1423,7 @@ export function mapPrivateAccumulatedDataToNoir(data: PrivateAccumulatedData): P note_encrypted_logs_hashes: mapTuple(data.noteEncryptedLogsHashes, mapNoteLogHashToNoir), encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapScopedEncryptedLogHashToNoir), unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapScopedLogHashToNoir), - public_call_requests: mapTuple(data.publicCallRequests, mapPublicCallRequestToNoir), + public_call_requests: mapTuple(data.publicCallRequests, mapCountedPublicCallRequestToNoir), private_call_stack: mapTuple(data.privateCallStack, mapPrivateCallRequestToNoir), }; } @@ -1405,11 +1451,7 @@ export function mapPublicAccumulatedDataFromNoir( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, mapPublicDataUpdateRequestFromNoir, ), - mapTupleFromNoir( - publicAccumulatedData.public_call_stack, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - mapPublicCallRequestFromNoir, - ), + mapTupleFromNoir(publicAccumulatedData.public_call_stack, MAX_ENQUEUED_CALLS_PER_TX, mapPublicCallRequestFromNoir), mapGasFromNoir(publicAccumulatedData.gas_used), ); } @@ -1502,6 +1544,62 @@ export function mapMaxBlockNumberFromNoir(maxBlockNumber: MaxBlockNumberNoir): M return new MaxBlockNumber(maxBlockNumber._opt._is_some, mapFieldFromNoir(maxBlockNumber._opt._value)); } +function mapPrivateToPublicAccumulatedDataFromNoir(data: PrivateToPublicAccumulatedDataNoir) { + return new PrivateToPublicAccumulatedData( + mapTupleFromNoir(data.note_hashes, MAX_NOTE_HASHES_PER_TX, mapFieldFromNoir), + mapTupleFromNoir(data.nullifiers, MAX_NULLIFIERS_PER_TX, mapFieldFromNoir), + mapTupleFromNoir(data.l2_to_l1_msgs, MAX_L2_TO_L1_MSGS_PER_TX, mapScopedL2ToL1MessageFromNoir), + mapTupleFromNoir(data.note_encrypted_logs_hashes, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, mapLogHashFromNoir), + mapTupleFromNoir(data.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapScopedLogHashFromNoir), + mapTupleFromNoir(data.unencrypted_logs_hashes, MAX_UNENCRYPTED_LOGS_PER_TX, mapScopedLogHashFromNoir), + mapTupleFromNoir(data.public_call_requests, MAX_ENQUEUED_CALLS_PER_TX, mapPublicCallRequestFromNoir), + mapGasFromNoir(data.gas_used), + ); +} + +function mapPrivateToPublicAccumulatedDataToNoir( + data: PrivateToPublicAccumulatedData, +): PrivateToPublicAccumulatedDataNoir { + return { + note_hashes: mapTuple(data.noteHashes, mapFieldToNoir), + nullifiers: mapTuple(data.nullifiers, mapFieldToNoir), + l2_to_l1_msgs: mapTuple(data.l2ToL1Msgs, mapScopedL2ToL1MessageToNoir), + note_encrypted_logs_hashes: mapTuple(data.noteEncryptedLogsHashes, mapLogHashToNoir), + encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapScopedLogHashToNoir), + unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapScopedLogHashToNoir), + public_call_requests: mapTuple(data.publicCallRequests, mapPublicCallRequestToNoir), + gas_used: mapGasToNoir(data.gasUsed), + }; +} + +function mapPrivateToAvmAccumulatedDataToNoir(data: PrivateToAvmAccumulatedData): PrivateToAvmAccumulatedDataNoir { + return { + note_hashes: mapTuple(data.noteHashes, mapFieldToNoir), + nullifiers: mapTuple(data.nullifiers, mapFieldToNoir), + l2_to_l1_msgs: mapTuple(data.l2ToL1Msgs, mapScopedL2ToL1MessageToNoir), + }; +} + +function mapPrivateToAvmAccumulatedDataArrayLengthsToNoir( + data: PrivateToAvmAccumulatedDataArrayLengths, +): PrivateToAvmAccumulatedDataArrayLengthsNoir { + return { + note_hashes: mapNumberToNoir(data.noteHashes), + nullifiers: mapNumberToNoir(data.nullifiers), + l2_to_l1_msgs: mapNumberToNoir(data.l2ToL1Msgs), + }; +} + +function mapAvmAccumulatedDataToNoir(data: AvmAccumulatedData): AvmAccumulatedDataNoir { + return { + note_hashes: mapTuple(data.noteHashes, mapFieldToNoir), + nullifiers: mapTuple(data.nullifiers, mapFieldToNoir), + l2_to_l1_msgs: mapTuple(data.l2ToL1Msgs, mapScopedL2ToL1MessageToNoir), + unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapScopedLogHashToNoir), + public_data_writes: mapTuple(data.publicDataWrites, mapPublicDataWriteToNoir), + }; +} + /** * Maps combined accumulated data from noir to the parsed type. * @param combinedAccumulatedData - The noir combined accumulated data. @@ -1533,9 +1631,9 @@ export function mapCombinedAccumulatedDataFromNoir( mapFieldFromNoir(combinedAccumulatedData.encrypted_log_preimages_length), mapFieldFromNoir(combinedAccumulatedData.unencrypted_log_preimages_length), mapTupleFromNoir( - combinedAccumulatedData.public_data_update_requests, + combinedAccumulatedData.public_data_writes, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - mapPublicDataUpdateRequestFromNoir, + mapPublicDataWriteFromNoir, ), mapGasFromNoir(combinedAccumulatedData.gas_used), ); @@ -1554,20 +1652,30 @@ export function mapCombinedAccumulatedDataToNoir( note_encrypted_log_preimages_length: mapFieldToNoir(combinedAccumulatedData.noteEncryptedLogPreimagesLength), encrypted_log_preimages_length: mapFieldToNoir(combinedAccumulatedData.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(combinedAccumulatedData.unencryptedLogPreimagesLength), - public_data_update_requests: mapTuple( - combinedAccumulatedData.publicDataUpdateRequests, - mapPublicDataUpdateRequestToNoir, - ), + public_data_writes: mapTuple(combinedAccumulatedData.publicDataWrites, mapPublicDataWriteToNoir), gas_used: mapGasToNoir(combinedAccumulatedData.gasUsed), }; } -/** - * Maps combined constant data from noir to the parsed type. - * @param combinedConstantData - The noir combined constant data. - * @returns The parsed combined constant data. - */ -export function mapCombinedConstantDataFromNoir(combinedConstantData: CombinedConstantDataNoir): CombinedConstantData { +function mapTxConstantDataFromNoir(data: TxConstantDataNoir) { + return new TxConstantData( + mapHeaderFromNoir(data.historical_header), + mapTxContextFromNoir(data.tx_context), + mapFieldFromNoir(data.vk_tree_root), + mapFieldFromNoir(data.protocol_contract_tree_root), + ); +} + +function mapTxConstantDataToNoir(data: TxConstantData): TxConstantDataNoir { + return { + historical_header: mapHeaderToNoir(data.historicalHeader), + tx_context: mapTxContextToNoir(data.txContext), + vk_tree_root: mapFieldToNoir(data.vkTreeRoot), + protocol_contract_tree_root: mapFieldToNoir(data.protocolContractTreeRoot), + }; +} + +function mapCombinedConstantDataFromNoir(combinedConstantData: CombinedConstantDataNoir): CombinedConstantData { return new CombinedConstantData( mapHeaderFromNoir(combinedConstantData.historical_header), mapTxContextFromNoir(combinedConstantData.tx_context), @@ -1577,12 +1685,7 @@ export function mapCombinedConstantDataFromNoir(combinedConstantData: CombinedCo ); } -/** - * Maps combined constant data to noir combined constant data. - * @param combinedConstantData - The combined constant data. - * @returns The noir combined constant data. - */ -export function mapCombinedConstantDataToNoir(combinedConstantData: CombinedConstantData): CombinedConstantDataNoir { +function mapCombinedConstantDataToNoir(combinedConstantData: CombinedConstantData): CombinedConstantDataNoir { return { historical_header: mapHeaderToNoir(combinedConstantData.historicalHeader), tx_context: mapTxContextToNoir(combinedConstantData.txContext), @@ -1607,6 +1710,19 @@ export function mapPublicKernelCircuitPublicInputsToNoir( }; } +export function mapPrivateToPublicKernelCircuitPublicInputsToNoir( + inputs: PrivateToPublicKernelCircuitPublicInputs, +): PrivateToPublicKernelCircuitPublicInputsNoir { + return { + constants: mapTxConstantDataToNoir(inputs.constants), + rollup_validation_requests: mapRollupValidationRequestsToNoir(inputs.rollupValidationRequests), + non_revertible_accumulated_data: mapPrivateToPublicAccumulatedDataToNoir(inputs.nonRevertibleAccumulatedData), + revertible_accumulated_data: mapPrivateToPublicAccumulatedDataToNoir(inputs.revertibleAccumulatedData), + public_teardown_call_request: mapPublicCallRequestToNoir(inputs.publicTeardownCallRequest), + fee_payer: mapAztecAddressToNoir(inputs.feePayer), + }; +} + export function mapKernelCircuitPublicInputsFromNoir(inputs: KernelCircuitPublicInputsNoir) { return new KernelCircuitPublicInputs( mapRollupValidationRequestsFromNoir(inputs.rollup_validation_requests), @@ -1677,10 +1793,10 @@ export function mapPrivateKernelCircuitPublicInputsFromNoir( inputs: PrivateKernelCircuitPublicInputsNoir, ): PrivateKernelCircuitPublicInputs { return new PrivateKernelCircuitPublicInputs( + mapTxConstantDataFromNoir(inputs.constants), mapFieldFromNoir(inputs.min_revertible_side_effect_counter), mapPrivateValidationRequestsFromNoir(inputs.validation_requests), mapPrivateAccumulatedDataFromNoir(inputs.end), - mapCombinedConstantDataFromNoir(inputs.constants), mapPublicCallRequestFromNoir(inputs.public_teardown_call_request), mapAztecAddressFromNoir(inputs.fee_payer), ); @@ -1690,7 +1806,7 @@ export function mapPrivateKernelCircuitPublicInputsToNoir( inputs: PrivateKernelCircuitPublicInputs, ): PrivateKernelCircuitPublicInputsNoir { return { - constants: mapCombinedConstantDataToNoir(inputs.constants), + constants: mapTxConstantDataToNoir(inputs.constants), validation_requests: mapPrivateValidationRequestsToNoir(inputs.validationRequests), end: mapPrivateAccumulatedDataToNoir(inputs.end), min_revertible_side_effect_counter: mapFieldToNoir(inputs.minRevertibleSideEffectCounter), @@ -1717,13 +1833,10 @@ export function mapPrivateKernelDataToNoir( export function mapPrivateKernelTailCircuitPublicInputsForRollupFromNoir( inputs: KernelCircuitPublicInputsNoir, ): PrivateKernelTailCircuitPublicInputs { - const forRollup = new PartialPrivateTailPublicInputsForRollup( - mapRollupValidationRequestsFromNoir(inputs.rollup_validation_requests), - mapCombinedAccumulatedDataFromNoir(inputs.end), - ); + const forRollup = new PartialPrivateTailPublicInputsForRollup(mapCombinedAccumulatedDataFromNoir(inputs.end)); return new PrivateKernelTailCircuitPublicInputs( - mapCombinedConstantDataFromNoir(inputs.constants), - mapRevertCodeFromNoir(inputs.revert_code), + mapTxConstantDataFromNoir(inputs.constants), + mapRollupValidationRequestsFromNoir(inputs.rollup_validation_requests), mapAztecAddressFromNoir(inputs.fee_payer), undefined, forRollup, @@ -1731,17 +1844,16 @@ export function mapPrivateKernelTailCircuitPublicInputsForRollupFromNoir( } export function mapPrivateKernelTailCircuitPublicInputsForPublicFromNoir( - inputs: PublicKernelCircuitPublicInputsNoir, + inputs: PrivateToPublicKernelCircuitPublicInputsNoir, ): PrivateKernelTailCircuitPublicInputs { const forPublic = new PartialPrivateTailPublicInputsForPublic( - mapPublicValidationRequestsFromNoir(inputs.validation_requests), - mapPublicAccumulatedDataFromNoir(inputs.end_non_revertible), - mapPublicAccumulatedDataFromNoir(inputs.end), + mapPrivateToPublicAccumulatedDataFromNoir(inputs.non_revertible_accumulated_data), + mapPrivateToPublicAccumulatedDataFromNoir(inputs.revertible_accumulated_data), mapPublicCallRequestFromNoir(inputs.public_teardown_call_request), ); return new PrivateKernelTailCircuitPublicInputs( - mapCombinedConstantDataFromNoir(inputs.constants), - mapRevertCodeFromNoir(inputs.revert_code), + mapTxConstantDataFromNoir(inputs.constants), + mapRollupValidationRequestsFromNoir(inputs.rollup_validation_requests), mapAztecAddressFromNoir(inputs.fee_payer), forPublic, ); @@ -2078,7 +2190,7 @@ export function mapVMCircuitPublicInputsFromNoir(inputs: VMCircuitPublicInputsNo return new VMCircuitPublicInputs( mapCombinedConstantDataFromNoir(inputs.constants), mapPublicCallRequestFromNoir(inputs.call_request), - mapTupleFromNoir(inputs.public_call_stack, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, mapPublicInnerCallRequestFromNoir), + mapTupleFromNoir(inputs.public_call_stack, MAX_ENQUEUED_CALLS_PER_TX, mapPublicInnerCallRequestFromNoir), mapPublicValidationRequestArrayLengthsFromNoir(inputs.previous_validation_request_array_lengths), mapPublicValidationRequestsFromNoir(inputs.validation_requests), mapPublicAccumulatedDataArrayLengthsFromNoir(inputs.previous_accumulated_data_array_lengths), @@ -2098,6 +2210,33 @@ function mapEnqueuedCallDataToNoir(enqueuedCallData: EnqueuedCallData): Enqueued }; } +function mapAvmCircuitPublicInputsToNoir(inputs: AvmCircuitPublicInputs): AvmCircuitPublicInputsNoir { + return { + global_variables: mapGlobalVariablesToNoir(inputs.globalVariables), + start_tree_snapshots: mapTreeSnapshotsToNoir(inputs.startTreeSnapshots), + gas_settings: mapGasSettingsToNoir(inputs.gasSettings), + public_setup_call_requests: mapTuple(inputs.publicSetupCallRequests, mapPublicCallRequestToNoir), + public_app_logic_call_requests: mapTuple(inputs.publicAppLogicCallRequests, mapPublicCallRequestToNoir), + public_teardown_call_request: mapPublicCallRequestToNoir(inputs.publicTeardownCallRequest), + previous_non_revertible_accumulated_data_array_lengths: mapPrivateToAvmAccumulatedDataArrayLengthsToNoir( + inputs.previousNonRevertibleAccumulatedDataArrayLengths, + ), + previous_revertible_accumulated_data_array_lengths: mapPrivateToAvmAccumulatedDataArrayLengthsToNoir( + inputs.previousRevertibleAccumulatedDataArrayLengths, + ), + previous_non_revertible_accumulated_data: mapPrivateToAvmAccumulatedDataToNoir( + inputs.previousNonRevertibleAccumulatedData, + ), + previous_revertible_accumulated_data: mapPrivateToAvmAccumulatedDataToNoir( + inputs.previousRevertibleAccumulatedData, + ), + end_tree_snapshots: mapTreeSnapshotsToNoir(inputs.endTreeSnapshots), + accumulated_data: mapAvmAccumulatedDataToNoir(inputs.accumulatedData), + transaction_fee: mapFieldToNoir(inputs.transactionFee), + reverted: inputs.reverted, + }; +} + /** * Maps a base or merge rollup public inputs from noir to the circuits.js type. * @param baseOrMergeRollupPublicInputs - The noir base or merge rollup public inputs. @@ -2426,6 +2565,24 @@ export function mapPartialStateReferenceFromNoir( ); } +function mapTreeSnapshotsToNoir(snapshots: TreeSnapshots): TreeSnapshotsNoir { + return { + l1_to_l2_message_tree: mapAppendOnlyTreeSnapshotToNoir(snapshots.l1ToL2MessageTree), + note_hash_tree: mapAppendOnlyTreeSnapshotToNoir(snapshots.noteHashTree), + nullifier_tree: mapAppendOnlyTreeSnapshotToNoir(snapshots.nullifierTree), + public_data_tree: mapAppendOnlyTreeSnapshotToNoir(snapshots.publicDataTree), + }; +} + +// function mapTreeSnapshotsFromNoir(snapshots: TreeSnapshotsNoir) { +// return new TreeSnapshots( +// mapAppendOnlyTreeSnapshotFromNoir(snapshots.l1_to_l2_message_tree), +// mapAppendOnlyTreeSnapshotFromNoir(snapshots.note_hash_tree), +// mapAppendOnlyTreeSnapshotFromNoir(snapshots.nullifier_tree), +// mapAppendOnlyTreeSnapshotFromNoir(snapshots.public_data_tree), +// ); +// } + /** * Maps the merge rollup inputs to noir. * @param mergeRollupInputs - The circuits.js merge rollup inputs. @@ -2599,7 +2756,7 @@ export function mapPrivateBaseRollupInputsToNoir(inputs: PrivateBaseRollupInputs function mapPublicTubeDataToNoir(data: PublicTubeData): PublicTubeDataNoir { return { - public_inputs: mapKernelCircuitPublicInputsToNoir(data.publicInputs), + public_inputs: mapPrivateToPublicKernelCircuitPublicInputsToNoir(data.publicInputs), proof: mapRecursiveProofToNoir(data.proof), vk_data: mapVkWitnessDataToNoir(data.vkData, HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS), }; @@ -2607,7 +2764,7 @@ function mapPublicTubeDataToNoir(data: PublicTubeData): PublicTubeDataNoir { function mapAvmProofDataToNoir(data: AvmProofData): AvmProofDataNoir { return { - public_inputs: mapVMCircuitPublicInputsToNoir(data.publicInputs), + public_inputs: mapAvmCircuitPublicInputsToNoir(data.publicInputs), proof: mapRecursiveProofToNoir(data.proof), vk_data: mapVkWitnessDataToNoir(data.vkData, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS), }; diff --git a/yarn-project/p2p/src/tx_validator/data_validator.test.ts b/yarn-project/p2p/src/tx_validator/data_validator.test.ts index 729e7818b66..6b7f42859f6 100644 --- a/yarn-project/p2p/src/tx_validator/data_validator.test.ts +++ b/yarn-project/p2p/src/tx_validator/data_validator.test.ts @@ -29,8 +29,8 @@ describe('TxDataValidator', () => { it('rejects txs with mismatch non revertible execution requests', async () => { const goodTxs = mockTxs(3); const badTxs = mockTxs(2); - badTxs[0].data.forPublic!.endNonRevertibleData.publicCallStack[0].argsHash = Fr.random(); - badTxs[1].data.forPublic!.endNonRevertibleData.publicCallStack[1].callContext.contractAddress = + badTxs[0].data.forPublic!.nonRevertibleAccumulatedData.publicCallRequests[0].argsHash = Fr.random(); + badTxs[1].data.forPublic!.nonRevertibleAccumulatedData.publicCallRequests[1].contractAddress = AztecAddress.random(); await expect(validator.validateTxs([...goodTxs, ...badTxs])).resolves.toEqual([goodTxs, badTxs]); @@ -39,10 +39,11 @@ describe('TxDataValidator', () => { it('rejects txs with mismatch revertible execution requests', async () => { const goodTxs = mockTxs(3); const badTxs = mockTxs(4); - badTxs[0].data.forPublic!.end.publicCallStack[0].callContext.msgSender = AztecAddress.random(); - badTxs[1].data.forPublic!.end.publicCallStack[1].callContext.contractAddress = AztecAddress.random(); - badTxs[2].data.forPublic!.end.publicCallStack[0].callContext.functionSelector = FunctionSelector.random(); - badTxs[3].data.forPublic!.end.publicCallStack[0].callContext.isStaticCall = + badTxs[0].data.forPublic!.revertibleAccumulatedData.publicCallRequests[0].msgSender = AztecAddress.random(); + badTxs[1].data.forPublic!.revertibleAccumulatedData.publicCallRequests[1].contractAddress = AztecAddress.random(); + badTxs[2].data.forPublic!.revertibleAccumulatedData.publicCallRequests[0].functionSelector = + FunctionSelector.random(); + badTxs[3].data.forPublic!.revertibleAccumulatedData.publicCallRequests[0].isStaticCall = !badTxs[3].enqueuedPublicFunctionCalls[0].callContext.isStaticCall; await expect(validator.validateTxs([...badTxs, ...goodTxs])).resolves.toEqual([goodTxs, badTxs]); @@ -51,8 +52,8 @@ describe('TxDataValidator', () => { it('rejects txs with mismatch teardown execution requests', async () => { const goodTxs = mockTxs(3); const badTxs = mockTxs(2); - badTxs[0].data.forPublic!.publicTeardownCallRequest.callContext.contractAddress = AztecAddress.random(); - badTxs[1].data.forPublic!.publicTeardownCallRequest.callContext.msgSender = AztecAddress.random(); + badTxs[0].data.forPublic!.publicTeardownCallRequest.contractAddress = AztecAddress.random(); + badTxs[1].data.forPublic!.publicTeardownCallRequest.msgSender = AztecAddress.random(); await expect(validator.validateTxs([...goodTxs, ...badTxs])).resolves.toEqual([goodTxs, badTxs]); }); diff --git a/yarn-project/p2p/src/tx_validator/double_spend_validator.test.ts b/yarn-project/p2p/src/tx_validator/double_spend_validator.test.ts index cdca2861578..1c123319f33 100644 --- a/yarn-project/p2p/src/tx_validator/double_spend_validator.test.ts +++ b/yarn-project/p2p/src/tx_validator/double_spend_validator.test.ts @@ -34,7 +34,8 @@ describe('DoubleSpendTxValidator', () => { numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, }); - badTx.data.forPublic!.end.nullifiers[0] = badTx.data.forPublic!.endNonRevertibleData.nullifiers[0]; + badTx.data.forPublic!.revertibleAccumulatedData.nullifiers[0] = + badTx.data.forPublic!.nonRevertibleAccumulatedData.nullifiers[0]; await expect(txValidator.validateTxs([badTx])).resolves.toEqual([[], [badTx]]); }); diff --git a/yarn-project/p2p/src/tx_validator/double_spend_validator.ts b/yarn-project/p2p/src/tx_validator/double_spend_validator.ts index 15ba9f76d27..8556359150a 100644 --- a/yarn-project/p2p/src/tx_validator/double_spend_validator.ts +++ b/yarn-project/p2p/src/tx_validator/double_spend_validator.ts @@ -36,7 +36,9 @@ export class DoubleSpendTxValidator implements TxValidator { } async #uniqueNullifiers(tx: AnyTx, thisBlockNullifiers: Set): Promise { - const nullifiers = tx.data.getNonEmptyNullifiers().map(x => x.toBigInt()); + const nullifiers = (tx instanceof Tx ? tx.data.getNonEmptyNullifiers() : tx.txEffect.nullifiers).map(x => + x.toBigInt(), + ); // Ditch this tx if it has repeated nullifiers const uniqueNullifiers = new Set(nullifiers); diff --git a/yarn-project/p2p/src/tx_validator/metadata_validator.test.ts b/yarn-project/p2p/src/tx_validator/metadata_validator.test.ts index 261618f2a3e..211d4ad0e66 100644 --- a/yarn-project/p2p/src/tx_validator/metadata_validator.test.ts +++ b/yarn-project/p2p/src/tx_validator/metadata_validator.test.ts @@ -32,7 +32,7 @@ describe('MetadataTxValidator', () => { it.each([42, 43])('allows txs with valid max block number', async maxBlockNumber => { const goodTx = mockTxForRollup(1); goodTx.data.constants.txContext.chainId = chainId; - goodTx.data.forRollup!.rollupValidationRequests.maxBlockNumber = new MaxBlockNumber(true, new Fr(maxBlockNumber)); + goodTx.data.rollupValidationRequests.maxBlockNumber = new MaxBlockNumber(true, new Fr(maxBlockNumber)); await expect(validator.validateTxs([goodTx])).resolves.toEqual([[goodTx], []]); }); @@ -40,7 +40,7 @@ describe('MetadataTxValidator', () => { it('allows txs with unset max block number', async () => { const goodTx = mockTxForRollup(1); goodTx.data.constants.txContext.chainId = chainId; - goodTx.data.forRollup!.rollupValidationRequests.maxBlockNumber = new MaxBlockNumber(false, Fr.ZERO); + goodTx.data.rollupValidationRequests.maxBlockNumber = new MaxBlockNumber(false, Fr.ZERO); await expect(validator.validateTxs([goodTx])).resolves.toEqual([[goodTx], []]); }); @@ -48,10 +48,7 @@ describe('MetadataTxValidator', () => { it('rejects txs with lower max block number', async () => { const badTx = mockTxForRollup(1); badTx.data.constants.txContext.chainId = chainId; - badTx.data.forRollup!.rollupValidationRequests.maxBlockNumber = new MaxBlockNumber( - true, - blockNumber.sub(new Fr(1)), - ); + badTx.data.rollupValidationRequests.maxBlockNumber = new MaxBlockNumber(true, blockNumber.sub(new Fr(1))); await expect(validator.validateTxs([badTx])).resolves.toEqual([[], [badTx]]); }); }); diff --git a/yarn-project/p2p/src/tx_validator/metadata_validator.ts b/yarn-project/p2p/src/tx_validator/metadata_validator.ts index 995e61cdb00..3629e400c91 100644 --- a/yarn-project/p2p/src/tx_validator/metadata_validator.ts +++ b/yarn-project/p2p/src/tx_validator/metadata_validator.ts @@ -45,11 +45,7 @@ export class MetadataTxValidator implements TxValidator { } #isValidForBlockNumber(tx: T): boolean { - const target = - tx instanceof Tx - ? tx.data.forRollup?.rollupValidationRequests || tx.data.forPublic!.validationRequests.forRollup - : tx.data.rollupValidationRequests; - const maxBlockNumber = target.maxBlockNumber; + const maxBlockNumber = tx.data.rollupValidationRequests.maxBlockNumber; if (maxBlockNumber.isSome && maxBlockNumber.value < this.blockNumber) { this.#log.warn( diff --git a/yarn-project/protocol-contracts/src/protocol_contract_data.ts b/yarn-project/protocol-contracts/src/protocol_contract_data.ts index 3e901637877..7eb1cdc3397 100644 --- a/yarn-project/protocol-contracts/src/protocol_contract_data.ts +++ b/yarn-project/protocol-contracts/src/protocol_contract_data.ts @@ -50,14 +50,14 @@ export const ProtocolContractAddress: Record }; export const ProtocolContractLeaf = { - AuthRegistry: Fr.fromString('0x00d6c808f3c8a78645cce0ba37e17837da720d37a42d30814ce3aa80bb273e53'), - ContractInstanceDeployer: Fr.fromString('0x144e518ae79c22843ce5736fa723cbc072b93cb4508500f779037d5114c88310'), - ContractClassRegisterer: Fr.fromString('0x0503a6a49c9671be4b6d03be3db2bb36440631062755c776e9838e05a9afb1bd'), - MultiCallEntrypoint: Fr.fromString('0x2be4d47f4c42bf7c74e75387229c8e0cc89d0d086449122a5265abdf5ea70129'), - FeeJuice: Fr.fromString('0x1a47084d9b143a50a18292b2677588b3d575a473a0edc11466696f5e1f434fb1'), - Router: Fr.fromString('0x26d7b664d410b94a7b0543defc361669cae93382087d92f875a411910c695167'), + AuthRegistry: Fr.fromString('0x0931f3bf89563f3898ae9650851083cd560ad800c2e3c561c3853eec4dd7ea8b'), + ContractInstanceDeployer: Fr.fromString('0x266ea4c9917455daa905c1dd1a10753714c6d0369b6f2fe23feeca6de556d164'), + ContractClassRegisterer: Fr.fromString('0x1ccb7a219f72a851089e956d527997b01068d5a28c9ae96b35ebeb45f068af23'), + MultiCallEntrypoint: Fr.fromString('0x1d060217817cf472a579638db722903fd1bbc4c3bdb0ecefa5694c0d4eed851a'), + FeeJuice: Fr.fromString('0x1dab5b687d0c04d2f17a1c8623dea23e7416700891ba1c6e0e86ef678f4727cb'), + Router: Fr.fromString('0x00827d5a8aedb9627d9e5de04735600a4dbb817d4a2f51281aab991699f5de99'), }; export const protocolContractTreeRoot = Fr.fromString( - '0x141e7aceb024c6b5aa82f9d5a9da7207bdb2953679674a5ee306290a193d674c', + '0x0f174f6837842b1004a9a41dd736800c12c5dc19f206aed35551b07f8ca6edfb', ); diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index fd7fa1d80e6..a3b507b13b8 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -3,9 +3,8 @@ import { type MerkleTreeReadOperations, type MerkleTreeWriteOperations, type ProcessedTx, - makeEmptyProcessedTx as makeEmptyProcessedTxFromHistoricalTreeRoots, } from '@aztec/circuit-types'; -import { makeBloatedProcessedTx as makeBloatedProcessedTxWithVKRoot } from '@aztec/circuit-types/test'; +import { makeBloatedProcessedTx } from '@aztec/circuit-types/test'; import { AztecAddress, EthAddress, @@ -14,9 +13,10 @@ import { GlobalVariables, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT, - PublicDataTreeLeaf, + PublicDataWrite, } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; import { randomBytes } from '@aztec/foundation/crypto'; @@ -97,49 +97,28 @@ export async function getSimulationProvider( return new WASMSimulator(); } -export const makeBloatedProcessedTx = (builderDb: MerkleTreeReadOperations, seed = 0x1) => - makeBloatedProcessedTxWithVKRoot(builderDb, getVKTreeRoot(), protocolContractTreeRoot, seed); - -export const makeEmptyProcessedTx = (builderDb: MerkleTreeReadOperations, chainId: Fr, version: Fr) => { - const header = builderDb.getInitialHeader(); - return makeEmptyProcessedTxFromHistoricalTreeRoots( - header, - chainId, - version, - getVKTreeRoot(), - protocolContractTreeRoot, - ); -}; +export const makeBloatedProcessedTxWithVKRoot = (builderDb: MerkleTreeReadOperations, seed = 0x1) => + makeBloatedProcessedTx({ db: builderDb, vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, seed }); // Updates the expectedDb trees based on the new note hashes, contracts, and nullifiers from these txs export const updateExpectedTreesFromTxs = async (db: MerkleTreeWriteOperations, txs: ProcessedTx[]) => { await db.appendLeaves( MerkleTreeId.NOTE_HASH_TREE, - txs.flatMap(tx => - padArrayEnd( - tx.data.end.noteHashes.filter(x => !x.isZero()), - Fr.zero(), - MAX_NOTE_HASHES_PER_TX, - ), - ), + txs.flatMap(tx => padArrayEnd(tx.txEffect.noteHashes, Fr.zero(), MAX_NOTE_HASHES_PER_TX)), ); await db.batchInsert( MerkleTreeId.NULLIFIER_TREE, - txs.flatMap(tx => - padArrayEnd( - tx.data.end.nullifiers.filter(x => !x.isZero()), - Fr.zero(), - MAX_NULLIFIERS_PER_TX, - ).map(x => x.toBuffer()), - ), + txs.flatMap(tx => padArrayEnd(tx.txEffect.nullifiers, Fr.zero(), MAX_NULLIFIERS_PER_TX).map(x => x.toBuffer())), NULLIFIER_TREE_HEIGHT, ); for (const tx of txs) { await db.batchInsert( MerkleTreeId.PUBLIC_DATA_TREE, - tx.data.end.publicDataUpdateRequests.map(write => { - return new PublicDataTreeLeaf(write.leafSlot, write.newValue).toBuffer(); - }), + padArrayEnd( + tx.txEffect.publicDataWrites, + PublicDataWrite.empty(), + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ).map(write => write.toBuffer()), PUBLIC_DATA_SUBTREE_HEIGHT, ); } @@ -157,6 +136,3 @@ export const makeGlobals = (blockNumber: number) => { GasFees.empty(), ); }; - -export const makeEmptyProcessedTestTx = (builderDb: MerkleTreeReadOperations): ProcessedTx => - makeEmptyProcessedTx(builderDb, Fr.ZERO, Fr.ZERO); diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index b0d658b5e8d..75044301ba5 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -18,6 +18,7 @@ import { Fr, type GlobalVariables, Header, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, @@ -41,7 +42,7 @@ import { PublicDataHint, PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, - PublicDataUpdateRequest, + PublicDataWrite, type RecursiveProof, RootRollupInputs, StateDiffHints, @@ -97,18 +98,15 @@ export async function buildBaseRollupHints( // Create data hint for reading fee payer initial balance in Fee Juice // If no fee payer is set, read hint should be empty - // If there is already a public data write for this slot, also skip the read hint const hintsBuilder = new HintsBuilder(db); const leafSlot = computeFeePayerBalanceLeafSlot(tx.data.feePayer); - const existingBalanceWrite = tx.data.end.publicDataUpdateRequests.find(write => write.leafSlot.equals(leafSlot)); - const feePayerFeeJuiceBalanceReadHint = - leafSlot.isZero() || existingBalanceWrite - ? PublicDataHint.empty() - : await hintsBuilder.getPublicDataHint(leafSlot.toBigInt()); + const feePayerFeeJuiceBalanceReadHint = tx.data.feePayer.isZero() + ? PublicDataHint.empty() + : await hintsBuilder.getPublicDataHint(leafSlot.toBigInt()); // Update the note hash trees with the new items being inserted to get the new roots // that will be used by the next iteration of the base rollup circuit, skipping the empty ones - const noteHashes = tx.data.end.noteHashes; + const noteHashes = padArrayEnd(tx.txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX); await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashes); // The read witnesses for a given TX should be generated before the writes of the same TX are applied. @@ -123,7 +121,7 @@ export async function buildBaseRollupHints( sortedNewLeavesIndexes, } = await db.batchInsert( MerkleTreeId.NULLIFIER_TREE, - tx.data.end.nullifiers.map(n => n.toBuffer()), + padArrayEnd(tx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()), NULLIFIER_SUBTREE_HEIGHT, ); if (nullifierWitnessLeaves === undefined) { @@ -162,7 +160,7 @@ export async function buildBaseRollupHints( publicDataSiblingPath, }); - const blockHash = tx.data.constants.historicalHeader.hash(); + const blockHash = tx.constants.historicalHeader.hash(); const archiveRootMembershipWitness = await getMembershipWitnessFor( blockHash, MerkleTreeId.ARCHIVE, @@ -398,15 +396,15 @@ export function makeEmptyMembershipWitness(height: N) { ); } -export async function processPublicDataUpdateRequests(tx: ProcessedTx, db: MerkleTreeWriteOperations) { +async function processPublicDataUpdateRequests(tx: ProcessedTx, db: MerkleTreeWriteOperations) { const allPublicDataUpdateRequests = padArrayEnd( - tx.finalPublicDataUpdateRequests, - PublicDataUpdateRequest.empty(), + tx.txEffect.publicDataWrites, + PublicDataWrite.empty(), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); const allPublicDataWrites = allPublicDataUpdateRequests.map( - ({ leafSlot, newValue }) => new PublicDataTreeLeaf(leafSlot, newValue), + ({ leafSlot, value }) => new PublicDataTreeLeaf(leafSlot, value), ); const { lowLeavesWitnessData, newSubtreeSiblingPath, sortedNewLeaves, sortedNewLeavesIndexes } = await db.batchInsert( MerkleTreeId.PUBLIC_DATA_TREE, @@ -509,7 +507,7 @@ export function validatePartialState( } // Helper for comparing two trees snapshots -export function validateSimulatedTree( +function validateSimulatedTree( localTree: AppendOnlyTreeSnapshot, simulatedTree: AppendOnlyTreeSnapshot, name: TreeNames, @@ -528,7 +526,7 @@ export function validateSimulatedTree( } export function validateTx(tx: ProcessedTx) { - const txHeader = tx.data.constants.historicalHeader; + const txHeader = tx.constants.historicalHeader; if (txHeader.state.l1ToL2MessageTree.isZero()) { throw new Error(`Empty L1 to L2 messages tree in tx: ${toFriendlyJSON(tx)}`); } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 67bbf75b88d..b802db69b44 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -2,15 +2,16 @@ import { Body, L2Block, MerkleTreeId, - type PaddingProcessedTx, type ProcessedTx, type ServerCircuitProver, type TxEffect, makeEmptyProcessedTx, - makePaddingProcessedTx, - toTxEffect, } from '@aztec/circuit-types'; -import { type EpochProver, type MerkleTreeWriteOperations } from '@aztec/circuit-types/interfaces'; +import { + type EpochProver, + type MerkleTreeWriteOperations, + type ProofAndVerificationKey, +} from '@aztec/circuit-types/interfaces'; import { type CircuitName } from '@aztec/circuit-types/stats'; import { AVM_PROOF_LENGTH_IN_FIELDS, @@ -95,7 +96,7 @@ const logger = createDebugLogger('aztec:prover:proving-orchestrator'); export class ProvingOrchestrator implements EpochProver { private provingState: EpochProvingState | undefined = undefined; private pendingProvingJobs: AbortController[] = []; - private paddingTx: PaddingProcessedTx | undefined = undefined; + private paddingTxProof?: ProofAndVerificationKey>; private provingPromise: Promise | undefined = undefined; private metrics: ProvingOrchestratorMetrics; @@ -121,7 +122,7 @@ export class ProvingOrchestrator implements EpochProver { * Resets the orchestrator's cached padding tx. */ public reset() { - this.paddingTx = undefined; + this.paddingTxProof = undefined; } public startNewEpoch(epochNumber: number, totalNumBlocks: number) { @@ -415,9 +416,8 @@ export class ProvingOrchestrator implements EpochProver { private async buildBlock(provingState: BlockProvingState, expectedHeader?: Header) { // Collect all new nullifiers, commitments, and contracts from all txs in this block to build body - const gasFees = provingState.globalVariables.gasFees; const nonEmptyTxEffects: TxEffect[] = provingState!.allTxs - .map(txProvingState => toTxEffect(txProvingState.processedTx, gasFees)) + .map(txProvingState => txProvingState.processedTx.txEffect) .filter(txEffect => !txEffect.isEmpty()); const body = new Body(nonEmptyTxEffects); @@ -459,12 +459,12 @@ export class ProvingOrchestrator implements EpochProver { private enqueuePaddingTxs( provingState: BlockProvingState, txInputs: Array<{ hints: BaseRollupHints; snapshot: TreeSnapshots }>, - unprovenPaddingTx: ProcessedTx, + paddingTx: ProcessedTx, ) { - if (this.paddingTx) { + if (this.paddingTxProof) { // We already have the padding transaction logger.debug(`Enqueuing ${txInputs.length} padding transactions using existing padding tx`); - this.provePaddingTransactions(txInputs, this.paddingTx, provingState); + this.provePaddingTransactions(txInputs, paddingTx, this.paddingTxProof, provingState); return; } logger.debug(`Enqueuing deferred proving for padding txs to enqueue ${txInputs.length} paddings`); @@ -480,14 +480,14 @@ export class ProvingOrchestrator implements EpochProver { signal => this.prover.getEmptyPrivateKernelProof( new PrivateKernelEmptyInputData( - unprovenPaddingTx.data.constants.historicalHeader, + paddingTx.constants.historicalHeader, // Chain id and version should not change even if the proving state does, so it's safe to use them for the padding tx // which gets cached across multiple runs of the orchestrator with different proving states. If they were to change, // we'd have to clear out the paddingTx here and regenerate it when they do. - unprovenPaddingTx.data.constants.txContext.chainId, - unprovenPaddingTx.data.constants.txContext.version, - getVKTreeRoot(), - protocolContractTreeRoot, + paddingTx.constants.txContext.chainId, + paddingTx.constants.txContext.version, + paddingTx.constants.vkTreeRoot, + paddingTx.constants.protocolContractTreeRoot, ), signal, provingState.epochNumber, @@ -495,8 +495,8 @@ export class ProvingOrchestrator implements EpochProver { ), result => { logger.debug(`Completed proof for padding tx, now enqueuing ${txInputs.length} padding txs`); - this.paddingTx = makePaddingProcessedTx(result); - this.provePaddingTransactions(txInputs, this.paddingTx, provingState); + this.paddingTxProof = { proof: result.proof, verificationKey: result.verificationKey }; + this.provePaddingTransactions(txInputs, paddingTx, this.paddingTxProof, provingState); }, ); } @@ -504,12 +504,14 @@ export class ProvingOrchestrator implements EpochProver { /** * Prepares the cached sets of base rollup inputs for padding transactions and proves them * @param txInputs - The base rollup inputs, start and end hash paths etc - * @param paddingTx - The padding tx, contains the header, proof, vk, public inputs used in the proof + * @param paddingTx - The padding tx, contains the header and public inputs used in the proof + * @param proofAndVk - The proof and vk of the paddingTx. * @param provingState - The block proving state */ private provePaddingTransactions( txInputs: Array<{ hints: BaseRollupHints; snapshot: TreeSnapshots }>, - paddingTx: PaddingProcessedTx, + paddingTx: ProcessedTx, + proofAndVk: ProofAndVerificationKey>, provingState: BlockProvingState, ) { // The padding tx contains the proof and vk, generated separately from the base inputs @@ -517,7 +519,7 @@ export class ProvingOrchestrator implements EpochProver { for (let i = 0; i < txInputs.length; i++) { const { hints, snapshot } = txInputs[i]; const txProvingState = new TxProvingState(paddingTx, hints, snapshot); - txProvingState.assignTubeProof({ proof: paddingTx.recursiveProof, verificationKey: paddingTx.verificationKey }); + txProvingState.assignTubeProof(proofAndVk); const txIndex = provingState.addNewTx(txProvingState); this.enqueueBaseRollup(provingState, txIndex); } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts index dd21cbd2dd2..56bb5996868 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts @@ -1,7 +1,10 @@ +import { makeEmptyProcessedTx } from '@aztec/circuit-types'; import { Fr } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; +import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; +import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; -import { makeBloatedProcessedTx, makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTxWithVKRoot } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; const logger = createDebugLogger('aztec:orchestrator-errors'); @@ -9,6 +12,11 @@ const logger = createDebugLogger('aztec:orchestrator-errors'); describe('prover/orchestrator/errors', () => { let context: TestContext; + const makeEmptyProcessedTestTx = () => { + const header = context.actualDb.getInitialHeader(); + return makeEmptyProcessedTx(header, Fr.ZERO, Fr.ZERO, getVKTreeRoot(), protocolContractTreeRoot); + }; + beforeEach(async () => { context = await TestContext.new(logger); }); @@ -22,10 +30,10 @@ describe('prover/orchestrator/errors', () => { describe('errors', () => { it('throws if adding too many transactions', async () => { const txs = [ - makeBloatedProcessedTx(context.actualDb, 1), - makeBloatedProcessedTx(context.actualDb, 2), - makeBloatedProcessedTx(context.actualDb, 3), - makeBloatedProcessedTx(context.actualDb, 4), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 1), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 2), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 3), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 4), ]; context.orchestrator.startNewEpoch(1, 1); @@ -35,9 +43,9 @@ describe('prover/orchestrator/errors', () => { await context.orchestrator.addNewTx(tx); } - await expect( - async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx(context.actualDb)), - ).rejects.toThrow('Rollup not accepting further transactions'); + await expect(async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx())).rejects.toThrow( + 'Rollup not accepting further transactions', + ); const block = await context.orchestrator.setBlockCompleted(); expect(block.number).toEqual(context.blockNumber); @@ -55,16 +63,16 @@ describe('prover/orchestrator/errors', () => { }); it('throws if adding a transaction before starting epoch', async () => { - await expect( - async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx(context.actualDb)), - ).rejects.toThrow(`Invalid proving state, call startNewBlock before adding transactions`); + await expect(async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx())).rejects.toThrow( + `Invalid proving state, call startNewBlock before adding transactions`, + ); }); it('throws if adding a transaction before starting block', async () => { context.orchestrator.startNewEpoch(1, 1); - await expect( - async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx(context.actualDb)), - ).rejects.toThrow(`Invalid proving state, call startNewBlock before adding transactions`); + await expect(async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx())).rejects.toThrow( + `Invalid proving state, call startNewBlock before adding transactions`, + ); }); it('throws if completing a block before start', async () => { @@ -87,9 +95,9 @@ describe('prover/orchestrator/errors', () => { await context.orchestrator.startNewBlock(2, context.globalVariables, []); context.orchestrator.cancel(); - await expect( - async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx(context.actualDb)), - ).rejects.toThrow('Invalid proving state when adding a tx'); + await expect(async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx())).rejects.toThrow( + 'Invalid proving state when adding a tx', + ); }); it.each([[-4], [0], [1], [8.1]] as const)( diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts index 8c87642522d..40dd1b10901 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts @@ -1,15 +1,17 @@ -import { ProvingRequestType, type ServerCircuitProver } from '@aztec/circuit-types'; +import { type ServerCircuitProver } from '@aztec/circuit-types'; +import { makeBloatedProcessedTx } from '@aztec/circuit-types/test'; import { Fr } from '@aztec/circuits.js'; -import { makeAvmCircuitInputs } from '@aztec/circuits.js/testing'; import { times } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; +import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; +import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; import { WASMSimulator } from '@aztec/simulator'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { jest } from '@jest/globals'; import { TestCircuitProver } from '../../../bb-prover/src/test/test_circuit_prover.js'; -import { makeBloatedProcessedTx, makeGlobals } from '../mocks/fixtures.js'; +import { makeGlobals } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; import { ProvingOrchestrator } from './orchestrator.js'; @@ -40,15 +42,21 @@ describe('prover/orchestrator/failures', () => { // We need at least 3 blocks and 3 txs to ensure all circuits are used for (let i = 0; i < 3; i++) { - const txs = times(3, j => makeBloatedProcessedTx(context.actualDb, i * 10 + j + 1)); - txs[1].avmProvingRequest = { - type: ProvingRequestType.PUBLIC_VM, - inputs: makeAvmCircuitInputs(i), - }; + const globalVariables = makeGlobals(i + 1); + const txs = times(3, j => + makeBloatedProcessedTx({ + db: context.actualDb, + globalVariables, + vkTreeRoot: getVKTreeRoot(), + protocolContractTreeRoot, + seed: i * 10 + j + 1, + privateOnly: j === 1, + }), + ); const msgs = [new Fr(i + 100)]; // these operations could fail if the target circuit fails before adding all blocks or txs try { - await orchestrator.startNewBlock(txs.length, makeGlobals(i + 1), msgs); + await orchestrator.startNewBlock(txs.length, globalVariables, msgs); let allTxsAdded = true; for (const tx of txs) { try { diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts index eae588abd2d..9aa8a2e793e 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts @@ -7,7 +7,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { type MerkleTreeAdminDatabase } from '@aztec/world-state'; import { NativeWorldStateService } from '@aztec/world-state/native'; -import { makeBloatedProcessedTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTxWithVKRoot, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; const logger = createDebugLogger('aztec:orchestrator-mixed-blocks'); @@ -29,9 +29,9 @@ describe('prover/orchestrator/mixed-blocks', () => { describe('blocks', () => { it('builds an unbalanced L2 block', async () => { const txs = [ - makeBloatedProcessedTx(context.actualDb, 1), - makeBloatedProcessedTx(context.actualDb, 2), - makeBloatedProcessedTx(context.actualDb, 3), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 1), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 2), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 3), ]; const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); @@ -48,7 +48,7 @@ describe('prover/orchestrator/mixed-blocks', () => { }); it.each([2, 4, 5, 8] as const)('builds an L2 block with %i bloated txs', async (totalCount: number) => { - const txs = times(totalCount, (i: number) => makeBloatedProcessedTx(context.actualDb, i)); + const txs = times(totalCount, (i: number) => makeBloatedProcessedTxWithVKRoot(context.actualDb, i)); const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts index e4205dab158..5919fa383bf 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts @@ -1,7 +1,9 @@ +import { makeBloatedProcessedTx } from '@aztec/circuit-types/test'; import { createDebugLogger } from '@aztec/foundation/log'; import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; +import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; -import { makeBloatedProcessedTx, makeGlobals } from '../mocks/fixtures.js'; +import { makeGlobals } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; const logger = createDebugLogger('aztec:orchestrator-multi-blocks'); @@ -24,9 +26,12 @@ describe('prover/orchestrator/multi-block', () => { for (let i = 0; i < numBlocks; i++) { logger.info(`Creating block ${i + 1000}`); - const tx = makeBloatedProcessedTx(context.actualDb, i + 1); - tx.data.constants.historicalHeader = header; - tx.data.constants.vkTreeRoot = getVKTreeRoot(); + const tx = makeBloatedProcessedTx({ + header, + vkTreeRoot: getVKTreeRoot(), + protocolContractTreeRoot, + seed: i + 1, + }); const blockNum = i + 1000; const globals = makeGlobals(blockNum); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts index bde92105587..5c82382d054 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts @@ -4,7 +4,7 @@ import { range } from '@aztec/foundation/array'; import { createDebugLogger } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; -import { makeBloatedProcessedTx } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTxWithVKRoot } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; const logger = createDebugLogger('aztec:orchestrator-single-blocks'); @@ -31,7 +31,7 @@ describe('prover/orchestrator/blocks', () => { }); it('builds a block with 1 transaction', async () => { - const txs = [makeBloatedProcessedTx(context.actualDb, 1)]; + const txs = [makeBloatedProcessedTxWithVKRoot(context.actualDb, 1)]; // This will need to be a 2 tx block context.orchestrator.startNewEpoch(1, 1); @@ -48,10 +48,10 @@ describe('prover/orchestrator/blocks', () => { it('builds a block concurrently with transaction simulation', async () => { const txs = [ - makeBloatedProcessedTx(context.actualDb, 1), - makeBloatedProcessedTx(context.actualDb, 2), - makeBloatedProcessedTx(context.actualDb, 3), - makeBloatedProcessedTx(context.actualDb, 4), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 1), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 2), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 3), + makeBloatedProcessedTxWithVKRoot(context.actualDb, 4), ]; const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_workflow.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_workflow.test.ts index 53f37fea7bd..a04d36e3d77 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_workflow.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_workflow.test.ts @@ -15,7 +15,7 @@ import { type MerkleTreeReadOperations } from '@aztec/world-state'; import { type MockProxy, mock } from 'jest-mock-extended'; -import { makeBloatedProcessedTx } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTxWithVKRoot } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; import { type ProvingOrchestrator } from './orchestrator.js'; @@ -86,8 +86,8 @@ describe('prover/orchestrator', () => { it('waits for block to be completed before enqueueing block root proof', async () => { orchestrator.startNewEpoch(1, 1); await orchestrator.startNewBlock(2, globalVariables, []); - await orchestrator.addNewTx(makeBloatedProcessedTx(actualDb, 1)); - await orchestrator.addNewTx(makeBloatedProcessedTx(actualDb, 2)); + await orchestrator.addNewTx(makeBloatedProcessedTxWithVKRoot(actualDb, 1)); + await orchestrator.addNewTx(makeBloatedProcessedTxWithVKRoot(actualDb, 2)); // wait for the block root proof to try to be enqueued await sleep(1000); diff --git a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts index 3c681585bfd..efd5c918029 100644 --- a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts @@ -16,11 +16,11 @@ import { PrivateBaseRollupInputs, PrivateTubeData, PublicBaseRollupInputs, + PublicTubeData, type RecursiveProof, type TUBE_PROOF_LENGTH, TUBE_VK_INDEX, TubeInputs, - VMCircuitPublicInputs, VkWitnessData, } from '@aztec/circuits.js'; import { getVKIndex, getVKSiblingPath } from '@aztec/noir-protocol-circuits-types'; @@ -65,13 +65,13 @@ export class TxProvingState { } const vkData = this.getTubeVkData(); - const tubeData = new PrivateTubeData(this.processedTx.data, this.tube.proof, vkData); + const tubeData = new PrivateTubeData(this.processedTx.data.toKernelCircuitPublicInputs(), this.tube.proof, vkData); return new PrivateBaseRollupInputs(tubeData, this.baseRollupHints); } public getPublicBaseInputs() { - if (!this.requireAvmProof) { + if (!this.processedTx.avmProvingRequest) { throw new Error('Should create private base rollup for a tx not requiring avm proof.'); } if (!this.tube) { @@ -81,15 +81,14 @@ export class TxProvingState { throw new Error('Tx not ready for proving base rollup: avm proof undefined'); } - // Temporary hack. - // Passing this.processedTx.data to the tube, which is the output of the simulated public_kernel_tail, - // so that the output of the public base will contain all the side effects. - // This should be the output of the private_kernel_tail_to_public when the output of the avm proof is the result of - // simulating the entire public call stack. - const tubeData = new PrivateTubeData(this.processedTx.data, this.tube.proof, this.getTubeVkData()); + const tubeData = new PublicTubeData( + this.processedTx.data.toPublicKernelCircuitPublicInputs(), + this.tube.proof, + this.getTubeVkData(), + ); const avmProofData = new AvmProofData( - VMCircuitPublicInputs.empty(), // TODO + this.processedTx.avmProvingRequest.inputs.output, this.avm.proof, this.getAvmVkData(), ); @@ -106,33 +105,48 @@ export class TxProvingState { } public verifyStateOrReject(): string | undefined { - const kernelPublicInputs = this.processedTx.data; - - const txNoteEncryptedLogs = EncryptedNoteTxL2Logs.hashNoteLogs( - kernelPublicInputs.end.noteEncryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.value.toBuffer()), + const txEffect = this.processedTx.txEffect; + const fromPrivate = this.processedTx.data; + + const noteEncryptedLogsHashes = [ + fromPrivate.forRollup?.end.noteEncryptedLogsHashes || [], + fromPrivate.forPublic?.nonRevertibleAccumulatedData.noteEncryptedLogsHashes || [], + fromPrivate.forPublic?.revertibleAccumulatedData.noteEncryptedLogsHashes || [], + ].flat(); + const txNoteEncryptedLogsHash = EncryptedNoteTxL2Logs.hashNoteLogs( + noteEncryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.value.toBuffer()), ); - if (!txNoteEncryptedLogs.equals(this.processedTx.noteEncryptedLogs.hash())) { - return `Note encrypted logs hash mismatch: ${Fr.fromBuffer(txNoteEncryptedLogs)} === ${Fr.fromBuffer( - this.processedTx.noteEncryptedLogs.hash(), + if (!txNoteEncryptedLogsHash.equals(txEffect.noteEncryptedLogs.hash())) { + return `Note encrypted logs hash mismatch: ${Fr.fromBuffer(txNoteEncryptedLogsHash)} === ${Fr.fromBuffer( + txEffect.noteEncryptedLogs.hash(), )}`; } - const txEncryptedLogs = EncryptedTxL2Logs.hashSiloedLogs( - kernelPublicInputs.end.encryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.getSiloedHash()), + const encryptedLogsHashes = [ + fromPrivate.forRollup?.end.encryptedLogsHashes || [], + fromPrivate.forPublic?.nonRevertibleAccumulatedData.encryptedLogsHashes || [], + fromPrivate.forPublic?.revertibleAccumulatedData.encryptedLogsHashes || [], + ].flat(); + const txEncryptedLogsHash = EncryptedTxL2Logs.hashSiloedLogs( + encryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.getSiloedHash()), ); - if (!txEncryptedLogs.equals(this.processedTx.encryptedLogs.hash())) { + if (!txEncryptedLogsHash.equals(txEffect.encryptedLogs.hash())) { // @todo This rejection messages is never seen. Never making it out to the logs - return `Encrypted logs hash mismatch: ${Fr.fromBuffer(txEncryptedLogs)} === ${Fr.fromBuffer( - this.processedTx.encryptedLogs.hash(), + return `Encrypted logs hash mismatch: ${Fr.fromBuffer(txEncryptedLogsHash)} === ${Fr.fromBuffer( + txEffect.encryptedLogs.hash(), )}`; } - const txUnencryptedLogs = UnencryptedTxL2Logs.hashSiloedLogs( - kernelPublicInputs.end.unencryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.getSiloedHash()), + const avmOutput = this.processedTx.avmProvingRequest?.inputs.output; + const unencryptedLogsHashes = avmOutput + ? avmOutput.accumulatedData.unencryptedLogsHashes + : fromPrivate.forRollup!.end.unencryptedLogsHashes; + const txUnencryptedLogsHash = UnencryptedTxL2Logs.hashSiloedLogs( + unencryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.getSiloedHash()), ); - if (!txUnencryptedLogs.equals(this.processedTx.unencryptedLogs.hash())) { - return `Unencrypted logs hash mismatch: ${Fr.fromBuffer(txUnencryptedLogs)} === ${Fr.fromBuffer( - this.processedTx.unencryptedLogs.hash(), + if (!txUnencryptedLogsHash.equals(txEffect.unencryptedLogs.hash())) { + return `Unencrypted logs hash mismatch: ${Fr.fromBuffer(txUnencryptedLogsHash)} === ${Fr.fromBuffer( + txEffect.unencryptedLogs.hash(), )}`; } } diff --git a/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts b/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts index 74053580723..326d91124d5 100644 --- a/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts +++ b/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts @@ -44,8 +44,6 @@ describe('Prover agent <-> queue integration', () => { getBlockRootRollupProof: makeBlockRootRollupInputs, getEmptyPrivateKernelProof: () => new PrivateKernelEmptyInputData(makeHeader(), Fr.random(), Fr.random(), Fr.random(), Fr.random()), - getEmptyTubeProof: () => - new PrivateKernelEmptyInputData(makeHeader(), Fr.random(), Fr.random(), Fr.random(), Fr.random()), getMergeRollupProof: makeMergeRollupInputs, getRootRollupProof: makeRootRollupInputs, getTubeProof: () => new TubeInputs(ClientIvcProof.empty()), diff --git a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts index 251e9014004..03eb267be56 100644 --- a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts +++ b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts @@ -280,14 +280,6 @@ export class MemoryProvingQueue implements ServerCircuitProver, ProvingJobSource return this.enqueue({ type: ProvingRequestType.TUBE_PROOF, inputs }, signal, epochNumber); } - getEmptyTubeProof( - inputs: PrivateKernelEmptyInputData, - signal?: AbortSignal, - epochNumber?: number, - ): Promise> { - return this.enqueue({ type: ProvingRequestType.PRIVATE_KERNEL_EMPTY, inputs }, signal, epochNumber); - } - /** * Creates a proof for the given input. * @param input - Input to the circuit. diff --git a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts index d8ba95940ee..de9828a3c70 100644 --- a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts @@ -1,13 +1,11 @@ import { BBNativeRollupProver, type BBProverConfig } from '@aztec/bb-prover'; -import { makePaddingProcessedTxFromTubeProof } from '@aztec/circuit-types'; +import { makeEmptyProcessedTx } from '@aztec/circuit-types'; import { - NESTED_RECURSIVE_PROOF_LENGTH, PRIVATE_KERNEL_EMPTY_INDEX, PrivateBaseRollupInputs, PrivateKernelEmptyInputData, PrivateTubeData, VkWitnessData, - makeEmptyRecursiveProof, } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { getVKSiblingPath, getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; @@ -41,22 +39,24 @@ describe('prover/bb_prover/base-rollup', () => { const version = context.globalVariables.version; const vkTreeRoot = getVKTreeRoot(); - const inputs = new PrivateKernelEmptyInputData(header, chainId, version, vkTreeRoot, protocolContractTreeRoot); - const paddingTxPublicInputsAndProof = await context.prover.getEmptyTubeProof(inputs); - const tx = makePaddingProcessedTxFromTubeProof(paddingTxPublicInputsAndProof); + const tx = makeEmptyProcessedTx(header, chainId, version, vkTreeRoot, protocolContractTreeRoot); - logger.verbose('Building base rollup inputs'); - const baseRollupInputProof = makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH); - const verificationKey = paddingTxPublicInputsAndProof.verificationKey; - baseRollupInputProof.proof[0] = verificationKey.keyAsFields.key[0]; - baseRollupInputProof.proof[1] = verificationKey.keyAsFields.key[1]; - baseRollupInputProof.proof[2] = verificationKey.keyAsFields.key[2]; + logger.verbose('Building empty private proof'); + const privateInputs = new PrivateKernelEmptyInputData( + header, + chainId, + version, + vkTreeRoot, + protocolContractTreeRoot, + ); + const tubeProof = await context.prover.getEmptyPrivateKernelProof(privateInputs); + expect(tubeProof.inputs).toEqual(tx.data.toKernelCircuitPublicInputs()); const vkIndex = PRIVATE_KERNEL_EMPTY_INDEX; const vkPath = getVKSiblingPath(vkIndex); - const vkData = new VkWitnessData(verificationKey, vkIndex, vkPath); + const vkData = new VkWitnessData(tubeProof.verificationKey, vkIndex, vkPath); - const tubeData = new PrivateTubeData(tx.data, baseRollupInputProof, vkData); + const tubeData = new PrivateTubeData(tubeProof.inputs, tubeProof.proof, vkData); const baseRollupHints = await buildBaseRollupHints(tx, context.globalVariables, context.actualDb); const baseRollupInputs = new PrivateBaseRollupInputs(tubeData, baseRollupHints); diff --git a/yarn-project/prover-client/src/test/mock_prover.ts b/yarn-project/prover-client/src/test/mock_prover.ts index 212c8b549fd..cb08f8da8e9 100644 --- a/yarn-project/prover-client/src/test/mock_prover.ts +++ b/yarn-project/prover-client/src/test/mock_prover.ts @@ -117,16 +117,6 @@ export class MockProver implements ServerCircuitProver { ); } - getEmptyTubeProof(): Promise> { - return Promise.resolve( - makePublicInputsAndRecursiveProof( - makeKernelCircuitPublicInputs(), - makeRecursiveProof(RECURSIVE_PROOF_LENGTH), - VerificationKeyData.makeFakeHonk(), - ), - ); - } - getRootRollupProof(): Promise> { return Promise.resolve( makePublicInputsAndRecursiveProof( diff --git a/yarn-project/prover-node/src/job/epoch-proving-job.ts b/yarn-project/prover-node/src/job/epoch-proving-job.ts index 4d039b9ab7d..bed463abef8 100644 --- a/yarn-project/prover-node/src/job/epoch-proving-job.ts +++ b/yarn-project/prover-node/src/job/epoch-proving-job.ts @@ -202,9 +202,7 @@ export class EpochProvingJob { NULLIFIER_SUBTREE_HEIGHT, ); const allPublicDataWrites = padArrayEnd( - emptyKernelOutput.end.publicDataUpdateRequests.map( - ({ leafSlot, newValue }) => new PublicDataTreeLeaf(leafSlot, newValue), - ), + emptyKernelOutput.end.publicDataWrites.map(({ leafSlot, value }) => new PublicDataTreeLeaf(leafSlot, value)), PublicDataTreeLeaf.empty(), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); diff --git a/yarn-project/sequencer-client/src/block_builder/light.test.ts b/yarn-project/sequencer-client/src/block_builder/light.test.ts index b909191f070..e4a636f2e00 100644 --- a/yarn-project/sequencer-client/src/block_builder/light.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/light.test.ts @@ -13,6 +13,7 @@ import { BaseParityInputs, BlockRootRollupInputs, Fr, + GasSettings, type GlobalVariables, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, @@ -67,7 +68,7 @@ describe('LightBlockBuilder', () => { let logger: DebugLogger; let globals: GlobalVariables; let l1ToL2Messages: Fr[]; - let vkRoot: Fr; + let vkTreeRoot: Fr; let db: MerkleTreeAdminDatabase; let fork: MerkleTreeWriteOperations; @@ -79,7 +80,7 @@ describe('LightBlockBuilder', () => { beforeAll(async () => { logger = createDebugLogger('aztec:sequencer-client:test:block-builder'); simulator = new TestCircuitProver(new NoopTelemetryClient()); - vkRoot = getVKTreeRoot(); + vkTreeRoot = getVKTreeRoot(); emptyProof = makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH); db = await NativeWorldStateService.tmp(); }); @@ -164,7 +165,7 @@ describe('LightBlockBuilder', () => { }); it('builds a single tx header', async () => { - const txs = times(1, i => makeBloatedProcessedTx(fork, vkRoot, protocolContractTreeRoot, i)); + const txs = times(1, makeTx); const header = await buildHeader(txs, l1ToL2Messages); const expectedHeader = await buildExpectedHeader(txs, l1ToL2Messages); @@ -183,7 +184,16 @@ describe('LightBlockBuilder', () => { // Makes a tx with a non-zero inclusion fee for testing const makeTx = (i: number) => - makeBloatedProcessedTx(fork, vkRoot, protocolContractTreeRoot, i, { inclusionFee: new Fr(i) }); + makeBloatedProcessedTx({ + header: fork.getInitialHeader(), + chainId: globals.chainId, + version: globals.version, + gasSettings: GasSettings.default({ inclusionFee: new Fr(i + 1) }), + vkTreeRoot, + protocolContractTreeRoot, + seed: i + 1, + privateOnly: true, + }); // Builds the block header using the ts block builder const buildHeader = async (txs: ProcessedTx[], l1ToL2Messages: Fr[]) => { @@ -214,7 +224,7 @@ describe('LightBlockBuilder', () => { expectsFork.getInitialHeader(), globals.chainId, globals.version, - vkRoot, + vkTreeRoot, protocolContractTreeRoot, ), ), @@ -260,7 +270,7 @@ describe('LightBlockBuilder', () => { const vkIndex = TUBE_VK_INDEX; const vkPath = getVKSiblingPath(vkIndex); const vkData = new VkWitnessData(TubeVk, vkIndex, vkPath); - const tubeData = new PrivateTubeData(tx.data, emptyProof, vkData); + const tubeData = new PrivateTubeData(tx.data.toKernelCircuitPublicInputs(), emptyProof, vkData); const hints = await buildBaseRollupHints(tx, globals, expectsFork); const inputs = new PrivateBaseRollupInputs(tubeData, hints); const result = await simulator.getPrivateBaseRollupProof(inputs); @@ -287,7 +297,7 @@ describe('LightBlockBuilder', () => { const baseParityVk = ProtocolCircuitVks['BaseParityArtifact'].keyAsFields; const baseParityVkWitness = getVkMembershipWitness(baseParityVk); for (let i = 0; i < NUM_BASE_PARITY_PER_ROOT_PARITY; i++) { - const input = BaseParityInputs.fromSlice(l1ToL2Messages, i, vkRoot); + const input = BaseParityInputs.fromSlice(l1ToL2Messages, i, vkTreeRoot); const { publicInputs } = await simulator.getBaseParityProof(input); const rootInput = new RootParityInput(emptyProof, baseParityVk, baseParityVkWitness.siblingPath, publicInputs); rootParityInputs.push(rootInput); diff --git a/yarn-project/sequencer-client/src/block_builder/light.ts b/yarn-project/sequencer-client/src/block_builder/light.ts index 8598fc37ed4..90075c3f020 100644 --- a/yarn-project/sequencer-client/src/block_builder/light.ts +++ b/yarn-project/sequencer-client/src/block_builder/light.ts @@ -8,7 +8,6 @@ import { type ProcessedTx, type TxEffect, makeEmptyProcessedTx, - toTxEffect, } from '@aztec/circuit-types'; import { Fr, type GlobalVariables, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -68,9 +67,7 @@ export class LightweightBlockBuilder implements BlockBuilder { private async buildBlock(): Promise { this.logger.verbose(`Finalising block`); - const nonEmptyTxEffects: TxEffect[] = this.txs - .map(tx => toTxEffect(tx, this.globalVariables!.gasFees)) - .filter(txEffect => !txEffect.isEmpty()); + const nonEmptyTxEffects: TxEffect[] = this.txs.map(tx => tx.txEffect).filter(txEffect => !txEffect.isEmpty()); const body = new Body(nonEmptyTxEffects); const header = await buildHeaderFromTxEffects(body, this.globalVariables!, this.l1ToL2Messages!, this.db); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index ef1685bc3bd..57ce2ad02b3 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -16,7 +16,7 @@ import { UnencryptedTxL2Logs, WorldStateRunningState, type WorldStateSynchronizer, - makeProcessedTx, + makeProcessedTxFromPrivateOnlyTx, mockEpochProofQuote, mockTxForRollup, } from '@aztec/circuit-types'; @@ -144,7 +144,9 @@ describe('sequencer', () => { publicProcessor = mock({ process: async txs => [ - await Promise.all(txs.map(tx => makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs()))), + await Promise.all( + txs.map(tx => makeProcessedTxFromPrivateOnlyTx(tx, Fr.ZERO, undefined, block.header.globalVariables)), + ), [], [], ], diff --git a/yarn-project/sequencer-client/src/tx_validator/test_utils.ts b/yarn-project/sequencer-client/src/tx_validator/test_utils.ts index f28b80cdbc0..dace92c0258 100644 --- a/yarn-project/sequencer-client/src/tx_validator/test_utils.ts +++ b/yarn-project/sequencer-client/src/tx_validator/test_utils.ts @@ -7,7 +7,7 @@ export function patchNonRevertibleFn( index: number, overrides: { address?: AztecAddress; selector: FunctionSelector; args?: Fr[]; msgSender?: AztecAddress }, ): { address: AztecAddress; selector: FunctionSelector } { - return patchFn('endNonRevertibleData', tx, index, overrides); + return patchFn('nonRevertibleAccumulatedData', tx, index, overrides); } export function patchRevertibleFn( @@ -15,11 +15,11 @@ export function patchRevertibleFn( index: number, overrides: { address?: AztecAddress; selector: FunctionSelector; args?: Fr[]; msgSender?: AztecAddress }, ): { address: AztecAddress; selector: FunctionSelector } { - return patchFn('end', tx, index, overrides); + return patchFn('revertibleAccumulatedData', tx, index, overrides); } function patchFn( - where: 'end' | 'endNonRevertibleData', + where: 'revertibleAccumulatedData' | 'nonRevertibleAccumulatedData', tx: Tx, index: number, overrides: { address?: AztecAddress; selector: FunctionSelector; args?: Fr[]; msgSender?: AztecAddress }, @@ -31,11 +31,13 @@ function patchFn( fn.callContext.msgSender = overrides.msgSender ?? fn.callContext.msgSender; tx.enqueuedPublicFunctionCalls[index] = fn; - const request = tx.data.forPublic![where].publicCallStack[index]; - request.callContext.contractAddress = fn.callContext.contractAddress; - request.callContext = fn.callContext; + const request = tx.data.forPublic![where].publicCallRequests[index]; + request.contractAddress = fn.callContext.contractAddress; + request.msgSender = fn.callContext.msgSender; + request.functionSelector = fn.callContext.functionSelector; + request.isStaticCall = fn.callContext.isStaticCall; request.argsHash = computeVarArgsHash(fn.args); - tx.data.forPublic![where].publicCallStack[index] = request; + tx.data.forPublic![where].publicCallRequests[index] = request; return { address: fn.callContext.contractAddress, diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index dfc3e0d59a4..6595659a323 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -334,8 +334,8 @@ export class AvmPersistableStateManager { } const functionName = await getPublicFunctionDebugName( this.worldStateDB, - publicCallRequest.callContext.contractAddress, - publicCallRequest.callContext.functionSelector, + publicCallRequest.contractAddress, + publicCallRequest.functionSelector, calldata, ); diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts index b076c12cc3c..a3a1c9e7e13 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts @@ -1,7 +1,6 @@ import { UnencryptedL2Log } from '@aztec/circuit-types'; import { AztecAddress, - CallContext, CombinedConstantData, EthAddress, Gas, @@ -45,13 +44,13 @@ import { SideEffectLimitReachedError } from './side_effect_errors.js'; * Helper function to create a public execution request from an AVM execution environment */ function createPublicCallRequest(avmEnvironment: AvmExecutionEnvironment): PublicCallRequest { - const callContext = CallContext.from({ - msgSender: avmEnvironment.sender, - contractAddress: avmEnvironment.address, - functionSelector: avmEnvironment.functionSelector, - isStaticCall: avmEnvironment.isStaticCall, - }); - return new PublicCallRequest(callContext, computeVarArgsHash(avmEnvironment.calldata), /*counter=*/ 0); + return new PublicCallRequest( + avmEnvironment.sender, + avmEnvironment.address, + avmEnvironment.functionSelector, + avmEnvironment.isStaticCall, + computeVarArgsHash(avmEnvironment.calldata), + ); } describe('Enqueued-call Side Effect Trace', () => { diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index 77c4394b65e..1f50f4ba13c 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -14,6 +14,7 @@ import { L2ToL1Message, LogHash, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_ENQUEUED_CALLS_PER_TX, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, @@ -22,7 +23,6 @@ import { MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, @@ -443,9 +443,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI this.enqueuedCalls.push(publicCallRequest); - this.avmCircuitHints.enqueuedCalls.items.push( - new AvmEnqueuedCallHint(publicCallRequest.callContext.contractAddress, calldata), - ); + this.avmCircuitHints.enqueuedCalls.items.push(new AvmEnqueuedCallHint(publicCallRequest.contractAddress, calldata)); } /** @@ -475,7 +473,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI this.enqueuedCalls.push(publicCallRequests[i]); this.avmCircuitHints.enqueuedCalls.items.push( - new AvmEnqueuedCallHint(publicCallRequests[i].callContext.contractAddress, calldatas[i]), + new AvmEnqueuedCallHint(publicCallRequests[i].contractAddress, calldatas[i]), ); } } @@ -581,7 +579,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI return new VMCircuitPublicInputs( /*constants=*/ constants, /*callRequest=*/ callRequest, - /*publicCallStack=*/ makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicInnerCallRequest.empty), + /*publicCallStack=*/ makeTuple(MAX_ENQUEUED_CALLS_PER_TX, PublicInnerCallRequest.empty), /*previousValidationRequestArrayLengths=*/ this.previousValidationRequestArrayLengths, /*validationRequests=*/ this.getValidationRequests(), /*previousAccumulatedDataArrayLengths=*/ this.previousAccumulatedDataArrayLengths, @@ -643,7 +641,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI /*encryptedLogsHashes=*/ makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), padArrayEnd(this.unencryptedLogsHashes, ScopedLogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_TX), padArrayEnd(this.publicDataWrites, PublicDataUpdateRequest.empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), - /*publicCallStack=*/ makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest.empty), + /*publicCallStack=*/ makeTuple(MAX_ENQUEUED_CALLS_PER_TX, PublicCallRequest.empty), /*gasUsed=*/ gasUsed, ); } diff --git a/yarn-project/simulator/src/public/enqueued_call_simulator.ts b/yarn-project/simulator/src/public/enqueued_call_simulator.ts index 2f4be543a40..43e8bbc4a6b 100644 --- a/yarn-project/simulator/src/public/enqueued_call_simulator.ts +++ b/yarn-project/simulator/src/public/enqueued_call_simulator.ts @@ -10,6 +10,7 @@ import { } from '@aztec/circuit-types'; import { AvmCircuitInputs, + AvmCircuitPublicInputs, AztecAddress, ContractStorageRead, ContractStorageUpdateRequest, @@ -19,6 +20,7 @@ import { type Header, L2ToL1Message, LogHash, + MAX_ENQUEUED_CALLS_PER_CALL, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_L2_GAS_PER_ENQUEUED_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, @@ -27,7 +29,6 @@ import { MAX_NULLIFIERS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, @@ -66,7 +67,13 @@ function emptyAvmProvingRequest(): AvmProvingRequest { function makeAvmProvingRequest(inputs: PublicCircuitPublicInputs, result: PublicFunctionCallResult): AvmProvingRequest { return { type: ProvingRequestType.PUBLIC_VM, - inputs: new AvmCircuitInputs(result.functionName, result.calldata, inputs, result.avmCircuitHints), + inputs: new AvmCircuitInputs( + result.functionName, + result.calldata, + inputs, + result.avmCircuitHints, + AvmCircuitPublicInputs.empty(), + ), }; } @@ -280,8 +287,8 @@ export class EnqueuedCallSimulator { publicCallRequests: padArrayEnd( result.publicCallRequests, PublicInnerCallRequest.empty(), - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - `Too many public call requests. Got ${result.publicCallRequests.length} with max being ${MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL}`, + MAX_ENQUEUED_CALLS_PER_CALL, + `Too many public call requests. Got ${result.publicCallRequests.length} with max being ${MAX_ENQUEUED_CALLS_PER_CALL}`, ), unencryptedLogsHashes: padArrayEnd( result.unencryptedLogsHashes, diff --git a/yarn-project/simulator/src/public/enqueued_calls_processor.test.ts b/yarn-project/simulator/src/public/enqueued_calls_processor.test.ts index d7e681b1dad..4c188249a5b 100644 --- a/yarn-project/simulator/src/public/enqueued_calls_processor.test.ts +++ b/yarn-project/simulator/src/public/enqueued_calls_processor.test.ts @@ -1,4 +1,10 @@ -import { type MerkleTreeWriteOperations, SimulationError, type TreeInfo, mockTx } from '@aztec/circuit-types'; +import { + type MerkleTreeWriteOperations, + PublicKernelPhase, + SimulationError, + type TreeInfo, + mockTx, +} from '@aztec/circuit-types'; import { AppendOnlyTreeSnapshot, AztecAddress, @@ -10,9 +16,9 @@ import { Header, PUBLIC_DATA_TREE_HEIGHT, PartialStateReference, - PublicAccumulatedDataBuilder, + PrivateToPublicAccumulatedDataBuilder, PublicDataTreeLeafPreimage, - PublicDataUpdateRequest, + PublicDataWrite, RevertCode, StateReference, } from '@aztec/circuits.js'; @@ -111,17 +117,15 @@ describe('enqueued_calls_processor', () => { expect(txResult.processedPhases).toHaveLength(1); expect(txResult.processedPhases[0]).toEqual(expect.objectContaining({ revertReason: undefined })); + expect(txResult.revertCode).toEqual(RevertCode.OK); expect(txResult.revertReason).toBe(undefined); expect(tailSpy).toHaveBeenCalledTimes(1); expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); - const outputs = txResult.tailKernelOutput.end; + const outputs = txResult.avmProvingRequest!.inputs.output.accumulatedData; // we keep the non-revertible logs - expect(arrayNonEmptyLength(outputs.encryptedLogsHashes, l => l.logHash.isEmpty())).toBe(6); expect(arrayNonEmptyLength(outputs.unencryptedLogsHashes, l => l.logHash.isEmpty())).toBe(2); - - expect(txResult.tailKernelOutput.revertCode).toEqual(RevertCode.OK); }); it('includes a transaction that reverts in teardown', async function () { @@ -196,28 +200,19 @@ describe('enqueued_calls_processor', () => { expect(tailSpy).toHaveBeenCalledTimes(1); expect(publicExecutor.simulate).toHaveBeenCalledTimes(3); - const outputs = txResult.tailKernelOutput.end; + const outputs = txResult.avmProvingRequest!.inputs.output.accumulatedData; const numPublicDataWrites = 3; - expect(arrayNonEmptyLength(outputs.publicDataUpdateRequests, PublicDataUpdateRequest.isEmpty)).toBe( - numPublicDataWrites, - ); - expect(outputs.publicDataUpdateRequests.slice(0, numPublicDataWrites)).toEqual([ - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.contractAddress, contractSlotA), - newValue: fr(0x101), - }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), - newValue: fr(0x102), - }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), - newValue: fr(0x151), - }), + expect(arrayNonEmptyLength(outputs.publicDataWrites, PublicDataWrite.isEmpty)).toBe(numPublicDataWrites); + expect(outputs.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ + new PublicDataWrite( + computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.contractAddress, contractSlotA), + fr(0x101), + ), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), fr(0x102)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x151)), ]); // we keep the non-revertible logs - expect(arrayNonEmptyLength(outputs.encryptedLogsHashes, l => l.logHash.isEmpty())).toBe(3); expect(arrayNonEmptyLength(outputs.unencryptedLogsHashes, l => l.logHash.isEmpty())).toBe(1); }); @@ -281,6 +276,7 @@ describe('enqueued_calls_processor', () => { expect(tailSpy).toHaveBeenCalledTimes(0); expect(publicExecutor.simulate).toHaveBeenCalledTimes(1); }); + it('rolls back app logic db updates on failed public execution, but persists setup', async function () { const tx = mockTx(1, { hasLogs: true, @@ -360,36 +356,21 @@ describe('enqueued_calls_processor', () => { expect(tailSpy).toHaveBeenCalledTimes(1); expect(publicExecutor.simulate).toHaveBeenCalledTimes(3); - const outputs = txResult.tailKernelOutput.end; + const outputs = txResult.avmProvingRequest!.inputs.output.accumulatedData; const numPublicDataWrites = 5; - expect(arrayNonEmptyLength(outputs.publicDataUpdateRequests, PublicDataUpdateRequest.isEmpty)).toBe( - numPublicDataWrites, - ); - expect(outputs.publicDataUpdateRequests.slice(0, numPublicDataWrites)).toEqual([ - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.contractAddress, contractSlotA), - newValue: fr(0x101), - }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotC), - newValue: fr(0x201), - }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotD), - newValue: fr(0x251), - }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotE), - newValue: fr(0x301), - }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotF), - newValue: fr(0x351), - }), + expect(arrayNonEmptyLength(outputs.publicDataWrites, PublicDataWrite.isEmpty)).toBe(numPublicDataWrites); + expect(outputs.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ + new PublicDataWrite( + computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.contractAddress, contractSlotA), + fr(0x101), + ), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotC), fr(0x201)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotD), fr(0x251)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotE), fr(0x301)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotF), fr(0x351)), ]); // we keep the non-revertible logs - expect(arrayNonEmptyLength(outputs.encryptedLogsHashes, l => l.logHash.isEmpty())).toBe(3); expect(arrayNonEmptyLength(outputs.unencryptedLogsHashes, l => l.logHash.isEmpty())).toBe(1); }); @@ -462,38 +443,29 @@ describe('enqueued_calls_processor', () => { expect(txResult.processedPhases[0]).toEqual(expect.objectContaining({ revertReason: undefined })); expect(txResult.processedPhases[1]).toEqual(expect.objectContaining({ revertReason: appLogicFailure })); expect(txResult.processedPhases[2]).toEqual(expect.objectContaining({ revertReason: teardownFailure })); + expect(txResult.revertCode).toEqual(RevertCode.BOTH_REVERTED); // tx reports app logic failure expect(txResult.revertReason).toBe(appLogicFailure); expect(tailSpy).toHaveBeenCalledTimes(1); expect(publicExecutor.simulate).toHaveBeenCalledTimes(3); - const outputs = txResult.tailKernelOutput.end; + const outputs = txResult.avmProvingRequest!.inputs.output.accumulatedData; const numPublicDataWrites = 3; - expect(arrayNonEmptyLength(outputs.publicDataUpdateRequests, PublicDataUpdateRequest.isEmpty)).toBe( - numPublicDataWrites, - ); - expect(outputs.publicDataUpdateRequests.slice(0, numPublicDataWrites)).toEqual([ - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.contractAddress, contractSlotA), - newValue: fr(0x101), - }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), - newValue: fr(0x102), - }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), - newValue: fr(0x151), - }), + expect(arrayNonEmptyLength(outputs.publicDataWrites, PublicDataWrite.isEmpty)).toBe(numPublicDataWrites); + expect(outputs.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ + new PublicDataWrite( + computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.contractAddress, contractSlotA), + fr(0x101), + ), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), fr(0x102)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x151)), ]); // we keep the non-revertible logs - expect(arrayNonEmptyLength(outputs.encryptedLogsHashes, l => l.logHash.isEmpty())).toBe(3); expect(arrayNonEmptyLength(outputs.unencryptedLogsHashes, l => l.logHash.isEmpty())).toBe(1); - - expect(txResult.tailKernelOutput.revertCode).toEqual(RevertCode.BOTH_REVERTED); }); + it('runs a tx with all phases', async function () { const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 1, @@ -505,22 +477,25 @@ describe('enqueued_calls_processor', () => { // Keep gas numbers MAX_L2_GAS_PER_ENQUEUED_CALL or the logic below has to get weird const gasLimits = Gas.from({ l2Gas: 1e6, daGas: 1e6 }); - const teardownGas = Gas.from({ l2Gas: 1e5, daGas: 1e5 }); + const teardownGasLimits = Gas.from({ l2Gas: 1e5, daGas: 1e5 }); tx.data.constants.txContext.gasSettings = GasSettings.from({ gasLimits: gasLimits, - teardownGasLimits: teardownGas, + teardownGasLimits, inclusionFee: new Fr(1e4), maxFeesPerGas: { feePerDaGas: new Fr(10), feePerL2Gas: new Fr(10) }, }); - // Private kernel tail to public pushes teardown gas allocation into revertible gas used - tx.data.forPublic!.end = PublicAccumulatedDataBuilder.fromPublicAccumulatedData(tx.data.forPublic!.end) - .withGasUsed(teardownGas) + const privateNonRevertibleGasUsed = Gas.from({ l2Gas: 20 }); + const privateRevertibleGasUsed = Gas.from({ l2Gas: 30 }); + tx.data.forPublic!.revertibleAccumulatedData = PrivateToPublicAccumulatedDataBuilder.fromPublicAccumulatedData( + tx.data.forPublic!.revertibleAccumulatedData, + ) + .withGasUsed(privateRevertibleGasUsed) .build(); - tx.data.forPublic!.endNonRevertibleData = PublicAccumulatedDataBuilder.fromPublicAccumulatedData( - tx.data.forPublic!.endNonRevertibleData, + tx.data.forPublic!.nonRevertibleAccumulatedData = PrivateToPublicAccumulatedDataBuilder.fromPublicAccumulatedData( + tx.data.forPublic!.nonRevertibleAccumulatedData, ) - .withGasUsed(Gas.empty()) + .withGasUsed(privateNonRevertibleGasUsed) .build(); const contractAddress = revertibleRequests[0].callContext.contractAddress; @@ -532,23 +507,25 @@ describe('enqueued_calls_processor', () => { // Keep gas numbers below MAX_L2_GAS_PER_ENQUEUED_CALL or we need // to separately compute available start gas and "effective" start gas // for each enqueued call after applying that max. - const initialGas = gasLimits.sub(teardownGas); + const privateGasUsed = tx.data.forPublic!.nonRevertibleAccumulatedData.gasUsed.add( + tx.data.forPublic!.revertibleAccumulatedData.gasUsed, + ); + const initialGas = gasLimits.sub(privateGasUsed); const setupGasUsed = Gas.from({ l2Gas: 1e4 }); const appGasUsed = Gas.from({ l2Gas: 2e4, daGas: 2e4 }); const teardownGasUsed = Gas.from({ l2Gas: 3e4, daGas: 3e4 }); const afterSetupGas = initialGas.sub(setupGasUsed); const afterAppGas = afterSetupGas.sub(appGasUsed); - const afterTeardownGas = teardownGas.sub(teardownGasUsed); + const afterTeardownGas = teardownGasLimits.sub(teardownGasUsed); - // Total gas used is the sum of teardown gas allocation plus all expenditures along the way, - // without including the gas used in the teardown phase (since that's consumed entirely up front). - const expectedTotalGasUsed = teardownGas.add(setupGasUsed).add(appGasUsed); - - // Inclusion fee plus block gas fees times total gas used + // Gas used for computing fees is different to the total gas consumed. + // For computing fees, the teardownGasLimits specified in the gasSettings is used instead of the actual gas in the teardown phase. + const feeGasUsed = privateGasUsed.add(setupGasUsed).add(appGasUsed).add(teardownGasLimits); + // Inclusion fee plus block gas fees times fee gas used const expectedTxFee = tx.data.constants.txContext.gasSettings.inclusionFee.toNumber() + - expectedTotalGasUsed.l2Gas * 1 + - expectedTotalGasUsed.daGas * 1; + feeGasUsed.l2Gas * GasFees.default().feePerL2Gas.toNumber() + + feeGasUsed.daGas * GasFees.default().feePerDaGas.toNumber(); const simulatorResults: EnqueuedPublicCallExecutionResult[] = [ // Setup @@ -612,6 +589,11 @@ describe('enqueued_calls_processor', () => { expect(txResult.processedPhases[0]).toEqual(expect.objectContaining({ revertReason: undefined })); expect(txResult.processedPhases[1]).toEqual(expect.objectContaining({ revertReason: undefined })); expect(txResult.processedPhases[2]).toEqual(expect.objectContaining({ revertReason: undefined })); + expect(txResult.gasUsed).toEqual({ + [PublicKernelPhase.SETUP]: setupGasUsed, + [PublicKernelPhase.APP_LOGIC]: appGasUsed, + [PublicKernelPhase.TEARDOWN]: teardownGasUsed, + }); expect(txResult.revertReason).toBe(undefined); expect(tailSpy).toHaveBeenCalledTimes(1); @@ -628,37 +610,30 @@ describe('enqueued_calls_processor', () => { expect(publicExecutor.simulate).toHaveBeenCalledTimes(3); expect(publicExecutor.simulate).toHaveBeenNthCalledWith(1, ...expectedSimulateCall(initialGas, 0)); expect(publicExecutor.simulate).toHaveBeenNthCalledWith(2, ...expectedSimulateCall(afterSetupGas, 0)); - expect(publicExecutor.simulate).toHaveBeenNthCalledWith(3, ...expectedSimulateCall(teardownGas, expectedTxFee)); + expect(publicExecutor.simulate).toHaveBeenNthCalledWith( + 3, + ...expectedSimulateCall(teardownGasLimits, expectedTxFee), + ); - const outputs = txResult.tailKernelOutput.end; - expect(outputs.gasUsed).toEqual(Gas.from(expectedTotalGasUsed)); + const output = txResult.avmProvingRequest!.inputs.output; + expect(output.transactionFee.toNumber()).toEqual(expectedTxFee); const numPublicDataWrites = 3; - expect(arrayNonEmptyLength(outputs.publicDataUpdateRequests, PublicDataUpdateRequest.isEmpty)).toBe( + expect(arrayNonEmptyLength(output.accumulatedData.publicDataWrites, PublicDataWrite.isEmpty)).toBe( numPublicDataWrites, ); - expect(outputs.publicDataUpdateRequests.slice(0, numPublicDataWrites)).toEqual([ + expect(output.accumulatedData.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ // squashed - //expect.objectContaining({ leafSlot: computePublicDataTreeLeafSlot(contractAddress, contractSlotA), newValue: fr(0x101), }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(contractAddress, contractSlotB), - newValue: fr(0x151), - }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(contractAddress, contractSlotA), - newValue: fr(0x103), - }), + // new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotA), fr(0x101)), + new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotB), fr(0x151)), + new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotA), fr(0x103)), // squashed - //expect.objectContaining({ leafSlot: computePublicDataTreeLeafSlot(contractAddress, contractSlotC), newValue: fr(0x201), }), - //expect.objectContaining({ leafSlot: computePublicDataTreeLeafSlot(contractAddress, contractSlotC), newValue: fr(0x102), }), - expect.objectContaining({ - leafSlot: computePublicDataTreeLeafSlot(contractAddress, contractSlotC), - newValue: fr(0x152), - }), + // new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotC), fr(0x201)), + // new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotC), fr(0x102)), + new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddress, contractSlotC), fr(0x152)), ]); - expect(arrayNonEmptyLength(outputs.encryptedLogsHashes, l => l.logHash.isEmpty())).toBe(0); - expect(arrayNonEmptyLength(outputs.unencryptedLogsHashes, l => l.logHash.isEmpty())).toBe(0); + expect(arrayNonEmptyLength(output.accumulatedData.unencryptedLogsHashes, l => l.logHash.isEmpty())).toBe(0); }); it('runs a tx with only teardown', async function () { @@ -677,16 +652,6 @@ describe('enqueued_calls_processor', () => { maxFeesPerGas: { feePerDaGas: new Fr(10), feePerL2Gas: new Fr(10) }, }); - // Private kernel tail to public pushes teardown gas allocation into revertible gas used - tx.data.forPublic!.end = PublicAccumulatedDataBuilder.fromPublicAccumulatedData(tx.data.forPublic!.end) - .withGasUsed(teardownGas) - .build(); - tx.data.forPublic!.endNonRevertibleData = PublicAccumulatedDataBuilder.fromPublicAccumulatedData( - tx.data.forPublic!.endNonRevertibleData, - ) - .withGasUsed(Gas.empty()) - .build(); - const teardownGasUsed = Gas.from({ l2Gas: 1e6, daGas: 1e6 }); const simulatorResults: EnqueuedPublicCallExecutionResult[] = [ @@ -705,6 +670,9 @@ describe('enqueued_calls_processor', () => { expect(txResult.processedPhases).toHaveLength(1); expect(txResult.processedPhases[0]).toEqual(expect.objectContaining({ revertReason: undefined })); + expect(txResult.gasUsed).toEqual({ + [PublicKernelPhase.TEARDOWN]: teardownGasUsed, + }); expect(txResult.revertReason).toBe(undefined); expect(tailSpy).toHaveBeenCalledTimes(1); diff --git a/yarn-project/simulator/src/public/enqueued_calls_processor.ts b/yarn-project/simulator/src/public/enqueued_calls_processor.ts index 3f13b35e110..918e33cb0e3 100644 --- a/yarn-project/simulator/src/public/enqueued_calls_processor.ts +++ b/yarn-project/simulator/src/public/enqueued_calls_processor.ts @@ -2,13 +2,16 @@ import { type AvmProvingRequest, type MerkleTreeReadOperations, type NestedProcessReturnValues, - type ProcessedTx, type PublicExecutionRequest, PublicKernelPhase, type SimulationError, type Tx, } from '@aztec/circuit-types'; import { + AvmAccumulatedData, + AvmCircuitPublicInputs, + type CombinedAccumulatedData, + CombinedConstantData, EnqueuedCallData, Fr, Gas, @@ -16,14 +19,23 @@ import { type Header, type KernelCircuitPublicInputs, NESTED_RECURSIVE_PROOF_LENGTH, + type PrivateKernelTailCircuitPublicInputs, + PrivateToAvmAccumulatedData, + PrivateToAvmAccumulatedDataArrayLengths, + type PrivateToPublicAccumulatedData, + PublicAccumulatedData, PublicAccumulatedDataArrayLengths, type PublicCallRequest, PublicKernelCircuitPrivateInputs, - type PublicKernelCircuitPublicInputs, + PublicKernelCircuitPublicInputs, PublicKernelData, PublicValidationRequestArrayLengths, + PublicValidationRequests, + RevertCode, + TreeSnapshots, type VMCircuitPublicInputs, VerificationKeyData, + countAccumulatedItems, makeEmptyProof, makeEmptyRecursiveProof, } from '@aztec/circuits.js'; @@ -65,6 +77,8 @@ type PublicPhaseResult = { revertReason?: SimulationError; }; +type PublicPhaseGasUsed = Partial>; + export type ProcessedPhase = { phase: PublicKernelPhase; durationMs: number; @@ -73,13 +87,12 @@ export type ProcessedPhase = { export type TxPublicCallsResult = { avmProvingRequest: AvmProvingRequest; - /** The output of the public kernel tail circuit simulation for this tx */ - tailKernelOutput: KernelCircuitPublicInputs; /** Return values of simulating complete callstack */ returnValues: NestedProcessReturnValues[]; /** Gas used during the execution this tx */ - gasUsed: ProcessedTx['gasUsed']; + gasUsed: PublicPhaseGasUsed; /** Revert reason, if any */ + revertCode: RevertCode; revertReason?: SimulationError; processedPhases: ProcessedPhase[]; }; @@ -165,9 +178,9 @@ export class EnqueuedCallsProcessor { PublicKernelPhase.TEARDOWN, ]; const processedPhases: ProcessedPhase[] = []; - const gasUsed: ProcessedTx['gasUsed'] = {}; + const gasUsed: PublicPhaseGasUsed = {}; let avmProvingRequest: AvmProvingRequest; - let publicKernelOutput = tx.data.toPublicKernelCircuitPublicInputs(); + let publicKernelOutput = this.getPublicKernelCircuitPublicInputs(tx.data); let isFromPrivate = true; let returnValues: NestedProcessReturnValues[] = []; let revertReason: SimulationError | undefined; @@ -270,12 +283,15 @@ export class EnqueuedCallsProcessor { }, ); + const transactionFee = this.getTransactionFee(tx, publicKernelOutput); + avmProvingRequest!.inputs.output = this.generateAvmCircuitPublicInputs(tx, tailKernelOutput, transactionFee); + return { avmProvingRequest: avmProvingRequest!, - tailKernelOutput, returnValues, gasUsed, processedPhases, + revertCode: tailKernelOutput.revertCode, revertReason, }; } @@ -311,7 +327,8 @@ export class EnqueuedCallsProcessor { await this.worldStateDB.addNewContracts(tx); const availableGas = this.getAvailableGas(tx, publicKernelOutput, phase); - const transactionFee = this.getTransactionFee(tx, publicKernelOutput, phase); + const transactionFee = + phase !== PublicKernelPhase.TEARDOWN ? Fr.ZERO : this.getTransactionFee(tx, publicKernelOutput); // each enqueued call starts with an incremented side effect counter const enqueuedCallStateManager = txStateManager.fork(/*incrementSideEffectCounter=*/ true); @@ -394,24 +411,16 @@ export class EnqueuedCallsProcessor { } } - private getTransactionFee( - tx: Tx, - previousPublicKernelOutput: PublicKernelCircuitPublicInputs, - phase: PublicKernelPhase, - ): Fr { - if (phase !== PublicKernelPhase.TEARDOWN) { - return Fr.ZERO; - } else { - const gasSettings = tx.data.constants.txContext.gasSettings; - const gasFees = this.globalVariables.gasFees; - // No need to add teardown limits since they are already included in end.gasUsed - const gasUsed = previousPublicKernelOutput.end.gasUsed.add( - previousPublicKernelOutput.endNonRevertibleData.gasUsed, - ); - const txFee = gasSettings.inclusionFee.add(gasUsed.computeFee(gasFees)); - this.log.debug(`Computed tx fee`, { txFee, gasUsed: inspect(gasUsed), gasFees: inspect(gasFees) }); - return txFee; - } + private getTransactionFee(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs): Fr { + const gasSettings = tx.data.constants.txContext.gasSettings; + const gasFees = this.globalVariables.gasFees; + // No need to add teardown limits since they are already included in end.gasUsed + const gasUsed = previousPublicKernelOutput.end.gasUsed + .add(previousPublicKernelOutput.endNonRevertibleData.gasUsed) + .add(gasSettings.teardownGasLimits); + const txFee = gasSettings.inclusionFee.add(gasUsed.computeFee(gasFees)); + this.log.debug(`Computed tx fee`, { txFee, gasUsed: inspect(gasUsed), gasFees: inspect(gasFees) }); + return txFee; } private async runMergeKernelCircuit( @@ -443,4 +452,86 @@ export class EnqueuedCallsProcessor { return new PublicKernelData(previousOutput, proof, vk, vkIndex, siblingPath); } + + // Temporary hack to create PublicKernelCircuitPublicInputs from PrivateKernelTailCircuitPublicInputs. + private getPublicKernelCircuitPublicInputs(data: PrivateKernelTailCircuitPublicInputs) { + const constants = CombinedConstantData.combine(data.constants, this.globalVariables); + + const validationRequest = PublicValidationRequests.empty(); + validationRequest.forRollup = data.rollupValidationRequests; + + const convertAccumulatedData = (from: PrivateToPublicAccumulatedData) => { + const to = PublicAccumulatedData.empty(); + to.noteHashes.forEach((_, i) => (to.noteHashes[i].noteHash.value = from.noteHashes[i])); + to.nullifiers.forEach((_, i) => (to.nullifiers[i].value = from.nullifiers[i])); + to.l2ToL1Msgs.forEach((_, i) => (to.l2ToL1Msgs[i] = from.l2ToL1Msgs[i])); + to.noteEncryptedLogsHashes.forEach((_, i) => (to.noteEncryptedLogsHashes[i] = from.noteEncryptedLogsHashes[i])); + to.encryptedLogsHashes.forEach((_, i) => (to.encryptedLogsHashes[i] = from.encryptedLogsHashes[i])); + to.unencryptedLogsHashes.forEach((_, i) => (to.unencryptedLogsHashes[i] = from.unencryptedLogsHashes[i])); + to.publicCallStack.forEach((_, i) => (to.publicCallStack[i] = from.publicCallRequests[i])); + (to.gasUsed as any) = from.gasUsed; + return to; + }; + + return new PublicKernelCircuitPublicInputs( + constants, + validationRequest, + convertAccumulatedData(data.forPublic!.nonRevertibleAccumulatedData), + convertAccumulatedData(data.forPublic!.revertibleAccumulatedData), + 0, + data.forPublic!.publicTeardownCallRequest, + data.feePayer, + RevertCode.OK, + ); + } + + // Temporary hack to create the AvmCircuitPublicInputs from public tail's public inputs. + private generateAvmCircuitPublicInputs(tx: Tx, tailOutput: KernelCircuitPublicInputs, transactionFee: Fr) { + const startTreeSnapshots = new TreeSnapshots( + tailOutput.constants.historicalHeader.state.l1ToL2MessageTree, + tailOutput.startState.noteHashTree, + tailOutput.startState.nullifierTree, + tailOutput.startState.publicDataTree, + ); + + const getArrayLengths = (from: PrivateToPublicAccumulatedData) => + new PrivateToAvmAccumulatedDataArrayLengths( + countAccumulatedItems(from.noteHashes), + countAccumulatedItems(from.nullifiers), + countAccumulatedItems(from.l2ToL1Msgs), + ); + + const convertAccumulatedData = (from: PrivateToPublicAccumulatedData) => + new PrivateToAvmAccumulatedData(from.noteHashes, from.nullifiers, from.l2ToL1Msgs); + + const convertAvmAccumulatedData = (from: CombinedAccumulatedData) => + new AvmAccumulatedData( + from.noteHashes, + from.nullifiers, + from.l2ToL1Msgs, + from.unencryptedLogsHashes, + from.publicDataWrites, + ); + + // This is wrong. But this is not used or checked in the rollup at the moment. + // Should fetch the updated roots from db. + const endTreeSnapshots = startTreeSnapshots; + + return new AvmCircuitPublicInputs( + tailOutput.constants.globalVariables, + startTreeSnapshots, + tx.data.constants.txContext.gasSettings, + tx.data.forPublic!.nonRevertibleAccumulatedData.publicCallRequests, + tx.data.forPublic!.revertibleAccumulatedData.publicCallRequests, + tx.data.forPublic!.publicTeardownCallRequest, + getArrayLengths(tx.data.forPublic!.nonRevertibleAccumulatedData), + getArrayLengths(tx.data.forPublic!.revertibleAccumulatedData), + convertAccumulatedData(tx.data.forPublic!.nonRevertibleAccumulatedData), + convertAccumulatedData(tx.data.forPublic!.revertibleAccumulatedData), + endTreeSnapshots, + convertAvmAccumulatedData(tailOutput.end), + transactionFee, + !tailOutput.revertCode.equals(RevertCode.OK), + ); + } } diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 2159e77bc18..b8d7869f06f 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -16,16 +16,13 @@ import { GasSettings, GlobalVariables, Header, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, PartialStateReference, PublicDataTreeLeafPreimage, - PublicDataUpdateRequest, + PublicDataWrite, StateReference, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; -import { times } from '@aztec/foundation/collection'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type AppendOnlyTree, Poseidon, StandardTree, newTree } from '@aztec/merkle-tree'; import { type PublicExecutor, WASMSimulator, computeFeePayerBalanceLeafSlot } from '@aztec/simulator'; @@ -86,25 +83,12 @@ describe('public_processor', () => { const [processed, failed] = await processor.process([tx], 1, handler); expect(processed.length).toBe(1); - - const expected: ProcessedTx = { - hash, - data: tx.data.toKernelCircuitPublicInputs(), - noteEncryptedLogs: tx.noteEncryptedLogs, - encryptedLogs: tx.encryptedLogs, - unencryptedLogs: tx.unencryptedLogs, - clientIvcProof: tx.clientIvcProof, - isEmpty: false, - revertReason: undefined, - avmProvingRequest: undefined, - gasUsed: {}, - finalPublicDataUpdateRequests: times( - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - PublicDataUpdateRequest.empty, - ), - }; - - expect(processed[0]).toEqual(expected); + expect(processed[0]).toEqual( + expect.objectContaining({ + hash, + data: tx.data, + }), + ); expect(failed).toEqual([]); expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); @@ -195,8 +179,8 @@ describe('public_processor', () => { expect(worldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); // we keep the logs - expect(processed[0].encryptedLogs.getTotalLogCount()).toBe(6); - expect(processed[0].unencryptedLogs.getTotalLogCount()).toBe(2); + expect(processed[0].txEffect.encryptedLogs.getTotalLogCount()).toBe(6); + expect(processed[0].txEffect.unencryptedLogs.getTotalLogCount()).toBe(2); expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); }); @@ -268,12 +252,8 @@ describe('public_processor', () => { expect(worldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(1); expect(processed[0].data.feePayer).toEqual(feePayer); - expect(processed[0].finalPublicDataUpdateRequests[MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]).toEqual( - PublicDataUpdateRequest.from({ - leafIndex: computeFeePayerBalanceLeafSlot(feePayer), - newValue: new Fr(initialBalance - inclusionFee), - sideEffectCounter: 0, - }), + expect(processed[0].txEffect.publicDataWrites[0]).toEqual( + new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), new Fr(initialBalance - inclusionFee)), ); expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); @@ -310,12 +290,10 @@ describe('public_processor', () => { expect(worldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(1); expect(processed[0].data.feePayer).toEqual(feePayer); - expect(processed[0].finalPublicDataUpdateRequests[MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]).toEqual( - PublicDataUpdateRequest.from({ - leafIndex: computeFeePayerBalanceLeafSlot(feePayer), - newValue: new Fr(initialBalance - inclusionFee), - sideEffectCounter: 0, - }), + + const transactionFee = processed[0].txEffect.transactionFee.toBigInt(); + expect(processed[0].txEffect.publicDataWrites[0]).toEqual( + new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), new Fr(initialBalance - transactionFee)), ); expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); @@ -327,7 +305,7 @@ describe('public_processor', () => { const inclusionFee = 100n; const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 0, - numberOfRevertiblePublicCallRequests: 2, + numberOfRevertiblePublicCallRequests: 0, feePayer, }); @@ -341,11 +319,12 @@ describe('public_processor', () => { Promise.resolve(computePublicDataTreeLeafSlot(address, slot).toBigInt()), ); - tx.data.publicInputs.end.publicDataUpdateRequests[0] = PublicDataUpdateRequest.from({ - leafIndex: computeFeePayerBalanceLeafSlot(feePayer), - newValue: new Fr(initialBalance), - sideEffectCounter: 0, - }); + // TODO: Find a better way to test this. + // This is wrong. Private kernel tail cannot output any publicDataWrites. + tx.data.forRollup!.end.publicDataWrites[0] = new PublicDataWrite( + computeFeePayerBalanceLeafSlot(feePayer), + new Fr(initialBalance), + ); const [processed, failed] = await processor.process([tx], 1, handler); @@ -353,17 +332,14 @@ describe('public_processor', () => { expect(processed).toHaveLength(1); expect(processed[0].hash).toEqual(tx.getTxHash()); expect(processed[0].clientIvcProof).toEqual(proof); - expect(publicExecutor.simulate).toHaveBeenCalledTimes(2); expect(worldStateDB.commit).toHaveBeenCalledTimes(1); expect(worldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); expect(worldStateDB.storageWrite).toHaveBeenCalledTimes(1); expect(processed[0].data.feePayer).toEqual(feePayer); - expect(processed[0].finalPublicDataUpdateRequests[0]).toEqual( - PublicDataUpdateRequest.from({ - leafIndex: computeFeePayerBalanceLeafSlot(feePayer), - newValue: new Fr(initialBalance - inclusionFee), - sideEffectCounter: 0, - }), + + const transactionFee = processed[0].txEffect.transactionFee.toBigInt(); + expect(processed[0].txEffect.publicDataWrites[0]).toEqual( + new PublicDataWrite(computeFeePayerBalanceLeafSlot(feePayer), new Fr(initialBalance - transactionFee)), ); expect(handler.addNewTx).toHaveBeenCalledWith(processed[0]); diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index 4e0cda3b947..ef43a25b28a 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -5,25 +5,27 @@ import { NestedProcessReturnValues, type ProcessedTx, type ProcessedTxHandler, + PublicKernelPhase, Tx, type TxValidator, - makeProcessedTx, - validateProcessedTx, + makeProcessedTxFromPrivateOnlyTx, + makeProcessedTxFromTxWithPublicCalls, } from '@aztec/circuit-types'; import { ContractClassRegisteredEvent, type ContractDataSource, + Fr, + Gas, type GlobalVariables, type Header, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NULLIFIER_SUBTREE_HEIGHT, - PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_SUBTREE_HEIGHT, - PublicDataTreeLeaf, - PublicDataUpdateRequest, + PublicDataWrite, } from '@aztec/circuits.js'; -import { padArrayEnd, times } from '@aztec/foundation/collection'; +import { padArrayEnd } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; @@ -157,21 +159,17 @@ export class PublicProcessor { } try { const [processedTx, returnValues] = !tx.hasPublicCalls() - ? [makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs())] + ? await this.processPrivateOnlyTx(tx) : await this.processTxWithPublicCalls(tx); this.log.debug(`Processed tx`, { txHash: processedTx.hash, - historicalHeaderHash: processedTx.data.constants.historicalHeader.hash(), - blockNumber: processedTx.data.constants.globalVariables.blockNumber, - lastArchiveRoot: processedTx.data.constants.historicalHeader.lastArchive.root, + historicalHeaderHash: processedTx.constants.historicalHeader.hash(), + blockNumber: processedTx.constants.globalVariables.blockNumber, + lastArchiveRoot: processedTx.constants.historicalHeader.lastArchive.root, }); - // Set fee payment update request into the processed tx - processedTx.finalPublicDataUpdateRequests = await this.createFinalDataUpdateRequests(processedTx); - // Commit the state updates from this transaction await this.worldStateDB.commit(); - validateProcessedTx(processedTx); // Re-validate the transaction if (txValidator) { @@ -194,11 +192,14 @@ export class PublicProcessor { // b) always had a txHandler with the same db passed to it as this.db, which updated the db in buildBaseRollupHints in this loop // To see how this ^ happens, move back to one shared db in test_context and run orchestrator_multi_public_functions.test.ts // The below is taken from buildBaseRollupHints: - await this.db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, processedTx.data.end.noteHashes); + await this.db.appendLeaves( + MerkleTreeId.NOTE_HASH_TREE, + padArrayEnd(processedTx.txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX), + ); try { await this.db.batchInsert( MerkleTreeId.NULLIFIER_TREE, - processedTx.data.end.nullifiers.map(n => n.toBuffer()), + padArrayEnd(processedTx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()), NULLIFIER_SUBTREE_HEIGHT, ); } catch (error) { @@ -211,14 +212,11 @@ export class PublicProcessor { } } - const allPublicDataUpdateRequests = padArrayEnd( - processedTx.finalPublicDataUpdateRequests, - PublicDataUpdateRequest.empty(), + const allPublicDataWrites = padArrayEnd( + processedTx.txEffect.publicDataWrites, + PublicDataWrite.empty(), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ); - const allPublicDataWrites = allPublicDataUpdateRequests.map( - ({ leafSlot, newValue }) => new PublicDataTreeLeaf(leafSlot, newValue), - ); await this.db.batchInsert( MerkleTreeId.PUBLIC_DATA_TREE, allPublicDataWrites.map(x => x.toBuffer()), @@ -247,32 +245,26 @@ export class PublicProcessor { * request for updating fee balance. It also updates the local public state db. * See build_or_patch_payment_update_request in base_rollup_inputs.nr for more details. */ - private async createFinalDataUpdateRequests(tx: ProcessedTx) { - const finalPublicDataUpdateRequests = [ - ...tx.data.end.publicDataUpdateRequests, - ...times(PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, () => PublicDataUpdateRequest.empty()), - ]; - - const feePayer = tx.data.feePayer; + private async getFeePaymentPublicDataWrite( + publicDataWrites: PublicDataWrite[], + txFee: Fr, + feePayer: Fr, + ): Promise { if (feePayer.isZero()) { - return finalPublicDataUpdateRequests; + return; } const feeJuiceAddress = ProtocolContractAddress.FeeJuice; const balanceSlot = computeFeePayerBalanceStorageSlot(feePayer); const leafSlot = computeFeePayerBalanceLeafSlot(feePayer); - const txFee = tx.data.getTransactionFee(this.globalVariables.gasFees); this.log.debug(`Deducting ${txFee} balance in Fee Juice for ${feePayer}`); - const existingBalanceWriteIndex = finalPublicDataUpdateRequests.findIndex(request => - request.leafSlot.equals(leafSlot), - ); + const existingBalanceWrite = publicDataWrites.find(write => write.leafSlot.equals(leafSlot)); - const balance = - existingBalanceWriteIndex > -1 - ? finalPublicDataUpdateRequests[existingBalanceWriteIndex].newValue - : await this.worldStateDB.storageRead(feeJuiceAddress, balanceSlot); + const balance = existingBalanceWrite + ? existingBalanceWrite.value + : await this.worldStateDB.storageRead(feeJuiceAddress, balanceSlot); if (balance.lt(txFee)) { throw new Error(`Not enough balance for fee payer to pay for transaction (got ${balance} needs ${txFee})`); @@ -281,11 +273,30 @@ export class PublicProcessor { const updatedBalance = balance.sub(txFee); await this.worldStateDB.storageWrite(feeJuiceAddress, balanceSlot, updatedBalance); - finalPublicDataUpdateRequests[ - existingBalanceWriteIndex > -1 ? existingBalanceWriteIndex : MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX - ] = new PublicDataUpdateRequest(leafSlot, updatedBalance, 0); + return new PublicDataWrite(leafSlot, updatedBalance); + } + + private async processPrivateOnlyTx(tx: Tx): Promise<[ProcessedTx]> { + const txData = tx.data.toKernelCircuitPublicInputs(); + + const gasFees = this.globalVariables.gasFees; + const transactionFee = txData.end.gasUsed + .computeFee(gasFees) + .add(txData.constants.txContext.gasSettings.inclusionFee); - return finalPublicDataUpdateRequests; + const feePaymentPublicDataWrite = await this.getFeePaymentPublicDataWrite( + txData.end.publicDataWrites, + transactionFee, + txData.feePayer, + ); + + const processedTx = makeProcessedTxFromPrivateOnlyTx( + tx, + transactionFee, + feePaymentPublicDataWrite, + this.globalVariables, + ); + return [processedTx]; } @trackSpan('PublicProcessor.processTxWithPublicCalls', tx => ({ @@ -294,12 +305,18 @@ export class PublicProcessor { private async processTxWithPublicCalls(tx: Tx): Promise<[ProcessedTx, NestedProcessReturnValues[]]> { const timer = new Timer(); - const { avmProvingRequest, tailKernelOutput, returnValues, revertReason, gasUsed, processedPhases } = - await this.enqueuedCallsProcessor.process(tx); + const { + avmProvingRequest, + returnValues, + revertCode, + revertReason, + gasUsed: phaseGasUsed, + processedPhases, + } = await this.enqueuedCallsProcessor.process(tx); - if (!tailKernelOutput) { + if (!avmProvingRequest) { this.metrics.recordFailedTx(); - throw new Error('Final public kernel was not executed.'); + throw new Error('Avm proving result was not generated.'); } processedPhases.forEach(phase => { @@ -320,7 +337,31 @@ export class PublicProcessor { const phaseCount = processedPhases.length; this.metrics.recordTx(phaseCount, timer.ms()); - const processedTx = makeProcessedTx(tx, tailKernelOutput, { avmProvingRequest, revertReason, gasUsed }); + const data = avmProvingRequest.inputs.output; + const feePaymentPublicDataWrite = await this.getFeePaymentPublicDataWrite( + data.accumulatedData.publicDataWrites, + data.transactionFee, + tx.data.feePayer, + ); + + const privateGasUsed = tx.data.forPublic!.revertibleAccumulatedData.gasUsed.add( + tx.data.forPublic!.nonRevertibleAccumulatedData.gasUsed, + ); + const publicGasUsed = Object.values(phaseGasUsed).reduce((total, gas) => total.add(gas), Gas.empty()); + const gasUsed = { + totalGas: privateGasUsed.add(publicGasUsed), + teardownGas: phaseGasUsed[PublicKernelPhase.TEARDOWN] ?? Gas.empty(), + }; + + const processedTx = makeProcessedTxFromTxWithPublicCalls( + tx, + avmProvingRequest, + feePaymentPublicDataWrite, + gasUsed, + revertCode, + revertReason, + ); + return [processedTx, returnValues]; } } diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index dff3c63ac7d..f4d8e097acc 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -6,7 +6,6 @@ import { type NoteStatus, NullifierMembershipWitness, PublicDataWitness, - PublicDataWrite, PublicExecutionRequest, SimulationError, type UnencryptedL2Log, @@ -504,14 +503,14 @@ export class TXE implements TypedOracle { const publicDataWrites = values.map((value, i) => { const storageSlot = startStorageSlot.add(new Fr(i)); this.logger.debug(`Oracle storage write: slot=${storageSlot.toString()} value=${value}`); - return new PublicDataWrite(computePublicDataTreeLeafSlot(this.contractAddress, storageSlot), value); + return new PublicDataTreeLeaf(computePublicDataTreeLeafSlot(this.contractAddress, storageSlot), value); }); await db.batchInsert( MerkleTreeId.PUBLIC_DATA_TREE, - publicDataWrites.map(write => new PublicDataTreeLeaf(write.leafIndex, write.newValue).toBuffer()), + publicDataWrites.map(write => write.toBuffer()), PUBLIC_DATA_SUBTREE_HEIGHT, ); - return publicDataWrites.map(write => write.newValue); + return publicDataWrites.map(write => write.value); } emitEncryptedLog(_contractAddress: AztecAddress, _randomness: Fr, _encryptedNote: Buffer, counter: number): void { diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 107211915f8..7abccd7cb45 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -1,5 +1,5 @@ import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr'; -import { L2Block, MerkleTreeId, PublicDataWrite, SimulationError } from '@aztec/circuit-types'; +import { L2Block, MerkleTreeId, SimulationError } from '@aztec/circuit-types'; import { Fr, FunctionSelector, @@ -151,14 +151,14 @@ export class TXEService { const publicDataWrites = valuesFr.map((value, i) => { const storageSlot = startStorageSlotFr.add(new Fr(i)); this.logger.debug(`Oracle storage write: slot=${storageSlot.toString()} value=${value}`); - return new PublicDataWrite(computePublicDataTreeLeafSlot(contractAddressFr, storageSlot), value); + return new PublicDataTreeLeaf(computePublicDataTreeLeafSlot(contractAddressFr, storageSlot), value); }); await db.batchInsert( MerkleTreeId.PUBLIC_DATA_TREE, - publicDataWrites.map(write => new PublicDataTreeLeaf(write.leafIndex, write.newValue).toBuffer()), + publicDataWrites.map(write => write.toBuffer()), PUBLIC_DATA_SUBTREE_HEIGHT, ); - return toForeignCallResult([toArray(publicDataWrites.map(write => write.newValue))]); + return toForeignCallResult([toArray(publicDataWrites.map(write => write.value))]); } async createAccount() { diff --git a/yarn-project/world-state/src/native/native_world_state.ts b/yarn-project/world-state/src/native/native_world_state.ts index 8d1d83818c0..7be252683e1 100644 --- a/yarn-project/world-state/src/native/native_world_state.ts +++ b/yarn-project/world-state/src/native/native_world_state.ts @@ -153,7 +153,7 @@ export class NativeWorldStateService implements MerkleTreeDatabase { PublicDataTreeLeaf.empty(), ); for (const [i, write] of txEffect.publicDataWrites.entries()) { - batch[i] = new PublicDataTreeLeaf(write.leafIndex, write.newValue); + batch[i] = new PublicDataTreeLeaf(write.leafSlot, write.value); } batchesOfPaddedPublicDataWrites.push(batch); diff --git a/yarn-project/world-state/src/test/utils.ts b/yarn-project/world-state/src/test/utils.ts index f8b74bcef0a..e6148637fef 100644 --- a/yarn-project/world-state/src/test/utils.ts +++ b/yarn-project/world-state/src/test/utils.ts @@ -3,7 +3,6 @@ import { MerkleTreeId, type MerkleTreeReadOperations, type MerkleTreeWriteOperations, - PublicDataWrite, TxEffect, } from '@aztec/circuit-types'; import { @@ -15,7 +14,7 @@ import { NULLIFIER_SUBTREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, PUBLIC_DATA_SUBTREE_HEIGHT, - PublicDataTreeLeaf, + PublicDataWrite, } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -54,7 +53,7 @@ export async function mockBlock(blockNum: number, size: number, fork: MerkleTree await fork.batchInsert( MerkleTreeId.PUBLIC_DATA_TREE, - publicDataWrites.map(write => new PublicDataTreeLeaf(write.leafIndex, write.newValue).toBuffer()), + publicDataWrites.map(write => write.toBuffer()), PUBLIC_DATA_SUBTREE_HEIGHT, ); diff --git a/yarn-project/world-state/src/world-state-db/merkle_trees.ts b/yarn-project/world-state/src/world-state-db/merkle_trees.ts index 23923699f27..7b0f9214d44 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_trees.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_trees.ts @@ -1,4 +1,4 @@ -import { type L2Block, MerkleTreeId, PublicDataWrite, type SiblingPath, TxEffect } from '@aztec/circuit-types'; +import { type L2Block, MerkleTreeId, type SiblingPath, TxEffect } from '@aztec/circuit-types'; import { type BatchInsertionResult, type IndexedTreeId, @@ -27,6 +27,7 @@ import { PartialStateReference, PublicDataTreeLeaf, PublicDataTreeLeafPreimage, + PublicDataWrite, StateReference, } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -678,7 +679,7 @@ export class MerkleTrees implements MerkleTreeAdminDatabase { ); await publicDataTree.batchInsert( - publicDataWrites.map(write => new PublicDataTreeLeaf(write.leafIndex, write.newValue).toBuffer()), + publicDataWrites.map(write => write.toBuffer()), PUBLIC_DATA_SUBTREE_HEIGHT, ); }