diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp index 156c52d7dc3b..0dffaa69e4d9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp @@ -27,10 +27,11 @@ #define LOG_HASH_LENGTH 3 #define NOTE_HASH_LENGTH 2 #define NULLIFIER_LENGTH 3 +#define PUBLIC_CALL_REQUEST_LENGTH 14 #define STATE_REFERENCE_LENGTH 8 #define TOTAL_FEES_LENGTH 1 #define HEADER_LENGTH 23 -#define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 481 +#define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 689 #define PUBLIC_CONTEXT_INPUTS_LENGTH 40 #define SENDER_SELECTOR 0 #define ADDRESS_SELECTOR 1 diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp index 62d2cbc49459..4d63d8c0a0bf 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp @@ -60,7 +60,7 @@ inline const uint32_t PCPI_PUBLIC_CALLSTACK_OFFSET = PCPI_PUBLIC_DATA_READ_OFFSET + (MAX_PUBLIC_DATA_READS_PER_CALL * CONTRACT_STORAGE_READ_LENGTH); inline const uint32_t PCPI_NEW_NOTE_HASHES_OFFSET = - PCPI_PUBLIC_CALLSTACK_OFFSET + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; + PCPI_PUBLIC_CALLSTACK_OFFSET + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL * PUBLIC_CALL_REQUEST_LENGTH); inline const uint32_t PCPI_NEW_NULLIFIERS_OFFSET = PCPI_NEW_NOTE_HASHES_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 afd0a4490fa7..5349b9661931 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -165,18 +165,18 @@ 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 CALLER_CONTEXT_LENGTH = 3; - uint256 internal constant PRIVATE_CALL_REQUEST_LENGTH = 15; - uint256 internal constant SCOPED_PRIVATE_CALL_REQUEST_LENGTH = 16; + uint256 internal constant PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 13; + uint256 internal constant PRIVATE_CALL_REQUEST_LENGTH = 10; + uint256 internal constant PUBLIC_CALL_REQUEST_LENGTH = 14; uint256 internal constant ROLLUP_VALIDATION_REQUESTS_LENGTH = 2; uint256 internal constant STATE_REFERENCE_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 = 23; - uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 444; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 481; - uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 447; + uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 645; + uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 689; + uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 648; uint256 internal constant PUBLIC_CONTEXT_INPUTS_LENGTH = 40; uint256 internal constant AGGREGATION_OBJECT_LENGTH = 16; uint256 internal constant SCOPED_READ_REQUEST_LEN = 3; @@ -185,16 +185,13 @@ library Constants { uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 364; uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = 41; - uint256 internal constant PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 15; - uint256 internal constant CALL_REQUEST_LENGTH = 7; - uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1160; - uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2300; - uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 991; - uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3339; + uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1336; + uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2483; + uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 1215; + uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 4011; uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 415; uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 11; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 28; - uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 9; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; 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 c381f9866aef..4ea1d70fcec5 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -6,20 +6,18 @@ use crate::{ key_validation_request::get_key_validation_request, arguments, returns::pack_returns, call_private_function::call_private_function_internal, header::get_header_at, logs::{emit_encrypted_note_log, emit_encrypted_event_log}, - enqueue_public_function_call::{ - enqueue_public_function_call_internal, set_public_teardown_function_call_internal, - parse_public_call_stack_item_from_oracle -} + enqueue_public_function_call::{enqueue_public_function_call_internal, set_public_teardown_function_call_internal} } }; use dep::protocol_types::{ abis::{ - caller_context::CallerContext, function_selector::FunctionSelector, + call_context::CallContext, function_selector::FunctionSelector, gas::Gas, max_block_number::MaxBlockNumber, validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator}, private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs, - public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash, - nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash} + public_call_request::PublicCallRequest, public_call_stack_item::PublicCallStackItem, + public_call_stack_item_compressed::PublicCallStackItemCompressed, read_request::ReadRequest, + note_hash::NoteHash, nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash} }, address::{AztecAddress, EthAddress}, constants::{ @@ -54,8 +52,8 @@ struct PrivateContext { nullifiers: BoundedVec, private_call_requests : BoundedVec, - public_call_stack_hashes : BoundedVec, - public_teardown_function_hash: Field, + public_call_requests : BoundedVec, + public_teardown_call_request: PublicCallRequest, l2_to_l1_msgs : BoundedVec, // docs:end:private-context @@ -89,8 +87,8 @@ impl PrivateContext { nullifiers: BoundedVec::new(), historical_header: inputs.historical_header, private_call_requests: BoundedVec::new(), - public_call_stack_hashes: BoundedVec::new(), - public_teardown_function_hash: 0, + public_call_requests: BoundedVec::new(), + public_teardown_call_request: PublicCallRequest::empty(), l2_to_l1_msgs: BoundedVec::new(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), @@ -164,8 +162,8 @@ impl PrivateContext { note_hashes: self.note_hashes.storage, nullifiers: self.nullifiers.storage, private_call_requests: self.private_call_requests.storage, - public_call_stack_hashes: self.public_call_stack_hashes.storage, - public_teardown_function_hash: self.public_teardown_function_hash, + public_call_requests: self.public_call_requests.storage, + public_teardown_call_request: self.public_teardown_call_request, l2_to_l1_msgs: self.l2_to_l1_msgs.storage, start_side_effect_counter: self.inputs.start_side_effect_counter, end_side_effect_counter: self.side_effect_counter, @@ -353,7 +351,7 @@ impl PrivateContext { ) -> PackedReturns { let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call; let start_side_effect_counter = self.side_effect_counter; - let item = call_private_function_internal( + let (end_side_effect_counter, returns_hash) = call_private_function_internal( contract_address, function_selector, args_hash, @@ -362,8 +360,6 @@ impl PrivateContext { is_delegate_call ); - assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter); - let end_side_effect_counter = item.public_inputs.end_side_effect_counter; self.side_effect_counter = end_side_effect_counter + 1; // TODO (fees) figure out why this crashes the prover and enable it @@ -379,49 +375,25 @@ impl PrivateContext { // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter; // } - assert(contract_address.eq(item.contract_address)); - assert(function_selector.eq(item.function_data.selector)); - - assert(args_hash == item.public_inputs.args_hash); - - // Assert that the call context of the call generated by the oracle matches our request. - assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call); - assert(item.public_inputs.call_context.is_static_call == is_static_call); - - if (is_delegate_call) { - // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address. - assert( - item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address) - ); - assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender)); - } else { - // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called. - assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address)); - assert( - item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address) - ); - } + let call_context = self.generate_call_context( + contract_address, + function_selector, + is_static_call, + is_delegate_call + ); - let mut caller_context = CallerContext::empty(); - caller_context.is_static_call = self.inputs.call_context.is_static_call; - if is_delegate_call { - caller_context.msg_sender = self.inputs.call_context.msg_sender; - caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address; - } self.private_call_requests.push( PrivateCallRequest { - target: item.contract_address, - call_context: item.public_inputs.call_context, - function_data: item.function_data, - args_hash: item.public_inputs.args_hash, - returns_hash: item.public_inputs.returns_hash, - caller_context, + contract_address, + call_context, + args_hash, + returns_hash, start_side_effect_counter, end_side_effect_counter } ); - PackedReturns::new(item.public_inputs.returns_hash) + PackedReturns::new(returns_hash) } pub fn call_public_function( @@ -489,28 +461,37 @@ impl PrivateContext { is_static_call: bool, is_delegate_call: bool ) { + let counter = self.next_counter(); + let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call; - let fields = enqueue_public_function_call_internal( + enqueue_public_function_call_internal( contract_address, function_selector, args_hash, - self.side_effect_counter, + counter, is_static_call, is_delegate_call ); - let item = parse_public_call_stack_item_from_oracle(fields); - self.validate_call_stack_item_from_oracle( - item, + let call_context = self.generate_call_context( contract_address, function_selector, - args_hash, is_static_call, is_delegate_call ); - self.side_effect_counter = self.side_effect_counter + 1; - self.public_call_stack_hashes.push(item.get_compressed().hash()); + let item = PublicCallStackItemCompressed { + contract_address, + call_context, + args_hash, + returns_hash: 0, + revert_code: 0, + start_gas_left: Gas::empty(), + end_gas_left: Gas::empty() + }; + + let call_request = PublicCallRequest { item, counter }; + self.public_call_requests.push(call_request); } pub fn set_public_teardown_function( @@ -532,63 +513,59 @@ impl PrivateContext { is_static_call: bool, is_delegate_call: bool ) { + let counter = self.next_counter(); + let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call; - let fields = set_public_teardown_function_call_internal( + set_public_teardown_function_call_internal( contract_address, function_selector, args_hash, - self.side_effect_counter, + counter, is_static_call, is_delegate_call ); - let item = parse_public_call_stack_item_from_oracle(fields); - self.validate_call_stack_item_from_oracle( - item, + let call_context = self.generate_call_context( contract_address, function_selector, - args_hash, is_static_call, is_delegate_call ); - self.side_effect_counter = self.side_effect_counter + 1; - self.public_teardown_function_hash = item.get_compressed().hash(); + let item = PublicCallStackItemCompressed { + contract_address, + call_context, + args_hash, + returns_hash: 0, + revert_code: 0, + start_gas_left: Gas::empty(), + end_gas_left: Gas::empty() + }; + + self.public_teardown_call_request = PublicCallRequest { + item, + counter, + }; } - fn validate_call_stack_item_from_oracle( + fn generate_call_context( self, - item: PublicCallStackItem, contract_address: AztecAddress, function_selector: FunctionSelector, - args_hash: Field, is_static_call: bool, is_delegate_call: bool - ) { - assert(contract_address.eq(item.contract_address)); - assert(function_selector.eq(item.function_data.selector)); - - assert_eq(item.public_inputs.start_side_effect_counter, self.side_effect_counter); - - assert(args_hash == item.public_inputs.args_hash); - - // Assert that the call context of the enqueued call generated by the oracle matches our request. - assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call); - assert(item.public_inputs.call_context.is_static_call == is_static_call); - - if (is_delegate_call) { - // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address. - assert( - item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address) - ); - assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender)); + ) -> CallContext { + let msg_sender = if is_delegate_call { + self.msg_sender() } else { - // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called. - assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address)); - assert( - item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address) - ); - } + self.this_address() + }; + let storage_contract_address = if is_delegate_call { + self.this_address() + } else { + contract_address + }; + CallContext { msg_sender, storage_contract_address, function_selector, is_static_call, is_delegate_call } } fn next_counter(&mut self) -> u32 { @@ -614,8 +591,8 @@ impl Empty for PrivateContext { note_hashes: BoundedVec::new(), nullifiers: BoundedVec::new(), private_call_requests: BoundedVec::new(), - public_call_stack_hashes: BoundedVec::new(), - public_teardown_function_hash: 0, + public_call_requests: BoundedVec::new(), + public_teardown_call_request: PublicCallRequest::empty(), l2_to_l1_msgs: BoundedVec::new(), historical_header: Header::empty(), note_encrypted_logs_hashes: BoundedVec::new(), diff --git a/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr b/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr index 913ea9a9fbdf..4423595f99bd 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr @@ -1,7 +1,4 @@ -use dep::protocol_types::{ - abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem}, - address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH -}; +use dep::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, utils::reader::Reader}; #[oracle(callPrivateFunction)] unconstrained fn call_private_function_oracle( @@ -11,7 +8,7 @@ unconstrained fn call_private_function_oracle( _start_side_effect_counter: u32, _is_static_call: bool, _is_delegate_call: bool -) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {} +) -> [Field; 2] {} unconstrained pub fn call_private_function_internal( contract_address: AztecAddress, @@ -20,7 +17,7 @@ unconstrained pub fn call_private_function_internal( start_side_effect_counter: u32, is_static_call: bool, is_delegate_call: bool -) -> PrivateCallStackItem { +) -> (u32, Field) { let fields = call_private_function_oracle( contract_address, function_selector, @@ -30,5 +27,9 @@ unconstrained pub fn call_private_function_internal( is_delegate_call ); - PrivateCallStackItem::deserialize(fields) + let mut reader = Reader::new(fields); + let end_side_effect_counter = reader.read_u32(); + let returns_hash = reader.read(); + + (end_side_effect_counter, returns_hash) } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr index df89503ce0ac..97c2553299f5 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr @@ -1,22 +1,4 @@ -use dep::protocol_types::{ - abis::{ - function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem, - function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs, - call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier, - log_hash::LogHash, global_variables::GlobalVariables, gas::Gas -}, - contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, - messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress, - utils::reader::Reader, - constants::{ - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NOTE_HASHES_PER_CALL, MAX_L2_TO_L1_MSGS_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_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, - ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH -} -}; +use dep::protocol_types::{abis::{function_selector::FunctionSelector}, address::AztecAddress}; #[oracle(enqueuePublicFunctionCall)] unconstrained fn enqueue_public_function_call_oracle( @@ -26,7 +8,7 @@ unconstrained fn enqueue_public_function_call_oracle( _side_effect_counter: u32, _is_static_call: bool, _is_delegate_call: bool -) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {} +) {} unconstrained pub fn enqueue_public_function_call_internal( contract_address: AztecAddress, @@ -35,7 +17,7 @@ unconstrained pub fn enqueue_public_function_call_internal( side_effect_counter: u32, is_static_call: bool, is_delegate_call: bool -) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] { +) { enqueue_public_function_call_oracle( contract_address, function_selector, @@ -43,7 +25,7 @@ unconstrained pub fn enqueue_public_function_call_internal( side_effect_counter, is_static_call, is_delegate_call - ) + ); } #[oracle(setPublicTeardownFunctionCall)] @@ -54,7 +36,7 @@ unconstrained fn set_public_teardown_function_call_oracle( _side_effect_counter: u32, _is_static_call: bool, _is_delegate_call: bool -) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {} +) {} unconstrained pub fn set_public_teardown_function_call_internal( contract_address: AztecAddress, @@ -63,7 +45,7 @@ unconstrained pub fn set_public_teardown_function_call_internal( side_effect_counter: u32, is_static_call: bool, is_delegate_call: bool -) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] { +) { set_public_teardown_function_call_oracle( contract_address, function_selector, @@ -71,46 +53,6 @@ unconstrained pub fn set_public_teardown_function_call_internal( side_effect_counter, is_static_call, is_delegate_call - ) + ); } -pub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem { - let mut reader = Reader::new(fields); - - // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and - // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields! - // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash() - let item = PublicCallStackItem { - contract_address: AztecAddress::from_field(reader.read()), - function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false }, - public_inputs: PublicCircuitPublicInputs { - call_context: reader.read_struct(CallContext::deserialize), - start_side_effect_counter: reader.read_u32(), - args_hash: reader.read(), - returns_hash: 0, - note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], - nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL], - nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL], - l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL], - contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], - contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL], - public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_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], - end_side_effect_counter: 0, - unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], - historical_header: Header::empty(), - global_variables: GlobalVariables::empty(), - prover_address: AztecAddress::zero(), - revert_code: 0, - start_gas_left: Gas::empty(), - end_gas_left: Gas::empty(), - transaction_fee: 0 - }, - is_execution_request: true - }; - reader.finish(); - - item -} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr index a162d98eb8e0..b1f6836edd82 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr @@ -14,12 +14,12 @@ impl PreviousKernelValidator { pub fn validate_for_private_tail(self) { self.validate_common(); - self.validate_empty_public_call_stack(); + self.validate_empty_public_call_requests(); } pub fn validate_for_private_tail_to_public(self) { self.validate_common(); - self.validate_non_empty_public_call_stack(); + self.validate_non_empty_public_call_requests(); } fn validate_common(self) { @@ -34,19 +34,19 @@ impl PreviousKernelValidator { ); } - fn validate_empty_public_call_stack(self) { + fn validate_empty_public_call_requests(self) { assert_eq( - array_length(self.previous_kernel.end.public_call_stack), 0, "Public call stack must be empty when executing the tail circuit" + array_length(self.previous_kernel.end.public_call_requests), 0, "Public call stack must be empty when executing the tail circuit" ); assert( is_empty(self.previous_kernel.public_teardown_call_request), "Public teardown call request must be empty when executing the tail circuit" ); } - fn validate_non_empty_public_call_stack(self) { - let call_stack_len = array_length(self.previous_kernel.end.public_call_stack); + fn validate_non_empty_public_call_requests(self) { + let len = array_length(self.previous_kernel.end.public_call_requests); assert( - (call_stack_len != 0) | !is_empty(self.previous_kernel.public_teardown_call_request), "Must have public calls when exporting public kernel data from the tail circuit" + (len != 0) | !is_empty(self.previous_kernel.public_teardown_call_request), "Must have public calls when exporting public kernel data from the tail circuit" ); } 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 faabc594d3ba..dec6d9d005b5 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 @@ -7,10 +7,8 @@ use crate::components::private_call_data_validator::{ }; use dep::types::{ abis::{ - call_context::CallContext, call_request::CallRequest, caller_context::CallerContext, - kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, log_hash::NoteLogHash, - note_hash::ScopedNoteHash, private_call_request::ScopedPrivateCallRequest, - private_call_stack_item::PrivateCallStackItem, + call_context::CallContext, kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, + log_hash::NoteLogHash, note_hash::ScopedNoteHash, private_call_request::PrivateCallRequest, private_circuit_public_inputs::{PrivateCircuitPublicInputs, PrivateCircuitPublicInputsArrayLengths}, private_kernel::private_call_data::PrivateCallData, side_effect::{Ordered, RangeOrdered} }, @@ -37,22 +35,28 @@ unconstrained fn find_first_revertible_private_call_request_index(public_inputs: ) } -fn validate_caller_context(caller_context: CallerContext, this_context: CallContext) { - let matching_caller_context = caller_context.msg_sender.eq(this_context.msg_sender) - & caller_context.storage_contract_address.eq(this_context.storage_contract_address); - let hidden_caller_context = caller_context.is_hidden(); - assert(matching_caller_context | hidden_caller_context, "invalid caller context"); - - assert_eq(caller_context.is_static_call, this_context.is_static_call, "mismatch is_static_call flag"); -} - -fn validate_call_request(request: CallRequest, hash: Field, caller: PrivateCallStackItem) { - if hash != 0 { - assert_eq(request.hash, hash, "call stack hash does not match call request hash"); - assert_eq(request.caller_contract_address, caller.contract_address, "invalid caller contract address"); - validate_caller_context(request.caller_context, caller.public_inputs.call_context) +fn validate_call_context( + target_contract: AztecAddress, + target_context: CallContext, + this_context: CallContext +) { + if target_context.is_delegate_call { + assert_eq( + target_context.msg_sender, this_context.msg_sender, "incorrect msg_sender for delegate call request" + ); + assert_eq( + target_context.storage_contract_address, this_context.storage_contract_address, "incorrect storage_contract_address for delegate call request" + ); } else { - assert(is_empty(request), "call requests length does not match the expected length"); + assert_eq( + target_context.msg_sender, this_context.storage_contract_address, "incorrect msg_sender for call request" + ); + assert_eq( + target_context.storage_contract_address, target_contract, "incorrect storage_contract_address for call request" + ); + } + if !target_context.is_static_call { + assert(this_context.is_static_call == false, "static call cannot make non-static calls"); } } @@ -144,37 +148,27 @@ impl PrivateCallDataValidator { ); } - pub fn validate_against_call_request(self, scoped_call_request: ScopedPrivateCallRequest) { + pub fn validate_against_call_request(self, request: PrivateCallRequest) { let call_stack_item = self.data.call_stack_item; - let caller_contract_address = scoped_call_request.contract_address; - let request = scoped_call_request.call_request; - assert( - request.matches_stack_item(call_stack_item), "calculated private_call_hash does not match provided private_call_hash at the top of the call stack" + assert_eq( + request.contract_address, call_stack_item.contract_address, "contract_address does not match call request" + ); + assert_eq( + request.call_context, call_stack_item.public_inputs.call_context, "call_context does not match call request" + ); + assert_eq( + request.args_hash, call_stack_item.public_inputs.args_hash, "args_hash does not match call request" + ); + assert_eq( + request.returns_hash, call_stack_item.public_inputs.returns_hash, "returns_hash does not match call request" + ); + assert_eq( + request.start_side_effect_counter, call_stack_item.public_inputs.start_side_effect_counter, "start_side_effect_counter does not match call request" + ); + assert_eq( + request.end_side_effect_counter, call_stack_item.public_inputs.end_side_effect_counter, "end_side_effect_counter does not match call request" ); - - let call_context = call_stack_item.public_inputs.call_context; - let caller_context = request.caller_context; - let is_caller_hidden = caller_context.is_hidden(); - - if call_context.is_delegate_call { - assert(!is_caller_hidden, "caller context cannot be hidden for delegate calls"); - assert_eq( - call_context.msg_sender, caller_context.msg_sender, "call stack msg_sender does not match expected msg_sender for delegate calls" - ); - assert_eq( - call_context.storage_contract_address, caller_context.storage_contract_address, "call stack storage address does not match expected contract address for delegate calls" - ); - } else { - assert(is_caller_hidden, "caller context must be hidden for non-delegate calls"); - assert_eq( - call_context.msg_sender, caller_contract_address, "call stack msg_sender does not match caller contract address" - ); - } - - if !call_context.is_static_call { - assert(caller_context.is_static_call == false, "static call cannot make non-static calls"); - } } pub fn validate_against_previous_kernel(self, previous_kernel: PrivateKernelCircuitPublicInputs) { @@ -238,6 +232,10 @@ impl PrivateCallDataValidator { assert(is_own_storage, "call stack storage address does not match expected contract address"); } + assert_eq( + call_context.function_selector, self.data.call_stack_item.function_data.selector, "function selector in call context does not match call stack item" + ); + if call_context.is_static_call { // No state changes are allowed for static calls: assert_eq(self.array_lengths.note_hashes, 0, "note_hashes must be empty for static calls"); @@ -263,7 +261,11 @@ impl PrivateCallDataValidator { for i in 0..call_requests.len() { should_check &= i != num_requests; if should_check { - validate_caller_context(call_requests[i].caller_context, public_inputs.call_context); + validate_call_context( + call_requests[i].contract_address, + call_requests[i].call_context, + public_inputs.call_context + ); } } @@ -287,19 +289,32 @@ impl PrivateCallDataValidator { } fn validate_public_call_requests(self) { - let call_requests = self.data.public_call_stack; - let hashes = self.data.call_stack_item.public_inputs.public_call_stack_hashes; + let public_inputs = self.data.call_stack_item.public_inputs; + let call_requests = self.data.call_stack_item.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() { - validate_call_request(call_requests[i], hashes[i], self.data.call_stack_item); + should_check &= i != num_requests; + if should_check { + validate_call_context( + call_requests[i].item.contract_address, + call_requests[i].item.call_context, + public_inputs.call_context + ); + } } } fn validate_teardown_call_request(self) { - validate_call_request( - self.data.public_teardown_call_request, - self.data.call_stack_item.public_inputs.public_teardown_function_hash, - self.data.call_stack_item - ); + let public_inputs = self.data.call_stack_item.public_inputs; + let request = self.data.call_stack_item.public_inputs.public_teardown_call_request; + if request.counter != 0 { + validate_call_context( + request.item.contract_address, + request.item.call_context, + public_inputs.call_context + ); + } } fn validate_counters(self) { @@ -362,11 +377,11 @@ impl PrivateCallDataValidator { validate_incrementing_counters_within_range( counter_start, counter_end, - self.data.public_call_stack, - self.array_lengths.public_call_stack_hashes + public_inputs.public_call_requests, + self.array_lengths.public_call_requests ); - let teardown_call_request_count = if self.data.public_teardown_call_request.hash == 0 { + let teardown_call_request_count = if public_inputs.public_teardown_call_request.counter == 0 { 0 } else { 1 @@ -374,7 +389,7 @@ impl PrivateCallDataValidator { validate_incrementing_counters_within_range( counter_start, counter_end, - [self.data.public_teardown_call_request], + [public_inputs.public_teardown_call_request], teardown_call_request_count ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr index 6c50ff6c50c6..fd967b2572c2 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr @@ -44,8 +44,8 @@ mod tests { pub fn add_private_call_request(&mut self, counter_start: u32, counter_end: u32) { let index = self.private_call.private_call_requests.len(); self.private_call.append_private_call_requests(1); - self.private_call.private_call_requests.storage[index].call_request.start_side_effect_counter = counter_start; - self.private_call.private_call_requests.storage[index].call_request.end_side_effect_counter = counter_end; + self.private_call.private_call_requests.storage[index].start_side_effect_counter = counter_start; + self.private_call.private_call_requests.storage[index].end_side_effect_counter = counter_end; self.private_call.counter = counter_end + 1; } 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 0fdc92830d94..37a858d04e5f 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 @@ -1,7 +1,6 @@ use crate::components::private_kernel_circuit_public_inputs_composer::create_first_nullifier; use dep::types::{ abis::{ - call_request::CallRequest, kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsArrayLengths}, max_block_number::MaxBlockNumber, private_circuit_public_inputs::{PrivateCircuitPublicInputs, PrivateCircuitPublicInputsArrayLengths}, @@ -73,14 +72,13 @@ fn validate_array_appended_scoped( } } -// Similar to validate_array_appended_scoped, except that the souce items will be appended to dest in reversed order. -fn validate_array_appended_reversed_scoped( - dest: [ST; N], +// Similar to validate_array_appended, except that the souce items will be appended to dest in reversed order. +fn validate_array_appended_reversed( + dest: [T; N], source: [T; M], num_source_items: u32, - num_prepended_items: u32, - contract_address: AztecAddress -) where ST: Scoped + Empty + Eq, T: Eq { + num_prepended_items: u32 +) where T: Empty + Eq { let items_propagated = num_prepended_items + num_source_items; assert(items_propagated <= N, "number of total items exceeds limit"); let mut should_check = false; @@ -91,10 +89,7 @@ fn validate_array_appended_reversed_scoped( if should_check { if is_non_empty_item { assert_eq( - dest[i].inner(), source[items_propagated - i - 1], "source item does not reversed append to dest" - ); - assert_eq( - dest[i].contract_address(), contract_address, "propagated contract address does not match" + dest[i], source[items_propagated - i - 1], "source item does not reversed append to dest" ); } else { assert(is_empty(dest[i]), "output should be appended with empty items"); @@ -112,53 +107,38 @@ impl PrivateKernelCircuitOutputValidator { PrivateKernelCircuitOutputValidator { output } } - pub fn validate_as_first_call( + pub fn validate_as_first_call( self, tx_request: TxRequest, private_call: PrivateCircuitPublicInputs, private_call_array_lengths: PrivateCircuitPublicInputsArrayLengths, - contract_address: AztecAddress, - public_call_requests: [CallRequest; PUBLIC_CALL_REQUESTS_LEN], - public_teardown_call_request: CallRequest, vk_tree_root: Field ) { - self.validate_initial_values( - tx_request, - private_call, - public_teardown_call_request, - vk_tree_root - ); + self.validate_initial_values(tx_request, private_call, vk_tree_root); let mut offsets = PrivateKernelCircuitPublicInputsArrayLengths::empty(); offsets.nullifiers = 1; // The first nullifier is not propagated from the private call. self.validate_propagated_from_private_call( private_call, private_call_array_lengths, offsets, - 0, // num_popped_call - contract_address, - public_call_requests + 0 // num_popped_call ); } - pub fn validate_as_inner_call( + pub fn validate_as_inner_call( self, previous_kernel: PrivateKernelCircuitPublicInputs, previous_kernel_array_lengths: PrivateKernelCircuitPublicInputsArrayLengths, private_call: PrivateCircuitPublicInputs, - private_call_array_lengths: PrivateCircuitPublicInputsArrayLengths, - contract_address: AztecAddress, - public_call_requests: [CallRequest; PUBLIC_CALL_REQUESTS_LEN], - public_teardown_call_request: CallRequest + private_call_array_lengths: PrivateCircuitPublicInputsArrayLengths ) { - self.validate_aggregated_values(previous_kernel, private_call, public_teardown_call_request); + self.validate_aggregated_values(previous_kernel, private_call); self.validate_propagated_from_previous_kernel(previous_kernel, previous_kernel_array_lengths); self.validate_propagated_from_private_call( private_call, private_call_array_lengths, previous_kernel_array_lengths, - 1, // num_popped_call - contract_address, - public_call_requests + 1 // num_popped_call ); } @@ -166,7 +146,6 @@ impl PrivateKernelCircuitOutputValidator { self, tx_request: TxRequest, private_call: PrivateCircuitPublicInputs, - public_teardown_call_request: CallRequest, vk_tree_root: Field ) { // Constants. @@ -191,7 +170,7 @@ impl PrivateKernelCircuitOutputValidator { self.output.validation_requests.for_rollup.max_block_number, private_call.max_block_number, "incorrect initial max_block_number" ); assert_eq( - self.output.public_teardown_call_request, public_teardown_call_request, "incorrect initial public_teardown_call_request" + self.output.public_teardown_call_request, private_call.public_teardown_call_request, "incorrect initial public_teardown_call_request" ); let initial_fee_payer = if private_call.is_fee_payer { private_call.call_context.storage_contract_address @@ -204,8 +183,7 @@ impl PrivateKernelCircuitOutputValidator { fn validate_aggregated_values( self, previous_kernel: PrivateKernelCircuitPublicInputs, - private_call: PrivateCircuitPublicInputs, - public_teardown_call_request: CallRequest + private_call: PrivateCircuitPublicInputs ) { // min_revertible_side_effect_counter let propagated_min_revertible_counter = if previous_kernel.min_revertible_side_effect_counter != 0 { @@ -231,10 +209,12 @@ impl PrivateKernelCircuitOutputValidator { // public_teardown_call_request let propagated_public_teardown_call_request = if !is_empty(previous_kernel.public_teardown_call_request) { - assert(is_empty(public_teardown_call_request), "cannot overwrite public_teardown_call_request"); + assert( + is_empty(private_call.public_teardown_call_request), "cannot overwrite public_teardown_call_request" + ); previous_kernel.public_teardown_call_request } else { - public_teardown_call_request + private_call.public_teardown_call_request }; assert_eq( self.output.public_teardown_call_request, propagated_public_teardown_call_request, "incorrect output public_teardown_call_request" @@ -304,6 +284,11 @@ impl PrivateKernelCircuitOutputValidator { previous_kernel.end.unencrypted_logs_hashes, array_lengths.unencrypted_logs_hashes ); + validate_array_prepended( + self.output.end.public_call_requests, + previous_kernel.end.public_call_requests, + array_lengths.public_call_requests + ); // array_lengths.private_call_stack is guaranteed to be greater than 0. // It's checked in private_kernel_inner when comparing the top item in the stack with the current private call. validate_array_prepended( @@ -311,21 +296,14 @@ impl PrivateKernelCircuitOutputValidator { previous_kernel.end.private_call_stack, array_lengths.private_call_stack - 1 // Do not copy the top item in the stack. ); - validate_array_prepended( - self.output.end.public_call_stack, - previous_kernel.end.public_call_stack, - array_lengths.public_call_stack - ); } - fn validate_propagated_from_private_call( + fn validate_propagated_from_private_call( self, private_call: PrivateCircuitPublicInputs, array_lengths: PrivateCircuitPublicInputsArrayLengths, offsets: PrivateKernelCircuitPublicInputsArrayLengths, - num_popped_call: u32, - contract_address: AztecAddress, - public_call_requests: [CallRequest; PUBLIC_CALL_REQUESTS_LEN] + num_popped_call: u32 ) { let storage_contract_address = private_call.call_context.storage_contract_address; validate_array_appended_scoped( @@ -390,20 +368,17 @@ impl PrivateKernelCircuitOutputValidator { offsets.unencrypted_logs_hashes, storage_contract_address ); - validate_array_appended_reversed_scoped( + validate_array_appended( + self.output.end.public_call_requests, + private_call.public_call_requests, + array_lengths.public_call_requests, + offsets.public_call_requests + ); + validate_array_appended_reversed( self.output.end.private_call_stack, private_call.private_call_requests, array_lengths.private_call_requests, - offsets.private_call_stack - num_popped_call, - contract_address - ); - // TODO: Should push call requests instead of hashes to the accumulated data. - validate_array_appended( - self.output.end.public_call_stack, - public_call_requests, - // private_call.public_call_requests, - array_lengths.public_call_stack_hashes, - offsets.public_call_stack + offsets.private_call_stack - num_popped_call ); } } 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 faafffcdf70c..1993ea11092c 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,6 +1,6 @@ use dep::types::{ abis::{ - call_request::CallRequest, combined_constant_data::CombinedConstantData, + combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder}, max_block_number::MaxBlockNumber, nullifier::{Nullifier, ScopedNullifier}, private_circuit_public_inputs::PrivateCircuitPublicInputs @@ -19,8 +19,6 @@ struct DataSource { private_call_public_inputs: PrivateCircuitPublicInputs, contract_address: AztecAddress, storage_contract_address: AztecAddress, - public_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], - public_teardown_call_request: CallRequest, } pub fn create_first_nullifier(tx_request: TxRequest) -> ScopedNullifier { @@ -76,8 +74,8 @@ impl PrivateKernelCircuitPublicInputsComposer { public_inputs.end.note_encrypted_logs_hashes = array_to_bounded_vec(start.note_encrypted_logs_hashes); public_inputs.end.encrypted_logs_hashes = array_to_bounded_vec(start.encrypted_logs_hashes); public_inputs.end.unencrypted_logs_hashes = array_to_bounded_vec(start.unencrypted_logs_hashes); + public_inputs.end.public_call_requests = array_to_bounded_vec(start.public_call_requests); public_inputs.end.private_call_stack = array_to_bounded_vec(start.private_call_stack); - public_inputs.end.public_call_stack = array_to_bounded_vec(start.public_call_stack); PrivateKernelCircuitPublicInputsComposer { public_inputs } } @@ -91,18 +89,10 @@ impl PrivateKernelCircuitPublicInputsComposer { pub fn with_private_call( &mut self, private_call_public_inputs: PrivateCircuitPublicInputs, - contract_address: AztecAddress, - public_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], - public_teardown_call_request: CallRequest + contract_address: AztecAddress ) -> Self { let storage_contract_address = private_call_public_inputs.call_context.storage_contract_address; - let source = DataSource { - private_call_public_inputs, - contract_address, - storage_contract_address, - public_call_requests, - public_teardown_call_request - }; + let source = DataSource { private_call_public_inputs, contract_address, storage_contract_address }; self.propagate_from_private_call(source); @@ -237,29 +227,26 @@ impl PrivateKernelCircuitPublicInputsComposer { fn propagate_private_call_requests(&mut self, source: DataSource) { let call_requests = source.private_call_public_inputs.private_call_requests; let num_requests = array_length(call_requests); - let mut proceed = true; for i in 0..call_requests.len() { - proceed &= i != num_requests; - if proceed { + if i < num_requests { // Push the call requests to the stack in reverse order. let call_request = call_requests[num_requests - i - 1]; - self.public_inputs.end.private_call_stack.push(call_request.scope(source.contract_address)); + self.public_inputs.end.private_call_stack.push(call_request); } } } fn propagate_public_call_requests(&mut self, source: DataSource) { - let call_requests = source.public_call_requests; + let call_requests = source.private_call_public_inputs.public_call_requests; for i in 0..call_requests.len() { - let call_request = call_requests[i]; - if !is_empty(call_request) { - self.public_inputs.end.public_call_stack.push(call_request); + if !is_empty(call_requests[i]) { + self.public_inputs.end.public_call_requests.push(call_requests[i]); } } } fn propagate_public_teardown_call_request(&mut self, source: DataSource) { - let call_request = source.public_teardown_call_request; + let call_request = source.private_call_public_inputs.public_teardown_call_request; if !is_empty(call_request) { assert( is_empty(self.public_inputs.public_teardown_call_request), "Public teardown call request already set" @@ -282,7 +269,7 @@ impl PrivateKernelCircuitPublicInputsComposer { self.public_inputs.end.note_encrypted_logs_hashes.storage = sort_by_counters_asc(self.public_inputs.end.note_encrypted_logs_hashes.storage); self.public_inputs.end.encrypted_logs_hashes.storage = sort_by_counters_asc(self.public_inputs.end.encrypted_logs_hashes.storage); self.public_inputs.end.unencrypted_logs_hashes.storage = sort_by_counters_asc(self.public_inputs.end.unencrypted_logs_hashes.storage); - self.public_inputs.end.public_call_stack.storage = sort_by_counters_desc(self.public_inputs.end.public_call_stack.storage); + self.public_inputs.end.public_call_requests.storage = sort_by_counters_desc(self.public_inputs.end.public_call_requests.storage); } fn silo_scoped_values(&mut self) { 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 52fdf81766b2..d947609bd6c7 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 @@ -8,7 +8,7 @@ use crate::components::{ split_to_public::split_to_public } }; -use dep::types::abis::kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}; +use dep::types::abis::{kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}}; struct TailToPublicOutputComposer { output_composer: PrivateKernelCircuitPublicInputsComposer, @@ -27,7 +27,7 @@ impl TailToPublicOutputComposer { let mut output = PublicKernelCircuitPublicInputs::empty(); output.validation_requests = source.validation_requests.finish(); output.constants = source.constants; - output.public_teardown_call_stack[0] = source.public_teardown_call_request; + output.public_teardown_call_stack[0] = source.public_teardown_call_request.expose_to_public(); output.fee_payer = source.fee_payer; let mut (end_non_revertible, end) = split_to_public(source.end, source.min_revertible_side_effect_counter); 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 e6d19a486e51..43108d70a202 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 @@ -92,17 +92,15 @@ pub fn split_to_public( } } - let public_call_stack = data.public_call_stack; - for i in 0..public_call_stack.max_len() { - if i < public_call_stack.len() { - let call_stack_item = public_call_stack.get_unchecked(i); - // TODO: Hide the counter of a public call request. - // let public_call_request = call_stack_item.expose_to_public(); - let public_call_request = call_stack_item; - if call_stack_item.start_side_effect_counter < min_revertible_side_effect_counter { - non_revertible_builder.public_call_stack.push(public_call_request); + let public_call_requests = data.public_call_requests; + 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); } else { - revertible_builder.public_call_stack.push(public_call_request); + revertible_builder.public_call_stack.push(exposed_call_request); } } } 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 ece36c83ad04..bc375dc4c19a 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 @@ -7,13 +7,16 @@ use crate::components::{ }; use dep::types::{ abis::{ - call_request::CallRequest, kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, - log_hash::{LogHash, ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, nullifier::Nullifier + log_hash::{LogHash, ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, nullifier::Nullifier, + public_call_request::PublicCallRequest }, hash::{silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier}, - traits::{Empty, is_empty_array}, - utils::arrays::{assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc} + traits::{Empty, is_empty, is_empty_array}, + utils::arrays::{ + assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc, + validate_array +} }; struct TailToPublicOutputValidator { @@ -56,6 +59,18 @@ impl TailToPublicOutputValidator { ); assert_eq(self.output.fee_payer, self.previous_kernel.fee_payer, "mismatch fee_payer"); + + // public_teardown_call_stack + let num_teardown_calls = validate_array(self.output.public_teardown_call_stack); + assert( + (num_teardown_calls == 0) | (num_teardown_calls == 1), "invalid number of teardown call requests" + ); + assert_eq( + self.output.public_teardown_call_stack[0].item, self.previous_kernel.public_teardown_call_request.item, "mismatch public_teardown_call_request" + ); + assert_eq( + self.output.public_teardown_call_stack[0].counter, 0, "cannot expose teardown call request counter" + ); } fn validate_propagated_sorted_siloed_values(self, hints: TailToPublicOutputHints) { @@ -149,7 +164,6 @@ impl TailToPublicOutputValidator { ); // unencrypted_logs_hashes - assert_split_sorted_transformed_value_arrays_asc( prev_data.unencrypted_logs_hashes, prev_data.unencrypted_logs_hashes, @@ -159,20 +173,22 @@ impl TailToPublicOutputValidator { hints.sorted_unencrypted_log_hash_hints ); - // public_call_stack + // public_data_update_requests + let num_non_revertible_writes = validate_array(output_non_revertible.public_data_update_requests); + assert_eq(num_non_revertible_writes, 0, "unexpected non-revertible public_data_update_requests"); + let num_revertible_writes = validate_array(output_revertible.public_data_update_requests); + assert_eq(num_revertible_writes, 0, "unexpected revertible public_data_update_requests"); + + // public_call_requests validate_value_transformation( - prev_data.public_call_stack, + prev_data.public_call_requests, hints.public_call_requests, - |cr: CallRequest, public_cr: CallRequest| (public_cr.hash == cr.hash) - & (public_cr.caller_contract_address == cr.caller_contract_address) - & (public_cr.caller_context == cr.caller_context) - // TODO: Hide the counter of a public call request. - // & (public_cr.start_side_effect_counter == 0) - & (public_cr.end_side_effect_counter == 0) + |cr: PublicCallRequest, public_cr: PublicCallRequest| (public_cr.item == cr.item) + & (public_cr.counter == 0) ); assert_split_sorted_transformed_value_arrays_desc( - prev_data.public_call_stack, + prev_data.public_call_requests, hints.public_call_requests, split_counter, output_non_revertible.public_call_stack, 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 1602dc9f43ee..5a0172239162 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,8 @@ use dep::types::{ abis::{ - call_request::CallRequest, kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, + kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, log_hash::{LogHash, NoteLogHash, ScopedLogHash, ScopedEncryptedLogHash}, note_hash::NoteHash, - nullifier::Nullifier + nullifier::Nullifier, public_call_request::PublicCallRequest }, constants::{ MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, @@ -32,7 +32,7 @@ struct TailToPublicOutputHints { // Unencrypted log hashes. sorted_unencrypted_log_hash_hints: SplitOrderHints, // Public call requests. - public_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_requests: [PublicCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], sorted_public_call_request_hints: SplitOrderHints, } @@ -90,10 +90,8 @@ unconstrained pub fn generate_tail_to_public_output_hints(previous_kernel: Priva let sorted_unencrypted_log_hash_hints = sort_get_split_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes, split_counter); // public_call_requests - // TODO: Hide the counter of a public call request. - // let public_call_requests = previous_kernel.end.public_call_stack.map(|cr: CallRequest| cr.expose_to_public()); - let public_call_requests = previous_kernel.end.public_call_stack; - let sorted_public_call_request_hints = sort_get_split_order_hints_desc(previous_kernel.end.public_call_stack, split_counter); + let public_call_requests = previous_kernel.end.public_call_requests.map(|cr: PublicCallRequest| cr.expose_to_public()); + let sorted_public_call_request_hints = sort_get_split_order_hints_desc(previous_kernel.end.public_call_requests, split_counter); TailToPublicOutputHints { siloed_note_hashes, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index d3648028657b..34042b5cb68c 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -25,9 +25,7 @@ impl PrivateKernelInitCircuitPrivateInputs { let private_call_public_inputs = self.private_call.call_stack_item.public_inputs; PrivateKernelCircuitPublicInputsComposer::new_from_tx_request(self.tx_request, private_call_public_inputs, self.vk_tree_root).with_private_call( private_call_public_inputs, - self.private_call.call_stack_item.contract_address, - self.private_call.public_call_stack, - self.private_call.public_teardown_call_request + self.private_call.call_stack_item.contract_address ).finish() } @@ -47,9 +45,6 @@ impl PrivateKernelInitCircuitPrivateInputs { self.tx_request, self.private_call.call_stack_item.public_inputs, private_call_data_validator.array_lengths, - self.private_call.call_stack_item.contract_address, - self.private_call.public_call_stack, - self.private_call.public_teardown_call_request, self.vk_tree_root ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index 51ca50f4d3b7..f9a16f54ca29 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -36,9 +36,7 @@ impl PrivateKernelInnerCircuitPrivateInputs { unconstrained fn generate_output(self) -> PrivateKernelCircuitPublicInputs { PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(self.previous_kernel.public_inputs).pop_top_call_request().with_private_call( self.private_call.call_stack_item.public_inputs, - self.private_call.call_stack_item.contract_address, - self.private_call.public_call_stack, - self.private_call.public_teardown_call_request + self.private_call.call_stack_item.contract_address ).finish() } @@ -65,10 +63,7 @@ impl PrivateKernelInnerCircuitPrivateInputs { self.previous_kernel.public_inputs, previous_kernel_array_lengths, self.private_call.call_stack_item.public_inputs, - private_call_data_validator.array_lengths, - self.private_call.call_stack_item.contract_address, - self.private_call.public_call_stack, - self.private_call.public_teardown_call_request + private_call_data_validator.array_lengths ); } output 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 f455f500d566..74ac47a60be7 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 @@ -281,21 +281,21 @@ mod tests { #[test(should_fail_with="Private call stack must be empty when executing the tail circuit")] fn non_empty_private_call_stack_should_fail() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.add_private_call_request(1, false); + builder.previous_kernel.append_private_call_requests(1); builder.failed(); } #[test(should_fail_with="Public call stack must be empty when executing the tail circuit")] fn non_empty_public_call_stack_should_fail() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.push_public_call_request(1, false); + builder.previous_kernel.append_public_call_requests(1); builder.failed(); } #[test(should_fail_with="Public teardown call request must be empty when executing the tail circuit")] fn non_empty_public_teardown_call_request_should_fail() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.push_public_teardown_call_request(1, false); + builder.previous_kernel.append_public_teardown_call_request(); builder.failed(); } 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 f093f0bd07f4..a0e5e66de9db 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 @@ -79,7 +79,7 @@ mod tests { previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1_000_000, 1_000_000); previous_kernel.set_first_nullifier(); previous_kernel.end_setup(); - previous_kernel.push_public_call_request(1, false); + previous_kernel.append_public_call_requests(1); PrivateKernelTailToPublicInputsBuilder { previous_kernel } } @@ -168,7 +168,7 @@ mod tests { #[test(should_fail_with="Private call stack must be empty when executing the tail circuit")] fn non_empty_private_call_stack_should_fail() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - builder.previous_kernel.add_private_call_request(1, false); + builder.previous_kernel.append_private_call_requests(1); builder.failed(); } @@ -190,7 +190,7 @@ mod tests { fn can_run_with_only_teardown() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.public_call_requests = BoundedVec::new(); - builder.previous_kernel.push_public_teardown_call_request(1, false); + builder.previous_kernel.append_public_teardown_call_request(); builder.succeeded(); } @@ -355,12 +355,10 @@ mod tests { unconstrained fn enqueued_public_calls_consume_startup_gas() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); // add an extra non-revertible call - builder.previous_kernel.push_public_call_request(42, false); + builder.previous_kernel.append_public_call_requests(1); builder.previous_kernel.end_setup(); // add some revertible calls - builder.previous_kernel.push_public_call_request(42, false); - builder.previous_kernel.push_public_call_request(42, false); - builder.previous_kernel.push_public_call_request(42, false); + builder.previous_kernel.append_public_call_requests(3); let public_inputs = builder.execute(); let expected_revertible_gas_used = Gas::new(0, 3 * FIXED_AVM_STARTUP_L2_GAS); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr index a0d93befda5d..3e395b9843b2 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr @@ -12,7 +12,10 @@ mod validate_private_call_requests; use crate::components::private_call_data_validator::PrivateCallDataValidator; use dep::types::{ - abis::{note_hash::ScopedNoteHash, private_call_request::ScopedPrivateCallRequest}, + abis::{ + note_hash::ScopedNoteHash, private_call_request::PrivateCallRequest, + private_kernel::private_call_data::PrivateCallData +}, tests::fixture_builder::FixtureBuilder, transaction::tx_request::TxRequest }; @@ -48,6 +51,10 @@ impl PrivateCallDataValidatorBuilder { *self } + pub fn get_private_call_data(self) -> PrivateCallData { + self.private_call.to_private_call_data() + } + pub fn validate(self) { let private_call = self.private_call.to_private_call_data(); let mut accumulated_note_hashes = self.previous_note_hashes; @@ -65,8 +72,13 @@ impl PrivateCallDataValidatorBuilder { PrivateCallDataValidator::new(private_call).validate_against_tx_request(request); } - pub fn validate_against_call_request(self, request: ScopedPrivateCallRequest) { + pub fn validate_against_call_request(self, request: PrivateCallRequest) { let private_call = self.private_call.to_private_call_data(); PrivateCallDataValidator::new(private_call).validate_against_call_request(request); } + + pub fn validate_with_private_call_data(self, data: PrivateCallData) { + let accumulated_note_hashes = self.previous_note_hashes; + PrivateCallDataValidator::new(data).validate(accumulated_note_hashes.storage); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_against_call_request.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_against_call_request.nr index 67978f544413..fa24782af29f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_against_call_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_against_call_request.nr @@ -1,5 +1,4 @@ use crate::tests::private_call_data_validator_builder::PrivateCallDataValidatorBuilder; -use dep::types::abis::caller_context::CallerContext; #[test] fn validate_against_call_request_succeeds() { @@ -28,100 +27,68 @@ fn validate_against_call_request_static_call_succeeds() { builder.validate_against_call_request(request); } -#[test(should_fail_with="calculated private_call_hash does not match provided private_call_hash at the top of the call stack")] -fn validate_against_call_request_mismatch_hash_fails() { +#[test(should_fail_with="contract_address does not match call request")] +fn validate_against_call_request_mismatch_contract_address_fails() { let builder = PrivateCallDataValidatorBuilder::new(); let mut request = builder.private_call.build_private_call_request(); - // Tweak the hash to be a different value. - request.call_request.args_hash += 1; - - builder.validate_against_call_request(request); -} - -#[test(should_fail_with="caller context cannot be hidden for delegate calls")] -fn validate_against_call_request_empty_caller_context_for_delegate_calls_fails() { - let builder = PrivateCallDataValidatorBuilder::new().is_delegate_call(); - - let mut request = builder.private_call.build_private_call_request(); - request.call_request.caller_context = CallerContext::empty(); - - builder.validate_against_call_request(request); -} - -#[test(should_fail_with="call stack msg_sender does not match expected msg_sender for delegate calls")] -fn validate_against_call_request_incorrect_msg_sender_for_delegate_call_fails() { - let builder = PrivateCallDataValidatorBuilder::new().is_delegate_call(); - - let mut request = builder.private_call.build_private_call_request(); - // Tweak the msg_sender to be a different value. - request.call_request.caller_context.msg_sender.inner += 1; - - builder.validate_against_call_request(request); -} - -#[test(should_fail_with="call stack storage address does not match expected contract address for delegate calls")] -fn validate_against_call_request_incorrect_storage_contract_address_for_delegate_call_fails() { - let builder = PrivateCallDataValidatorBuilder::new().is_delegate_call(); - - let mut request = builder.private_call.build_private_call_request(); - // Tweak the storage contract address to be a different value. - request.call_request.caller_context.storage_contract_address.inner += 1; + // Tweak the contract_address to be a different value. + request.contract_address.inner += 1; builder.validate_against_call_request(request); } -#[test(should_fail_with="call stack msg_sender does not match caller contract address")] -fn validate_against_call_request_incorrect_msg_sender_for_regular_call_fails() { +#[test(should_fail_with="call_context does not match call request")] +fn validate_against_call_request_mismatch_call_context_storage_contract_address_fails() { let builder = PrivateCallDataValidatorBuilder::new(); let mut request = builder.private_call.build_private_call_request(); - // Tweak the caller's contract address to be a different value. - request.contract_address.inner += 1; + // Tweak the storage_contract_address to be a different value. + request.call_context.storage_contract_address.inner += 1; builder.validate_against_call_request(request); } -#[test(should_fail_with="caller context must be hidden for non-delegate calls")] -fn validate_against_call_request_non_empty_caller_for_regular_call_fails() { +#[test(should_fail_with="args_hash does not match call request")] +fn validate_against_call_request_mismatch_args_hash_fails() { let builder = PrivateCallDataValidatorBuilder::new(); let mut request = builder.private_call.build_private_call_request(); - // Tweak the caller's msg_sender to be non-empty. - request.call_request.caller_context.msg_sender.inner = 1234; + // Tweak the args_hash to be a different value. + request.args_hash += 1; builder.validate_against_call_request(request); } -#[test(should_fail_with="caller context must be hidden for non-delegate calls")] -fn validate_against_call_request_non_empty_caller_for_static_call_fails() { - let builder = PrivateCallDataValidatorBuilder::new().is_static_call(); +#[test(should_fail_with="returns_hash does not match call request")] +fn validate_against_call_request_mismatch_returns_hash_fails() { + let builder = PrivateCallDataValidatorBuilder::new(); let mut request = builder.private_call.build_private_call_request(); - // Tweak the caller's msg_sender to be non-empty. - request.call_request.caller_context.msg_sender.inner = 1234; + // Tweak the returns_hash to be a different value. + request.returns_hash += 1; builder.validate_against_call_request(request); } -#[test(should_fail_with="static call cannot make non-static calls")] -fn validate_against_call_request_static_call_regular_call_fails() { +#[test(should_fail_with="start_side_effect_counter does not match call request")] +fn validate_against_call_request_mismatch_start_side_effect_counter_fails() { let builder = PrivateCallDataValidatorBuilder::new(); let mut request = builder.private_call.build_private_call_request(); - // Tweak the caller to be making a static call. - request.call_request.caller_context.is_static_call = true; + // Tweak the start_side_effect_counter to be a different value. + request.start_side_effect_counter += 1; builder.validate_against_call_request(request); } -#[test(should_fail_with="static call cannot make non-static calls")] -fn validate_against_call_request_static_call_delegate_call_fails() { - let builder = PrivateCallDataValidatorBuilder::new().is_delegate_call(); +#[test(should_fail_with="end_side_effect_counter does not match call request")] +fn validate_against_call_request_mismatch_end_side_effect_counter_fails() { + let builder = PrivateCallDataValidatorBuilder::new(); let mut request = builder.private_call.build_private_call_request(); - // Tweak the caller to be making a static call. - request.call_request.caller_context.is_static_call = true; + // Tweak the end_side_effect_counter to be a different value. + request.end_side_effect_counter += 1; builder.validate_against_call_request(request); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr index 45e332bb2398..92fe29e3ba34 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr @@ -38,6 +38,17 @@ fn validate_call_is_delegate_call_from_same_contract_fails() { builder.validate(); } +#[test(should_fail_with="function selector in call context does not match call stack item")] +fn validate_call_mismatch_function_selector_fails() { + let mut builder = PrivateCallDataValidatorBuilder::new(); + + let mut data = builder.get_private_call_data(); + // Tweak the function selector in the call context to be different to the one in call stack item. + data.call_stack_item.public_inputs.call_context.function_selector.inner += 1; + + builder.validate_with_private_call_data(data); +} + #[test] fn validate_call_is_static_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); 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 b8f6be6902dd..fdfb832fce2e 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 @@ -1,18 +1,4 @@ -use crate::{ - components::private_call_data_validator::PrivateCallDataValidator, - tests::private_call_data_validator_builder::PrivateCallDataValidatorBuilder -}; -use dep::types::abis::private_kernel::private_call_data::PrivateCallData; - -impl PrivateCallDataValidatorBuilder { - pub fn get_private_call_data(self) -> PrivateCallData { - self.private_call.to_private_call_data() - } - - pub fn validate_with_private_call(private_call: PrivateCallData) { - PrivateCallDataValidator::new(private_call).validate([]); - } -} +use crate::tests::private_call_data_validator_builder::PrivateCallDataValidatorBuilder; /** * validate_public_call_requests @@ -28,7 +14,7 @@ fn validate_public_call_requests_succeeds() { } #[test] -fn validate_public_call_requests_delegate_calls_succeeds() { +fn validate_public_call_requests_delegate_call_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_public_call_requests_delegate(2); @@ -36,79 +22,82 @@ fn validate_public_call_requests_delegate_calls_succeeds() { builder.validate(); } -#[test(should_fail_with="call stack hash does not match call request hash")] -fn validate_public_call_requests_incorrect_hash_fails() { +#[test] +fn validate_public_call_requests_mix_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_public_call_requests(2); - let mut private_call = builder.get_private_call_data(); - // Change the hash to be a different value. - private_call.call_stack_item.public_inputs.public_call_stack_hashes[0] += 1; + builder.private_call.append_public_call_requests(1); + builder.private_call.append_public_call_requests_delegate(1); + builder.private_call.append_public_call_requests(1); - PrivateCallDataValidatorBuilder::validate_with_private_call(private_call); + builder.validate(); } -#[test(should_fail_with="invalid caller contract address")] -fn validate_public_call_requests_incorrect_caller_address_fails() { - let mut builder = PrivateCallDataValidatorBuilder::new(); +#[test] +fn validate_public_call_requests_from_static_call_succeeds() { + let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); builder.private_call.append_public_call_requests(1); - let mut call_request = builder.private_call.public_call_requests.pop(); - // Change the caller contract address to be a different value. - call_request.caller_contract_address.inner += 1; - builder.private_call.public_call_requests.push(call_request); + builder.private_call.append_public_call_requests_delegate(1); + builder.private_call.append_public_call_requests(1); builder.validate(); } -#[test(should_fail_with="invalid caller context")] -fn validate_public_call_requests_incorrect_caller_storage_contract_address_fails() { +#[test(should_fail_with="incorrect msg_sender for delegate call request")] +fn validate_public_call_requests_incorrect_msg_sender_for_delegate_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_public_call_requests_delegate(1); - let mut call_request = builder.private_call.public_call_requests.pop(); - // Change the storage contract to be a different value. - call_request.caller_context.storage_contract_address.inner += 1; - builder.private_call.public_call_requests.push(call_request); + // Change the msg_sender to be the contract address. + builder.private_call.public_call_requests.storage[0].item.call_context.msg_sender = builder.private_call.contract_address; builder.validate(); } -#[test(should_fail_with="invalid caller context")] -fn validate_public_call_requests_incorrect_caller_msg_sender_fails() { +#[test(should_fail_with="incorrect storage_contract_address for delegate call request")] +fn validate_public_call_requests_incorrect_storage_contract_address_for_delegate_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_public_call_requests_delegate(1); - let mut call_request = builder.private_call.public_call_requests.pop(); - // Change the msg_sender to be a different value. - call_request.caller_context.msg_sender.inner += 1; - builder.private_call.public_call_requests.push(call_request); + // Change the storage_contract_address to be the target contract address. + let target_contract = builder.private_call.public_call_requests.storage[0].item.contract_address; + builder.private_call.public_call_requests.storage[0].item.call_context.storage_contract_address = target_contract; builder.validate(); } -#[test(should_fail_with="call requests length does not match the expected length")] -fn validate_public_call_requests_fewer_hashes_fails() { +#[test(should_fail_with="incorrect msg_sender for call request")] +fn validate_public_call_requests_incorrect_msg_sender_for_regular_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_public_call_requests(2); - let mut private_call = builder.get_private_call_data(); - // Remove one call stack item hash. - private_call.call_stack_item.public_inputs.public_call_stack_hashes[1] = 0; + 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].item.call_context.msg_sender = builder.private_call.msg_sender; - PrivateCallDataValidatorBuilder::validate_with_private_call(private_call); + builder.validate(); } -#[test(should_fail_with="call stack hash does not match call request hash")] -fn validate_public_call_requests_more_hashes_fails() { +#[test(should_fail_with="incorrect storage_contract_address for call request")] +fn validate_public_call_requests_incorrect_storage_contract_address_for_regular_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_public_call_requests(2); - let mut private_call = builder.get_private_call_data(); - // Add one random call stack item hash. - private_call.call_stack_item.public_inputs.public_call_stack_hashes[2] = 123; + builder.private_call.append_public_call_requests(1); + // Change the storage_contract_address to be the caller's storage contract address. + builder.private_call.public_call_requests.storage[0].item.call_context.storage_contract_address = builder.private_call.storage_contract_address; + + builder.validate(); +} + +#[test(should_fail_with="static call cannot make non-static calls")] +fn validate_public_call_requests_static_call_regular_call_fails() { + let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); - PrivateCallDataValidatorBuilder::validate_with_private_call(private_call); + 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].item.call_context.is_static_call = false; + + builder.validate(); } /** @@ -125,7 +114,7 @@ fn validate_teardown_call_request_succeeds() { } #[test] -fn validate_teardown_call_request_delegate_calls_succeeds() { +fn validate_teardown_call_request_delegate_call_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_public_teardown_call_request_delegate(); @@ -133,71 +122,76 @@ fn validate_teardown_call_request_delegate_calls_succeeds() { builder.validate(); } -#[test(should_fail_with="call stack hash does not match call request hash")] -fn validate_teardown_call_request_incorrect_hash_fails() { - let mut builder = PrivateCallDataValidatorBuilder::new(); +#[test] +fn validate_teardown_call_request_from_static_call_succeeds() { + let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); - builder.private_call.append_public_teardown_call_request_delegate(); - let mut private_call = builder.get_private_call_data(); - // Change the hash to be a different value. - private_call.call_stack_item.public_inputs.public_teardown_function_hash += 1; + builder.private_call.append_public_teardown_call_request(); - PrivateCallDataValidatorBuilder::validate_with_private_call(private_call); + builder.validate(); } -#[test(should_fail_with="invalid caller contract address")] -fn validate_teardown_call_request_incorrect_caller_address_fails() { - let mut builder = PrivateCallDataValidatorBuilder::new(); +#[test] +fn validate_teardown_call_request_delegate_from_static_call_succeeds() { + let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); builder.private_call.append_public_teardown_call_request_delegate(); - // Change the caller contract address to be a different value. - builder.private_call.public_teardown_call_stack.storage[0].caller_contract_address.inner += 1; builder.validate(); } -#[test(should_fail_with="invalid caller context")] -fn validate_teardown_call_request_incorrect_caller_storage_contract_address_fails() { +#[test(should_fail_with="incorrect msg_sender for delegate call request")] +fn validate_teardown_call_request_incorrect_msg_sender_for_delegate_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_public_teardown_call_request_delegate(); - // Change the storage contract to be a different value. - builder.private_call.public_teardown_call_stack.storage[0].caller_context.storage_contract_address.inner += 1; + // Change the msg_sender to be the contract address. + builder.private_call.public_teardown_call_stack.storage[0].item.call_context.msg_sender = builder.private_call.contract_address; builder.validate(); } -#[test(should_fail_with="invalid caller context")] -fn validate_teardown_call_request_incorrect_caller_msg_sender_fails() { +#[test(should_fail_with="incorrect storage_contract_address for delegate call request")] +fn validate_teardown_call_request_incorrect_storage_contract_address_for_delegate_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_public_teardown_call_request_delegate(); - // Change the msg_sender to be a different value. - builder.private_call.public_teardown_call_stack.storage[0].caller_context.msg_sender.inner += 1; + // Change the storage_contract_address to be the target contract address. + let target_contract = builder.private_call.public_teardown_call_stack.storage[0].item.contract_address; + builder.private_call.public_teardown_call_stack.storage[0].item.call_context.storage_contract_address = target_contract; builder.validate(); } -#[test(should_fail_with="call requests length does not match the expected length")] -fn validate_teardown_call_request_fewer_hashes_fails() { +#[test(should_fail_with="incorrect msg_sender for call request")] +fn validate_teardown_call_request_incorrect_msg_sender_for_regular_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_public_teardown_call_request_delegate(); - let mut private_call = builder.get_private_call_data(); - // Remove the call stack item hash. - private_call.call_stack_item.public_inputs.public_teardown_function_hash = 0; + builder.private_call.append_public_teardown_call_request(); + // Change the msg_sender to be the caller's msg_sender. + builder.private_call.public_teardown_call_stack.storage[0].item.call_context.msg_sender = builder.private_call.msg_sender; - PrivateCallDataValidatorBuilder::validate_with_private_call(private_call); + builder.validate(); } -#[test(should_fail_with="call stack hash does not match call request hash")] -fn validate_teardown_call_request_more_hashes_fails() { +#[test(should_fail_with="incorrect storage_contract_address for call request")] +fn validate_teardown_call_request_incorrect_storage_contract_address_for_regular_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_public_teardown_call_request_delegate(); - let mut private_call = builder.get_private_call_data(); - // Add a random call stack item hash. - private_call.call_stack_item.public_inputs.public_teardown_function_hash = 123; + builder.private_call.append_public_teardown_call_request(); + // Change the storage_contract_address to be the caller's storage contract address. + builder.private_call.public_teardown_call_stack.storage[0].item.call_context.storage_contract_address = builder.private_call.storage_contract_address; - PrivateCallDataValidatorBuilder::validate_with_private_call(private_call); + builder.validate(); +} + +#[test(should_fail_with="static call cannot make non-static calls")] +fn validate_teardown_call_request_static_call_regular_call_fails() { + let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); + + builder.private_call.append_public_teardown_call_request(); + // Tweak the request to be making a non-static call. + builder.private_call.public_teardown_call_stack.storage[0].item.call_context.is_static_call = false; + + builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_counters.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_counters.nr index 02ef4c181a8a..76882fe2a2ea 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_counters.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_counters.nr @@ -137,7 +137,7 @@ fn validate_counters_private_call_requests_less_than_call_start_fails() { builder.private_call.append_private_call_requests(1); // Tweak the start counter of the first nested call to be LESS than the start counter of the call. let counter_start = builder.private_call.counter_start; - builder.private_call.private_call_requests.storage[0].call_request.start_side_effect_counter = counter_start - 1; + builder.private_call.private_call_requests.storage[0].start_side_effect_counter = counter_start - 1; builder.validate(); } @@ -149,7 +149,7 @@ fn validate_counters_private_call_requests_equal_call_start_fails() { builder.private_call.append_private_call_requests(1); // Tweak the start counter of the call to EQUAL the start counter of the first nested call. let counter_start = builder.private_call.counter_start; - builder.private_call.private_call_requests.storage[0].call_request.start_side_effect_counter = counter_start; + builder.private_call.private_call_requests.storage[0].start_side_effect_counter = counter_start; builder.validate(); } @@ -160,8 +160,8 @@ fn validate_counters_private_call_requests_less_than_previous_end_fails() { builder.private_call.append_private_call_requests(2); // Tweak the start counter of the second nested call to be LESS than the end counter of the first nested call. - let counter_end = builder.private_call.private_call_requests.get(0).call_request.end_side_effect_counter; - builder.private_call.private_call_requests.storage[1].call_request.start_side_effect_counter = counter_end - 1; + let counter_end = builder.private_call.private_call_requests.get(0).end_side_effect_counter; + builder.private_call.private_call_requests.storage[1].start_side_effect_counter = counter_end - 1; builder.validate(); } @@ -172,8 +172,8 @@ fn validate_counters_private_call_requests_same_as_previous_end_fails() { builder.private_call.append_private_call_requests(2); // Tweak the start counter of the second nested call to EQUAL the end counter of the first nested call. - let counter_end = builder.private_call.private_call_requests.get(0).call_request.end_side_effect_counter; - builder.private_call.private_call_requests.storage[1].call_request.start_side_effect_counter = counter_end; + let counter_end = builder.private_call.private_call_requests.get(0).end_side_effect_counter; + builder.private_call.private_call_requests.storage[1].start_side_effect_counter = counter_end; builder.validate(); } @@ -184,8 +184,8 @@ fn validate_counters_private_call_requests_end_less_than_start_fails() { builder.private_call.append_private_call_requests(1); // Tweak the end counter of the first nested call to be LESS than its start counter. - let counter_start = builder.private_call.private_call_requests.get(0).call_request.start_side_effect_counter; - builder.private_call.private_call_requests.storage[0].call_request.end_side_effect_counter = counter_start - 1; + let counter_start = builder.private_call.private_call_requests.get(0).start_side_effect_counter; + builder.private_call.private_call_requests.storage[0].end_side_effect_counter = counter_start - 1; builder.validate(); } @@ -196,8 +196,8 @@ fn validate_counters_private_call_requests_end_equal_start_fails() { builder.private_call.append_private_call_requests(1); // Tweak the end counter of the first nested call to EQUAL its start counter. - let counter_start = builder.private_call.private_call_requests.get(0).call_request.start_side_effect_counter; - builder.private_call.private_call_requests.storage[0].call_request.end_side_effect_counter = counter_start; + let counter_start = builder.private_call.private_call_requests.get(0).start_side_effect_counter; + builder.private_call.private_call_requests.storage[0].end_side_effect_counter = counter_start; builder.validate(); } @@ -209,7 +209,7 @@ fn validate_counters_private_call_requests_greater_than_call_end_fails() { builder.private_call.append_private_call_requests(1); // Tweak the end counter of the nested call to be GREATER than the end counter of the call. let counter_end = builder.private_call.counter; - builder.private_call.private_call_requests.storage[0].call_request.end_side_effect_counter = counter_end + 1; + builder.private_call.private_call_requests.storage[0].end_side_effect_counter = counter_end + 1; builder.validate(); } @@ -220,7 +220,7 @@ fn validate_counters_private_call_requests_equal_call_end_fails() { builder.private_call.append_private_call_requests(1); // Tweak the end counter of the nested call to EQUAL the end counter of the call. - builder.private_call.private_call_requests.storage[0].call_request.end_side_effect_counter = builder.private_call.counter; + builder.private_call.private_call_requests.storage[0].end_side_effect_counter = builder.private_call.counter; builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_private_call_requests.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_private_call_requests.nr index 0393deb1af7b..3ce78ba5a034 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_private_call_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_private_call_requests.nr @@ -13,8 +13,8 @@ impl PrivateCallDataValidatorBuilder { pub fn add_private_call_request(&mut self, counter_start: u32, counter_end: u32) { let index = self.private_call.private_call_requests.len(); self.private_call.append_private_call_requests(1); - self.private_call.private_call_requests.storage[index].call_request.start_side_effect_counter = counter_start; - self.private_call.private_call_requests.storage[index].call_request.end_side_effect_counter = counter_end; + self.private_call.private_call_requests.storage[index].start_side_effect_counter = counter_start; + self.private_call.private_call_requests.storage[index].end_side_effect_counter = counter_end; self.private_call.counter = counter_end + 1; } } @@ -23,16 +23,23 @@ impl PrivateCallDataValidatorBuilder { fn validate_private_call_requests_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_private_call_requests(1); - builder.private_call.append_private_call_requests_delegate(1); - builder.private_call.append_private_call_requests(1); + builder.private_call.append_private_call_requests(2); + + builder.validate(); +} + +#[test] +fn validate_private_call_requests_delegate_call_succeeds() { + let mut builder = PrivateCallDataValidatorBuilder::new(); + + builder.private_call.append_private_call_requests_delegate(2); builder.validate(); } #[test] -fn validate_private_call_requests_from_delegate_call_succeeds() { - let mut builder = PrivateCallDataValidatorBuilder::new().is_delegate_call(); +fn validate_private_call_requests_mix_succeeds() { + let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_private_call_requests(1); builder.private_call.append_private_call_requests_delegate(1); @@ -52,54 +59,58 @@ fn validate_private_call_requests_from_static_call_succeeds() { builder.validate(); } -#[test(should_fail_with="invalid caller context")] -fn validate_private_call_requests_incorrect_caller_storage_contract_address_fails() { +#[test(should_fail_with="incorrect msg_sender for delegate call request")] +fn validate_private_call_requests_incorrect_msg_sender_for_delegate_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_private_call_requests_delegate(1); - let mut call_request = builder.private_call.private_call_requests.pop(); - // Tweak the storage contract to be a different value. - call_request.call_request.caller_context.storage_contract_address.inner += 1; - builder.private_call.private_call_requests.push(call_request); + // Change the msg_sender to be the contract address. + builder.private_call.private_call_requests.storage[0].call_context.msg_sender = builder.private_call.contract_address; builder.validate(); } -#[test(should_fail_with="invalid caller context")] -fn validate_private_call_requests_incorrect_caller_msg_sender_fails() { +#[test(should_fail_with="incorrect storage_contract_address for delegate call request")] +fn validate_private_call_requests_incorrect_storage_contract_address_for_delegate_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_private_call_requests_delegate(1); - let mut call_request = builder.private_call.private_call_requests.pop(); - // Tweak the msg_sender to be a different value. - call_request.call_request.caller_context.msg_sender.inner += 1; - builder.private_call.private_call_requests.push(call_request); + // Change the storage_contract_address to be the target contract address. + let target_contract = builder.private_call.private_call_requests.storage[0].contract_address; + builder.private_call.private_call_requests.storage[0].call_context.storage_contract_address = target_contract; + + builder.validate(); +} + +#[test(should_fail_with="incorrect msg_sender for call request")] +fn validate_private_call_requests_incorrect_msg_sender_for_regular_call_fails() { + let mut builder = PrivateCallDataValidatorBuilder::new(); + + builder.private_call.append_private_call_requests(1); + // Change the msg_sender to be the caller's msg_sender. + builder.private_call.private_call_requests.storage[0].call_context.msg_sender = builder.private_call.msg_sender; builder.validate(); } -#[test(should_fail_with="mismatch is_static_call flag")] -fn validate_private_call_requests_regular_call_is_static_true_fails() { +#[test(should_fail_with="incorrect storage_contract_address for call request")] +fn validate_private_call_requests_incorrect_storage_contract_address_for_regular_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); builder.private_call.append_private_call_requests(1); - let mut call_request = builder.private_call.private_call_requests.pop(); - // Tweak the is_static_call flag to be true. - call_request.call_request.caller_context.is_static_call = true; - builder.private_call.private_call_requests.push(call_request); + // Change the storage_contract_address to be the caller's storage contract address. + builder.private_call.private_call_requests.storage[0].call_context.storage_contract_address = builder.private_call.storage_contract_address; builder.validate(); } -#[test(should_fail_with="mismatch is_static_call flag")] -fn validate_private_call_requests_static_call_is_static_false_fails() { +#[test(should_fail_with="static call cannot make non-static calls")] +fn validate_private_call_requests_static_call_regular_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); builder.private_call.append_private_call_requests(1); - let mut call_request = builder.private_call.private_call_requests.pop(); - // Tweak the is_static_call flag to be false. - call_request.call_request.caller_context.is_static_call = false; - builder.private_call.private_call_requests.push(call_request); + // Tweak the request to be making a non-static call. + builder.private_call.private_call_requests.storage[0].call_context.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/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/mod.nr index 9eda032c4221..621fc3f494ef 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/mod.nr @@ -11,7 +11,7 @@ use crate::{ }; use dep::types::{ abis::{ - private_call_request::ScopedPrivateCallRequest, + private_call_request::PrivateCallRequest, kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputsArrayLengths, private_circuit_public_inputs::PrivateCircuitPublicInputsArrayLengths }, @@ -60,9 +60,6 @@ impl PrivateKernelCircuitOutputValidatorBuilder { self.tx_request, private_call.call_stack_item.public_inputs, array_lengths, - private_call.call_stack_item.contract_address, - private_call.public_call_stack, - private_call.public_teardown_call_request, FixtureBuilder::vk_tree_root() ); } @@ -71,8 +68,8 @@ impl PrivateKernelCircuitOutputValidatorBuilder { let mut previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); // Append one private call request for the current call. let num_private_call_requests = self.previous_kernel.private_call_requests.len(); - previous_kernel.end.private_call_stack[num_private_call_requests] = ScopedPrivateCallRequest::empty(); - previous_kernel.end.private_call_stack[num_private_call_requests].call_request.args_hash = 98765432; + previous_kernel.end.private_call_stack[num_private_call_requests] = PrivateCallRequest::empty(); + previous_kernel.end.private_call_stack[num_private_call_requests].args_hash = 98765432; let previous_kernel_array_lengths = PrivateKernelCircuitPublicInputsArrayLengths::new(previous_kernel); let private_call = self.private_call.to_private_call_data(); @@ -82,10 +79,7 @@ impl PrivateKernelCircuitOutputValidatorBuilder { previous_kernel, previous_kernel_array_lengths, private_call.call_stack_item.public_inputs, - private_call_array_lengths, - private_call.call_stack_item.contract_address, - private_call.public_call_stack, - private_call.public_teardown_call_request + private_call_array_lengths ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_aggregated_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_aggregated_values.nr index 8e25e7fd7819..a68647a2cc7b 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_aggregated_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_aggregated_values.nr @@ -189,7 +189,7 @@ fn validate_aggregated_values_public_teardown_call_request_from_previous_mismatc builder.previous_kernel.append_public_teardown_call_request(); builder.output.append_public_teardown_call_request(); // Tweak the output. - builder.output.public_teardown_call_stack.storage[0].hash += 1; + builder.output.public_teardown_call_stack.storage[0].item.args_hash += 1; builder.validate_as_inner_call(); } @@ -201,7 +201,7 @@ fn validate_aggregated_values_public_teardown_call_request_from_private_call_mis builder.private_call.append_public_teardown_call_request(); builder.output.append_public_teardown_call_request(); // Tweak the output. - builder.output.public_teardown_call_stack.storage[0].hash += 1; + builder.output.public_teardown_call_stack.storage[0].item.args_hash += 1; builder.validate_as_inner_call(); } 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 63cd2b9e8791..f2586db2c0c5 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 @@ -165,7 +165,7 @@ fn validate_initial_values_public_teardown_call_request_mismatch_fails() { builder.private_call.append_public_teardown_call_request(); builder.output.append_public_teardown_call_request(); // Tweak the output. - builder.output.public_teardown_call_stack.storage[0].hash += 1; + builder.output.public_teardown_call_stack.storage[0].item.args_hash += 1; builder.validate_as_first_call(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/mod.nr index 699b6991032b..3b1bbec4d121 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/mod.nr @@ -6,7 +6,7 @@ use crate::components::private_kernel_circuit_public_inputs_composer::PrivateKer use dep::types::{ abis::{ kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - private_call_request::ScopedPrivateCallRequest + private_call_request::PrivateCallRequest }, tests::fixture_builder::FixtureBuilder, transaction::tx_request::TxRequest }; @@ -43,9 +43,7 @@ impl PrivateKernelCircuitPublicInputsComposerBuilder { let private_call = self.private_call.to_private_call_data(); self.new_from_tx_request().with_private_call( private_call.call_stack_item.public_inputs, - private_call.call_stack_item.contract_address, - private_call.public_call_stack, - private_call.public_teardown_call_request + private_call.call_stack_item.contract_address ).finish() } @@ -53,16 +51,14 @@ impl PrivateKernelCircuitPublicInputsComposerBuilder { // Append one private call request for the previous kernel. let mut previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); let num_private_call_requests = self.previous_kernel.private_call_requests.len(); - previous_kernel.end.private_call_stack[num_private_call_requests] = ScopedPrivateCallRequest::empty(); - previous_kernel.end.private_call_stack[num_private_call_requests].call_request.args_hash = 98765432; + previous_kernel.end.private_call_stack[num_private_call_requests] = PrivateCallRequest::empty(); + previous_kernel.end.private_call_stack[num_private_call_requests].args_hash = 98765432; let private_call = self.private_call.to_private_call_data(); PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(previous_kernel).pop_top_call_request().with_private_call( private_call.call_stack_item.public_inputs, - private_call.call_stack_item.contract_address, - private_call.public_call_stack, - private_call.public_teardown_call_request + private_call.call_stack_item.contract_address ).finish() } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr index d80e1fa3fdb7..85a0831fc468 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr @@ -271,7 +271,7 @@ fn new_from_previous_kernel_with_private_call_public_call_requests_succeeds() { let output = builder.compose_from_previous_kernel(); assert_array_eq( - output.end.public_call_stack, + output.end.public_call_requests, [prev[0], prev[1], curr[0], curr[1]] ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr index d0cb79ec0f34..f3c119504d08 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr @@ -194,7 +194,7 @@ fn propagate_from_private_call_public_call_requests_succeeds() { let output = builder.compose_from_tx_request(); - assert_array_eq(output.end.public_call_stack, [res[0], res[1]]); + assert_array_eq(output.end.public_call_requests, [res[0], res[1]]); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr index a485380deb3e..eb8e9956eb40 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr @@ -1,11 +1,12 @@ use dep::types::{ abis::{ - call_request::CallRequest, public_call_stack_item::PublicCallStackItem, + public_call_stack_item::PublicCallStackItem, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputsBuilder, public_kernel_data::PublicKernelData, note_hash::NoteHash, nullifier::Nullifier, - public_call_data::PublicCallData, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest, log_hash::{ScopedLogHash, LogHash}, - global_variables::GlobalVariables, combined_constant_data::CombinedConstantData + public_call_data::PublicCallData, public_call_request::PublicCallRequest, + public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, + log_hash::{ScopedLogHash, LogHash}, global_variables::GlobalVariables, + combined_constant_data::CombinedConstantData }, address::AztecAddress, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, @@ -30,6 +31,9 @@ pub fn validate_inputs(public_call: PublicCallData) { assert( this_call_stack_item.function_data.is_private == false, "Cannot execute a private function with the public kernel circuit" ); + assert_eq( + this_call_stack_item.function_data.selector, this_call_stack_item.public_inputs.call_context.function_selector, "function selector in call context does not match call stack item" + ); assert(public_call.bytecode_hash != 0, "Bytecode hash cannot be zero"); } @@ -133,14 +137,29 @@ fn perform_static_call_checks(public_call: PublicCallData) { } } -fn is_valid_caller(request: CallRequest, public_call: PublicCallData) -> bool { - let call_context = public_call.call_stack_item.public_inputs.call_context; - - let valid_caller_context = request.caller_context.msg_sender.eq(call_context.msg_sender) - & request.caller_context.storage_contract_address.eq(call_context.storage_contract_address); +fn validate_call_context(request: PublicCallRequest, public_call: PublicCallData) { + let target_context = request.item.call_context; + let target_contract = request.item.contract_address; + let this_context = public_call.call_stack_item.public_inputs.call_context; - request.caller_contract_address.eq(public_call.call_stack_item.contract_address) - & (request.caller_context.is_empty() | valid_caller_context) + if target_context.is_delegate_call { + assert_eq( + target_context.msg_sender, this_context.msg_sender, "incorrect msg_sender for delegate call request" + ); + assert_eq( + target_context.storage_contract_address, this_context.storage_contract_address, "incorrect storage_contract_address for delegate call request" + ); + } else { + assert_eq( + target_context.msg_sender, this_context.storage_contract_address, "incorrect msg_sender for call request" + ); + assert_eq( + target_context.storage_contract_address, target_contract, "incorrect storage_contract_address for call request" + ); + } + if !target_context.is_static_call { + assert(this_context.is_static_call == false, "static call cannot make non-static calls"); + } } pub fn update_end_non_revertible_call_stack( @@ -164,29 +183,15 @@ pub fn update_teardown_call_stack(public_call: PublicCallData, circuit_outputs: circuit_outputs.public_teardown_call_stack.extend_from_bounded_vec(requests); } -fn validate_public_call_stack(public_call: PublicCallData) -> BoundedVec { - let public_call_requests = array_to_bounded_vec(public_call.public_call_stack); - let hashes = public_call.call_stack_item.public_inputs.public_call_stack_hashes; - validate_call_requests(public_call_requests, hashes, public_call); - public_call_requests -} - -fn validate_call_requests( - call_requests: BoundedVec, - hashes: [Field; N], - public_call: PublicCallData -) { - assert_eq( - array_length(hashes), call_requests.len(), "call requests length does not match the expected length" - ); - for i in 0..N { - let hash = hashes[i]; - if hash != 0 { - let request = call_requests.get_unchecked(i); - assert_eq(request.hash, hash, "call stack hash does not match call request hash"); - assert(is_valid_caller(request, public_call), "invalid caller"); +fn validate_public_call_stack(public_call: PublicCallData) -> BoundedVec { + let public_call_requests = public_call.call_stack_item.public_inputs.public_call_requests; + for i in 0..public_call_requests.len() { + let request = public_call_requests[i]; + if !request.item.contract_address.is_zero() { + validate_call_context(request, public_call); } } + array_to_bounded_vec(public_call_requests) } pub fn update_validation_requests(public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder) { @@ -543,34 +548,20 @@ pub fn propagate_new_unencrypted_logs_non_revertible( * @param builder The circuit builder * @param public_kernel_inputs The inputs to this iteration of the kernel circuit */ -pub fn validate_call_against_request(public_call: PublicCallData, request: CallRequest) { +pub fn validate_call_against_request(public_call: PublicCallData, request: PublicCallRequest) { // TODO: this logic might need to change to accommodate the weird edge 3 initial txs (the 'main' tx, the 'fee' tx, // and the 'gas rebate' tx). let call_stack_item = public_call.call_stack_item; - assert( - request.hash == call_stack_item.get_compressed().hash(), "calculated public_kernel_inputs_hash does not match provided public_kernel_inputs_hash at the top of the call stack" + call_stack_item.get_compressed() == request.item, "call stack item does not match item at the top of the call stack" ); let call_context = call_stack_item.public_inputs.call_context; - if call_context.is_delegate_call { - let caller_context = request.caller_context; - assert(!caller_context.is_empty(), "caller context cannot be empty for delegate calls"); - assert( - call_context.msg_sender.eq(caller_context.msg_sender), "call stack msg_sender does not match expected msg_sender for delegate calls" - ); - assert( - call_context.storage_contract_address.eq(caller_context.storage_contract_address), "call stack storage address does not match expected contract address for delegate calls" - ); assert( !call_stack_item.contract_address.eq(call_context.storage_contract_address), "curent contract address must not match storage contract address for delegate calls" ); } else { - let caller_contract_address = request.caller_contract_address; - assert( - call_context.msg_sender.eq(caller_contract_address), "call stack msg_sender does not match caller contract address" - ); assert( call_context.storage_contract_address.eq(call_stack_item.contract_address), "call stack storage address does not match expected contract address" ); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index 7c046d0cc155..afdf5495f540 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -91,7 +91,7 @@ impl PublicKernelAppLogicCircuitPrivateInputs { // and we aren't updating the public end values, so we want this kernel circuit to solve. // So just check that the call request is the same as the one we expected. assert( - reverted_call_request.hash == self.public_call.call_stack_item.get_compressed().hash(), "calculated public_kernel_inputs_hash does not match provided public_kernel_inputs_hash at the top of the call stack" + reverted_call_request.item == self.public_call.call_stack_item.get_compressed(), "call stack item does not match item at the top of the call stack" ); } @@ -102,22 +102,24 @@ impl PublicKernelAppLogicCircuitPrivateInputs { mod tests { use crate::{ public_kernel_app_logic::{PublicKernelAppLogicCircuitPrivateInputs, ALLOWED_PREVIOUS_CIRCUITS}, - utils::{ - assert_eq_call_requests, assert_eq_public_data_reads, assert_eq_public_data_update_requests, - compute_public_data_reads, compute_public_data_update_requests - } + utils::{compute_public_data_reads, compute_public_data_update_requests} }; use dep::types::{ abis::{ gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, note_hash::{NoteHash, ScopedNoteHash}, log_hash::ScopedLogHash, - nullifier::{Nullifier, ScopedNullifier}, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequest + nullifier::{Nullifier, ScopedNullifier}, + public_call_stack_item_compressed::PublicCallStackItemCompressed, + public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, + read_request::ReadRequest }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, hash::{compute_l2_to_l1_hash, compute_siloed_note_hash, compute_siloed_nullifier}, messaging::l2_to_l1_message::L2ToL1Message, - tests::{fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder}, + tests::{ + fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder, + utils::assert_array_eq + }, utils::arrays::{array_eq, array_length}, traits::is_empty }; use dep::types::constants::{ @@ -158,9 +160,8 @@ mod tests { pub fn execute(&mut self) -> PublicKernelCircuitPublicInputs { let public_call = self.public_call.finish(); // Adjust the call stack item hash for the current call in the previous iteration. - let hash = public_call.call_stack_item.get_compressed().hash(); - let is_delegate_call = public_call.call_stack_item.public_inputs.call_context.is_delegate_call; - self.previous_kernel.push_public_call_request(hash, is_delegate_call); + let compressed = public_call.call_stack_item.get_compressed(); + self.previous_kernel.push_public_call_request(compressed); let previous_kernel = self.previous_kernel.to_public_kernel_data(true); let kernel = PublicKernelAppLogicCircuitPrivateInputs { previous_kernel, public_call }; @@ -168,6 +169,19 @@ mod tests { kernel.public_kernel_app_logic() } + pub fn get_call_request_item(self) -> PublicCallStackItemCompressed { + let public_call = self.public_call.finish(); + public_call.call_stack_item.get_compressed() + } + + pub fn failed_with_call_request_item(&mut self, item: PublicCallStackItemCompressed) { + let public_call = self.public_call.finish(); + self.previous_kernel.push_public_call_request(item); + let previous_kernel = self.previous_kernel.to_public_kernel_data(true); + let kernel = PublicKernelAppLogicCircuitPrivateInputs { previous_kernel, public_call }; + let _ = kernel.public_kernel_app_logic(); + } + pub fn succeeded(&mut self) { let _ = self.execute(); } @@ -259,7 +273,7 @@ mod tests { let public_data_update_requests = [previous[0], previous[1], current[0], current[1]]; let public_inputs = builder.execute(); - assert_eq_public_data_update_requests( + assert_array_eq( public_inputs.end.public_data_update_requests, public_data_update_requests ); @@ -278,7 +292,7 @@ mod tests { let public_data_read_requests = [previous[0], previous[1], current[0], current[1]]; let public_inputs = builder.execute(); - assert_eq_public_data_reads( + assert_array_eq( public_inputs.validation_requests.public_data_reads, public_data_read_requests ); @@ -419,25 +433,15 @@ mod tests { builder.failed(); } - #[test(should_fail_with="call stack storage address does not match expected contract address for delegate calls")] + #[test(should_fail_with="call stack item does not match item at the top of the call stack")] fn public_kernel_circuit_fails_on_incorrect_storage_contract_in_delegate_call() { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new().is_delegate_call(); + let mut item = builder.get_call_request_item(); // Set the storage contract address to be the contract address. - builder.public_call.public_inputs.call_context.storage_contract_address = builder.public_call.contract_address; - - builder.failed(); - } + item.call_context.storage_contract_address = builder.public_call.contract_address; - #[test(should_fail_with = "call requests length does not match the expected length")] - fn incorrect_call_requests_length_fails() { - let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); - - builder.public_call.append_public_call_requests(2, false); - // Remove one call request. - let _ = builder.public_call.public_call_stack.pop(); - - builder.failed(); + builder.failed_with_call_request_item(item); } #[test] @@ -452,7 +456,7 @@ mod tests { // Only the 2 valid reads should have been propagated. let expected = [public_data_update_requests[0], public_data_update_requests[2]]; - assert_eq_public_data_update_requests(public_inputs.end.public_data_update_requests, expected); + assert_array_eq(public_inputs.end.public_data_update_requests, expected); } #[test] @@ -460,7 +464,7 @@ mod tests { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); builder.public_call.append_public_call_requests_for_regular_calls(2); - let storage = builder.public_call.public_call_stack.storage; + let storage = builder.public_call.public_inputs.public_call_requests.storage; let public_call_stack = [storage[0], storage[1]]; builder.public_call.append_update_requests(2); @@ -473,12 +477,12 @@ mod tests { let public_inputs = builder.execute(); - assert_eq_call_requests(public_inputs.end.public_call_stack, public_call_stack); - assert_eq_public_data_update_requests( + assert_array_eq(public_inputs.end.public_call_stack, public_call_stack); + assert_array_eq( public_inputs.end.public_data_update_requests, update_requests ); - assert_eq_public_data_reads( + assert_array_eq( public_inputs.validation_requests.public_data_reads, read_requests ); @@ -607,13 +611,13 @@ mod tests { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); builder.public_call.public_inputs.revert_code = 1; let public_call = builder.public_call.finish(); - let hash = public_call.call_stack_item.get_compressed().hash(); + let item = public_call.call_stack_item.get_compressed(); - builder.previous_kernel.push_public_call_request(hash, false); - builder.previous_kernel.push_public_call_request(hash, false); + builder.previous_kernel.append_public_call_requests(2); + builder.previous_kernel.push_public_call_request(item); - builder.previous_kernel.push_public_teardown_call_request(hash, false); - builder.previous_kernel.push_public_teardown_call_request(hash, false); + builder.previous_kernel.append_public_teardown_call_request(); + builder.previous_kernel.append_public_teardown_call_request(); let previous_kernel = builder.previous_kernel.to_public_kernel_data(true); let kernel = PublicKernelAppLogicCircuitPrivateInputs { previous_kernel, public_call }; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index ea8542f56e39..bc343e0d002d 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -86,21 +86,22 @@ impl PublicKernelSetupCircuitPrivateInputs { mod tests { use crate::{ public_kernel_setup::{PublicKernelSetupCircuitPrivateInputs, ALLOWED_PREVIOUS_CIRCUITS}, - utils::{ - assert_eq_call_requests, assert_eq_public_data_reads, assert_eq_public_data_update_requests, - compute_public_data_reads, compute_public_data_update_requests - } + utils::{compute_public_data_reads, compute_public_data_update_requests} }; use dep::types::{ abis::{ - call_request::CallRequest, function_selector::FunctionSelector, gas::Gas, + function_selector::FunctionSelector, gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, max_block_number::MaxBlockNumber, + public_call_stack_item_compressed::PublicCallStackItemCompressed, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, public_call_data::PublicCallData, read_request::ReadRequest, log_hash::ScopedLogHash }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, contrakt::storage_read::StorageRead, - tests::{fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder}, + tests::{ + fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder, + utils::assert_array_eq + }, utils::{arrays::{array_eq, array_length}}, traits::is_empty }; use dep::types::constants::{ @@ -126,15 +127,13 @@ mod tests { pub fn stub_teardown_call(&mut self) { let teardown_call = PublicCallDataBuilder::new(); let teardown_call = teardown_call.finish(); - let teardown_call_hash = teardown_call.call_stack_item.get_compressed().hash(); - let teardown_is_delegate_call = teardown_call.call_stack_item.public_inputs.call_context.is_delegate_call; - self.previous_kernel.push_public_call_request(teardown_call_hash, teardown_is_delegate_call); + let compressed_item = teardown_call.call_stack_item.get_compressed(); + self.previous_kernel.push_public_call_request(compressed_item); } pub fn push_public_call(&mut self, public_call: PublicCallData) { - let public_call_hash = public_call.call_stack_item.get_compressed().hash(); - let setup_is_delegate_call = public_call.call_stack_item.public_inputs.call_context.is_delegate_call; - self.previous_kernel.push_public_call_request(public_call_hash, setup_is_delegate_call); + let compressed_item = public_call.call_stack_item.get_compressed(); + self.previous_kernel.push_public_call_request(compressed_item); } pub fn is_delegate_call(&mut self) -> Self { @@ -174,6 +173,23 @@ mod tests { kernel.public_kernel_setup() } + pub fn get_call_request_item(self) -> PublicCallStackItemCompressed { + let public_call = self.public_call.finish(); + public_call.call_stack_item.get_compressed() + } + + pub fn failed_with_call_request_item(&mut self, item: PublicCallStackItemCompressed) { + // The teardown call is at the bottom of the call stack. + self.stub_teardown_call(); + + let public_call = self.public_call.finish(); + self.previous_kernel.push_public_call_request(item); + let previous_kernel = self.previous_kernel.to_public_kernel_data(false); + + let kernel = PublicKernelSetupCircuitPrivateInputs { previous_kernel, public_call }; + let _ = kernel.public_kernel_setup(); + } + pub fn succeeded(&mut self) { let _ = self.execute(); } @@ -195,7 +211,7 @@ mod tests { // TODO(fees) we don't yet handle non-revertible reads // Only the 2 valid reads should have been propagated. // let expected = [public_data_reads[0], public_data_reads[2]]; - // assert_eq_public_data_reads(public_inputs.end.public_data_reads, expected); + // assert_array_eq(public_inputs.end.public_data_reads, expected); } // TODO(fees) we don't yet handle non-revertible update requests @@ -211,7 +227,7 @@ mod tests { // // Only the 2 valid reads should have been propagated. // let expected = [public_data_update_requests[0], public_data_update_requests[2]]; - // assert_eq_public_data_update_requests(public_inputs.end.public_data_update_requests, expected); + // assert_array_eq(public_inputs.end.public_data_update_requests, expected); // } #[test(should_fail_with="Bytecode hash cannot be zero")] @@ -246,15 +262,16 @@ mod tests { builder.failed(); } - #[test(should_fail_with="calculated public_kernel_inputs_hash does not match provided public_kernel_inputs_hash at the top of the call stack")] - fn inconsistent_call_hash_should_fail() { + #[test(should_fail_with="call stack item does not match item at the top of the call stack")] + fn inconsistent_call_request_item_should_fail() { let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); builder.stub_teardown_call(); let public_call = builder.public_call.finish(); - let hash = public_call.call_stack_item.get_compressed().hash(); - // Tweak the call stack item hash. - builder.previous_kernel.push_public_call_request(hash + 1, false); + let mut item = public_call.call_stack_item.get_compressed(); + // Tweak the call stack item. + item.args_hash += 1; + builder.previous_kernel.push_public_call_request(item); let previous_kernel = builder.previous_kernel.to_public_kernel_data(false); let kernel = PublicKernelSetupCircuitPrivateInputs { previous_kernel, public_call }; @@ -262,14 +279,15 @@ mod tests { let _ = kernel.public_kernel_setup(); } - #[test(should_fail_with="call stack msg_sender does not match caller contract address")] + #[test(should_fail_with="call stack item does not match item at the top of the call stack")] fn incorrect_msg_sender_fails_for_regular_calls() { let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); + let mut item = builder.get_call_request_item(); // Set the msg_sender to a wrong value. - builder.public_call.public_inputs.call_context.msg_sender.inner += 1; + item.call_context.msg_sender.inner += 1; - builder.failed(); + builder.failed_with_call_request_item(item); } #[test(should_fail_with="call stack storage address does not match expected contract address")] @@ -288,32 +306,15 @@ mod tests { builder.succeeded(); } - #[test(should_fail_with="caller context cannot be empty for delegate calls")] - fn empty_caller_context_for_delegate_calls_fails() { - let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new().is_delegate_call(); - builder.stub_teardown_call(); - - let public_call = builder.public_call.finish(); - - let hash = public_call.call_stack_item.get_compressed().hash(); - // Caller context is empty for regular calls. - let is_delegate_call = false; - builder.previous_kernel.push_public_call_request(hash, is_delegate_call); - let previous_kernel = builder.previous_kernel.to_public_kernel_data(false); - - let kernel = PublicKernelSetupCircuitPrivateInputs { previous_kernel, public_call }; - - let _ = kernel.public_kernel_setup(); - } - - #[test(should_fail_with="call stack msg_sender does not match expected msg_sender for delegate calls")] + #[test(should_fail_with="call stack item does not match item at the top of the call stack")] fn incorrect_msg_sender_for_delegate_calls_fails() { let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new().is_delegate_call(); + let mut item = builder.get_call_request_item(); // Set the msg_sender to be the caller contract. - builder.public_call.public_inputs.call_context.msg_sender = builder.previous_kernel.contract_address; + item.call_context.msg_sender = builder.previous_kernel.contract_address; - builder.failed(); + builder.failed_with_call_request_item(item); } #[test(should_fail_with="curent contract address must not match storage contract address for delegate calls")] @@ -325,41 +326,28 @@ mod tests { builder.failed(); } - #[test(should_fail_with = "call stack hash does not match call request hash")] - fn incorrect_call_request_hash_fails() { - let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); - - builder.public_call.append_public_call_requests(2, false); - let mut call_request = builder.public_call.public_call_stack.pop(); - // Change the hash to be a different value. - call_request.hash += 1; - builder.public_call.public_call_stack.push(call_request); - - builder.failed(); - } - - #[test(should_fail_with = "invalid caller")] - fn incorrect_caller_address_for_call_request_fails() { + #[test(should_fail_with = "incorrect storage_contract_address for call request")] + fn incorrect_storage_contract_address_for_call_request_fails() { let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); - builder.public_call.append_public_call_requests(1, false); - let mut call_request = builder.public_call.public_call_stack.pop(); + builder.public_call.append_public_call_requests_for_regular_calls(1); + let mut call_request = builder.public_call.public_inputs.public_call_requests.pop(); // Change the caller contract address to be a different value. - call_request.caller_contract_address.inner += 1; - builder.public_call.public_call_stack.push(call_request); + call_request.item.call_context.storage_contract_address.inner += 1; + builder.public_call.public_inputs.public_call_requests.push(call_request); builder.failed(); } - #[test(should_fail_with = "invalid caller")] - fn incorrect_caller_context_for_delegate_call_request_fails() { + #[test(should_fail_with="incorrect storage_contract_address for delegate call request")] + fn incorrect_call_context_for_delegate_call_request_fails() { let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); - builder.public_call.append_public_call_requests(1, true); - let mut call_request = builder.public_call.public_call_stack.pop(); - // Change the storage contract to be a different value. - call_request.caller_context.storage_contract_address.inner += 1; - builder.public_call.public_call_stack.push(call_request); + builder.public_call.append_public_call_requests_for_delegate_calls(1); + let mut call_request = builder.public_call.public_inputs.public_call_requests.pop(); + // Change the storage contract address to be the contract address. + call_request.item.call_context.storage_contract_address = call_request.item.contract_address; + builder.public_call.public_inputs.public_call_requests.push(call_request); builder.failed(); } @@ -377,7 +365,7 @@ mod tests { builder.previous_kernel.max_block_number = MaxBlockNumber::new(13); builder.public_call.append_public_call_requests_for_regular_calls(2); - let storage = builder.public_call.public_call_stack.storage; + let storage = builder.public_call.public_inputs.public_call_requests.storage; builder.stub_teardown_call(); let non_revertible_call_stack = [ @@ -404,16 +392,16 @@ mod tests { let public_inputs = kernel.public_kernel_setup(); assert_eq(public_inputs.validation_requests.for_rollup.max_block_number.unwrap(), 13); - assert_eq_call_requests( + assert_array_eq( public_inputs.end_non_revertible.public_call_stack, non_revertible_call_stack ); // TODO(fees) we don't yet handle non-revertible update requests - // assert_eq_public_data_update_requests( + // assert_array_eq( // public_inputs.end.public_data_update_requests, // update_requests // ); - // assert_eq_public_data_reads(public_inputs.end.public_data_reads, read_requests); + // assert_array_eq(public_inputs.end.public_data_reads, read_requests); } // TODO: Find another way to test this. Currently it will crash because we are popping from an empty array: @@ -602,13 +590,13 @@ mod tests { let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); builder.public_call.public_inputs.revert_code = 0; let public_call = builder.public_call.finish(); - let hash = public_call.call_stack_item.get_compressed().hash(); + let item = public_call.call_stack_item.get_compressed(); - builder.previous_kernel.push_public_call_request(hash, false); - builder.previous_kernel.push_public_call_request(hash, false); + builder.previous_kernel.push_public_call_request(item); + builder.previous_kernel.push_public_call_request(item); - builder.previous_kernel.push_public_teardown_call_request(hash, false); - builder.previous_kernel.push_public_teardown_call_request(hash, false); + builder.previous_kernel.push_public_teardown_call_request(item); + builder.previous_kernel.push_public_teardown_call_request(item); let previous_kernel = builder.previous_kernel.to_public_kernel_data(false); let kernel = PublicKernelSetupCircuitPrivateInputs { previous_kernel, public_call }; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr index ac095b4b3cb0..e8ff3f09a8c5 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr @@ -146,7 +146,7 @@ impl PublicKernelTeardownCircuitPrivateInputs { let reverted_call_request = remaining_calls.pop(); assert( - reverted_call_request.hash == self.public_call.call_stack_item.get_compressed().hash(), "calculated public_kernel_inputs_hash does not match provided public_kernel_inputs_hash at the top of the teardown call stack" + reverted_call_request.item == self.public_call.call_stack_item.get_compressed(), "call stack item does not match item at the top of the call stack" ); } @@ -157,16 +157,15 @@ impl PublicKernelTeardownCircuitPrivateInputs { mod tests { use crate::{ public_kernel_teardown::{ALLOWED_PREVIOUS_CIRCUITS, PublicKernelTeardownCircuitPrivateInputs}, - utils::{ - assert_eq_call_requests, assert_eq_public_data_reads, assert_eq_public_data_update_requests, - compute_public_data_reads, compute_public_data_update_requests - } + utils::{compute_public_data_reads, compute_public_data_update_requests} }; use dep::types::{ abis::{ - call_request::CallRequest, function_selector::FunctionSelector, gas::Gas, - kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest, log_hash::ScopedLogHash + function_selector::FunctionSelector, gas::Gas, + kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, + public_call_stack_item_compressed::PublicCallStackItemCompressed, + public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, + log_hash::ScopedLogHash }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, contrakt::storage_read::StorageRead, @@ -213,9 +212,8 @@ mod tests { pub fn execute(&mut self) -> PublicKernelCircuitPublicInputs { let public_call = self.public_call.finish(); // Adjust the call stack item hash for the current call in the previous iteration. - let hash = public_call.call_stack_item.get_compressed().hash(); - let is_delegate_call = public_call.call_stack_item.public_inputs.call_context.is_delegate_call; - self.previous_kernel.push_public_teardown_call_request(hash, is_delegate_call); + let compressed = public_call.call_stack_item.get_compressed(); + self.previous_kernel.push_public_teardown_call_request(compressed); let mut previous_kernel = self.previous_kernel.to_public_kernel_data(true); let kernel = PublicKernelTeardownCircuitPrivateInputs { previous_kernel, public_call }; @@ -223,6 +221,19 @@ mod tests { kernel.public_kernel_teardown() } + pub fn get_call_request_item(self) -> PublicCallStackItemCompressed { + let public_call = self.public_call.finish(); + public_call.call_stack_item.get_compressed() + } + + pub fn failed_with_call_request_item(&mut self, item: PublicCallStackItemCompressed) { + let public_call = self.public_call.finish(); + self.previous_kernel.push_public_teardown_call_request(item); + let previous_kernel = self.previous_kernel.to_public_kernel_data(true); + let kernel = PublicKernelTeardownCircuitPrivateInputs { previous_kernel, public_call }; + let _ = kernel.public_kernel_teardown(); + } + pub fn succeeded(&mut self) { let _ = self.execute(); } @@ -264,14 +275,15 @@ mod tests { builder.failed(); } - #[test(should_fail_with="calculated public_kernel_inputs_hash does not match provided public_kernel_inputs_hash at the top of the call stack")] - fn inconsistent_call_hash_should_fail() { + #[test(should_fail_with="call stack item does not match item at the top of the call stack")] + fn inconsistent_call_request_item_should_fail() { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); let public_call = builder.public_call.finish(); - let hash = public_call.call_stack_item.get_compressed().hash(); - // Tweak the call stack item hash. - builder.previous_kernel.push_public_teardown_call_request(hash + 1, false); + let mut item = public_call.call_stack_item.get_compressed(); + // Tweak the call stack item. + item.args_hash += 1; + builder.previous_kernel.push_public_teardown_call_request(item); let previous_kernel = builder.previous_kernel.to_public_kernel_data(true); let kernel = PublicKernelTeardownCircuitPrivateInputs { previous_kernel, public_call }; @@ -279,14 +291,15 @@ mod tests { let _ = kernel.public_kernel_teardown(); } - #[test(should_fail_with="call stack msg_sender does not match caller contract address")] + #[test(should_fail_with="call stack item does not match item at the top of the call stack")] fn incorrect_msg_sender_fails_for_regular_calls() { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); + let mut item = builder.get_call_request_item(); // Set the msg_sender to a wrong value. - builder.public_call.public_inputs.call_context.msg_sender.inner += 1; + item.call_context.msg_sender.inner += 1; - builder.failed(); + builder.failed_with_call_request_item(item); } #[test(should_fail_with="call stack storage address does not match expected contract address")] @@ -305,40 +318,26 @@ mod tests { builder.succeeded(); } - #[test(should_fail_with="caller context cannot be empty for delegate calls")] - fn empty_caller_context_for_delegate_calls_fails() { - let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new().is_delegate_call(); - let public_call = builder.public_call.finish(); - - let hash = public_call.call_stack_item.get_compressed().hash(); - // Caller context is empty for regular calls. - let is_delegate_call = false; - builder.previous_kernel.push_public_teardown_call_request(hash, is_delegate_call); - let previous_kernel = builder.previous_kernel.to_public_kernel_data(true); - - let kernel = PublicKernelTeardownCircuitPrivateInputs { previous_kernel, public_call }; - - let _ = kernel.public_kernel_teardown(); - } - - #[test(should_fail_with="call stack msg_sender does not match expected msg_sender for delegate calls")] + #[test(should_fail_with="call stack item does not match item at the top of the call stack")] fn incorrect_msg_sender_for_delegate_calls_fails() { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new().is_delegate_call(); + let mut item = builder.get_call_request_item(); // Set the msg_sender to be the caller contract. - builder.public_call.public_inputs.call_context.msg_sender = builder.previous_kernel.contract_address; + item.call_context.msg_sender = builder.previous_kernel.contract_address; - builder.failed(); + builder.failed_with_call_request_item(item); } - #[test(should_fail_with="call stack storage address does not match expected contract address for delegate calls")] + #[test(should_fail_with="call stack item does not match item at the top of the call stack")] fn public_kernel_circuit_fails_on_incorrect_storage_contract_in_delegate_call() { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new().is_delegate_call(); + let mut item = builder.get_call_request_item(); // Set the storage contract address to be the contract address. - builder.public_call.public_inputs.call_context.storage_contract_address = builder.public_call.contract_address; + item.call_context.storage_contract_address = builder.public_call.contract_address; - builder.failed(); + builder.failed_with_call_request_item(item); } #[test(should_fail_with="curent contract address must not match storage contract address for delegate calls")] @@ -350,52 +349,28 @@ mod tests { builder.failed(); } - #[test(should_fail_with = "call requests length does not match the expected length")] - fn incorrect_call_requests_length_fails() { - let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); - - builder.public_call.append_public_call_requests(2, false); - // Remove one call request. - let _ = builder.public_call.public_call_stack.pop(); - - builder.failed(); - } - - #[test(should_fail_with = "call stack hash does not match call request hash")] - fn incorrect_call_request_hash_fails() { - let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); - - builder.public_call.append_public_call_requests(2, false); - let mut call_request = builder.public_call.public_call_stack.pop(); - // Change the hash to be a different value. - call_request.hash += 1; - builder.public_call.public_call_stack.push(call_request); - - builder.failed(); - } - - #[test(should_fail_with = "invalid caller")] - fn incorrect_caller_address_for_call_request_fails() { + #[test(should_fail_with="incorrect storage_contract_address for call request")] + fn incorrect_storage_contract_address_for_call_request_fails() { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); - builder.public_call.append_public_call_requests(1, false); - let mut call_request = builder.public_call.public_call_stack.pop(); + builder.public_call.append_public_call_requests_for_regular_calls(1); + let mut call_request = builder.public_call.public_inputs.public_call_requests.pop(); // Change the caller contract address to be a different value. - call_request.caller_contract_address.inner += 1; - builder.public_call.public_call_stack.push(call_request); + call_request.item.call_context.storage_contract_address.inner += 1; + builder.public_call.public_inputs.public_call_requests.push(call_request); builder.failed(); } - #[test(should_fail_with = "invalid caller")] - fn incorrect_caller_context_for_delegate_call_request_fails() { + #[test(should_fail_with="incorrect storage_contract_address for delegate call request")] + fn incorrect_call_context_for_delegate_call_request_fails() { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); - builder.public_call.append_public_call_requests(1, true); - let mut call_request = builder.public_call.public_call_stack.pop(); - // Change the storage contract to be a different value. - call_request.caller_context.storage_contract_address.inner += 1; - builder.public_call.public_call_stack.push(call_request); + builder.public_call.append_public_call_requests_for_delegate_calls(1); + let mut call_request = builder.public_call.public_inputs.public_call_requests.pop(); + // Change the storage contract address to be the target contract address. + call_request.item.call_context.storage_contract_address = call_request.item.contract_address; + builder.public_call.public_inputs.public_call_requests.push(call_request); builder.failed(); } @@ -533,10 +508,10 @@ mod tests { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); builder.public_call.public_inputs.revert_code = 1; let public_call = builder.public_call.finish(); - let hash = public_call.call_stack_item.get_compressed().hash(); - builder.previous_kernel.push_public_teardown_call_request(hash, false); + let item = public_call.call_stack_item.get_compressed(); + builder.previous_kernel.push_public_teardown_call_request(item); // push again to check that the stack is cleared - builder.previous_kernel.push_public_teardown_call_request(hash, false); + builder.previous_kernel.push_public_teardown_call_request(item); let previous_kernel = builder.previous_kernel.to_public_kernel_data(true); let kernel = PublicKernelTeardownCircuitPrivateInputs { previous_kernel, public_call }; @@ -551,10 +526,10 @@ mod tests { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); builder.previous_kernel.revert_code = 1; let public_call = builder.public_call.finish(); - let hash = public_call.call_stack_item.get_compressed().hash(); - builder.previous_kernel.push_public_teardown_call_request(hash, false); + let item = public_call.call_stack_item.get_compressed(); + builder.previous_kernel.push_public_teardown_call_request(item); // push again to check that we keep one item after popping the current call - builder.previous_kernel.push_public_teardown_call_request(hash, false); + builder.previous_kernel.push_public_teardown_call_request(item); let previous_kernel = builder.previous_kernel.to_public_kernel_data(true); let kernel = PublicKernelTeardownCircuitPrivateInputs { previous_kernel, public_call }; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/utils.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/utils.nr index 374807c4b5e2..974a124119ec 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/utils.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/utils.nr @@ -1,14 +1,13 @@ use dep::types::{ - abis::{ - call_request::CallRequest, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest -}, + abis::{public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest}, address::AztecAddress, - contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, - utils::{arrays::array_eq} + contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest} }; -pub fn compute_public_data_reads(contract_address: AztecAddress, read_requests: [StorageRead; N]) -> [PublicDataRead; N] { +pub fn compute_public_data_reads( + contract_address: AztecAddress, + read_requests: [StorageRead; N] +) -> [PublicDataRead; N] { let mut public_data_reads = [PublicDataRead::empty(); N]; for i in 0..N { let read_request = read_requests[i]; @@ -19,10 +18,6 @@ pub fn compute_public_data_reads(contract_address: AztecAddress, read_request public_data_reads } -pub fn assert_eq_call_requests(call_requests: [CallRequest; N], expected: [CallRequest; S]) { - assert(array_eq(call_requests, expected)); -} - pub fn compute_public_data_update_requests( contract_address: AztecAddress, update_requests: [StorageUpdateRequest; N] @@ -36,14 +31,3 @@ pub fn compute_public_data_update_requests( } public_data_update_requests } - -pub fn assert_eq_public_data_reads(public_data_reads: [PublicDataRead; N], expected: [PublicDataRead; S]) { - assert(array_eq(public_data_reads, expected)); -} - -pub fn assert_eq_public_data_update_requests( - public_data_update_requests: [PublicDataUpdateRequest; N], - expected: [PublicDataUpdateRequest; S] -) { - assert(array_eq(public_data_update_requests, expected)); -} 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 fe8491707574..5c8b35cc4721 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 @@ -1,7 +1,7 @@ use crate::{ abis::{ - call_request::CallRequest, gas::Gas, note_hash::ScopedNoteHash, nullifier::ScopedNullifier, - private_call_request::ScopedPrivateCallRequest, + gas::Gas, note_hash::ScopedNoteHash, nullifier::ScopedNullifier, + private_call_request::PrivateCallRequest, public_call_request::PublicCallRequest, log_hash::{ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash} }, traits::{Serialize, Deserialize, Eq, Empty}, messaging::l2_to_l1_message::ScopedL2ToL1Message, @@ -22,8 +22,8 @@ struct PrivateAccumulatedData { encrypted_logs_hashes: [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - private_call_stack: [ScopedPrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], - public_call_stack: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_requests: [PublicCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + private_call_stack: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], } impl Serialize for PrivateAccumulatedData { @@ -54,12 +54,12 @@ impl Serialize for PrivateAccumulatedData { fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); } - for i in 0..MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX { - fields.extend_from_array(self.private_call_stack[i].serialize()); + for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX { + fields.extend_from_array(self.public_call_requests[i].serialize()); } - for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX { - fields.extend_from_array(self.public_call_stack[i].serialize()); + for i in 0..MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX { + fields.extend_from_array(self.private_call_stack[i].serialize()); } assert_eq(fields.len(), PRIVATE_ACCUMULATED_DATA_LENGTH); @@ -79,8 +79,8 @@ impl Deserialize for PrivateAccumulatedData { note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX]), encrypted_logs_hashes: reader.read_struct_array(ScopedEncryptedLogHash::deserialize, [ScopedEncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX]), unencrypted_logs_hashes: reader.read_struct_array(ScopedLogHash::deserialize, [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX]), - private_call_stack: reader.read_struct_array(ScopedPrivateCallRequest::deserialize, [ScopedPrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX]), - public_call_stack: reader.read_struct_array(CallRequest::deserialize, [CallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX]), + public_call_requests: reader.read_struct_array(PublicCallRequest::deserialize, [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX]), + private_call_stack: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX]), }; reader.finish(); item @@ -95,8 +95,8 @@ impl Eq for PrivateAccumulatedData { (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.private_call_stack == other.private_call_stack) & - (self.public_call_stack == other.public_call_stack) + (self.public_call_requests == other.public_call_requests) & + (self.private_call_stack == other.private_call_stack) } } @@ -109,8 +109,8 @@ 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], - private_call_stack: [ScopedPrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], - public_call_stack: [CallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_requests: [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + private_call_stack: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], } } } 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 5828ec371934..7ea6e0402fcc 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 @@ -1,8 +1,8 @@ use crate::{ abis::{ - accumulated_data::{private_accumulated_data::PrivateAccumulatedData}, call_request::CallRequest, - note_hash::ScopedNoteHash, nullifier::ScopedNullifier, - private_call_request::ScopedPrivateCallRequest, + accumulated_data::{private_accumulated_data::PrivateAccumulatedData}, note_hash::ScopedNoteHash, + nullifier::ScopedNullifier, private_call_request::PrivateCallRequest, + public_call_request::PublicCallRequest, log_hash::{ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash} }, constants::{ @@ -23,8 +23,8 @@ struct PrivateAccumulatedDataBuilder { encrypted_logs_hashes: BoundedVec, unencrypted_logs_hashes: BoundedVec, - private_call_stack: BoundedVec, - public_call_stack: BoundedVec, + public_call_requests: BoundedVec, + private_call_stack: BoundedVec, } @@ -37,8 +37,8 @@ impl PrivateAccumulatedDataBuilder { 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, - private_call_stack: self.private_call_stack.storage, - public_call_stack: self.public_call_stack.storage + public_call_requests: self.public_call_requests.storage, + private_call_stack: self.private_call_stack.storage } } } @@ -52,8 +52,8 @@ impl Empty for PrivateAccumulatedDataBuilder { note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), + public_call_requests: BoundedVec::new(), private_call_stack: BoundedVec::new(), - public_call_stack: BoundedVec::new(), } } } 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 63c0217705e5..f42f0fa447a9 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 @@ -1,7 +1,8 @@ use crate::{ abis::{ - call_request::CallRequest, public_data_update_request::PublicDataUpdateRequest, gas::Gas, - note_hash::NoteHash, nullifier::Nullifier, log_hash::{LogHash, ScopedLogHash, NoteLogHash} + public_data_update_request::PublicDataUpdateRequest, gas::Gas, note_hash::NoteHash, + nullifier::Nullifier, log_hash::{LogHash, ScopedLogHash, NoteLogHash}, + public_call_request::PublicCallRequest }, constants::{ MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, @@ -22,7 +23,7 @@ struct PublicAccumulatedData { public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - public_call_stack: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_stack: [PublicCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], gas_used: Gas, } @@ -37,7 +38,7 @@ impl Empty for PublicAccumulatedData { encrypted_logs_hashes: [LogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], public_data_update_requests: [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - public_call_stack: [CallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_call_stack: [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], gas_used: Gas::empty(), } } @@ -97,7 +98,7 @@ impl Deserialize for PublicAccumulatedData { encrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX]), unencrypted_logs_hashes: reader.read_struct_array(ScopedLogHash::deserialize, [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX]), public_data_update_requests: reader.read_struct_array(PublicDataUpdateRequest::deserialize, [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]), - public_call_stack: reader.read_struct_array(CallRequest::deserialize, [CallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX]), + public_call_stack: reader.read_struct_array(PublicCallRequest::deserialize, [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX]), gas_used: reader.read_struct(Gas::deserialize), }; reader.finish(); 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 d7864bd945d3..25f0b96e7d63 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 @@ -1,7 +1,7 @@ use crate::{ abis::{ - gas::Gas, accumulated_data::public_accumulated_data::PublicAccumulatedData, - call_request::CallRequest, note_hash::NoteHash, nullifier::Nullifier, + gas::Gas, accumulated_data::public_accumulated_data::PublicAccumulatedData, note_hash::NoteHash, + nullifier::Nullifier, public_call_request::PublicCallRequest, public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, NoteLogHash, ScopedLogHash} }, constants::{ @@ -23,7 +23,7 @@ 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/call_context.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr index 9f6c6462c546..adc55d358951 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr @@ -1,17 +1,15 @@ use crate::{ - abis::function_selector::FunctionSelector, address::AztecAddress, - constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash, - traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader + abis::function_selector::FunctionSelector, address::AztecAddress, constants::CALL_CONTEXT_LENGTH, + traits::{Deserialize, Serialize, Empty}, utils::reader::Reader }; // docs:start:call-context struct CallContext { - msg_sender : AztecAddress, - storage_contract_address : AztecAddress, - function_selector : FunctionSelector, - - is_delegate_call : bool, - is_static_call : bool, + msg_sender: AztecAddress, + storage_contract_address: AztecAddress, + function_selector: FunctionSelector, + is_delegate_call: bool, + is_static_call: bool, } // docs:end:call-context @@ -21,12 +19,6 @@ impl Eq for CallContext { } } -impl Hash for CallContext { - fn hash(self) -> Field { - pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT) - } -} - impl Serialize for CallContext { fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] { let mut serialized: BoundedVec = BoundedVec::new(); @@ -105,9 +97,3 @@ fn not_eq_test_eq() { assert(context1.eq(context2)); } - -#[test] -fn hash_smoke() { - let context = CallContext::empty(); - let _hashed = context.hash(); -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_request.nr deleted file mode 100644 index 2f2ee96ba7d7..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_request.nr +++ /dev/null @@ -1,92 +0,0 @@ -use crate::{ - abis::{caller_context::CallerContext, side_effect::Ordered}, address::AztecAddress, - constants::CALL_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize}, utils::reader::Reader -}; - -struct CallRequest { - hash: Field, - caller_contract_address: AztecAddress, - caller_context: CallerContext, - start_side_effect_counter: u32, - end_side_effect_counter: u32, -} - -impl Ordered for CallRequest { - fn counter(self) -> u32 { - self.start_side_effect_counter - } -} - -impl Eq for CallRequest { - fn eq(self, call_request: CallRequest) -> bool { - (call_request.hash == self.hash) - & (call_request.caller_contract_address.eq(self.caller_contract_address)) - & (call_request.caller_context.eq(self.caller_context)) - & (call_request.start_side_effect_counter == self.start_side_effect_counter) - & (call_request.end_side_effect_counter == self.end_side_effect_counter) - } -} - -impl Empty for CallRequest { - fn empty() -> Self { - CallRequest { - hash: 0, - caller_contract_address: AztecAddress::zero(), - caller_context: CallerContext::empty(), - start_side_effect_counter: 0, - end_side_effect_counter: 0, - } - } -} - -impl CallRequest { - pub fn expose_to_public(self) -> Self { - CallRequest { - hash: self.hash, - caller_contract_address: self.caller_contract_address, - caller_context: self.caller_context, - start_side_effect_counter: 0, - end_side_effect_counter: 0 - } - } -} - -impl Serialize for CallRequest { - fn serialize(self) -> [Field; CALL_REQUEST_LENGTH] { - let mut fields: BoundedVec = BoundedVec::new(); - - fields.push(self.hash); - fields.extend_from_array(self.caller_contract_address.serialize()); - fields.extend_from_array(self.caller_context.serialize()); - fields.push(self.start_side_effect_counter as Field); - fields.push(self.end_side_effect_counter as Field); - - assert_eq(fields.len(), CALL_REQUEST_LENGTH); - - fields.storage - } -} - -impl Deserialize for CallRequest { - fn deserialize(fields: [Field; CALL_REQUEST_LENGTH]) -> CallRequest { - let mut reader = Reader::new(fields); - - let item = CallRequest { - hash: reader.read(), - caller_contract_address: reader.read_struct(AztecAddress::deserialize), - caller_context: reader.read_struct(CallerContext::deserialize), - start_side_effect_counter: reader.read() as u32, - end_side_effect_counter: reader.read() as u32, - }; - reader.finish(); - item - } -} - -#[test] -fn serialization_of_empty() { - let item = CallRequest::empty(); - let serialized = item.serialize(); - let deserialized = CallRequest::deserialize(serialized); - assert(item.eq(deserialized)); -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr deleted file mode 100644 index aad2461105f6..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr +++ /dev/null @@ -1,76 +0,0 @@ -use crate::address::AztecAddress; -use crate::traits::{Empty, Serialize, Deserialize}; -use crate::constants::CALLER_CONTEXT_LENGTH; -use crate::utils::reader::Reader; - -struct CallerContext { - msg_sender: AztecAddress, - storage_contract_address: AztecAddress, - is_static_call: bool, -} - -impl Eq for CallerContext { - fn eq(self, other: CallerContext) -> bool { - other.msg_sender.eq(self.msg_sender) - & other.storage_contract_address.eq(self.storage_contract_address) - & other.is_static_call == self.is_static_call - } -} - -impl Empty for CallerContext { - fn empty() -> Self { - CallerContext { - msg_sender: AztecAddress::zero(), - storage_contract_address: AztecAddress::zero(), - is_static_call: false, - } - } -} - -impl CallerContext { - pub fn is_empty(self) -> bool { - self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call - } - - // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address, - // but will still propagate the is_static_call flag. - pub fn is_hidden(self) -> bool { - self.msg_sender.is_zero() & self.storage_contract_address.is_zero() - } -} - -impl Serialize for CallerContext { - fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] { - let mut fields: BoundedVec = BoundedVec::new(); - - fields.extend_from_array(self.msg_sender.serialize()); - fields.extend_from_array(self.storage_contract_address.serialize()); - fields.push(self.is_static_call as Field); - - assert_eq(fields.len(), CALLER_CONTEXT_LENGTH); - - fields.storage - } -} - -impl Deserialize for CallerContext { - fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext { - let mut reader = Reader::new(fields); - - let item = CallerContext { - msg_sender: reader.read_struct(AztecAddress::deserialize), - storage_contract_address: reader.read_struct(AztecAddress::deserialize), - is_static_call: reader.read_bool(), - }; - reader.finish(); - item - } -} - -#[test] -fn serialization_of_empty() { - let item = CallerContext::empty(); - let serialized = item.serialize(); - let deserialized = CallerContext::deserialize(serialized); - assert(item.eq(deserialized)); -} 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 8d8ffb850074..734902e1666f 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,6 +1,6 @@ use crate::abis::{ accumulated_data::PrivateAccumulatedData, combined_constant_data::CombinedConstantData, - validation_requests::ValidationRequests, call_request::CallRequest + public_call_request::PublicCallRequest, validation_requests::ValidationRequests }; use crate::constants::PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH; use crate::traits::{Serialize, Deserialize, Eq, Empty}; @@ -17,8 +17,8 @@ struct PrivateKernelCircuitPublicInputsArrayLengths { note_encrypted_logs_hashes: u32, encrypted_logs_hashes: u32, unencrypted_logs_hashes: u32, + public_call_requests: u32, private_call_stack: u32, - public_call_stack: u32, } impl PrivateKernelCircuitPublicInputsArrayLengths { @@ -33,8 +33,8 @@ impl PrivateKernelCircuitPublicInputsArrayLengths { note_encrypted_logs_hashes: array_length(public_inputs.end.note_encrypted_logs_hashes), encrypted_logs_hashes: array_length(public_inputs.end.encrypted_logs_hashes), unencrypted_logs_hashes: array_length(public_inputs.end.unencrypted_logs_hashes), - private_call_stack: array_length(public_inputs.end.private_call_stack), - public_call_stack: array_length(public_inputs.end.public_call_stack) + public_call_requests: array_length(public_inputs.end.public_call_requests), + private_call_stack: array_length(public_inputs.end.private_call_stack) } } @@ -49,8 +49,8 @@ impl PrivateKernelCircuitPublicInputsArrayLengths { note_encrypted_logs_hashes: 0, encrypted_logs_hashes: 0, unencrypted_logs_hashes: 0, - private_call_stack: 0, - public_call_stack: 0 + public_call_requests: 0, + private_call_stack: 0 } } } @@ -66,8 +66,8 @@ impl Eq for PrivateKernelCircuitPublicInputsArrayLengths { (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.private_call_stack == other.private_call_stack) & - (self.public_call_stack== other.public_call_stack) + (self.public_call_requests== other.public_call_requests) & + (self.private_call_stack == other.private_call_stack) } } @@ -76,7 +76,7 @@ struct PrivateKernelCircuitPublicInputs { validation_requests: ValidationRequests, end: PrivateAccumulatedData, constants: CombinedConstantData, - public_teardown_call_request: CallRequest, + public_teardown_call_request: PublicCallRequest, fee_payer: AztecAddress } @@ -105,7 +105,7 @@ impl Deserialize for PrivateKernelC validation_requests: reader.read_struct(ValidationRequests::deserialize), end: reader.read_struct(PrivateAccumulatedData::deserialize), constants: reader.read_struct(CombinedConstantData::deserialize), - public_teardown_call_request: reader.read_struct(CallRequest::deserialize), + public_teardown_call_request: reader.read_struct(PublicCallRequest::deserialize), fee_payer: reader.read_struct(AztecAddress::deserialize), }; @@ -131,7 +131,7 @@ impl Empty for PrivateKernelCircuitPublicInputs { validation_requests: ValidationRequests::empty(), end: PrivateAccumulatedData::empty(), constants: CombinedConstantData::empty(), - public_teardown_call_request: CallRequest::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 c718b02430ff..fc1d57fd1c97 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 @@ -2,8 +2,8 @@ use crate::{ abis::{ accumulated_data::PrivateAccumulatedDataBuilder, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::private_kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - validation_requests::validation_requests_builder::ValidationRequestsBuilder, - call_request::CallRequest + public_call_request::PublicCallRequest, + validation_requests::validation_requests_builder::ValidationRequestsBuilder }, address::AztecAddress, traits::Empty }; @@ -13,7 +13,7 @@ struct PrivateKernelCircuitPublicInputsBuilder { validation_requests: ValidationRequestsBuilder, end: PrivateAccumulatedDataBuilder, constants: CombinedConstantData, - public_teardown_call_request: CallRequest, + public_teardown_call_request: PublicCallRequest, fee_payer: AztecAddress } @@ -37,7 +37,7 @@ impl Empty for PrivateKernelCircuitPublicInputsBuilder { validation_requests: ValidationRequestsBuilder::empty(), end: PrivateAccumulatedDataBuilder::empty(), constants: CombinedConstantData::empty(), - public_teardown_call_request: CallRequest::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/public_kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr index c9216326cb05..398013a1988f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr @@ -1,6 +1,7 @@ use crate::abis::{ accumulated_data::PublicAccumulatedData, combined_constant_data::CombinedConstantData, - validation_requests::{RollupValidationRequests, ValidationRequests}, call_request::CallRequest + public_call_request::PublicCallRequest, + validation_requests::{RollupValidationRequests, ValidationRequests} }; use crate::constants::{MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH}; use crate::traits::{Empty, Serialize, Deserialize, Eq}; @@ -13,7 +14,7 @@ struct PublicKernelCircuitPublicInputs { end: PublicAccumulatedData, constants: CombinedConstantData, revert_code: u8, - public_teardown_call_stack: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_teardown_call_stack: [PublicCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], fee_payer: AztecAddress } @@ -21,18 +22,18 @@ impl PublicKernelCircuitPublicInputs { pub fn needs_setup(self) -> bool { // public calls for setup are deposited in the non-revertible public call stack. // if an element is present, we need to run setup - self.end_non_revertible.public_call_stack[0].hash != 0 + !self.end_non_revertible.public_call_stack[0].item.contract_address.is_zero() } pub fn needs_app_logic(self) -> bool { // public calls for app logic are deposited in the revertible public call stack. // if an element is present, we need to run app logic - self.end.public_call_stack[0].hash != 0 + !self.end.public_call_stack[0].item.contract_address.is_zero() } pub fn needs_teardown(self) -> bool { // the public call specified for teardown, if any, is placed in the teardown call stack - self.public_teardown_call_stack[0].hash != 0 + !self.public_teardown_call_stack[0].item.contract_address.is_zero() } } @@ -44,7 +45,7 @@ impl Empty for PublicKernelCircuitPublicInputs { end: PublicAccumulatedData::empty(), constants: CombinedConstantData::empty(), revert_code: 0, - public_teardown_call_stack: [CallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + public_teardown_call_stack: [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], fee_payer: AztecAddress::empty() } } @@ -83,7 +84,7 @@ impl Deserialize for PublicKernelCir end: reader.read_struct(PublicAccumulatedData::deserialize), constants: reader.read_struct(CombinedConstantData::deserialize), revert_code: reader.read() as u8, - public_teardown_call_stack: reader.read_struct_array(CallRequest::deserialize, [CallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX]), + public_teardown_call_stack: reader.read_struct_array(PublicCallRequest::deserialize, [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX]), fee_payer: reader.read_struct(AztecAddress::deserialize), }; reader.finish(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr index a44f58f8116f..697d278015a3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr @@ -3,7 +3,7 @@ use crate::{ accumulated_data::{CombinedAccumulatedData, PublicAccumulatedDataBuilder}, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{public_kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs}, - validation_requests::ValidationRequestsBuilder, call_request::CallRequest + public_call_request::PublicCallRequest, validation_requests::ValidationRequestsBuilder }, address::AztecAddress, constants::MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, traits::Empty }; @@ -14,7 +14,7 @@ struct PublicKernelCircuitPublicInputsBuilder { end: PublicAccumulatedDataBuilder, constants: CombinedConstantData, revert_code: u8, - public_teardown_call_stack: BoundedVec, + public_teardown_call_stack: BoundedVec, fee_payer: AztecAddress, } 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 ee604875a951..3c2e588deff4 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 @@ -31,13 +31,12 @@ mod kernel_data; mod private_kernel_data; mod public_kernel_data; -mod call_request; mod private_call_request; mod private_call_stack_item; +mod public_call_request; mod public_call_stack_item; mod public_call_stack_item_compressed; mod call_context; -mod caller_context; mod public_call_data; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr index 778778d1ab93..ab462a60c4a5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr @@ -1,20 +1,14 @@ use crate::{ - abis::{ - private_call_stack_item::PrivateCallStackItem, call_context::CallContext, - function_data::FunctionData, caller_context::CallerContext, - side_effect::{Ordered, RangeOrdered, Scoped} -}, - address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH}, - traits::{Empty, Serialize, Deserialize}, utils::reader::Reader + abis::{call_context::CallContext, side_effect::{Ordered, RangeOrdered}}, address::AztecAddress, + constants::PRIVATE_CALL_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize}, + utils::reader::Reader }; struct PrivateCallRequest { - target: AztecAddress, + contract_address: AztecAddress, call_context: CallContext, - function_data: FunctionData, args_hash: Field, returns_hash: Field, - caller_context: CallerContext, start_side_effect_counter: u32, end_side_effect_counter: u32, } @@ -36,12 +30,10 @@ impl RangeOrdered for PrivateCallRequest { impl Eq for PrivateCallRequest { fn eq(self, other: PrivateCallRequest) -> bool { - (self.target == other.target) + (self.contract_address == other.contract_address) & (self.call_context == other.call_context) - & (self.function_data == other.function_data) & (self.args_hash == other.args_hash) & (self.returns_hash == other.returns_hash) - & (self.caller_context == other.caller_context) & (self.start_side_effect_counter == other.start_side_effect_counter) & (self.end_side_effect_counter == other.end_side_effect_counter) } @@ -50,12 +42,10 @@ impl Eq for PrivateCallRequest { impl Empty for PrivateCallRequest { fn empty() -> Self { PrivateCallRequest { - target: AztecAddress::empty(), + contract_address: AztecAddress::empty(), call_context: CallContext::empty(), - function_data: FunctionData::empty(), args_hash: 0, returns_hash: 0, - caller_context: CallerContext::empty(), start_side_effect_counter: 0, end_side_effect_counter: 0, } @@ -66,12 +56,10 @@ impl Serialize for PrivateCallRequest { fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(); - fields.push(self.target.to_field()); + fields.push(self.contract_address.to_field()); fields.extend_from_array(self.call_context.serialize()); - fields.extend_from_array(self.function_data.serialize()); fields.push(self.args_hash); fields.push(self.returns_hash); - fields.extend_from_array(self.caller_context.serialize()); fields.push(self.start_side_effect_counter as Field); fields.push(self.end_side_effect_counter as Field); @@ -85,12 +73,10 @@ impl Deserialize for PrivateCallRequest { fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest { let mut reader = Reader::new(fields); let item = PrivateCallRequest { - target: reader.read_struct(AztecAddress::deserialize), + contract_address: reader.read_struct(AztecAddress::deserialize), call_context: reader.read_struct(CallContext::deserialize), - function_data: reader.read_struct(FunctionData::deserialize), args_hash: reader.read(), returns_hash: reader.read(), - caller_context: reader.read_struct(CallerContext::deserialize), start_side_effect_counter: reader.read_u32(), end_side_effect_counter: reader.read_u32(), }; @@ -99,98 +85,10 @@ impl Deserialize for PrivateCallRequest { } } -impl PrivateCallRequest { - pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest { - ScopedPrivateCallRequest { call_request: self, contract_address } - } - - pub fn matches_stack_item(self, stack_item: PrivateCallStackItem) -> bool { - (self.target == stack_item.contract_address) - & (self.call_context == stack_item.public_inputs.call_context) - & (self.function_data == stack_item.function_data) - & (self.args_hash == stack_item.public_inputs.args_hash) - & (self.returns_hash == stack_item.public_inputs.returns_hash) - & (self.start_side_effect_counter - == stack_item.public_inputs.start_side_effect_counter) - & (self.end_side_effect_counter - == stack_item.public_inputs.end_side_effect_counter) - } -} - -struct ScopedPrivateCallRequest { - call_request: PrivateCallRequest, - contract_address: AztecAddress, -} - -impl Scoped for ScopedPrivateCallRequest { - fn inner(self) -> PrivateCallRequest { - self.call_request - } - fn contract_address(self) -> AztecAddress { - self.contract_address - } -} - -impl Ordered for ScopedPrivateCallRequest { - fn counter(self) -> u32 { - self.call_request.counter_start() - } -} - -impl RangeOrdered for ScopedPrivateCallRequest { - fn counter_start(self) -> u32 { - self.call_request.counter_start() - } - fn counter_end(self) -> u32 { - self.call_request.counter_end() - } -} - -impl Eq for ScopedPrivateCallRequest { - fn eq(self, other: ScopedPrivateCallRequest) -> bool { - (self.call_request == other.call_request) - & (self.contract_address == other.contract_address) - } -} - -impl Empty for ScopedPrivateCallRequest { - fn empty() -> Self { - ScopedPrivateCallRequest { - call_request: PrivateCallRequest::empty(), - contract_address: AztecAddress::zero(), - } - } -} - -impl Serialize for ScopedPrivateCallRequest { - fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] { - let mut fields: BoundedVec = BoundedVec::new(); - - fields.extend_from_array(self.call_request.serialize()); - fields.extend_from_array(self.contract_address.serialize()); - - assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH); - - fields.storage - } -} - -impl Deserialize for ScopedPrivateCallRequest { - fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest { - let mut reader = Reader::new(fields); - let item = ScopedPrivateCallRequest { - call_request: reader.read_struct(PrivateCallRequest::deserialize), - contract_address: reader.read_struct(AztecAddress::deserialize), - }; - reader.finish(); - item - } -} - #[test] fn serialization_of_empty() { - let item = ScopedPrivateCallRequest::empty(); + let item = PrivateCallRequest::empty(); let serialized = item.serialize(); - let deserialized = ScopedPrivateCallRequest::deserialize(serialized); + let deserialized = PrivateCallRequest::deserialize(serialized); assert(item.eq(deserialized)); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index 89454e05cefa..510c69df454a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x065f2831db9ac0db5e710bd3a865b5facd8cf83f1585e1af8fd1d6ce9c47f685; + let test_data_empty_hash = 0x22a93cff4c51d8d7eb0df339350343ff113a4db028a8c3b6f8fee8a586a51c2e; assert_eq(hash, test_data_empty_hash); } 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 6d01f09675ae..2fe0b1cb43f2 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 @@ -2,8 +2,8 @@ use crate::{ abis::{ call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings, validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier, - private_call_request::PrivateCallRequest, read_request::ReadRequest, - log_hash::{LogHash, NoteLogHash, EncryptedLogHash} + private_call_request::PrivateCallRequest, public_call_request::PublicCallRequest, + read_request::ReadRequest, log_hash::{LogHash, NoteLogHash, EncryptedLogHash} }, constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, @@ -26,7 +26,7 @@ struct PrivateCircuitPublicInputsArrayLengths { nullifiers: u32, l2_to_l1_msgs: u32, private_call_requests: u32, - public_call_stack_hashes: u32, + public_call_requests: u32, note_encrypted_logs_hashes: u32, encrypted_logs_hashes: u32, unencrypted_logs_hashes: u32, @@ -42,7 +42,7 @@ impl PrivateCircuitPublicInputsArrayLengths { nullifiers: validate_array(public_inputs.nullifiers), l2_to_l1_msgs: validate_array(public_inputs.l2_to_l1_msgs), private_call_requests: validate_array(public_inputs.private_call_requests), - public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes), + public_call_requests: validate_array(public_inputs.public_call_requests), note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes), encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes), unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes) @@ -68,8 +68,8 @@ 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_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], - public_teardown_function_hash: Field, + public_call_requests: [PublicCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + public_teardown_call_request: PublicCallRequest, l2_to_l1_msgs: [L2ToL1Message; MAX_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter : u32, @@ -101,7 +101,7 @@ impl Eq for PrivateCircuitPublicInputs { (self.note_hashes == other.note_hashes) & (self.nullifiers == other.nullifiers) & (self.private_call_requests == other.private_call_requests) & - (self.public_call_stack_hashes == other.public_call_stack_hashes) & + (self.public_call_requests == other.public_call_requests) & (self.l2_to_l1_msgs == other.l2_to_l1_msgs) & (self.start_side_effect_counter == other.start_side_effect_counter) & (self.end_side_effect_counter == other.end_side_effect_counter) & @@ -143,8 +143,10 @@ impl Serialize for PrivateCircuitPublicInp for i in 0..self.private_call_requests.len() { fields.extend_from_array(self.private_call_requests[i].serialize()); } - fields.extend_from_array(self.public_call_stack_hashes); - fields.push(self.public_teardown_function_hash); + for i in 0..self.public_call_requests.len() { + fields.extend_from_array(self.public_call_requests[i].serialize()); + } + fields.extend_from_array(self.public_teardown_call_request.serialize()); for i in 0..self.l2_to_l1_msgs.len() { fields.extend_from_array(self.l2_to_l1_msgs[i].serialize()); } @@ -185,8 +187,8 @@ impl Deserialize for PrivateCircuitPublicI note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL]), nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL]), private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]), - public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]), - public_teardown_function_hash: reader.read(), + public_call_requests: reader.read_struct_array(PublicCallRequest::deserialize, [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]), + public_teardown_call_request: reader.read_struct(PublicCallRequest::deserialize), l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL]), start_side_effect_counter: reader.read() as u32, end_side_effect_counter: reader.read() as u32, @@ -223,8 +225,8 @@ impl Empty for PrivateCircuitPublicInputs { note_hashes: [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL], nullifiers: [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL], private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL], - public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], - public_teardown_function_hash: 0, + public_call_requests: [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_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, end_side_effect_counter : 0 as u32, @@ -249,7 +251,8 @@ fn serialization_of_empty() { fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); + // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x15c9b0a92b9b541598e24c9f0b0b4b04b7f2408599751c45aa12de671fd9b363; + let test_data_empty_hash = 0x2f5d0ff52163d6b688be54324d50d173d9433658bb40e7c5140876df4eb95406; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index 6afa3fed807d..b9064f8b561e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -1,19 +1,16 @@ -use crate::address::{SaltedInitializationHash, PublicKeysHash, EthAddress}; -use crate::contract_class_id::ContractClassId; -use crate::recursion::{verification_key::VerificationKey, proof::RecursiveProof, traits::Verifiable}; -use crate::abis::{ - call_request::CallRequest, private_call_stack_item::PrivateCallStackItem, +use crate::{ + abis::{ + private_call_stack_item::PrivateCallStackItem, private_circuit_public_inputs::PrivateCircuitPublicInputs +}, + address::{SaltedInitializationHash, PublicKeysHash, EthAddress}, constants::FUNCTION_TREE_HEIGHT, + contract_class_id::ContractClassId, merkle_tree::membership::MembershipWitness, + recursion::{verification_key::VerificationKey, proof::RecursiveProof, traits::Verifiable} }; -use crate::constants::{MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, FUNCTION_TREE_HEIGHT}; -use crate::merkle_tree::membership::MembershipWitness; struct PrivateCallData { call_stack_item: PrivateCallStackItem, - public_call_stack: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], - public_teardown_call_request: CallRequest, - vk: VerificationKey, salted_initialization_hash: SaltedInitializationHash, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr index 6bf55ae40ec9..534b6882053e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr @@ -1,11 +1,10 @@ -use crate::{abis::{call_request::CallRequest, public_call_stack_item::PublicCallStackItem}, address::EthAddress}; -use crate::constants::MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; +use crate::abis::public_call_stack_item::PublicCallStackItem; + // Mocked here as the only remaining non-recursive proof struct Proof {} struct PublicCallData { call_stack_item: PublicCallStackItem, - public_call_stack: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], proof: Proof, bytecode_hash: Field, } 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 new file mode 100644 index 000000000000..fa8f27b781a1 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr @@ -0,0 +1,72 @@ +use crate::{ + abis::{public_call_stack_item_compressed::PublicCallStackItemCompressed, side_effect::Ordered}, + address::AztecAddress, constants::PUBLIC_CALL_REQUEST_LENGTH, + traits::{Empty, Serialize, Deserialize}, utils::reader::Reader +}; + +struct PublicCallRequest { + item: PublicCallStackItemCompressed, + counter: u32, +} + +impl Ordered for PublicCallRequest { + fn counter(self) -> u32 { + self.counter + } +} + +impl Eq for PublicCallRequest { + fn eq(self, other: PublicCallRequest) -> bool { + (other.item == self.item) + & (other.counter == self.counter) + } +} + +impl Empty for PublicCallRequest { + fn empty() -> Self { + PublicCallRequest { + item: PublicCallStackItemCompressed::empty(), + counter: 0, + } + } +} + +impl PublicCallRequest { + pub fn expose_to_public(self) -> Self { + PublicCallRequest { item: self.item, counter: 0 } + } +} + +impl Serialize for PublicCallRequest { + fn serialize(self) -> [Field; PUBLIC_CALL_REQUEST_LENGTH] { + let mut fields: BoundedVec = BoundedVec::new(); + + fields.extend_from_array(self.item.serialize()); + fields.push(self.counter as Field); + + assert_eq(fields.len(), PUBLIC_CALL_REQUEST_LENGTH); + + fields.storage + } +} + +impl Deserialize for PublicCallRequest { + fn deserialize(fields: [Field; PUBLIC_CALL_REQUEST_LENGTH]) -> PublicCallRequest { + let mut reader = Reader::new(fields); + + let request = PublicCallRequest { + item: reader.read_struct(PublicCallStackItemCompressed::deserialize), + counter: reader.read_u32(), + }; + reader.finish(); + request + } +} + +#[test] +fn serialization_of_empty() { + let item = PublicCallRequest::empty(); + let serialized = item.serialize(); + let deserialized = PublicCallRequest::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr index d8c22631fa8a..65adfd485939 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr @@ -3,8 +3,6 @@ use crate::abis::{ public_call_stack_item_compressed::PublicCallStackItemCompressed }; use crate::address::AztecAddress; -use crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM; -use crate::traits::Hash; struct PublicCallStackItem { contract_address: AztecAddress, @@ -17,7 +15,6 @@ struct PublicCallStackItem { impl PublicCallStackItem { fn as_execution_request(self) -> Self { - // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.getCompressed()` let public_inputs = self.public_inputs; let mut request_public_inputs = PublicCircuitPublicInputs::empty(); request_public_inputs.call_context = public_inputs.call_context; @@ -42,7 +39,6 @@ impl PublicCallStackItem { PublicCallStackItemCompressed { contract_address: item.contract_address, call_context: item.public_inputs.call_context, - function_data: item.function_data, args_hash: item.public_inputs.args_hash, returns_hash: item.public_inputs.returns_hash, revert_code: item.public_inputs.revert_code, @@ -51,50 +47,3 @@ impl PublicCallStackItem { } } } - -mod tests { - use crate::{ - abis::{ - function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash, - public_circuit_public_inputs::PublicCircuitPublicInputs, - public_call_stack_item::PublicCallStackItem - }, - address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash - }; - - #[test] - fn compute_call_stack_item_request_hash() { - let contract_address = AztecAddress::from_field(1); - let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false }; - - let mut public_inputs = PublicCircuitPublicInputs::empty(); - public_inputs.note_hashes[0] = NoteHash { - value: 1, - counter: 0, - }; - - let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data }; - - // Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test - let test_data_call_stack_item_request_hash = 0x2268218e4dd9e61345f407816d63de9c7a83b031b7820a17470748bae488fb50; - assert_eq(call_stack_item.get_compressed().hash(), test_data_call_stack_item_request_hash); - } - - #[test] - fn compute_call_stack_item_hash() { - let contract_address = AztecAddress::from_field(1); - let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false }; - - let mut public_inputs = PublicCircuitPublicInputs::empty(); - public_inputs.note_hashes[0] = NoteHash { - value: 1, - counter: 0, - }; - - let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data }; - - // Value from public_call_stack_item.test.ts "Computes a callstack item hash" test - let test_data_call_stack_item_hash = 0x2268218e4dd9e61345f407816d63de9c7a83b031b7820a17470748bae488fb50; - assert_eq(call_stack_item.get_compressed().hash(), test_data_call_stack_item_hash); - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item_compressed.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item_compressed.nr index f31b62975488..0efb273a8798 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item_compressed.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item_compressed.nr @@ -1,7 +1,7 @@ -use crate::abis::{call_context::CallContext, function_data::FunctionData, gas::Gas}; +use crate::abis::{call_context::CallContext, gas::Gas}; use crate::address::AztecAddress; -use crate::constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH}; -use crate::traits::{Hash, Empty, Serialize, Deserialize}; +use crate::constants::PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH; +use crate::traits::{Empty, Serialize, Deserialize}; use crate::utils::reader::Reader; /** @@ -21,7 +21,6 @@ use crate::utils::reader::Reader; struct PublicCallStackItemCompressed { contract_address: AztecAddress, call_context: CallContext, - function_data: FunctionData, args_hash: Field, returns_hash: Field, revert_code: u8, @@ -33,7 +32,6 @@ impl Eq for PublicCallStackItemCompressed { fn eq(self, other: PublicCallStackItemCompressed) -> bool { (self.contract_address == other.contract_address) & (self.call_context == other.call_context) - & (self.function_data == other.function_data) & (self.args_hash == other.args_hash) & (self.returns_hash == other.returns_hash) & (self.revert_code == other.revert_code) @@ -42,18 +40,11 @@ impl Eq for PublicCallStackItemCompressed { } } -impl Hash for PublicCallStackItemCompressed { - fn hash(self) -> Field { - std::hash::pedersen_hash_with_separator(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM) - } -} - impl Empty for PublicCallStackItemCompressed { fn empty() -> Self { PublicCallStackItemCompressed { contract_address: AztecAddress::empty(), call_context: CallContext::empty(), - function_data: FunctionData::empty(), args_hash: 0, returns_hash: 0, revert_code: 0, @@ -69,7 +60,6 @@ impl Serialize for PublicCallStackItem fields.push(self.contract_address.to_field()); fields.extend_from_array(self.call_context.serialize()); - fields.extend_from_array(self.function_data.serialize()); fields.push(self.args_hash); fields.push(self.returns_hash); fields.push(self.revert_code as Field); @@ -89,7 +79,6 @@ impl Deserialize for PublicCallStackIt let item = PublicCallStackItemCompressed { contract_address: reader.read_struct(AztecAddress::deserialize), call_context: reader.read_struct(CallContext::deserialize), - function_data: reader.read_struct(FunctionData::deserialize), args_hash: reader.read(), returns_hash: reader.read(), revert_code: reader.read() as u8, 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 fba93acda45c..306f86c4ac23 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 @@ -1,7 +1,8 @@ use crate::{ abis::{ call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest, - gas::Gas, global_variables::GlobalVariables, log_hash::LogHash + gas::Gas, global_variables::GlobalVariables, log_hash::LogHash, + public_call_request::PublicCallRequest }, address::AztecAddress, constants::{ @@ -31,7 +32,7 @@ struct PublicCircuitPublicInputs { contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL], // todo: add sideeffect ranges for the input to these hashes - public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + public_call_requests: [PublicCallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_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], @@ -87,8 +88,9 @@ impl Serialize for PublicCircuitPublicInput for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { fields.extend_from_array(self.contract_storage_reads[i].serialize()); } - fields.extend_from_array(self.public_call_stack_hashes); - + for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL { + fields.extend_from_array(self.public_call_requests[i].serialize()); + } for i in 0..MAX_NOTE_HASHES_PER_CALL { fields.extend_from_array(self.note_hashes[i].serialize()); } @@ -130,7 +132,7 @@ impl Deserialize for PublicCircuitPublicInp l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]), contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]), contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]), - public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]), + public_call_requests: reader.read_struct_array(PublicCallRequest::deserialize, [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]), note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL]), nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL]), l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL]), @@ -169,7 +171,7 @@ impl Empty for PublicCircuitPublicInputs { l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL], contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL], - public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + public_call_requests: [PublicCallRequest::empty(); MAX_PUBLIC_CALL_STACK_LENGTH_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], @@ -201,6 +203,6 @@ fn empty_hash() { let hash = inputs.hash(); // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x2b80e3db92cdbf588155e0eaa4f51b35366cbd6e10f587c335204be5bf337bac; + let test_data_empty_hash = 0x090d3b90d0aba84f6ffc2feb1c069728f803515054e328e410aeaca2a664adc6; assert_eq(hash, test_data_empty_hash); } 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 a6a1b25dad3f..282c01692328 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -218,17 +218,17 @@ global NOTE_HASH_LENGTH = 2; global SCOPED_NOTE_HASH_LENGTH = NOTE_HASH_LENGTH + 1; global NULLIFIER_LENGTH = 3; global SCOPED_NULLIFIER_LENGTH = NULLIFIER_LENGTH + 1; -global CALLER_CONTEXT_LENGTH = 2 * AZTEC_ADDRESS_LENGTH + 1; -global PRIVATE_CALL_REQUEST_LENGTH = AZTEC_ADDRESS_LENGTH + CALL_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH + 4 + CALLER_CONTEXT_LENGTH; -global SCOPED_PRIVATE_CALL_REQUEST_LENGTH = PRIVATE_CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH; +global PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = AZTEC_ADDRESS_LENGTH + CALL_CONTEXT_LENGTH + 3 + 2 * GAS_LENGTH; +global PRIVATE_CALL_REQUEST_LENGTH = AZTEC_ADDRESS_LENGTH + CALL_CONTEXT_LENGTH + 4; +global PUBLIC_CALL_REQUEST_LENGTH = PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH + 1 /* counter */; global ROLLUP_VALIDATION_REQUESTS_LENGTH = MAX_BLOCK_NUMBER_LENGTH; global STATE_REFERENCE_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; 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 = 1; global HEADER_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH + TOTAL_FEES_LENGTH; -global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + 4 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_CALL) + (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) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_L2_TO_L1_MSGS_PER_CALL) + 2 + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_CALL) + (ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + HEADER_LENGTH + TX_CONTEXT_LENGTH; -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + /*argsHash + returnsHash*/ 2 + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (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) + MAX_PUBLIC_CALL_STACK_LENGTH_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) + 2 + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; +global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + 4 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_CALL) + (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) + PUBLIC_CALL_REQUEST_LENGTH + (L2_TO_L1_MESSAGE_LENGTH * MAX_L2_TO_L1_MSGS_PER_CALL) + 2 + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_CALL) + (ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + HEADER_LENGTH + TX_CONTEXT_LENGTH; +global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + /*argsHash + returnsHash*/ 2 + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (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_CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_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) + 2 + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; global PRIVATE_CALL_STACK_ITEM_LENGTH: u32 = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; global PUBLIC_CONTEXT_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + GAS_LENGTH + 2; @@ -242,13 +242,11 @@ global PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + MAX_L2_TO_L1_MSGS_PER_TX + 5 + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; global COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH + 1; -global PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = AZTEC_ADDRESS_LENGTH + CALL_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH + 3 + 2 * GAS_LENGTH; -global CALL_REQUEST_LENGTH = 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + 2; -global PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_TX) + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (SCOPED_ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (SCOPED_LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + (SCOPED_PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); -global PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH; +global PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_TX) + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (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 = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + PUBLIC_CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH; -global PUBLIC_ACCUMULATED_DATA_LENGTH = (MAX_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_L2_TO_L1_MSGS_PER_TX * 1) + (MAX_NOTE_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_ENCRYPTED_LOGS_PER_TX * 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 * CALL_REQUEST_LENGTH) + GAS_LENGTH; -global PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = VALIDATION_REQUESTS_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + 1 + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH) + AZTEC_ADDRESS_LENGTH; +global PUBLIC_ACCUMULATED_DATA_LENGTH = (MAX_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_L2_TO_L1_MSGS_PER_TX * 1) + (MAX_NOTE_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_ENCRYPTED_LOGS_PER_TX * 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) + GAS_LENGTH; +global PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = VALIDATION_REQUESTS_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + 1 + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) + AZTEC_ADDRESS_LENGTH; global KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + COMBINED_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 1 + AZTEC_ADDRESS_LENGTH; @@ -257,7 +255,6 @@ global CONSTANT_ROLLUP_DATA_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 1 + GLOB // + 5 for rollup_type, height_in_block_tree, txs_effects_hash, out_hash, accumulated_fees global BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = CONSTANT_ROLLUP_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 5; -global ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH: u32 = 4 + CALL_CONTEXT_LENGTH; global GET_NOTES_ORACLE_RETURN_LENGTH: u32 = 674; global NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NOTE_HASHES_PER_TX; global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NULLIFIERS_PER_TX; 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 ca6296010b48..3bf793b4def3 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 @@ -1,7 +1,6 @@ use crate::{ abis::{ gas::Gas, gas_settings::GasSettings, call_context::CallContext, - call_request::{CallerContext, CallRequest}, accumulated_data::{ CombinedAccumulatedData, PrivateAccumulatedData, PrivateAccumulatedDataBuilder, PublicAccumulatedData, PublicAccumulatedDataBuilder @@ -11,11 +10,11 @@ use crate::{ kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, kernel_data::KernelData, public_kernel_data::PublicKernelData, max_block_number::MaxBlockNumber, private_kernel_data::PrivateKernelData, note_hash::{NoteHash, ScopedNoteHash}, - nullifier::{Nullifier, ScopedNullifier}, - private_call_request::{PrivateCallRequest, ScopedPrivateCallRequest}, + nullifier::{Nullifier, ScopedNullifier}, private_call_request::PrivateCallRequest, private_call_stack_item::PrivateCallStackItem, private_circuit_public_inputs::PrivateCircuitPublicInputs, - private_kernel::private_call_data::PrivateCallData, public_data_read::PublicDataRead, + private_kernel::private_call_data::PrivateCallData, public_call_request::PublicCallRequest, + public_call_stack_item_compressed::PublicCallStackItemCompressed, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::{ReadRequest, ScopedReadRequest}, log_hash::{LogHash, NoteLogHash, ScopedLogHash, EncryptedLogHash, ScopedEncryptedLogHash}, validation_requests::{ @@ -30,7 +29,8 @@ use crate::{ MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, VK_TREE_HEIGHT, - MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX + MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + PRIVATE_CALL_REQUEST_LENGTH, PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH }, hash::{ compute_l2_to_l1_hash, compute_tx_logs_hash, compute_tx_note_logs_hash, compute_siloed_nullifier, @@ -74,7 +74,7 @@ struct FixtureBuilder { // Fees. is_fee_payer: bool, fee_payer: AztecAddress, - public_teardown_call_stack: BoundedVec, + public_teardown_call_stack: BoundedVec, // Constant data. historical_header: Header, @@ -95,8 +95,8 @@ struct FixtureBuilder { encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, public_data_update_requests: BoundedVec, - private_call_requests: BoundedVec, - public_call_requests: BoundedVec, + private_call_requests: BoundedVec, + public_call_requests: BoundedVec, gas_used: Gas, non_revertible_gas_used: Gas, revert_code: u8, @@ -236,25 +236,15 @@ impl FixtureBuilder { } } - pub fn build_private_call_request(self) -> ScopedPrivateCallRequest { - let item = self.to_private_call_stack_item(); - let is_delegate_call = self.is_delegate_call; - let mut caller_context = CallerContext::empty(); - caller_context.is_static_call = self.is_static_call; - if is_delegate_call { - caller_context.msg_sender = self.msg_sender; - caller_context.storage_contract_address = self.storage_contract_address; - }; + pub fn build_private_call_request(self) -> PrivateCallRequest { PrivateCallRequest { - target: item.contract_address, - call_context: item.public_inputs.call_context, - function_data: item.function_data, - args_hash: item.public_inputs.args_hash, - returns_hash: item.public_inputs.returns_hash, - caller_context, + contract_address: self.contract_address, + call_context: self.build_call_context(), + args_hash: self.args_hash, + returns_hash: self.returns_hash, start_side_effect_counter: self.counter_start, end_side_effect_counter: self.counter - }.scope(self.msg_sender) + } } pub fn to_private_circuit_public_inputs(self) -> PrivateCircuitPublicInputs { @@ -272,9 +262,9 @@ impl FixtureBuilder { ), note_hashes: subarray(self.note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash)), nullifiers: subarray(self.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier)), - private_call_requests: subarray(self.private_call_requests.storage.map(|r: ScopedPrivateCallRequest| r.call_request)), - public_call_stack_hashes: subarray(self.public_call_requests.storage.map(|c: CallRequest| c.hash)), - public_teardown_function_hash: self.public_teardown_call_stack.storage[0].hash, + private_call_requests: subarray(self.private_call_requests.storage), + public_call_requests: subarray(self.public_call_requests.storage), + public_teardown_call_request: self.public_teardown_call_stack.storage[0], l2_to_l1_msgs: subarray(self.l2_to_l1_msgs.storage.map(|r: ScopedL2ToL1Message| r.message)), start_side_effect_counter: self.counter_start, end_side_effect_counter: self.counter, @@ -297,8 +287,6 @@ impl FixtureBuilder { pub fn to_private_call_data(self) -> PrivateCallData { PrivateCallData { call_stack_item: self.to_private_call_stack_item(), - public_call_stack: subarray(self.public_call_requests.storage), - public_teardown_call_request: self.public_teardown_call_stack.storage[0], vk: self.vk, function_leaf_membership_witness: self.function_leaf_membership_witness, salted_initialization_hash: self.salted_initialization_hash, @@ -317,8 +305,8 @@ impl FixtureBuilder { note_encrypted_logs_hashes: self.note_encrypted_logs_hashes, encrypted_logs_hashes: self.encrypted_logs_hashes, unencrypted_logs_hashes: self.unencrypted_logs_hashes, - private_call_stack: vec_reverse(self.private_call_requests), - public_call_stack: self.public_call_requests + public_call_requests: self.public_call_requests, + private_call_stack: vec_reverse(self.private_call_requests) } } @@ -368,9 +356,7 @@ impl FixtureBuilder { encrypted_logs_hashes: self.encrypted_logs_hashes.storage.map(|l: ScopedEncryptedLogHash| l.expose_to_public()), 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, - // TODO: Hide the counter of a public call request. - // public_call_stack: self.public_call_requests.storage.map(|cr: CallRequest| cr.expose_to_public()), - public_call_stack: self.public_call_requests.storage, + public_call_stack: self.public_call_requests.storage.map(|cr: PublicCallRequest| cr.expose_to_public()), gas_used: self.gas_used } } @@ -791,92 +777,62 @@ impl FixtureBuilder { } pub fn add_private_call_from_call_stack_item(&mut self, item: PrivateCallStackItem) { - let mut caller_context = CallerContext::empty(); - let is_delegate_call = item.public_inputs.call_context.is_delegate_call; - caller_context.is_static_call = self.is_static_call; - if is_delegate_call { - caller_context.msg_sender = self.msg_sender; - caller_context.storage_contract_address = self.storage_contract_address; - } let start_counter = item.public_inputs.start_side_effect_counter; let end_counter = item.public_inputs.end_side_effect_counter; self.counter = end_counter + 1; self.private_call_requests.push( PrivateCallRequest { - target: item.contract_address, + contract_address: item.contract_address, call_context: item.public_inputs.call_context, - function_data: item.function_data, args_hash: item.public_inputs.args_hash, returns_hash: item.public_inputs.returns_hash, - caller_context, start_side_effect_counter: start_counter, end_side_effect_counter: end_counter - }.scope(self.contract_address) + } ); } - pub fn add_private_call_request(&mut self, args_hash: Field, is_delegate_call: bool) { - let mut caller_context = CallerContext::empty(); - caller_context.is_static_call = self.is_static_call; - if is_delegate_call { - caller_context.msg_sender = self.msg_sender; - caller_context.storage_contract_address = self.storage_contract_address; - } + pub fn add_private_call_request(&mut self, is_delegate_call: bool) { + let index_offset = self.private_call_requests.len(); + let mut request = self.mock_private_call_request(index_offset); + request.call_context = self.generate_call_context(request.contract_address, is_delegate_call); + let start_counter = self.next_counter(); let end_counter = start_counter + 10; self.counter = end_counter + 1; + request.start_side_effect_counter = start_counter; + request.end_side_effect_counter = end_counter; - let target = AztecAddress::empty(); - let call_context = CallContext::empty(); - let function_data = FunctionData::empty(); - let returns_hash = 0; - - self.private_call_requests.push( - PrivateCallRequest { - target, - call_context, - function_data, - args_hash, - returns_hash, - caller_context, - start_side_effect_counter: start_counter, - end_side_effect_counter: end_counter - }.scope(self.contract_address) - ); + self.private_call_requests.push(request); } pub fn append_private_call_requests(&mut self, num: u32) { - let index_offset = self.private_call_requests.len(); for i in 0..self.private_call_requests.max_len() { if i < num { - let hash = self.mock_private_call_request_hash(index_offset + i); - self.add_private_call_request(hash, false); + self.add_private_call_request(false); } } } pub fn append_private_call_requests_delegate(&mut self, num: u32) { - let index_offset = self.private_call_requests.len(); for i in 0..self.private_call_requests.max_len() { if i < num { - let hash = self.mock_private_call_request_hash(index_offset + i); - self.add_private_call_request(hash, true); + self.add_private_call_request(true); } } } - pub fn push_public_call_request(&mut self, hash: Field, is_delegate_call: bool) { - let call_request = self.generate_public_call_request(hash, is_delegate_call); - self.public_call_requests.push(call_request); + pub fn push_public_call_request(&mut self, item: PublicCallStackItemCompressed) { + self.public_call_requests.push(PublicCallRequest { item, counter: 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 hash = self.mock_public_call_request_hash(index_offset + i); - self.push_public_call_request(hash, false); + let item = self.mock_public_call_request_item(index_offset + i, false); + self.push_public_call_request(item); } } } @@ -885,8 +841,8 @@ impl FixtureBuilder { let index_offset = self.public_call_requests.len(); for i in 0..self.public_call_requests.max_len() { if i < num { - let hash = self.mock_public_call_request_hash(index_offset + i); - self.push_public_call_request(hash, true); + let item = self.mock_public_call_request_item(index_offset + i, true); + self.push_public_call_request(item); } } } @@ -901,19 +857,20 @@ impl FixtureBuilder { self.storage_contract_address } - pub fn push_public_teardown_call_request(&mut self, hash: Field, is_delegate_call: bool) { - let call_stack_item = self.generate_public_call_request(hash, is_delegate_call); - self.public_teardown_call_stack.push(call_stack_item); + pub fn push_public_teardown_call_request(&mut self, item: PublicCallStackItemCompressed) { + self.public_teardown_call_stack.push(PublicCallRequest { item, counter: self.next_counter() }); } pub fn append_public_teardown_call_request(&mut self) { - let hash = self.mock_public_teardown_call_request_hash(0); - self.push_public_teardown_call_request(hash, false); + let index = self.public_teardown_call_stack.len(); + let item = self.mock_public_teardown_call_request_item(index, false); + self.push_public_teardown_call_request(item); } pub fn append_public_teardown_call_request_delegate(&mut self) { - let hash = self.mock_public_teardown_call_request_hash(0); - self.push_public_teardown_call_request(hash, true); + let index = self.public_teardown_call_stack.len(); + let item = self.mock_public_teardown_call_request_item(index, true); + self.push_public_teardown_call_request(item); } pub fn end_setup(&mut self) { @@ -924,22 +881,6 @@ impl FixtureBuilder { self.max_block_number = MaxBlockNumber::new(max_block_number); } - fn generate_public_call_request(&mut self, hash: Field, is_delegate_call: bool) -> CallRequest { - let mut caller_context = CallerContext::empty(); - if is_delegate_call { - caller_context.msg_sender = self.msg_sender; - caller_context.storage_contract_address = self.storage_contract_address; - } - let start_counter = self.next_counter(); - CallRequest { - hash, - caller_contract_address: self.contract_address, - caller_context, - start_side_effect_counter: start_counter, - end_side_effect_counter: 0 - } - } - fn mock_note_hash_read_value(self, index: u32) -> Field { 789 + self.value_offset + index as Field } @@ -1001,22 +942,48 @@ impl FixtureBuilder { (log_hash, length) } - fn mock_private_call_request_hash(self, index: u32) -> Field { - 766766 + self.value_offset + index as Field + fn mock_private_call_request(self, index: u32) -> PrivateCallRequest { + let value_offset = 766766 + self.value_offset + index as Field; + let mut fields = [0; PRIVATE_CALL_REQUEST_LENGTH]; + for i in 0..fields.len() { + fields[i] = value_offset + i as Field; + } + PrivateCallRequest::deserialize(fields) } - fn mock_public_call_request_hash(self, index: u32) -> Field { - 636363 + self.value_offset + index as Field + fn mock_public_call_request_item(self, index: u32, is_delegate_call: bool) -> PublicCallStackItemCompressed { + let value_offset = 636363 + self.value_offset + index as Field; + let mut fields = [0; PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH]; + for i in 0..fields.len() { + fields[i] = value_offset + i as Field; + } + let mut item = PublicCallStackItemCompressed::deserialize(fields); + item.call_context = self.generate_call_context(item.contract_address, is_delegate_call); + item } - fn mock_public_teardown_call_request_hash(self, index: u32) -> Field { - 54345 + self.value_offset + index as Field + fn mock_public_teardown_call_request_item(self, index: u32, is_delegate_call: bool) -> PublicCallStackItemCompressed { + self.mock_public_call_request_item(index + 54345, is_delegate_call) } fn mock_fee_payer(self) -> AztecAddress { AztecAddress::from_field(900900 + self.value_offset) } + fn generate_call_context(self, target_contract_address: AztecAddress, is_delegate_call: bool) -> CallContext { + let mut call_context = CallContext::empty(); + call_context.is_delegate_call = is_delegate_call; + call_context.is_static_call = self.is_static_call; + if is_delegate_call { + call_context.msg_sender = self.msg_sender; + call_context.storage_contract_address = self.storage_contract_address; + } else { + call_context.msg_sender = self.storage_contract_address; + call_context.storage_contract_address = target_contract_address; + } + call_context + } + fn next_counter(&mut self) -> u32 { let counter = self.counter; self.counter += 1; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr index 55de13e3a3c7..b9d8b3ffb6b4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr @@ -1,17 +1,17 @@ use crate::{ abis::{ - gas_settings::GasSettings, gas::Gas, call_context::CallContext, - call_request::{CallerContext, CallRequest}, function_data::FunctionData, - public_call_data::{PublicCallData, Proof}, public_call_stack_item::PublicCallStackItem, - public_circuit_public_inputs::PublicCircuitPublicInputs, log_hash::LogHash + gas_settings::GasSettings, gas::Gas, call_context::CallContext, function_data::FunctionData, + public_call_data::{PublicCallData, Proof}, public_call_request::PublicCallRequest, + public_call_stack_item::PublicCallStackItem, + public_call_stack_item_compressed::PublicCallStackItemCompressed, log_hash::LogHash }, - address::{AztecAddress, EthAddress}, + address::AztecAddress, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, tests::{fixtures, public_circuit_public_inputs_builder::PublicCircuitPublicInputsBuilder} }; use crate::constants::{ MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH }; struct PublicCallDataBuilder { @@ -19,7 +19,6 @@ struct PublicCallDataBuilder { public_inputs: PublicCircuitPublicInputsBuilder, is_execution_request: bool, function_data: FunctionData, - public_call_stack: BoundedVec, proof: Proof, bytecode_hash: Field, } @@ -47,7 +46,6 @@ impl PublicCallDataBuilder { public_inputs, is_execution_request: false, function_data, - public_call_stack: BoundedVec::new(), proof: Proof {}, bytecode_hash: contract_function.acir_hash } @@ -68,34 +66,37 @@ impl PublicCallDataBuilder { self.append_public_call_requests(num_requests, true); } - pub fn append_public_call_requests(&mut self, num_requests: u32, is_delegate_call: bool) { - let value_offset = self.public_inputs.public_call_stack_hashes.len(); - let mut caller_context = CallerContext::empty(); - if is_delegate_call { - let call_context = self.public_inputs.call_context; - caller_context.msg_sender = call_context.msg_sender; - caller_context.storage_contract_address = call_context.storage_contract_address; - } - let mut exceeded_len = false; + fn append_public_call_requests(&mut self, num_requests: u32, is_delegate_call: bool) { + let index_offset = self.public_inputs.public_call_requests.len(); for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL { - exceeded_len |= i == num_requests; - if !exceeded_len { - // The default hash is its index + 7788. - let hash = (value_offset + 7788) as Field; - let call_request = CallRequest { - hash, - caller_contract_address: self.contract_address, - caller_context, - // todo: real values? - start_side_effect_counter: i as u32, - end_side_effect_counter: (i + 1) as u32 - }; - self.public_inputs.public_call_stack_hashes.push(hash); - self.public_call_stack.push(call_request); + if i < num_requests { + let call_request = PublicCallRequest { item: self.mock_public_call_request_item(index_offset + i, is_delegate_call), counter: i }; + self.public_inputs.public_call_requests.push(call_request); } } } + fn mock_public_call_request_item(self, index: u32, is_delegate_call: bool) -> PublicCallStackItemCompressed { + let value_offset = 7788 + index as Field; + let mut fields = [0; PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH]; + for i in 0..fields.len() { + fields[i] = value_offset + i as Field; + } + let mut item = PublicCallStackItemCompressed::deserialize(fields); + item.call_context.msg_sender = if is_delegate_call { + self.public_inputs.call_context.msg_sender + } else { + self.public_inputs.call_context.storage_contract_address + }; + item.call_context.storage_contract_address = if is_delegate_call { + self.public_inputs.call_context.storage_contract_address + } else { + item.contract_address + }; + item.call_context.is_delegate_call = is_delegate_call; + item + } + pub fn append_public_data_read_requests(&mut self, num_reads: u32) { let value_offset = self.public_inputs.contract_storage_reads.len(); for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { @@ -158,7 +159,6 @@ impl PublicCallDataBuilder { is_execution_request: self.is_execution_request, public_inputs: self.public_inputs.finish() }, - public_call_stack: self.public_call_stack.storage, proof: self.proof, bytecode_hash: self.bytecode_hash } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr index 50aa8e0aa9d5..25ceeb398689 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr @@ -1,8 +1,8 @@ use crate::{ abis::{ gas::Gas, call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, - public_circuit_public_inputs::PublicCircuitPublicInputs, read_request::ReadRequest, - log_hash::LogHash, global_variables::GlobalVariables + public_call_request::PublicCallRequest, public_circuit_public_inputs::PublicCircuitPublicInputs, + read_request::ReadRequest, log_hash::LogHash, global_variables::GlobalVariables }, address::AztecAddress, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, header::Header, @@ -29,7 +29,7 @@ struct PublicCircuitPublicInputsBuilder { l1_to_l2_msg_read_requests: BoundedVec, contract_storage_update_requests: BoundedVec, contract_storage_reads: BoundedVec, - public_call_stack_hashes: BoundedVec, + public_call_requests: BoundedVec, note_hashes: BoundedVec, nullifiers: BoundedVec, l2_to_l1_msgs: BoundedVec, @@ -63,7 +63,7 @@ impl PublicCircuitPublicInputsBuilder { l1_to_l2_msg_read_requests: self.l1_to_l2_msg_read_requests.storage, contract_storage_update_requests: self.contract_storage_update_requests.storage, contract_storage_reads: self.contract_storage_reads.storage, - public_call_stack_hashes: self.public_call_stack_hashes.storage, + public_call_requests: self.public_call_requests.storage, note_hashes: self.note_hashes.storage, nullifiers: self.nullifiers.storage, l2_to_l1_msgs: self.l2_to_l1_msgs.storage, @@ -93,7 +93,7 @@ impl Empty for PublicCircuitPublicInputsBuilder { l1_to_l2_msg_read_requests: BoundedVec::new(), contract_storage_update_requests: BoundedVec::new(), contract_storage_reads: BoundedVec::new(), - public_call_stack_hashes: BoundedVec::new(), + public_call_requests: BoundedVec::new(), note_hashes: BoundedVec::new(), nullifiers: BoundedVec::new(), l2_to_l1_msgs: BoundedVec::new(), diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index bf5e7016f0ee..4489250c5353 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -1,7 +1,6 @@ import { createArchiver } from '@aztec/archiver'; import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; import { - AggregateTxValidator, type AztecNode, type FromLogType, type GetUnencryptedLogsResponse, @@ -60,7 +59,13 @@ import { getCanonicalInstanceDeployer } from '@aztec/protocol-contracts/instance import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; import { getCanonicalMultiCallEntrypointAddress } from '@aztec/protocol-contracts/multi-call-entrypoint'; import { createProverClient } from '@aztec/prover-client'; -import { type GlobalVariableBuilder, SequencerClient, getGlobalVariableBuilder } from '@aztec/sequencer-client'; +import { + AggregateTxValidator, + DataTxValidator, + type GlobalVariableBuilder, + SequencerClient, + getGlobalVariableBuilder, +} from '@aztec/sequencer-client'; import { PublicProcessorFactory, WASMSimulator, createSimulationProvider } from '@aztec/simulator'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -151,6 +156,7 @@ export class AztecNodeService implements AztecNode { const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); const txValidator = new AggregateTxValidator( + new DataTxValidator(), new MetadataTxValidator(config.l1ChainId), new TxProofValidator(proofVerifier), ); diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index f821a8266c97..f769425ad687 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -22,6 +22,7 @@ import { MAX_UNENCRYPTED_LOGS_PER_CALL, NoteHash, Nullifier, + PublicCallRequest, PublicCircuitPublicInputs, ReadRequest, RevertCode, @@ -327,7 +328,7 @@ const getPublicInputs = (result: PublicExecutionResult): PublicCircuitPublicInpu ContractStorageUpdateRequest.empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ), - publicCallStackHashes: padArrayEnd([], Fr.zero(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL), + publicCallRequests: padArrayEnd([], PublicCallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL), unencryptedLogsHashes: padArrayEnd(result.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_CALL), historicalHeader: Header.empty(), globalVariables: GlobalVariables.empty(), diff --git a/yarn-project/circuit-types/src/index.ts b/yarn-project/circuit-types/src/index.ts index e9154e4c24a8..3745ffca3eed 100644 --- a/yarn-project/circuit-types/src/index.ts +++ b/yarn-project/circuit-types/src/index.ts @@ -15,6 +15,7 @@ export * from './notes/index.js'; export * from './packed_values.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'; export * from './tx/index.js'; diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index f14f28d93b49..6ddd14e64b0e 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -1,6 +1,6 @@ import { AztecAddress, - CallRequest, + CallContext, ClientIvcProof, GasSettings, LogHash, @@ -11,11 +11,11 @@ import { PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, PublicAccumulatedDataBuilder, - PublicCallRequest, ScopedLogHash, computeContractClassId, getContractClassFromArtifact, } from '@aztec/circuits.js'; +import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { makeCombinedAccumulatedData, makeCombinedConstantData, @@ -30,6 +30,7 @@ import { type ContractInstanceWithAddress, SerializableContractInstance } from ' import { EncryptedNoteTxL2Logs, EncryptedTxL2Logs, Note, UnencryptedTxL2Logs } from './logs/index.js'; import { ExtendedNote } from './notes/index.js'; +import { PublicExecutionRequest } from './public_execution_request.js'; import { NestedProcessReturnValues, PublicSimulationOutput, SimulatedTx, Tx, TxHash } from './tx/index.js'; export const randomTxHash = (): TxHash => new TxHash(randomBytes(32)); @@ -40,27 +41,21 @@ export const mockTx = ( hasLogs = false, numberOfNonRevertiblePublicCallRequests = MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX / 2, numberOfRevertiblePublicCallRequests = MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX / 2, - publicCallRequests = [], - publicTeardownCallRequest = PublicCallRequest.empty(), + hasPublicTeardownCallRequest = false, feePayer = AztecAddress.ZERO, }: { hasLogs?: boolean; numberOfNonRevertiblePublicCallRequests?: number; numberOfRevertiblePublicCallRequests?: number; - publicCallRequests?: PublicCallRequest[]; - publicTeardownCallRequest?: PublicCallRequest; + hasPublicTeardownCallRequest?: boolean; feePayer?: AztecAddress; } = {}, ) => { const totalPublicCallRequests = - numberOfNonRevertiblePublicCallRequests + numberOfRevertiblePublicCallRequests || publicCallRequests.length; - if (publicCallRequests.length && publicCallRequests.length !== totalPublicCallRequests) { - throw new Error( - `Provided publicCallRequests does not match the required number of call requests. Expected ${totalPublicCallRequests}. Got ${publicCallRequests.length}`, - ); - } - - const isForPublic = totalPublicCallRequests > 0 || publicTeardownCallRequest.isEmpty() === false; + numberOfNonRevertiblePublicCallRequests + + numberOfRevertiblePublicCallRequests + + (hasPublicTeardownCallRequest ? 1 : 0); + const isForPublic = totalPublicCallRequests > 0; const data = PrivateKernelTailCircuitPublicInputs.empty(); const firstNullifier = new Nullifier(new Fr(seed + 1), 0, Fr.ZERO); const noteEncryptedLogs = EncryptedNoteTxL2Logs.empty(); // Mock seems to have no new notes => no note logs @@ -69,44 +64,51 @@ export const mockTx = ( data.constants.txContext.gasSettings = GasSettings.default(); data.feePayer = feePayer; + let enqueuedPublicFunctionCalls: PublicExecutionRequest[] = []; + let publicTeardownFunctionCall = PublicExecutionRequest.empty(); if (isForPublic) { data.forRollup = undefined; data.forPublic = PartialPrivateTailPublicInputsForPublic.empty(); - publicCallRequests = publicCallRequests.length - ? publicCallRequests.slice().sort((a, b) => b.sideEffectCounter - a.sideEffectCounter) - : times(totalPublicCallRequests, i => makePublicCallRequest(seed + 0x100 + i)); - const revertibleBuilder = new PublicAccumulatedDataBuilder(); const nonRevertibleBuilder = new PublicAccumulatedDataBuilder(); + 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)]); + publicCallRequests.forEach((r, i) => (r.item.argsHash = computeVarArgsHash(publicFunctionArgs[i]))); + + if (hasPublicTeardownCallRequest) { + const request = publicCallRequests.shift()!; + data.forPublic.publicTeardownCallRequest = request; + const args = publicFunctionArgs.shift()!; + publicTeardownFunctionCall = new PublicExecutionRequest( + request.item.contractAddress, + CallContext.fromFields(request.item.callContext.toFields()), + args, + ); + } + + enqueuedPublicFunctionCalls = publicCallRequests.map( + (r, i) => + new PublicExecutionRequest( + r.item.contractAddress, + CallContext.fromFields(r.item.callContext.toFields()), + publicFunctionArgs[i], + ), + ); + const nonRevertibleNullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, Nullifier.empty); nonRevertibleNullifiers[0] = firstNullifier; data.forPublic.endNonRevertibleData = nonRevertibleBuilder .withNullifiers(nonRevertibleNullifiers) - .withPublicCallStack( - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, i => - i < numberOfNonRevertiblePublicCallRequests - ? publicCallRequests[numberOfRevertiblePublicCallRequests + i].toCallRequest() - : CallRequest.empty(), - ), - ) + .withPublicCallStack(publicCallRequests.slice(numberOfRevertiblePublicCallRequests)) .build(); data.forPublic.end = revertibleBuilder - .withPublicCallStack( - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, i => - i < numberOfRevertiblePublicCallRequests ? publicCallRequests[i].toCallRequest() : CallRequest.empty(), - ), - ) + .withPublicCallStack(publicCallRequests.slice(0, numberOfRevertiblePublicCallRequests)) .build(); - data.forPublic.publicTeardownCallStack = makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, () => CallRequest.empty()); - data.forPublic.publicTeardownCallStack[0] = publicTeardownCallRequest.isEmpty() - ? CallRequest.empty() - : publicTeardownCallRequest.toCallRequest(); - if (hasLogs) { let i = 1; // 0 used in first nullifier let nonRevertibleIndex = 0; @@ -177,8 +179,8 @@ export const mockTx = ( noteEncryptedLogs, encryptedLogs, unencryptedLogs, - publicCallRequests, - publicTeardownCallRequest, + enqueuedPublicFunctionCalls, + publicTeardownFunctionCall, ); return tx; diff --git a/yarn-project/circuit-types/src/public_execution_request.ts b/yarn-project/circuit-types/src/public_execution_request.ts new file mode 100644 index 000000000000..83ad8d3f2008 --- /dev/null +++ b/yarn-project/circuit-types/src/public_execution_request.ts @@ -0,0 +1,75 @@ +import { CallContext, type PublicCallRequest, Vector } from '@aztec/circuits.js'; +import { computeVarArgsHash } from '@aztec/circuits.js/hash'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; + +import { inspect } from 'util'; + +/** + * The execution request of a public function. + */ +export class PublicExecutionRequest { + constructor( + public contractAddress: AztecAddress, + /** + * Context of the public call. + * TODO(#3417): Check if all fields of CallContext are actually needed. + */ + public callContext: CallContext, + /** + * Function arguments. + */ + public args: Fr[], + ) {} + + getSize() { + return this.isEmpty() ? 0 : this.toBuffer().length; + } + + toBuffer() { + return serializeToBuffer(this.contractAddress, this.callContext, new Vector(this.args)); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicExecutionRequest( + new AztecAddress(reader.readBytes(32)), + CallContext.fromBuffer(reader), + reader.readVector(Fr), + ); + } + + static from(fields: FieldsOf): PublicExecutionRequest { + return new PublicExecutionRequest(...PublicExecutionRequest.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.contractAddress, fields.callContext, fields.args] as const; + } + + static empty() { + return new PublicExecutionRequest(AztecAddress.ZERO, CallContext.empty(), []); + } + + isEmpty(): boolean { + return this.contractAddress.isZero() && this.callContext.isEmpty() && this.args.length === 0; + } + + isForCallRequest(callRequest: PublicCallRequest) { + return ( + this.contractAddress.equals(callRequest.item.contractAddress) && + this.callContext.equals(callRequest.item.callContext) && + computeVarArgsHash(this.args).equals(callRequest.item.argsHash) + ); + } + + [inspect.custom]() { + return `PublicExecutionRequest { + contractAddress: ${this.contractAddress} + callContext: ${this.callContext} + args: ${this.args} + }`; + } +} diff --git a/yarn-project/circuit-types/src/tx/index.ts b/yarn-project/circuit-types/src/tx/index.ts index 0198209ebeb7..abe8d8675748 100644 --- a/yarn-project/circuit-types/src/tx/index.ts +++ b/yarn-project/circuit-types/src/tx/index.ts @@ -4,6 +4,5 @@ export * from './simulated_tx.js'; export * from './tx.js'; export * from './tx_hash.js'; export * from './tx_receipt.js'; -export * from './validator/aggregate_tx_validator.js'; export * from './validator/tx_validator.js'; export * from './validator/empty_validator.js'; diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index 2a27b7938323..74d5d26993d9 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -2,7 +2,6 @@ import { ClientIvcProof, ContractClassRegisteredEvent, PrivateKernelTailCircuitPublicInputs, - PublicCallRequest, type PublicKernelCircuitPublicInputs, } from '@aztec/circuits.js'; import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; @@ -11,6 +10,7 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { type GetUnencryptedLogsResponse } from '../logs/get_unencrypted_logs_response.js'; import { type L2LogsSource } from '../logs/l2_logs_source.js'; import { EncryptedNoteTxL2Logs, EncryptedTxL2Logs, UnencryptedTxL2Logs } from '../logs/tx_l2_logs.js'; +import { PublicExecutionRequest } from '../public_execution_request.js'; import { type TxStats } from '../stats/stats.js'; import { TxHash } from './tx_hash.js'; @@ -43,28 +43,32 @@ export class Tx { public unencryptedLogs: UnencryptedTxL2Logs, /** * Enqueued public functions from the private circuit to be run by the sequencer. - * Preimages of the public call stack entries from the private kernel circuit output. */ - public readonly enqueuedPublicFunctionCalls: PublicCallRequest[], + public readonly enqueuedPublicFunctionCalls: PublicExecutionRequest[], /** * Public function call to be run by the sequencer as part of teardown. */ - public readonly publicTeardownFunctionCall: PublicCallRequest, - ) { - const kernelPublicCallStackSize = data.numberOfPublicCallRequests(); - const totalPublicCalls = enqueuedPublicFunctionCalls.length + (publicTeardownFunctionCall.isEmpty() ? 0 : 1); - if (kernelPublicCallStackSize !== totalPublicCalls) { - throw new Error( - `Mismatch number of enqueued public function calls in kernel circuit public inputs (expected - ${kernelPublicCallStackSize}, got ${totalPublicCalls})`, - ); - } - } + public readonly publicTeardownFunctionCall: PublicExecutionRequest, + ) {} hasPublicCalls() { return this.data.numberOfPublicCallRequests() > 0; } + getNonRevertiblePublicExecutionRequests(): PublicExecutionRequest[] { + const numRevertible = this.data.numberOfRevertiblePublicCallRequests(); + return this.enqueuedPublicFunctionCalls.slice(numRevertible); + } + + getRevertiblePublicExecutionRequests(): PublicExecutionRequest[] { + const numRevertible = this.data.numberOfRevertiblePublicCallRequests(); + return this.enqueuedPublicFunctionCalls.slice(0, numRevertible); + } + + getPublicTeardownExecutionRequest(): PublicExecutionRequest | undefined { + return this.publicTeardownFunctionCall.isEmpty() ? undefined : this.publicTeardownFunctionCall; + } + /** * Deserializes the Tx object from a Buffer. * @param buffer - Buffer or BufferReader object to deserialize. @@ -78,8 +82,8 @@ export class Tx { reader.readObject(EncryptedNoteTxL2Logs), reader.readObject(EncryptedTxL2Logs), reader.readObject(UnencryptedTxL2Logs), - reader.readArray(reader.readNumber(), PublicCallRequest), - reader.readObject(PublicCallRequest), + reader.readArray(reader.readNumber(), PublicExecutionRequest), + reader.readObject(PublicExecutionRequest), ); } @@ -137,9 +141,11 @@ export class Tx { const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(Buffer.from(obj.unencryptedLogs, 'hex')); const clientIvcProof = ClientIvcProof.fromBuffer(Buffer.from(obj.clientIvcProof, 'hex')); const enqueuedPublicFunctions = obj.enqueuedPublicFunctions - ? obj.enqueuedPublicFunctions.map((x: string) => PublicCallRequest.fromBuffer(Buffer.from(x, 'hex'))) + ? obj.enqueuedPublicFunctions.map((x: string) => PublicExecutionRequest.fromBuffer(Buffer.from(x, 'hex'))) : []; - const publicTeardownFunctionCall = PublicCallRequest.fromBuffer(Buffer.from(obj.publicTeardownFunctionCall, 'hex')); + const publicTeardownFunctionCall = PublicExecutionRequest.fromBuffer( + Buffer.from(obj.publicTeardownFunctionCall, 'hex'), + ); return new Tx( publicInputs, clientIvcProof, @@ -187,7 +193,11 @@ export class Tx { ? // 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.enqueuedPublicFunctionCalls.at(-1)!.functionSelector.toField().toBigInt() === 0x43417bb1n + this.data + .getNonRevertiblePublicCallRequests() + .at(-1)! + .item.callContext.functionSelector.toField() + .toBigInt() === 0x43417bb1n ? 'fpc_public' : 'fpc_private' : 'native' @@ -239,17 +249,17 @@ export class Tx { const noteEncryptedLogs = EncryptedNoteTxL2Logs.fromBuffer(Buffer.from(tx.noteEncryptedLogs.toBuffer())); const encryptedLogs = EncryptedTxL2Logs.fromBuffer(tx.encryptedLogs.toBuffer()); const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(tx.unencryptedLogs.toBuffer()); - const enqueuedPublicFunctions = tx.enqueuedPublicFunctionCalls.map(x => { - return PublicCallRequest.fromBuffer(x.toBuffer()); - }); - const publicTeardownFunctionCall = PublicCallRequest.fromBuffer(tx.publicTeardownFunctionCall.toBuffer()); + const enqueuedPublicFunctionCalls = tx.enqueuedPublicFunctionCalls.map(x => + PublicExecutionRequest.fromBuffer(x.toBuffer()), + ); + const publicTeardownFunctionCall = PublicExecutionRequest.fromBuffer(tx.publicTeardownFunctionCall.toBuffer()); return new Tx( publicInputs, clientIvcProof, noteEncryptedLogs, encryptedLogs, unencryptedLogs, - enqueuedPublicFunctions, + enqueuedPublicFunctionCalls, publicTeardownFunctionCall, ); } diff --git a/yarn-project/circuit-types/src/tx/validator/aggregate_tx_validator.test.ts b/yarn-project/circuit-types/src/tx/validator/aggregate_tx_validator.test.ts deleted file mode 100644 index 1eb7558bf25f..000000000000 --- a/yarn-project/circuit-types/src/tx/validator/aggregate_tx_validator.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { type AnyTx, Tx, type TxHash, type TxValidator, mockTx } from '@aztec/circuit-types'; - -import { AggregateTxValidator } from './aggregate_tx_validator.js'; - -describe('AggregateTxValidator', () => { - it('allows txs that pass all validation', async () => { - const txs = [mockTx(0), mockTx(1), mockTx(2), mockTx(3), mockTx(4)]; - const agg = new AggregateTxValidator( - new TxDenyList(txs[0].getTxHash(), txs[1].getTxHash()), - new TxDenyList(txs[2].getTxHash(), txs[3].getTxHash()), - ); - - await expect(agg.validateTxs(txs)).resolves.toEqual([[txs[4]], [txs[0], txs[1], txs[2], txs[3]]]); - }); - - class TxDenyList implements TxValidator { - denyList: Set; - constructor(...txHashes: TxHash[]) { - this.denyList = new Set(txHashes.map(hash => hash.toString())); - } - - validateTxs(txs: AnyTx[]): Promise<[AnyTx[], AnyTx[]]> { - return Promise.resolve([ - txs.filter(tx => !this.denyList.has(Tx.getHash(tx).toString())), - txs.filter(tx => this.denyList.has(Tx.getHash(tx).toString())), - ]); - } - } -}); diff --git a/yarn-project/circuit-types/src/tx/validator/aggregate_tx_validator.ts b/yarn-project/circuit-types/src/tx/validator/aggregate_tx_validator.ts deleted file mode 100644 index 6e78b2bfcecc..000000000000 --- a/yarn-project/circuit-types/src/tx/validator/aggregate_tx_validator.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { type ProcessedTx } from '../processed_tx.js'; -import { type Tx } from '../tx.js'; -import { type TxValidator } from './tx_validator.js'; - -export class AggregateTxValidator implements TxValidator { - #validators: TxValidator[]; - constructor(...validators: TxValidator[]) { - if (validators.length === 0) { - throw new Error('At least one validator must be provided'); - } - - this.#validators = validators; - } - - async validateTxs(txs: T[]): Promise<[validTxs: T[], invalidTxs: T[]]> { - const invalidTxs: T[] = []; - let txPool = txs; - for (const validator of this.#validators) { - const [valid, invalid] = await validator.validateTxs(txPool); - invalidTxs.push(...invalid); - txPool = valid; - } - - return [txPool, invalidTxs]; - } -} diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index c739e764449b..f283c901e782 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -149,18 +149,18 @@ 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 CALLER_CONTEXT_LENGTH = 3; -export const PRIVATE_CALL_REQUEST_LENGTH = 15; -export const SCOPED_PRIVATE_CALL_REQUEST_LENGTH = 16; +export const PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 13; +export const PRIVATE_CALL_REQUEST_LENGTH = 10; +export const PUBLIC_CALL_REQUEST_LENGTH = 14; export const ROLLUP_VALIDATION_REQUESTS_LENGTH = 2; export const STATE_REFERENCE_LENGTH = 8; export const TX_CONTEXT_LENGTH = 9; export const TX_REQUEST_LENGTH = 13; export const TOTAL_FEES_LENGTH = 1; export const HEADER_LENGTH = 23; -export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 444; -export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 481; -export const PRIVATE_CALL_STACK_ITEM_LENGTH = 447; +export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 645; +export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 689; +export const PRIVATE_CALL_STACK_ITEM_LENGTH = 648; export const PUBLIC_CONTEXT_INPUTS_LENGTH = 40; export const AGGREGATION_OBJECT_LENGTH = 16; export const SCOPED_READ_REQUEST_LEN = 3; @@ -169,16 +169,13 @@ export const VALIDATION_REQUESTS_LENGTH = 1090; export const PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; export const COMBINED_ACCUMULATED_DATA_LENGTH = 364; export const COMBINED_CONSTANT_DATA_LENGTH = 41; -export const PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH = 15; -export const CALL_REQUEST_LENGTH = 7; -export const PRIVATE_ACCUMULATED_DATA_LENGTH = 1160; -export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2300; -export const PUBLIC_ACCUMULATED_DATA_LENGTH = 991; -export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3339; +export const PRIVATE_ACCUMULATED_DATA_LENGTH = 1336; +export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2483; +export const PUBLIC_ACCUMULATED_DATA_LENGTH = 1215; +export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 4011; export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 415; export const CONSTANT_ROLLUP_DATA_LENGTH = 11; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 28; -export const ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 9; export const GET_NOTES_ORACLE_RETURN_LENGTH = 674; export const NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; export const NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/yarn-project/circuits.js/src/scripts/constants.in.ts b/yarn-project/circuits.js/src/scripts/constants.in.ts index 251a40be093c..bd53af1ea791 100644 --- a/yarn-project/circuits.js/src/scripts/constants.in.ts +++ b/yarn-project/circuits.js/src/scripts/constants.in.ts @@ -31,6 +31,7 @@ const CPP_CONSTANTS = [ 'CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH', 'MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL', 'CONTRACT_STORAGE_READ_LENGTH', + 'PUBLIC_CALL_REQUEST_LENGTH', 'MAX_PUBLIC_DATA_READS_PER_CALL', 'MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL', 'NOTE_HASH_LENGTH', diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index 92ededa914eb..edcca6a233ac 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x065f2831db9ac0db5e710bd3a865b5facd8cf83f1585e1af8fd1d6ce9c47f685>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x22a93cff4c51d8d7eb0df339350343ff113a4db028a8c3b6f8fee8a586a51c2e>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x284f821d2bcea6a1a7fbe596cd7e929085c1c0076133829ae60a6e0d16117bb9>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x2f9cf0558cd19e47cc8e3351bd2aadfb528da51b5b942e26851c1238a574a051>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 92f8895fc2af..16aa7d9559b7 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x15c9b0a92b9b541598e24c9f0b0b4b04b7f2408599751c45aa12de671fd9b363>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x2f5d0ff52163d6b688be54324d50d173d9433658bb40e7c5140876df4eb95406>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0fc0a3f32fc96cf98cea1365453385f9ea028ddea94019604e5b9279ccf029e2>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x1efbf0b1f83d5c96aa4f89e4310f00c6328ff65b0d603b08d3227d24941f7972>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap deleted file mode 100644 index 7ded37d41831..000000000000 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x2268218e4dd9e61345f407816d63de9c7a83b031b7820a17470748bae488fb50"`; - -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x2268218e4dd9e61345f407816d63de9c7a83b031b7820a17470748bae488fb50"`; - -exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x1741852830903d2d946b0406b738df1016ad0ce4c7c61cd81d005466eb1c57bc>`; - -exports[`PublicCallStackItem computes hash 1`] = `Fr<0x117437216ff7ce8362a16eeeca67f5b34f64a81ce57489887db1d77c1a16ef25>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index a19e83d6bea4..55fe9a3004e7 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x2b80e3db92cdbf588155e0eaa4f51b35366cbd6e10f587c335204be5bf337bac>`; +exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x090d3b90d0aba84f6ffc2feb1c069728f803515054e328e410aeaca2a664adc6>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0f068c8c19112300cf78744661d3af705340aed011fb1b6ceb49526b15649f84>`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x11d20f2a6dd654487e9d92d9ba89fef2b44f1a1ec2e237f6cd09bd5b9bfd2422>`; diff --git a/yarn-project/circuits.js/src/structs/call_context.ts b/yarn-project/circuits.js/src/structs/call_context.ts index 1805cd419b53..790c2cfdaf07 100644 --- a/yarn-project/circuits.js/src/structs/call_context.ts +++ b/yarn-project/circuits.js/src/structs/call_context.ts @@ -1,7 +1,7 @@ import { FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { pedersenHash } from '@aztec/foundation/crypto'; -import { Fr } from '@aztec/foundation/fields'; +import { type Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -46,7 +46,11 @@ export class CallContext { isEmpty() { return ( - this.msgSender.isZero() && this.storageContractAddress.isZero() && this.functionSelector.isEmpty() && Fr.ZERO + this.msgSender.isZero() && + this.storageContractAddress.isZero() && + this.functionSelector.isEmpty() && + !this.isDelegateCall && + !this.isStaticCall ); } @@ -85,7 +89,7 @@ export class CallContext { /** * Deserialize this from a buffer. * @param buffer - The bufferable type from which to deserialize. - * @returns The deserialized instance of PublicCallRequest. + * @returns The deserialized instance of CallContext. */ static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); diff --git a/yarn-project/circuits.js/src/structs/call_request.ts b/yarn-project/circuits.js/src/structs/call_request.ts deleted file mode 100644 index f3c96c1d42b2..000000000000 --- a/yarn-project/circuits.js/src/structs/call_request.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; - -import { CallerContext } from './caller_context.js'; - -/** - * Call request. - */ -export class CallRequest { - constructor( - /** - * The hash of the call stack item. - */ - public hash: Fr, - /** - * The address of the contract calling the function. - */ - public callerContractAddress: AztecAddress, - /** - * The call context of the contract calling the function. - */ - public callerContext: CallerContext, - /** - * The call context of the contract calling the function. - */ - public startSideEffectCounter: Fr, - /** - * The call context of the contract calling the function. - */ - public endSideEffectCounter: Fr, - ) {} - - toBuffer() { - return serializeToBuffer( - this.hash, - this.callerContractAddress, - this.callerContext, - this.startSideEffectCounter, - this.endSideEffectCounter, - ); - } - - get counter() { - return this.startSideEffectCounter.toNumber(); - } - - /** - * Deserializes from a buffer or reader. - * @param buffer - Buffer or reader to read from. - * @returns The deserialized instance of CallRequest. - */ - public static fromBuffer(buffer: Buffer | BufferReader) { - const reader = BufferReader.asReader(buffer); - return new CallRequest( - Fr.fromBuffer(reader), - reader.readObject(AztecAddress), - reader.readObject(CallerContext), - Fr.fromBuffer(reader), - Fr.fromBuffer(reader), - ); - } - - public static fromFields(fields: Fr[] | FieldReader) { - const reader = FieldReader.asReader(fields); - return new CallRequest( - reader.readField(), - reader.readObject(AztecAddress), - reader.readObject(CallerContext), - reader.readField(), - reader.readField(), - ); - } - - isEmpty() { - return ( - this.hash.isZero() && - this.callerContractAddress.isZero() && - this.callerContext.isEmpty() && - this.startSideEffectCounter.isZero() && - this.endSideEffectCounter.isZero() - ); - } - - /** - * Returns a new instance of CallRequest with zero hash, caller contract address and caller context. - * @returns A new instance of CallRequest with zero hash, caller contract address and caller context. - */ - public static empty() { - return new CallRequest(Fr.ZERO, AztecAddress.ZERO, CallerContext.empty(), Fr.ZERO, Fr.ZERO); - } - - equals(callRequest: CallRequest) { - return ( - callRequest.hash.equals(this.hash) && - callRequest.callerContractAddress.equals(this.callerContractAddress) && - callRequest.callerContext.equals(this.callerContext) && - callRequest.startSideEffectCounter.equals(this.startSideEffectCounter) && - callRequest.endSideEffectCounter.equals(this.endSideEffectCounter) - ); - } - - toString() { - return `CallRequest(hash: ${this.hash.toString()}, callerContractAddress: ${this.callerContractAddress.toString()}, callerContext: ${this.callerContext.toString()}, startSideEffectCounter: ${this.startSideEffectCounter.toString()}, endSideEffectCounter: ${this.endSideEffectCounter.toString()})`; - } -} diff --git a/yarn-project/circuits.js/src/structs/caller_context.ts b/yarn-project/circuits.js/src/structs/caller_context.ts deleted file mode 100644 index 7edceebc5a22..000000000000 --- a/yarn-project/circuits.js/src/structs/caller_context.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { type Fr } from '@aztec/foundation/fields'; -import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; -import { type FieldsOf } from '@aztec/foundation/types'; - -export class CallerContext { - constructor( - /** - * Message sender of the caller contract. - */ - public msgSender: AztecAddress, - /** - * Storage contract address of the caller contract. - */ - public storageContractAddress: AztecAddress, - /** - * Whether the caller was modifying state. - */ - public isStaticCall: boolean, - ) {} - - toFields(): Fr[] { - return serializeToFields([this.msgSender, this.storageContractAddress, this.isStaticCall]); - } - - static fromFields(fields: Fr[] | FieldReader) { - const reader = FieldReader.asReader(fields); - return new CallerContext(reader.readObject(AztecAddress), reader.readObject(AztecAddress), reader.readBoolean()); - } - - /** - * Returns a new instance of CallerContext with zero values. - * @returns A new instance of CallerContext with zero values. - */ - public static empty(): CallerContext { - return new CallerContext(AztecAddress.ZERO, AztecAddress.ZERO, false); - } - - isEmpty() { - return this.msgSender.isZero() && this.storageContractAddress.isZero() && !this.isStaticCall; - } - - static from(fields: FieldsOf): CallerContext { - return new CallerContext(...CallerContext.getFields(fields)); - } - - static getFields(fields: FieldsOf) { - return [fields.msgSender, fields.storageContractAddress, fields.isStaticCall] as const; - } - - /** - * Serialize this as a buffer. - * @returns The buffer. - */ - toBuffer() { - return serializeToBuffer(...CallerContext.getFields(this)); - } - - /** - * 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 CallerContext( - new AztecAddress(reader.readBytes(32)), - new AztecAddress(reader.readBytes(32)), - reader.readBoolean(), - ); - } - - equals(callerContext: CallerContext) { - return ( - callerContext.msgSender.equals(this.msgSender) && - callerContext.storageContractAddress.equals(this.storageContractAddress) && - callerContext.isStaticCall === this.isStaticCall - ); - } -} diff --git a/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts b/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts index 4d7d3d665c07..91875b29a247 100644 --- a/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts +++ b/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts @@ -41,9 +41,9 @@ export class ContractStorageUpdateRequest { } /** - * Create PublicCallRequest from a fields dictionary. + * Create ContractStorageUpdateRequest from a fields dictionary. * @param fields - The dictionary. - * @returns A PublicCallRequest object. + * @returns A ContractStorageUpdateRequest object. */ static from(fields: FieldsOf): ContractStorageUpdateRequest { return new ContractStorageUpdateRequest(...ContractStorageUpdateRequest.getFields(fields)); diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 15dff650a62e..be0313852e24 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -1,8 +1,6 @@ export * from '@aztec/foundation/eth-address'; export * from './avm/avm.js'; export * from './call_context.js'; -export * from './call_request.js'; -export * from './caller_context.js'; export * from './client_ivc_proof.js'; export * from './complete_address.js'; export * from './content_commitment.js'; @@ -58,6 +56,7 @@ export * from './private_circuit_public_inputs.js'; export * from './proof.js'; export * from './public_call_request.js'; export * from './public_call_stack_item.js'; +export * from './public_call_stack_item_compressed.js'; export * from './public_circuit_public_inputs.js'; export * from './public_data_hint.js'; export * from './public_data_read_request.js'; 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 7fd67916f4c0..156e8a6a6ee4 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 @@ -11,12 +11,12 @@ import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; -import { CallRequest } from '../call_request.js'; import { ScopedL2ToL1Message } from '../l2_to_l1_message.js'; import { NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash } from '../log_hash.js'; import { ScopedNoteHash } from '../note_hash.js'; import { ScopedNullifier } from '../nullifier.js'; -import { ScopedPrivateCallRequest } from '../private_call_request.js'; +import { PrivateCallRequest } from '../private_call_request.js'; +import { PublicCallRequest } from '../public_call_request.js'; /** * Specific accumulated data structure for the final ordering private kernel circuit. It is included @@ -52,13 +52,13 @@ export class PrivateAccumulatedData { */ public unencryptedLogsHashes: Tuple, /** - * Current private call stack. + * Accumulated public call requests from all the previous kernel iterations. */ - public privateCallStack: Tuple, + public publicCallRequests: Tuple, /** - * Current public call stack. + * Current private call stack. */ - public publicCallStack: Tuple, + public privateCallStack: Tuple, ) {} toBuffer() { @@ -69,8 +69,8 @@ export class PrivateAccumulatedData { this.noteEncryptedLogsHashes, this.encryptedLogsHashes, this.unencryptedLogsHashes, + this.publicCallRequests, this.privateCallStack, - this.publicCallStack, ); } @@ -92,8 +92,8 @@ 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_PRIVATE_CALL_STACK_LENGTH_PER_TX, ScopedPrivateCallRequest), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest), + reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest), + reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, PrivateCallRequest), ); } @@ -114,8 +114,8 @@ 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_PRIVATE_CALL_STACK_LENGTH_PER_TX, ScopedPrivateCallRequest.empty), - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest.empty), + makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest.empty), + makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, PrivateCallRequest.empty), ); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts index d01fefe28ab7..14253da6f58d 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_call_data.ts @@ -1,9 +1,8 @@ import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; -import { FUNCTION_TREE_HEIGHT, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL } from '../../constants.gen.js'; -import { CallRequest } from '../call_request.js'; +import { FUNCTION_TREE_HEIGHT } from '../../constants.gen.js'; import { MembershipWitness } from '../membership_witness.js'; import { PrivateCallStackItem } from '../private_call_stack_item.js'; import { VerificationKeyAsFields } from '../verification_key.js'; @@ -17,14 +16,6 @@ export class PrivateCallData { * The call stack item currently being processed. */ public callStackItem: PrivateCallStackItem, - /** - * Other public call stack items to be processed. - */ - public publicCallStack: Tuple, - /** - * The public call request for the teardown function. - */ - public publicTeardownCallRequest: CallRequest, /** * The verification key for the function being invoked. */ @@ -63,8 +54,6 @@ export class PrivateCallData { static getFields(fields: FieldsOf) { return [ fields.callStackItem, - fields.publicCallStack, - fields.publicTeardownCallRequest, fields.vk, fields.contractClassArtifactHash, fields.contractClassPublicBytecodeCommitment, @@ -96,8 +85,6 @@ export class PrivateCallData { const reader = BufferReader.asReader(buffer); return new PrivateCallData( reader.readObject(PrivateCallStackItem), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, CallRequest), - reader.readObject(CallRequest), reader.readObject(VerificationKeyAsFields), reader.readObject(Fr), reader.readObject(Fr), 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 592b1fd65fa3..25d85d9031bf 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 @@ -2,7 +2,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { CallRequest } from '../call_request.js'; +import { PublicCallRequest } from '../public_call_request.js'; import { ValidationRequests } from '../validation_requests.js'; import { CombinedConstantData } from './combined_constant_data.js'; import { PrivateAccumulatedData } from './private_accumulated_data.js'; @@ -31,7 +31,7 @@ export class PrivateKernelCircuitPublicInputs { /** * The call request for the public teardown function */ - public publicTeardownCallRequest: CallRequest, + public publicTeardownCallRequest: PublicCallRequest, /** * The address of the fee payer for the transaction */ @@ -61,7 +61,7 @@ export class PrivateKernelCircuitPublicInputs { reader.readObject(ValidationRequests), reader.readObject(PrivateAccumulatedData), reader.readObject(CombinedConstantData), - reader.readObject(CallRequest), + reader.readObject(PublicCallRequest), reader.readObject(AztecAddress), ); } @@ -72,7 +72,7 @@ export class PrivateKernelCircuitPublicInputs { ValidationRequests.empty(), PrivateAccumulatedData.empty(), CombinedConstantData.empty(), - CallRequest.empty(), + PublicCallRequest.empty(), AztecAddress.ZERO, ); } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts index 75d863ed1861..1f43c69fff55 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts @@ -144,7 +144,7 @@ export class PrivateKernelResetCircuitPrivateInputs< ) {} isForPublic() { - return countAccumulatedItems(this.previousKernel.publicInputs.end.publicCallStack) > 0; + return countAccumulatedItems(this.previousKernel.publicInputs.end.publicCallRequests) > 0; } /** diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts index eacbf97e365f..a56454827956 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts @@ -16,7 +16,7 @@ export class PrivateKernelTailCircuitPrivateInputs { isForPublic() { return ( - countAccumulatedItems(this.previousKernel.publicInputs.end.publicCallStack) > 0 || + countAccumulatedItems(this.previousKernel.publicInputs.end.publicCallRequests) > 0 || !this.previousKernel.publicInputs.publicTeardownCallRequest.isEmpty() ); } 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 1c60ce004aaa..be511028dec1 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 @@ -1,12 +1,11 @@ -import { makeTuple } from '@aztec/foundation/array'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; -import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { padArrayEnd } from '@aztec/foundation/collection'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX } from '../../constants.gen.js'; import { countAccumulatedItems, mergeAccumulatedData } from '../../utils/index.js'; -import { CallRequest } from '../call_request.js'; import { PartialStateReference } from '../partial_state_reference.js'; +import { PublicCallRequest } from '../public_call_request.js'; import { RevertCode } from '../revert_code.js'; import { RollupValidationRequests } from '../rollup_validation_requests.js'; import { ValidationRequests } from '../validation_requests.js'; @@ -33,7 +32,7 @@ export class PartialPrivateTailPublicInputsForPublic { /** * Call request for the public teardown function. */ - public publicTeardownCallStack: Tuple, + public publicTeardownCallRequest: PublicCallRequest, ) {} getSize() { @@ -41,7 +40,7 @@ export class PartialPrivateTailPublicInputsForPublic { this.validationRequests.getSize() + this.endNonRevertibleData.getSize() + this.end.getSize() + - arraySerializedSizeOfNonEmpty(this.publicTeardownCallStack) + this.publicTeardownCallRequest.getSize() ); } @@ -54,7 +53,7 @@ export class PartialPrivateTailPublicInputsForPublic { } get needsTeardown() { - return !this.publicTeardownCallStack[0].isEmpty(); + return !this.publicTeardownCallRequest.isEmpty(); } static fromBuffer(buffer: Buffer | BufferReader): PartialPrivateTailPublicInputsForPublic { @@ -63,7 +62,7 @@ export class PartialPrivateTailPublicInputsForPublic { reader.readObject(ValidationRequests), reader.readObject(PublicAccumulatedData), reader.readObject(PublicAccumulatedData), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest), + reader.readObject(PublicCallRequest), ); } @@ -72,7 +71,7 @@ export class PartialPrivateTailPublicInputsForPublic { this.validationRequests, this.endNonRevertibleData, this.end, - this.publicTeardownCallStack, + this.publicTeardownCallRequest, ); } @@ -81,7 +80,7 @@ export class PartialPrivateTailPublicInputsForPublic { ValidationRequests.empty(), PublicAccumulatedData.empty(), PublicAccumulatedData.empty(), - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest.empty), + PublicCallRequest.empty(), ); } } @@ -165,7 +164,11 @@ export class PrivateKernelTailCircuitPublicInputs { this.forPublic.end, this.constants, this.revertCode, - this.forPublic.publicTeardownCallStack, + padArrayEnd( + [this.forPublic.publicTeardownCallRequest], + PublicCallRequest.empty(), + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + ), this.feePayer, ); } @@ -185,11 +188,36 @@ export class PrivateKernelTailCircuitPublicInputs { } numberOfPublicCallRequests() { - return this.forPublic - ? countAccumulatedItems(this.forPublic.endNonRevertibleData.publicCallStack) + - countAccumulatedItems(this.forPublic.end.publicCallStack) + - countAccumulatedItems(this.forPublic.publicTeardownCallStack) - : 0; + return ( + this.numberOfNonRevertiblePublicCallRequests() + + this.numberOfRevertiblePublicCallRequests() + + (this.hasTeardownPublicCallRequest() ? 1 : 0) + ); + } + + numberOfNonRevertiblePublicCallRequests() { + return this.forPublic ? countAccumulatedItems(this.forPublic.endNonRevertibleData.publicCallStack) : 0; + } + + numberOfRevertiblePublicCallRequests() { + return this.forPublic ? countAccumulatedItems(this.forPublic.end.publicCallStack) : 0; + } + + hasTeardownPublicCallRequest() { + return this.forPublic ? !this.forPublic.publicTeardownCallRequest.isEmpty() : false; + } + + getNonRevertiblePublicCallRequests() { + return this.forPublic ? this.forPublic.endNonRevertibleData.publicCallStack.filter(r => !r.isEmpty()) : []; + } + + getRevertiblePublicCallRequests() { + return this.forPublic ? this.forPublic.end.publicCallStack.filter(r => !r.isEmpty()) : []; + } + + getTeardownPublicCallRequest() { + const publicTeardownCallRequest = this.forPublic?.publicTeardownCallRequest; + return !publicTeardownCallRequest?.isEmpty() ? publicTeardownCallRequest : undefined; } getNonEmptyNoteHashes() { 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 1d18673b79f3..058d3483d2b8 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 @@ -15,11 +15,11 @@ import { MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; -import { CallRequest } from '../call_request.js'; import { Gas } from '../gas.js'; import { LogHash, ScopedLogHash } from '../log_hash.js'; import { NoteHash } from '../note_hash.js'; import { Nullifier } from '../nullifier.js'; +import { PublicCallRequest } from '../public_call_request.js'; import { PublicDataUpdateRequest } from '../public_data_update_request.js'; export class PublicAccumulatedData { @@ -61,7 +61,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, @@ -167,7 +167,7 @@ export class PublicAccumulatedData { reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, LogHash), 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, CallRequest), + reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest), reader.readObject(Gas), ); } @@ -182,7 +182,7 @@ export class PublicAccumulatedData { reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, LogHash), 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, CallRequest), + reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest), reader.readObject(Gas), ); } @@ -205,7 +205,7 @@ export class PublicAccumulatedData { makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, LogHash.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, CallRequest.empty), + makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest.empty), Gas.empty(), ); } diff --git a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts index c01d01eb8c52..fce9fffa392e 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts @@ -11,11 +11,11 @@ import { MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; -import { CallRequest } from '../call_request.js'; import { Gas } from '../gas.js'; import { LogHash, ScopedLogHash } from '../log_hash.js'; import { NoteHash } 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'; @@ -33,7 +33,7 @@ export class PublicAccumulatedDataBuilder { private encryptedLogsHashes: LogHash[] = []; private unencryptedLogsHashes: ScopedLogHash[] = []; private publicDataUpdateRequests: PublicDataUpdateRequest[] = []; - private publicCallStack: CallRequest[] = []; + private publicCallStack: PublicCallRequest[] = []; private gasUsed: Gas = Gas.empty(); pushNoteHash(newNoteHash: NoteHash) { @@ -106,12 +106,12 @@ export class PublicAccumulatedDataBuilder { return this; } - pushPublicCall(publicCall: CallRequest) { + pushPublicCall(publicCall: PublicCallRequest) { this.publicCallStack.push(publicCall); return this; } - withPublicCallStack(publicCallStack: CallRequest[]) { + withPublicCallStack(publicCallStack: PublicCallRequest[]) { this.publicCallStack = publicCallStack; return this; } @@ -134,7 +134,7 @@ export class PublicAccumulatedDataBuilder { PublicDataUpdateRequest.empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ), - padArrayEnd(this.publicCallStack, CallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX), + padArrayEnd(this.publicCallStack, PublicCallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX), this.gasUsed, ); } diff --git a/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts index 3afdf41d3c7c..3f15a2e59030 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts @@ -1,8 +1,6 @@ import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL } from '../../constants.gen.js'; -import { CallRequest } from '../call_request.js'; import { Proof } from '../proof.js'; import { PublicCallStackItem } from '../public_call_stack_item.js'; @@ -15,10 +13,6 @@ export class PublicCallData { * Call stack item being processed by the current iteration of the kernel. */ public readonly callStackItem: PublicCallStackItem, - /** - * Children call stack items. - */ - public readonly publicCallStack: Tuple, /** * Proof of the call stack item execution. */ @@ -30,19 +24,11 @@ export class PublicCallData { ) {} toBuffer() { - return serializeToBuffer(this.callStackItem, this.publicCallStack, this.proof, this.bytecodeHash); + return serializeToBuffer(this.callStackItem, this.proof, this.bytecodeHash); } static fromBuffer(buffer: BufferReader | Buffer) { const reader = BufferReader.asReader(buffer); - return new PublicCallData( - reader.readObject(PublicCallStackItem), - reader.readArray( - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - CallRequest, - ), - reader.readObject(Proof), - reader.readObject(Fr), - ); + return new PublicCallData(reader.readObject(PublicCallStackItem), reader.readObject(Proof), reader.readObject(Fr)); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts index f789606f5d0a..7997158441da 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts @@ -6,7 +6,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 { CallRequest } from '../call_request.js'; +import { PublicCallRequest } from '../public_call_request.js'; import { RevertCode } from '../revert_code.js'; import { ValidationRequests } from '../validation_requests.js'; import { CombinedConstantData } from './combined_constant_data.js'; @@ -41,7 +41,7 @@ export class PublicKernelCircuitPublicInputs { /** * The call request for the public teardown function */ - public publicTeardownCallStack: Tuple, + public publicTeardownCallStack: Tuple, /** * The address of the fee payer for the transaction */ @@ -97,7 +97,7 @@ export class PublicKernelCircuitPublicInputs { reader.readObject(PublicAccumulatedData), reader.readObject(CombinedConstantData), reader.readObject(RevertCode), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest), + reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest), reader.readObject(AztecAddress), ); } @@ -109,7 +109,7 @@ export class PublicKernelCircuitPublicInputs { PublicAccumulatedData.empty(), CombinedConstantData.empty(), RevertCode.OK, - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest.empty), + makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest.empty), AztecAddress.ZERO, ); } @@ -122,7 +122,7 @@ export class PublicKernelCircuitPublicInputs { PublicAccumulatedData.fromFields(reader), CombinedConstantData.fromFields(reader), RevertCode.fromField(reader.readField()), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest), + reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest), AztecAddress.fromFields(reader), ); } diff --git a/yarn-project/circuits.js/src/structs/private_call_request.ts b/yarn-project/circuits.js/src/structs/private_call_request.ts index a81b8d36fa74..880cf2b8dc4b 100644 --- a/yarn-project/circuits.js/src/structs/private_call_request.ts +++ b/yarn-project/circuits.js/src/structs/private_call_request.ts @@ -3,8 +3,6 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; import { CallContext } from './call_context.js'; -import { CallerContext } from './caller_context.js'; -import { FunctionData } from './function_data.js'; import { type PrivateCallStackItem } from './index.js'; export class PrivateCallRequest { @@ -12,15 +10,11 @@ export class PrivateCallRequest { /** * The address of the contract being called. */ - public target: AztecAddress, + public contractAddress: AztecAddress, /** * The call context of the call. */ public callContext: CallContext, - /** - * The function data of the call. - */ - public functionData: FunctionData, /** * The hash of the arguments of the call. */ @@ -29,10 +23,6 @@ export class PrivateCallRequest { * The hash of the return values of the call. */ public returnsHash: Fr, - /** - * The call context of the contract making the call. - */ - public callerContext: CallerContext, /** * The start counter of the call. */ @@ -45,12 +35,10 @@ export class PrivateCallRequest { toFields(): Fr[] { return serializeToFields([ - this.target, + this.contractAddress, this.callContext, - this.functionData, this.argsHash, this.returnsHash, - this.callerContext, this.startSideEffectCounter, this.endSideEffectCounter, ]); @@ -61,10 +49,8 @@ export class PrivateCallRequest { return new PrivateCallRequest( reader.readObject(AztecAddress), reader.readObject(CallContext), - reader.readObject(FunctionData), reader.readField(), reader.readField(), - reader.readObject(CallerContext), reader.readU32(), reader.readU32(), ); @@ -72,12 +58,10 @@ export class PrivateCallRequest { toBuffer() { return serializeToBuffer( - this.target, + this.contractAddress, this.callContext, - this.functionData, this.argsHash, this.returnsHash, - this.callerContext, this.startSideEffectCounter, this.endSideEffectCounter, ); @@ -88,10 +72,8 @@ export class PrivateCallRequest { return new PrivateCallRequest( reader.readObject(AztecAddress), reader.readObject(CallContext), - reader.readObject(FunctionData), Fr.fromBuffer(reader), Fr.fromBuffer(reader), - reader.readObject(CallerContext), reader.readNumber(), reader.readNumber(), ); @@ -99,52 +81,38 @@ export class PrivateCallRequest { isEmpty() { return ( - this.target.isZero() && + this.contractAddress.isZero() && this.callContext.isEmpty() && - this.functionData.isEmpty() && this.argsHash.isZero() && this.returnsHash.isZero() && - this.callerContext.isEmpty() && this.startSideEffectCounter === 0 && this.endSideEffectCounter === 0 ); } public static empty() { - return new PrivateCallRequest( - AztecAddress.ZERO, - CallContext.empty(), - FunctionData.empty(), - Fr.ZERO, - Fr.ZERO, - CallerContext.empty(), - 0, - 0, - ); + return new PrivateCallRequest(AztecAddress.ZERO, CallContext.empty(), Fr.ZERO, Fr.ZERO, 0, 0); } equals(callRequest: PrivateCallRequest) { return ( - callRequest.target.equals(this.target) && + callRequest.contractAddress.equals(this.contractAddress) && callRequest.callContext.equals(this.callContext) && - callRequest.functionData.equals(this.functionData) && callRequest.argsHash.equals(this.argsHash) && callRequest.returnsHash.equals(this.returnsHash) && - callRequest.callerContext.equals(this.callerContext) && callRequest.startSideEffectCounter === this.startSideEffectCounter && callRequest.endSideEffectCounter === this.endSideEffectCounter ); } toString() { - return `PrivateCallRequest(target: ${this.target}, callContext: ${this.callContext}, functionData: ${this.functionData}, argsHash: ${this.argsHash}, returnsHash: ${this.returnsHash}, callerContext: ${this.callerContext}, startSideEffectCounter: ${this.startSideEffectCounter}, endSideEffectCounter: ${this.endSideEffectCounter})`; + return `PrivateCallRequest(target: ${this.contractAddress}, callContext: ${this.callContext}, argsHash: ${this.argsHash}, returnsHash: ${this.returnsHash}, startSideEffectCounter: ${this.startSideEffectCounter}, endSideEffectCounter: ${this.endSideEffectCounter})`; } matchesStackItem(stackItem: PrivateCallStackItem) { return ( - stackItem.contractAddress.equals(this.target) && + stackItem.contractAddress.equals(this.contractAddress) && stackItem.publicInputs.callContext.equals(this.callContext) && - stackItem.functionData.equals(this.functionData) && stackItem.publicInputs.argsHash.equals(this.argsHash) && stackItem.publicInputs.returnsHash.equals(this.returnsHash) && stackItem.publicInputs.startSideEffectCounter.equals(new Fr(this.startSideEffectCounter)) && @@ -152,32 +120,3 @@ export class PrivateCallRequest { ); } } - -export class ScopedPrivateCallRequest { - constructor(public callRequest: PrivateCallRequest, public contractAddress: AztecAddress) {} - - toBuffer() { - return serializeToBuffer(this.callRequest, this.contractAddress); - } - - public static fromBuffer(buffer: Buffer | BufferReader) { - const reader = BufferReader.asReader(buffer); - return new ScopedPrivateCallRequest(reader.readObject(PrivateCallRequest), reader.readObject(AztecAddress)); - } - - isEmpty() { - return this.callRequest.isEmpty() && this.contractAddress.isZero(); - } - - public static empty() { - return new ScopedPrivateCallRequest(PrivateCallRequest.empty(), AztecAddress.ZERO); - } - - equals(callRequest: ScopedPrivateCallRequest) { - return callRequest.callRequest.equals(this.callRequest) && callRequest.contractAddress.equals(this.contractAddress); - } - - toString() { - return `ScopedPrivateCallRequest(callRequest: ${this.callRequest}, contractAddress: ${this.contractAddress})`; - } -} 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 e8acb0c239b8..9a1503f630ea 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 @@ -1,5 +1,4 @@ import { makeTuple } from '@aztec/foundation/array'; -import { isArrayEmpty } from '@aztec/foundation/collection'; import { pedersenHash } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { @@ -36,6 +35,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 { ReadRequest } from './read_request.js'; import { TxContext } from './tx_context.js'; @@ -98,11 +98,11 @@ export class PrivateCircuitPublicInputs { /** * Public call stack at the current kernel iteration. */ - public publicCallStackHashes: Tuple, + public publicCallRequests: Tuple, /** * Hash of the public teardown function. */ - public publicTeardownFunctionHash: Fr, + public publicTeardownCallRequest: PublicCallRequest, /** * New L2 to L1 messages created by the corresponding function call. */ @@ -173,8 +173,8 @@ 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, Fr), - reader.readObject(Fr), + reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicCallRequest), + reader.readObject(PublicCallRequest), reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), reader.readObject(Fr), @@ -201,8 +201,8 @@ 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.readFieldArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL), - reader.readField(), + reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicCallRequest), + reader.readObject(PublicCallRequest), reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), reader.readField(), @@ -232,8 +232,8 @@ 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, Fr.zero), - Fr.ZERO, + makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicCallRequest.empty), + PublicCallRequest.empty(), makeTuple(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, Fr.ZERO, @@ -246,7 +246,6 @@ export class PrivateCircuitPublicInputs { } isEmpty() { - const isZeroArray = (arr: { isZero: (...args: any[]) => boolean }[]) => isArrayEmpty(arr, item => item.isZero()); return ( this.callContext.isEmpty() && this.argsHash.isZero() && @@ -260,8 +259,8 @@ export class PrivateCircuitPublicInputs { isEmptyArray(this.noteHashes) && isEmptyArray(this.nullifiers) && isEmptyArray(this.privateCallRequests) && - isZeroArray(this.publicCallStackHashes) && - this.publicTeardownFunctionHash.isZero() && + isEmptyArray(this.publicCallRequests) && + this.publicTeardownCallRequest.isEmpty() && isEmptyArray(this.l2ToL1Msgs) && isEmptyArray(this.noteEncryptedLogsHashes) && isEmptyArray(this.encryptedLogsHashes) && @@ -290,8 +289,8 @@ export class PrivateCircuitPublicInputs { fields.noteHashes, fields.nullifiers, fields.privateCallRequests, - fields.publicCallStackHashes, - fields.publicTeardownFunctionHash, + fields.publicCallRequests, + fields.publicTeardownCallRequest, fields.l2ToL1Msgs, fields.startSideEffectCounter, fields.endSideEffectCounter, 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 59560628d12b..2d53efb37ead 100644 --- a/yarn-project/circuits.js/src/structs/public_call_request.ts +++ b/yarn-project/circuits.js/src/structs/public_call_request.ts @@ -1,51 +1,21 @@ -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type 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 { computeVarArgsHash } from '../hash/hash.js'; -import { CallContext } from './call_context.js'; -import { CallRequest } from './call_request.js'; -import { CallerContext } from './caller_context.js'; -import { FunctionData, FunctionSelector } from './index.js'; -import { PublicCallStackItem } from './public_call_stack_item.js'; -import { PublicCircuitPublicInputs } from './public_circuit_public_inputs.js'; -import { Vector } from './shared.js'; +import { PublicCallStackItemCompressed } from './public_call_stack_item_compressed.js'; /** - * Represents a request to call a public function from a private function. Serialization is - * equivalent to a public call stack item, but without the result fields. + * Represents a request to call a public function. */ export class PublicCallRequest { constructor( + public item: PublicCallStackItemCompressed, /** - *Address of the contract on which the function is invoked. + * The counter for this call request. */ - public contractAddress: AztecAddress, - /** - * Data identifying the function being called. - */ - public functionSelector: FunctionSelector, - /** - * Context of the public call. - * TODO(#3417): Check if all fields of CallContext are actually needed. - */ - public callContext: CallContext, - /** - * Context of the public call. - * TODO(#3417): Check if all fields of CallContext are actually needed. - */ - public parentCallContext: CallContext, - /** - * The start side effect counter for this call request. - */ - public sideEffectCounter: number, - /** - * Function arguments. - */ - public args: Fr[], + public counter: number, ) {} getSize() { @@ -57,14 +27,7 @@ export class PublicCallRequest { * @returns The buffer. */ toBuffer() { - return serializeToBuffer( - this.contractAddress, - this.functionSelector, - this.callContext, - this.parentCallContext, - this.sideEffectCounter, - new Vector(this.args), - ); + return serializeToBuffer(this.item, this.counter); } /** @@ -74,14 +37,7 @@ export class PublicCallRequest { */ static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new PublicCallRequest( - new AztecAddress(reader.readBytes(32)), - FunctionSelector.fromBuffer(reader), - CallContext.fromBuffer(reader), - CallContext.fromBuffer(reader), - reader.readNumber(), - reader.readVector(Fr), - ); + return new PublicCallRequest(PublicCallStackItemCompressed.fromBuffer(reader), reader.readNumber()); } /** @@ -99,92 +55,30 @@ export class PublicCallRequest { * @returns The array. */ static getFields(fields: FieldsOf) { - return [ - fields.contractAddress, - fields.functionSelector, - fields.callContext, - fields.parentCallContext, - fields.sideEffectCounter, - fields.args, - ] as const; + return [fields.item, fields.counter] as const; } - /** - * Creates a new PublicCallStackItem by populating with zeroes all fields related to result in the public circuit output. - * @returns A PublicCallStackItem instance with the same contract address, function data, call context, and args. - */ - toPublicCallStackItem() { - const publicInputs = PublicCircuitPublicInputs.empty(); - publicInputs.callContext = this.callContext; - publicInputs.argsHash = this.getArgsHash(); - return new PublicCallStackItem( - this.contractAddress, - new FunctionData(this.functionSelector, false), - publicInputs, - true, - ); + toFields(): Fr[] { + return serializeToFields([this.item, this.counter]); } - /** - * Creates a new CallRequest with values of the calling contract. - * @returns A CallRequest instance with the contract address, caller context, and the hash of the call stack item. - */ - toCallRequest() { - const item = this.toPublicCallStackItem(); - const callerContext = this.callContext.isDelegateCall - ? new CallerContext( - this.parentCallContext.msgSender, - this.parentCallContext.storageContractAddress, - this.parentCallContext.isStaticCall, - ) - : CallerContext.empty(); - return new CallRequest( - item.getCompressed().hash(), - this.parentCallContext.storageContractAddress, - callerContext, - new Fr(this.sideEffectCounter), - Fr.ZERO, - ); - } - - /** - * Returns the hash of the arguments for this request. - * @returns Hash of the arguments for this request. - */ - getArgsHash() { - return computeVarArgsHash(this.args); + static fromFields(fields: Fr[] | FieldReader): PublicCallRequest { + const reader = FieldReader.asReader(fields); + return new PublicCallRequest(PublicCallStackItemCompressed.fromFields(reader), reader.readU32()); } static empty() { - return new PublicCallRequest( - AztecAddress.ZERO, - FunctionSelector.empty(), - CallContext.empty(), - CallContext.empty(), - 0, - [], - ); + return new PublicCallRequest(PublicCallStackItemCompressed.empty(), 0); } isEmpty(): boolean { - return ( - this.contractAddress.isZero() && - this.functionSelector.isEmpty() && - this.callContext.isEmpty() && - this.parentCallContext.isEmpty() && - this.sideEffectCounter == 0 && - this.args.length === 0 - ); + return this.item.isEmpty() && this.counter == 0; } [inspect.custom]() { return `PublicCallRequest { - contractAddress: ${this.contractAddress} - functionSelector: ${this.functionSelector} - callContext: ${this.callContext} - parentCallContext: ${this.parentCallContext} - sideEffectCounter: ${this.sideEffectCounter} - args: ${this.args} + item: ${this.item} + counter: ${this.counter} }`; } } diff --git a/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts b/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts index 3f966b416a94..b8e6c4cc1b6d 100644 --- a/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts +++ b/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts @@ -1,67 +1,13 @@ import { randomInt } from '@aztec/foundation/crypto'; -import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; import { makePublicCallStackItem } from '../tests/factories.js'; -import { AztecAddress, Fr, FunctionData, FunctionSelector } from './index.js'; -import { NoteHash } from './note_hash.js'; import { PublicCallStackItem } from './public_call_stack_item.js'; describe('PublicCallStackItem', () => { - setupCustomSnapshotSerializers(expect); it('serializes to buffer and deserializes it back', () => { const expected = makePublicCallStackItem(randomInt(1000)); const buffer = expected.toBuffer(); const res = PublicCallStackItem.fromBuffer(buffer); expect(res).toEqual(expected); }); - - it('computes hash', () => { - const seed = 9870243; - const item = makePublicCallStackItem(seed); - const hash = item.getCompressed().hash(); - expect(hash).toMatchSnapshot(); - }); - - it('computes empty item hash', () => { - const item = PublicCallStackItem.empty(); - const hash = item.getCompressed().hash(); - expect(hash).toMatchSnapshot(); - }); - - it('Computes a callstack item request hash', () => { - const callStack = PublicCallStackItem.empty(); - - callStack.contractAddress = AztecAddress.fromField(new Fr(1)); - callStack.functionData = new FunctionData(new FunctionSelector(2), /*isPrivate=*/ false); - callStack.isExecutionRequest = true; - callStack.publicInputs.noteHashes[0] = new NoteHash(new Fr(1), 0); - - const hash = callStack.getCompressed().hash(); - expect(hash.toString()).toMatchSnapshot(); - - // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data - updateInlineTestData( - 'noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr', - 'test_data_call_stack_item_request_hash', - hash.toString(), - ); - }); - - it('Computes a callstack item hash', () => { - const callStack = PublicCallStackItem.empty(); - - callStack.contractAddress = AztecAddress.fromField(new Fr(1)); - callStack.functionData = new FunctionData(new FunctionSelector(2), /*isPrivate=*/ false); - callStack.publicInputs.noteHashes[0] = new NoteHash(new Fr(1), 0); - - const hash = callStack.getCompressed().hash(); - expect(hash.toString()).toMatchSnapshot(); - - // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data - updateInlineTestData( - 'noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr', - 'test_data_call_stack_item_hash', - hash.toString(), - ); - }); }); diff --git a/yarn-project/circuits.js/src/structs/public_call_stack_item.ts b/yarn-project/circuits.js/src/structs/public_call_stack_item.ts index 17010b247df3..c05e9415259e 100644 --- a/yarn-project/circuits.js/src/structs/public_call_stack_item.ts +++ b/yarn-project/circuits.js/src/structs/public_call_stack_item.ts @@ -1,13 +1,9 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr } from '@aztec/foundation/fields'; +import { type Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; -import { type CallContext } from './call_context.js'; -import { CallRequest } from './call_request.js'; -import { CallerContext } from './caller_context.js'; import { FunctionData } from './function_data.js'; -import { PublicCallStackItemCompressed } from './public_call_stack_item_compressed.js'; import { PublicCircuitPublicInputs } from './public_circuit_public_inputs.js'; /** @@ -83,57 +79,4 @@ export class PublicCallStackItem { isEmpty() { return this.contractAddress.isZero() && this.functionData.isEmpty() && this.publicInputs.isEmpty(); } - - getCompressed(): PublicCallStackItemCompressed { - let publicInputsToHash = this.publicInputs; - if (this.isExecutionRequest) { - // An execution request (such as an enqueued call from private) is hashed with - // only the publicInput members present in a PublicCallRequest. - // This allows us to check that the request (which is created/hashed before - // side-effects and output info are unknown for public calls) matches the call - // being processed by a kernel iteration. - // WARNING: This subset of publicInputs that is set here must align with - // `parse_public_call_stack_item_from_oracle` in enqueue_public_function_call.nr - // and `PublicCallStackItem::as_execution_request()` in public_call_stack_item.ts - const { callContext, argsHash } = this.publicInputs; - publicInputsToHash = PublicCircuitPublicInputs.empty(); - publicInputsToHash.callContext = callContext; - publicInputsToHash.argsHash = argsHash; - } - - return new PublicCallStackItemCompressed( - this.contractAddress, - publicInputsToHash.callContext, - this.functionData, - publicInputsToHash.argsHash, - publicInputsToHash.returnsHash, - publicInputsToHash.revertCode, - publicInputsToHash.startGasLeft, - publicInputsToHash.endGasLeft, - ); - } - - /** - * Creates a new CallRequest with values of the calling contract. - * @returns A CallRequest instance with the contract address, caller context, and the hash of the call stack item. - */ - public toCallRequest(parentCallContext: CallContext) { - if (this.isEmpty()) { - return CallRequest.empty(); - } - - const currentCallContext = this.publicInputs.callContext; - const callerContext = currentCallContext.isDelegateCall - ? new CallerContext( - parentCallContext.msgSender, - parentCallContext.storageContractAddress, - parentCallContext.isStaticCall, - ) - : CallerContext.empty(); - // todo: populate side effect counters correctly - - const hash = this.getCompressed().hash(); - - return new CallRequest(hash, parentCallContext.storageContractAddress, callerContext, Fr.ZERO, Fr.ZERO); - } } diff --git a/yarn-project/circuits.js/src/structs/public_call_stack_item_compressed.ts b/yarn-project/circuits.js/src/structs/public_call_stack_item_compressed.ts index 49f6181b8590..4fa46ed9fca3 100644 --- a/yarn-project/circuits.js/src/structs/public_call_stack_item_compressed.ts +++ b/yarn-project/circuits.js/src/structs/public_call_stack_item_compressed.ts @@ -6,7 +6,6 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { GeneratorIndex, PUBLIC_CALL_STACK_ITEM_COMPRESSED_LENGTH } from '../constants.gen.js'; import { CallContext } from './call_context.js'; -import { FunctionData } from './function_data.js'; import { Gas } from './gas.js'; import { RevertCode } from './revert_code.js'; @@ -17,7 +16,6 @@ export class PublicCallStackItemCompressed { constructor( public contractAddress: AztecAddress, public callContext: CallContext, - public functionData: FunctionData, public argsHash: Fr, public returnsHash: Fr, public revertCode: RevertCode, @@ -31,7 +29,6 @@ export class PublicCallStackItemCompressed { return [ fields.contractAddress, fields.callContext, - fields.functionData, fields.argsHash, fields.returnsHash, fields.revertCode, @@ -64,7 +61,6 @@ export class PublicCallStackItemCompressed { return new PublicCallStackItemCompressed( reader.readObject(AztecAddress), reader.readObject(CallContext), - reader.readObject(FunctionData), reader.readObject(Fr), reader.readObject(Fr), reader.readObject(RevertCode), @@ -79,7 +75,6 @@ export class PublicCallStackItemCompressed { return new PublicCallStackItemCompressed( AztecAddress.fromFields(reader), CallContext.fromFields(reader), - FunctionData.fromFields(reader), reader.readField(), reader.readField(), RevertCode.fromFields(reader), @@ -96,7 +91,6 @@ export class PublicCallStackItemCompressed { return new PublicCallStackItemCompressed( AztecAddress.ZERO, CallContext.empty(), - FunctionData.empty({ isPrivate: false }), Fr.ZERO, Fr.ZERO, RevertCode.OK, @@ -109,10 +103,9 @@ export class PublicCallStackItemCompressed { return ( this.contractAddress.isZero() && this.callContext.isEmpty() && - this.functionData.isEmpty() && this.argsHash.isEmpty() && this.returnsHash.isEmpty() && - this.revertCode === RevertCode.OK && + this.revertCode.equals(RevertCode.OK) && this.startGasLeft.isEmpty() && this.endGasLeft.isEmpty() ); 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 efffffd65471..a4c94c07aa83 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 @@ -1,6 +1,5 @@ import { makeTuple } from '@aztec/foundation/array'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { isArrayEmpty } from '@aztec/foundation/collection'; import { pedersenHash } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { @@ -38,6 +37,7 @@ import { L2ToL1Message } from './l2_to_l1_message.js'; import { LogHash } from './log_hash.js'; import { NoteHash } from './note_hash.js'; import { Nullifier } from './nullifier.js'; +import { PublicCallRequest } from './public_call_request.js'; import { ReadRequest } from './read_request.js'; import { RevertCode } from './revert_code.js'; @@ -91,7 +91,7 @@ export class PublicCircuitPublicInputs { /** * Public call stack of the current kernel iteration. */ - public publicCallStackHashes: Tuple, + public publicCallRequests: Tuple, /** * New note hashes created within a public execution call */ @@ -168,7 +168,7 @@ export class PublicCircuitPublicInputs { makeTuple(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, ReadRequest.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, Fr.zero), + makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicCallRequest.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), @@ -186,7 +186,6 @@ export class PublicCircuitPublicInputs { } isEmpty() { - const isFrArrayEmpty = (arr: Fr[]) => isArrayEmpty(arr, item => item.isZero()); return ( this.callContext.isEmpty() && this.argsHash.isZero() && @@ -196,7 +195,7 @@ export class PublicCircuitPublicInputs { isEmptyArray(this.l1ToL2MsgReadRequests) && isEmptyArray(this.contractStorageUpdateRequests) && isEmptyArray(this.contractStorageReads) && - isFrArrayEmpty(this.publicCallStackHashes) && + isEmptyArray(this.publicCallRequests) && isEmptyArray(this.noteHashes) && isEmptyArray(this.nullifiers) && isEmptyArray(this.l2ToL1Msgs) && @@ -229,7 +228,7 @@ export class PublicCircuitPublicInputs { fields.l1ToL2MsgReadRequests, fields.contractStorageUpdateRequests, fields.contractStorageReads, - fields.publicCallStackHashes, + fields.publicCallRequests, fields.noteHashes, fields.nullifiers, fields.l2ToL1Msgs, @@ -281,7 +280,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, ReadRequest), 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, Fr), + reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicCallRequest), 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), @@ -311,7 +310,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, ReadRequest), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest), reader.readArray(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead), - reader.readFieldArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL), + reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PublicCallRequest), 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/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 414032008c8c..c70f31f334c2 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -14,7 +14,6 @@ import { import { SchnorrSignature } from '../barretenberg/index.js'; import { ARCHIVE_HEIGHT, - ARGS_LENGTH, AppendOnlyTreeSnapshot, AvmCircuitInputs, AvmContractInstanceHint, @@ -25,8 +24,6 @@ import { BaseParityInputs, BaseRollupInputs, CallContext, - CallRequest, - CallerContext, ClientIvcProof, CombineHints, CombinedAccumulatedData, @@ -107,6 +104,7 @@ import { PublicCallData, PublicCallRequest, PublicCallStackItem, + PublicCallStackItemCompressed, PublicCircuitPublicInputs, PublicDataHint, PublicDataRead, @@ -391,7 +389,7 @@ export function makePublicAccumulatedData(seed = 1, full = false): PublicAccumul seed + 0xd00, PublicDataUpdateRequest.empty, ), - tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makeCallRequest, seed + 0x500, CallRequest.empty), + tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makePublicCallRequest, seed + 0x500, PublicCallRequest.empty), makeGas(seed + 0x600), ); } @@ -441,7 +439,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, fr, seed + 0x600, Fr.zero), + tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, makePublicCallRequest, seed + 0x600, PublicCallRequest.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), @@ -474,7 +472,7 @@ export function makePublicKernelCircuitPublicInputs( makePublicAccumulatedData(seed, fullAccumulatedData), makeConstantData(seed + 0x100), RevertCode.OK, - tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makeCallRequest, seed + 0x600, CallRequest.empty), + tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makePublicCallRequest, seed + 0x600, PublicCallRequest.empty), makeAztecAddress(seed + 0x700), ); } @@ -493,7 +491,7 @@ export function makePrivateKernelTailCircuitPublicInputs( ValidationRequests.empty(), makePublicAccumulatedData(seed + 0x100, false), makePublicAccumulatedData(seed + 0x200, false), - makeHalfFullTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makeCallRequest, seed + 0x400, CallRequest.empty), + makePublicCallRequest(seed + 0x400), ) : undefined; const forRollup = !isForPublic @@ -527,25 +525,6 @@ export function makeKernelCircuitPublicInputs(seed = 1, fullAccumulatedData = tr ); } -/** - * Creates a public call request for testing. - * @param seed - The seed. - * @returns Public call request. - */ -export function makePublicCallRequest(seed = 1): PublicCallRequest { - const childCallContext = makeCallContext(seed + 0x2, { storageContractAddress: makeAztecAddress(seed) }); - const parentCallContext = makeCallContext(seed + 0x3, { storageContractAddress: childCallContext.msgSender }); - - return new PublicCallRequest( - makeAztecAddress(seed), - makeSelector(seed + 0x1), - childCallContext, - parentCallContext, - seed + 0x4, - makeTuple(ARGS_LENGTH, fr, seed + 0x10), - ); -} - /** * Creates arbitrary/mocked membership witness where the sibling paths is an array of fields in an ascending order starting from `start`. * @param size - The size of the membership witness. @@ -631,37 +610,34 @@ export function makeProof(seed = 1) { return new Proof(Buffer.alloc(16, seed), 0); } -/** - * Makes arbitrary call stack item. - * @param seed - The seed to use for generating the call stack item. - * @returns A call stack item. - */ -export function makeCallerContext(seed = 1): CallerContext { - return new CallerContext(makeAztecAddress(seed), makeAztecAddress(seed + 0x1), false); -} - -/** - * Makes arbitrary call stack item. - * @param seed - The seed to use for generating the call stack item. - * @returns A call stack item. - */ -export function makeCallRequest(seed = 1): CallRequest { - return new CallRequest(fr(seed), makeAztecAddress(seed + 0x1), makeCallerContext(seed + 0x2), fr(0), fr(0)); -} - function makePrivateCallRequest(seed = 1): PrivateCallRequest { return new PrivateCallRequest( makeAztecAddress(seed), makeCallContext(seed + 0x1), - new FunctionData(makeSelector(seed + 0x2), /*isPrivate=*/ true), fr(seed + 0x3), fr(seed + 0x4), - makeCallerContext(seed + 0x5), seed + 0x10, seed + 0x11, ); } +function makePublicCallStackItemCompressed(seed = 1, isPublicExecutionResult: boolean): PublicCallStackItemCompressed { + const callContext = makeCallContext(seed); + return new PublicCallStackItemCompressed( + callContext.storageContractAddress, + callContext, + fr(seed + 0x20), + isPublicExecutionResult ? fr(seed + 0x30) : fr(0), + RevertCode.OK, + isPublicExecutionResult ? makeGas(seed + 0x40) : Gas.empty(), + isPublicExecutionResult ? makeGas(seed + 0x50) : Gas.empty(), + ); +} + +export function makePublicCallRequest(seed = 1, isPublicExecutionResult = false): PublicCallRequest { + return new PublicCallRequest(makePublicCallStackItemCompressed(seed, isPublicExecutionResult), seed + 0x60); +} + /** * Makes arbitrary public call stack item. * @param seed - The seed to use for generating the public call stack item. @@ -685,12 +661,7 @@ export function makePublicCallStackItem(seed = 1, full = false): PublicCallStack * @returns A public call data. */ export function makePublicCallData(seed = 1, full = false): PublicCallData { - const publicCallData = new PublicCallData( - makePublicCallStackItem(seed, full), - makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, makeCallRequest, seed + 0x300), - makeProof(), - fr(seed + 1), - ); + const publicCallData = new PublicCallData(makePublicCallStackItem(seed, full), makeProof(), fr(seed + 1)); return publicCallData; } @@ -746,35 +717,6 @@ export function makePublicKernelTailCircuitPrivateInputs(seed = 1): PublicKernel ); } -/** - * Makes arbitrary public kernel private inputs. - * @param seed - The seed to use for generating the public kernel inputs. - * @param tweak - An optional function to tweak the output before computing hashes. - * @returns Public kernel inputs. - */ -export function makePublicKernelInputsWithTweak( - seed = 1, - tweak?: (publicKernelInputs: PublicKernelCircuitPrivateInputs) => void, -): PublicKernelCircuitPrivateInputs { - const kernelCircuitPublicInputs = makePublicKernelCircuitPublicInputs(seed, false); - const previousKernel = makePublicKernelData(seed, kernelCircuitPublicInputs); - const publicCall = makePublicCallData(seed + 0x1000); - const publicKernelInputs = new PublicKernelCircuitPrivateInputs(previousKernel, ClientIvcProof.empty(), publicCall); - if (tweak) { - tweak(publicKernelInputs); - } - // Set the call stack item for this circuit iteration at the top of the call stack - publicKernelInputs.previousKernel.publicInputs.end.publicCallStack[MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX - 1] = - new CallRequest( - publicCall.callStackItem.getCompressed().hash(), - publicCall.callStackItem.publicInputs.callContext.msgSender, - makeCallerContext(seed + 0x100), - Fr.ZERO, - Fr.ZERO, - ); - return publicKernelInputs; -} - /** * Makes arbitrary tx request. * @param seed - The seed to use for generating the tx request. @@ -824,8 +766,8 @@ 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), - publicCallStackHashes: makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, fr, seed + 0x700), - publicTeardownFunctionHash: fr(seed + 0x800), + publicCallRequests: makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, makePublicCallRequest, seed + 0x700), + publicTeardownCallRequest: makePublicCallRequest(seed + 0x800), l2ToL1Msgs: makeTuple(MAX_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x800), startSideEffectCounter: fr(seed + 0x849), endSideEffectCounter: fr(seed + 0x850), 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 949f64d8481b..22b256ec4a20 100644 --- a/yarn-project/end-to-end/src/e2e_ordering.test.ts +++ b/yarn-project/end-to-end/src/e2e_ordering.test.ts @@ -69,8 +69,9 @@ describe('e2e_ordering', () => { expect(enqueuedPublicCalls.length).toEqual(2); // The call stack items in the output of the kernel proof match the tx enqueuedPublicFunctionCalls - const callStackItems = await Promise.all(enqueuedPublicCalls.map(c => c.toCallRequest())); - expect(tx.data.forPublic!.end.publicCallStack.slice(0, 2)).toEqual(callStackItems); + enqueuedPublicCalls.forEach((c, i) => { + expect(c.isForCallRequest(tx.data.forPublic!.end.publicCallStack[i])).toBe(true); + }); // The enqueued public calls are in the expected order based on the argument they set (stack is reversed!) expect(enqueuedPublicCalls.map(c => c.args[0].toBigInt())).toEqual([...expectedOrder].reverse()); 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 7bc509a2562b..c5e787298f5c 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -5,8 +5,6 @@ import { type BaseParityInputs, type BaseRollupInputs, CallContext, - CallRequest, - CallerContext, type CombineHints, CombinedAccumulatedData, CombinedConstantData, @@ -87,7 +85,9 @@ import { PrivateKernelTailCircuitPublicInputs, PublicAccumulatedData, type PublicCallData, + PublicCallRequest, type PublicCallStackItem, + PublicCallStackItemCompressed, type PublicCircuitPublicInputs, type PublicDataHint, PublicDataRead, @@ -115,7 +115,6 @@ import { ScopedLogHash, ScopedNoteHash, ScopedNullifier, - ScopedPrivateCallRequest, ScopedReadRequest, type SettledReadHint, type StateDiffHints, @@ -134,8 +133,6 @@ import type { BaseParityInputs as BaseParityInputsNoir, BaseRollupInputs as BaseRollupInputsNoir, CallContext as CallContextNoir, - CallRequest as CallRequestNoir, - CallerContext as CallerContextNoir, CombineHints as CombineHintsNoir, CombinedAccumulatedData as CombinedAccumulatedDataNoir, CombinedConstantData as CombinedConstantDataNoir, @@ -200,6 +197,8 @@ import type { PrivateKernelTailToPublicCircuitPrivateInputs as PrivateKernelTailToPublicCircuitPrivateInputsNoir, PublicAccumulatedData as PublicAccumulatedDataNoir, PublicCallData as PublicCallDataNoir, + PublicCallRequest as PublicCallRequestNoir, + PublicCallStackItemCompressed as PublicCallStackItemCompressedNoir, PublicCallStackItem as PublicCallStackItemNoir, PublicCircuitPublicInputs as PublicCircuitPublicInputsNoir, PublicDataHint as PublicDataHintNoir, @@ -225,7 +224,6 @@ import type { ScopedLogHash as ScopedLogHashNoir, ScopedNoteHash as ScopedNoteHashNoir, ScopedNullifier as ScopedNullifierNoir, - ScopedPrivateCallRequest as ScopedPrivateCallRequestNoir, ScopedReadRequest as ScopedReadRequestNoir, StateDiffHints as StateDiffHintsNoir, StateReference as StateReferenceNoir, @@ -503,40 +501,12 @@ export function mapGasSettingsToNoir(gasSettings: GasSettings): GasSettingsNoir }; } -/** - * Maps a caller context to a noir caller context. - * @param callContext - The caller context. - * @returns The noir caller context. - */ -export function mapCallerContextFromNoir(callerContext: CallerContextNoir): CallerContext { - return new CallerContext( - mapAztecAddressFromNoir(callerContext.msg_sender), - mapAztecAddressFromNoir(callerContext.storage_contract_address), - callerContext.is_static_call, - ); -} - -/** - * Maps a caller context to a noir caller context. - * @param callContext - The caller context. - * @returns The noir caller context. - */ -export function mapCallerContextToNoir(callerContext: CallerContext): CallerContextNoir { - return { - msg_sender: mapAztecAddressToNoir(callerContext.msgSender), - storage_contract_address: mapAztecAddressToNoir(callerContext.storageContractAddress), - is_static_call: callerContext.isStaticCall, - }; -} - function mapPrivateCallRequestFromNoir(callRequest: PrivateCallRequestNoir) { return new PrivateCallRequest( - mapAztecAddressFromNoir(callRequest.target), + mapAztecAddressFromNoir(callRequest.contract_address), mapCallContextFromNoir(callRequest.call_context), - mapFunctionDataFromNoir(callRequest.function_data), mapFieldFromNoir(callRequest.args_hash), mapFieldFromNoir(callRequest.returns_hash), - mapCallerContextFromNoir(callRequest.caller_context), mapNumberFromNoir(callRequest.start_side_effect_counter), mapNumberFromNoir(callRequest.end_side_effect_counter), ); @@ -544,28 +514,38 @@ function mapPrivateCallRequestFromNoir(callRequest: PrivateCallRequestNoir) { function mapPrivateCallRequestToNoir(callRequest: PrivateCallRequest): PrivateCallRequestNoir { return { - target: mapAztecAddressToNoir(callRequest.target), + contract_address: mapAztecAddressToNoir(callRequest.contractAddress), call_context: mapCallContextToNoir(callRequest.callContext), - function_data: mapFunctionDataToNoir(callRequest.functionData), args_hash: mapFieldToNoir(callRequest.argsHash), returns_hash: mapFieldToNoir(callRequest.returnsHash), - caller_context: mapCallerContextToNoir(callRequest.callerContext), start_side_effect_counter: mapNumberToNoir(callRequest.startSideEffectCounter), end_side_effect_counter: mapNumberToNoir(callRequest.endSideEffectCounter), }; } -function mapScopedPrivateCallRequestFromNoir(callRequest: ScopedPrivateCallRequestNoir) { - return new ScopedPrivateCallRequest( - mapPrivateCallRequestFromNoir(callRequest.call_request), - mapAztecAddressFromNoir(callRequest.contract_address), +function mapPublicCallStackItemCompressedFromNoir(data: PublicCallStackItemCompressedNoir) { + return new PublicCallStackItemCompressed( + mapAztecAddressFromNoir(data.contract_address), + mapCallContextFromNoir(data.call_context), + mapFieldFromNoir(data.args_hash), + mapFieldFromNoir(data.returns_hash), + mapRevertCodeFromNoir(data.revert_code), + mapGasFromNoir(data.start_gas_left), + mapGasFromNoir(data.end_gas_left), ); } -function mapScopedPrivateCallRequestToNoir(callRequest: ScopedPrivateCallRequest): ScopedPrivateCallRequestNoir { +function mapPublicCallStackItemCompressedToNoir( + data: PublicCallStackItemCompressed, +): PublicCallStackItemCompressedNoir { return { - call_request: mapPrivateCallRequestToNoir(callRequest.callRequest), - contract_address: mapAztecAddressToNoir(callRequest.contractAddress), + contract_address: mapAztecAddressToNoir(data.contractAddress), + call_context: mapCallContextToNoir(data.callContext), + args_hash: mapFieldToNoir(data.argsHash), + returns_hash: mapFieldToNoir(data.returnsHash), + revert_code: mapRevertCodeToNoir(data.revertCode), + start_gas_left: mapGasToNoir(data.startGasLeft), + end_gas_left: mapGasToNoir(data.endGasLeft), }; } @@ -574,13 +554,10 @@ function mapScopedPrivateCallRequestToNoir(callRequest: ScopedPrivateCallRequest * @param callRequest - The noir call request. * @returns The call request. */ -export function mapCallRequestFromNoir(callRequest: CallRequestNoir): CallRequest { - return new CallRequest( - mapFieldFromNoir(callRequest.hash), - mapAztecAddressFromNoir(callRequest.caller_contract_address), - mapCallerContextFromNoir(callRequest.caller_context), - mapFieldFromNoir(callRequest.start_side_effect_counter), - mapFieldFromNoir(callRequest.end_side_effect_counter), +function mapPublicCallRequestFromNoir(request: PublicCallRequestNoir) { + return new PublicCallRequest( + mapPublicCallStackItemCompressedFromNoir(request.item), + mapNumberFromNoir(request.counter), ); } @@ -589,13 +566,10 @@ export function mapCallRequestFromNoir(callRequest: CallRequestNoir): CallReques * @param privateCallStackItem - The call stack item. * @returns The noir call stack item. */ -export function mapCallRequestToNoir(callRequest: CallRequest): CallRequestNoir { +export function mapPublicCallRequestToNoir(request: PublicCallRequest): PublicCallRequestNoir { return { - hash: mapFieldToNoir(callRequest.hash), - caller_contract_address: mapAztecAddressToNoir(callRequest.callerContractAddress), - caller_context: mapCallerContextToNoir(callRequest.callerContext), - start_side_effect_counter: mapFieldToNoir(callRequest.startSideEffectCounter), - end_side_effect_counter: mapFieldToNoir(callRequest.endSideEffectCounter), + item: mapPublicCallStackItemCompressedToNoir(request.item), + counter: mapNumberToNoir(request.counter), }; } @@ -938,8 +912,8 @@ export function mapPrivateCircuitPublicInputsToNoir( note_hashes: mapTuple(privateCircuitPublicInputs.noteHashes, mapNoteHashToNoir), nullifiers: mapTuple(privateCircuitPublicInputs.nullifiers, mapNullifierToNoir), private_call_requests: mapTuple(privateCircuitPublicInputs.privateCallRequests, mapPrivateCallRequestToNoir), - public_call_stack_hashes: mapTuple(privateCircuitPublicInputs.publicCallStackHashes, mapFieldToNoir), - public_teardown_function_hash: mapFieldToNoir(privateCircuitPublicInputs.publicTeardownFunctionHash), + public_call_requests: mapTuple(privateCircuitPublicInputs.publicCallRequests, mapPublicCallRequestToNoir), + public_teardown_call_request: mapPublicCallRequestToNoir(privateCircuitPublicInputs.publicTeardownCallRequest), l2_to_l1_msgs: mapTuple(privateCircuitPublicInputs.l2ToL1Msgs, mapL2ToL1MessageToNoir), start_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.startSideEffectCounter), end_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.endSideEffectCounter), @@ -974,8 +948,6 @@ export function mapPrivateCallStackItemToNoir(privateCallStackItem: PrivateCallS export function mapPrivateCallDataToNoir(privateCallData: PrivateCallData): PrivateCallDataNoir { return { call_stack_item: mapPrivateCallStackItemToNoir(privateCallData.callStackItem), - public_call_stack: mapTuple(privateCallData.publicCallStack, mapCallRequestToNoir), - public_teardown_call_request: mapCallRequestToNoir(privateCallData.publicTeardownCallRequest), vk: mapVerificationKeyToNoir(privateCallData.vk), function_leaf_membership_witness: mapMembershipWitnessToNoir(privateCallData.functionLeafMembershipWitness), contract_class_artifact_hash: mapFieldToNoir(privateCallData.contractClassArtifactHash), @@ -1260,14 +1232,14 @@ export function mapPrivateAccumulatedDataFromNoir( mapScopedLogHashFromNoir, ), mapTupleFromNoir( - privateAccumulatedData.private_call_stack, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - mapScopedPrivateCallRequestFromNoir, + privateAccumulatedData.public_call_requests, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + mapPublicCallRequestFromNoir, ), mapTupleFromNoir( - privateAccumulatedData.public_call_stack, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - mapCallRequestFromNoir, + privateAccumulatedData.private_call_stack, + MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, + mapPrivateCallRequestFromNoir, ), ); } @@ -1280,8 +1252,8 @@ 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), - private_call_stack: mapTuple(data.privateCallStack, mapScopedPrivateCallRequestToNoir), - public_call_stack: mapTuple(data.publicCallStack, mapCallRequestToNoir), + public_call_requests: mapTuple(data.publicCallRequests, mapPublicCallRequestToNoir), + private_call_stack: mapTuple(data.privateCallStack, mapPrivateCallRequestToNoir), }; } @@ -1311,7 +1283,7 @@ export function mapPublicAccumulatedDataFromNoir( mapTupleFromNoir( publicAccumulatedData.public_call_stack, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - mapCallRequestFromNoir, + mapPublicCallRequestFromNoir, ), mapGasFromNoir(publicAccumulatedData.gas_used), ); @@ -1331,7 +1303,7 @@ export function mapPublicAccumulatedDataToNoir( publicAccumulatedData.publicDataUpdateRequests, mapPublicDataUpdateRequestToNoir, ), - public_call_stack: mapTuple(publicAccumulatedData.publicCallStack, mapCallRequestToNoir), + public_call_stack: mapTuple(publicAccumulatedData.publicCallStack, mapPublicCallRequestToNoir), gas_used: mapGasToNoir(publicAccumulatedData.gasUsed), }; } @@ -1466,7 +1438,7 @@ export function mapPublicKernelCircuitPublicInputsToNoir( end: mapPublicAccumulatedDataToNoir(inputs.end), end_non_revertible: mapPublicAccumulatedDataToNoir(inputs.endNonRevertibleData), revert_code: mapRevertCodeToNoir(inputs.revertCode), - public_teardown_call_stack: mapTuple(inputs.publicTeardownCallStack, mapCallRequestToNoir), + public_teardown_call_stack: mapTuple(inputs.publicTeardownCallStack, mapPublicCallRequestToNoir), fee_payer: mapAztecAddressToNoir(inputs.feePayer), }; } @@ -1533,7 +1505,7 @@ export function mapPrivateKernelCircuitPublicInputsFromNoir( mapValidationRequestsFromNoir(inputs.validation_requests), mapPrivateAccumulatedDataFromNoir(inputs.end), mapCombinedConstantDataFromNoir(inputs.constants), - mapCallRequestFromNoir(inputs.public_teardown_call_request), + mapPublicCallRequestFromNoir(inputs.public_teardown_call_request), mapAztecAddressFromNoir(inputs.fee_payer), ); } @@ -1546,7 +1518,7 @@ export function mapPrivateKernelCircuitPublicInputsToNoir( validation_requests: mapValidationRequestsToNoir(inputs.validationRequests), end: mapPrivateAccumulatedDataToNoir(inputs.end), min_revertible_side_effect_counter: mapFieldToNoir(inputs.minRevertibleSideEffectCounter), - public_teardown_call_request: mapCallRequestToNoir(inputs.publicTeardownCallRequest), + public_teardown_call_request: mapPublicCallRequestToNoir(inputs.publicTeardownCallRequest), fee_payer: mapAztecAddressToNoir(inputs.feePayer), }; } @@ -1588,7 +1560,7 @@ export function mapPrivateKernelTailCircuitPublicInputsForPublicFromNoir( mapValidationRequestsFromNoir(inputs.validation_requests), mapPublicAccumulatedDataFromNoir(inputs.end_non_revertible), mapPublicAccumulatedDataFromNoir(inputs.end), - mapTupleFromNoir(inputs.public_teardown_call_stack, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, mapCallRequestFromNoir), + mapPublicCallRequestFromNoir(inputs.public_teardown_call_stack[0]), ); return new PrivateKernelTailCircuitPublicInputs( mapCombinedConstantDataFromNoir(inputs.constants), @@ -1751,7 +1723,11 @@ export function mapPublicKernelCircuitPublicInputsFromNoir( mapPublicAccumulatedDataFromNoir(inputs.end), mapCombinedConstantDataFromNoir(inputs.constants), mapRevertCodeFromNoir(inputs.revert_code), - mapTupleFromNoir(inputs.public_teardown_call_stack, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, mapCallRequestFromNoir), + mapTupleFromNoir( + inputs.public_teardown_call_stack, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + mapPublicCallRequestFromNoir, + ), mapAztecAddressFromNoir(inputs.fee_payer), ); } @@ -1861,7 +1837,7 @@ export function mapPublicCircuitPublicInputsToNoir( mapStorageUpdateRequestToNoir, ), contract_storage_reads: mapTuple(publicInputs.contractStorageReads, mapStorageReadToNoir), - public_call_stack_hashes: mapTuple(publicInputs.publicCallStackHashes, mapFieldToNoir), + public_call_requests: mapTuple(publicInputs.publicCallRequests, mapPublicCallRequestToNoir), note_hashes: mapTuple(publicInputs.noteHashes, mapNoteHashToNoir), nullifiers: mapTuple(publicInputs.nullifiers, mapNullifierToNoir), l2_to_l1_msgs: mapTuple(publicInputs.l2ToL1Msgs, mapL2ToL1MessageToNoir), @@ -1932,7 +1908,6 @@ export function mapPublicCallStackItemToNoir(publicCallStackItem: PublicCallStac export function mapPublicCallDataToNoir(publicCall: PublicCallData): PublicCallDataNoir { return { call_stack_item: mapPublicCallStackItemToNoir(publicCall.callStackItem), - public_call_stack: mapTuple(publicCall.publicCallStack, mapCallRequestToNoir), proof: {}, bytecode_hash: mapFieldToNoir(publicCall.bytecodeHash), }; diff --git a/yarn-project/p2p/src/service/tx_messages.ts b/yarn-project/p2p/src/service/tx_messages.ts index cec7a59f5a4d..32ac7894d776 100644 --- a/yarn-project/p2p/src/service/tx_messages.ts +++ b/yarn-project/p2p/src/service/tx_messages.ts @@ -1,5 +1,11 @@ -import { EncryptedNoteTxL2Logs, EncryptedTxL2Logs, Tx, UnencryptedTxL2Logs } from '@aztec/circuit-types'; -import { ClientIvcProof, PrivateKernelTailCircuitPublicInputs, PublicCallRequest } from '@aztec/circuits.js'; +import { + EncryptedNoteTxL2Logs, + EncryptedTxL2Logs, + PublicExecutionRequest, + Tx, + UnencryptedTxL2Logs, +} from '@aztec/circuit-types'; +import { ClientIvcProof, PrivateKernelTailCircuitPublicInputs } from '@aztec/circuits.js'; import { numToUInt32BE } from '@aztec/foundation/serialize'; import { type SemVer } from 'semver'; @@ -128,9 +134,9 @@ export function fromTxMessage(buffer: Buffer): Tx { unencryptedLogs.obj = new UnencryptedTxL2Logs([]); } - const publicCalls = toObjectArray(unencryptedLogs.remainingData, PublicCallRequest); + const publicCalls = toObjectArray(unencryptedLogs.remainingData, PublicExecutionRequest); - const publicTeardownCall = toObject(publicCalls.remainingData, PublicCallRequest); + const publicTeardownCall = toObject(publicCalls.remainingData, PublicExecutionRequest); return new Tx( publicInputs.obj!, clientIvcProof.obj!, diff --git a/yarn-project/prover-client/src/mocks/test_context.ts b/yarn-project/prover-client/src/mocks/test_context.ts index 91d6c9bac984..c1852eaca9de 100644 --- a/yarn-project/prover-client/src/mocks/test_context.ts +++ b/yarn-project/prover-client/src/mocks/test_context.ts @@ -4,6 +4,7 @@ import { type BlockResult, type ProcessedTx, type ProvingTicket, + type PublicExecutionRequest, type ServerCircuitProver, type Tx, type TxValidator, @@ -14,7 +15,6 @@ import { type DebugLogger } from '@aztec/foundation/log'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type ContractsDataSourcePublicDB, - type PublicExecutionRequest, type PublicExecutionResult, PublicExecutionResultBuilder, type PublicExecutor, @@ -171,7 +171,7 @@ export class TestContext { : [...tx.enqueuedPublicFunctionCalls, tx.publicTeardownFunctionCall]; for (const request of allCalls) { if (execution.contractAddress.equals(request.contractAddress)) { - const result = PublicExecutionResultBuilder.fromPublicCallRequest({ request }).build({ + const result = PublicExecutionResultBuilder.fromPublicExecutionRequest({ request }).build({ startGasLeft: availableGas, endGasLeft: availableGas, transactionFee, diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index a3a0bf9d24f8..78da12312cf0 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -1,4 +1,4 @@ -import { Note, type PrivateKernelProver } from '@aztec/circuit-types'; +import { Note, type PrivateKernelProver, PublicExecutionRequest } from '@aztec/circuit-types'; import { FunctionData, FunctionSelector, @@ -10,7 +10,6 @@ import { PrivateCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PrivateKernelTailCircuitPublicInputs, - PublicCallRequest, ScopedNoteHash, type TxRequest, VK_TREE_HEIGHT, @@ -74,7 +73,7 @@ describe('Kernel Prover', () => { acir: Buffer.alloc(0), partialWitness: new Map(), enqueuedPublicFunctionCalls: [], - publicTeardownFunctionCall: PublicCallRequest.empty(), + publicTeardownFunctionCall: PublicExecutionRequest.empty(), noteEncryptedLogs: [], encryptedLogs: [], unencryptedLogs: [], diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index 728e41124012..e1831598666e 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -1,6 +1,5 @@ import { type PrivateKernelProver, type PrivateKernelSimulateOutput } from '@aztec/circuit-types'; import { - CallRequest, Fr, MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, @@ -8,7 +7,6 @@ import { MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PrivateCallData, PrivateKernelCircuitPublicInputs, PrivateKernelData, @@ -21,7 +19,6 @@ import { VerificationKeyAsFields, getNonEmptyItems, } from '@aztec/circuits.js'; -import { padArrayEnd } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; import { assertLength } from '@aztec/foundation/serialize'; import { pushTestData } from '@aztec/foundation/testing'; @@ -97,11 +94,6 @@ export class KernelProver { const currentExecution = executionStack.pop()!; executionStack.push(...[...currentExecution.nestedExecutions].reverse()); - const publicCallRequests = currentExecution.enqueuedPublicFunctionCalls.map(result => result.toCallRequest()); - const publicTeardownCallRequest = currentExecution.publicTeardownFunctionCall.isEmpty() - ? CallRequest.empty() - : currentExecution.publicTeardownFunctionCall.toCallRequest(); - const functionName = await this.oracle.getDebugFunctionName( currentExecution.callStackItem.contractAddress, currentExecution.callStackItem.functionData.selector, @@ -113,12 +105,7 @@ export class KernelProver { acirs.push(currentExecution.acir); witnessStack.push(currentExecution.partialWitness); - const privateCallData = await this.createPrivateCallData( - currentExecution, - publicCallRequests, - publicTeardownCallRequest, - appVk.verificationKey, - ); + const privateCallData = await this.createPrivateCallData(currentExecution, appVk.verificationKey); if (firstIteration) { const proofInput = new PrivateKernelInitCircuitPrivateInputs(txRequest, getVKTreeRoot(), privateCallData); @@ -248,16 +235,9 @@ export class KernelProver { ); } - private async createPrivateCallData( - { callStackItem }: ExecutionResult, - publicCallRequests: CallRequest[], - publicTeardownCallRequest: CallRequest, - vk: VerificationKeyAsFields, - ) { + private async createPrivateCallData({ callStackItem }: ExecutionResult, vk: VerificationKeyAsFields) { const { contractAddress, functionData } = callStackItem; - const publicCallStack = padArrayEnd(publicCallRequests, CallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL); - const functionLeafMembershipWitness = await this.oracle.getFunctionMembershipWitness( contractAddress, functionData.selector, @@ -274,8 +254,6 @@ export class KernelProver { return PrivateCallData.from({ callStackItem, - publicCallStack, - publicTeardownCallRequest, vk, publicKeysHash, contractClassArtifactHash, diff --git a/yarn-project/sequencer-client/src/index.ts b/yarn-project/sequencer-client/src/index.ts index 66c243968535..8dd0cf238897 100644 --- a/yarn-project/sequencer-client/src/index.ts +++ b/yarn-project/sequencer-client/src/index.ts @@ -2,6 +2,8 @@ export * from './client/index.js'; export * from './config.js'; export * from './publisher/index.js'; export * from './sequencer/index.js'; +export * from './tx_validator/aggregate_tx_validator.js'; +export * from './tx_validator/data_validator.js'; // Used by the node to simulate public parts of transactions. Should these be moved to a shared library? export * from './global_variable_builder/index.js'; diff --git a/yarn-project/sequencer-client/src/tx_validator/data_validator.test.ts b/yarn-project/sequencer-client/src/tx_validator/data_validator.test.ts new file mode 100644 index 000000000000..670660c28f48 --- /dev/null +++ b/yarn-project/sequencer-client/src/tx_validator/data_validator.test.ts @@ -0,0 +1,71 @@ +import { mockTx } from '@aztec/circuit-types'; +import { AztecAddress, Fr, FunctionSelector } from '@aztec/circuits.js'; + +import { DataTxValidator } from './data_validator.js'; + +const mockTxs = (numTxs: number) => + Array(numTxs) + .fill(0) + .map((_, i) => + mockTx(i, { + numberOfNonRevertiblePublicCallRequests: 2, + numberOfRevertiblePublicCallRequests: 2, + hasPublicTeardownCallRequest: true, + }), + ); + +describe('TxDataValidator', () => { + let validator: DataTxValidator; + + beforeEach(() => { + validator = new DataTxValidator(); + }); + + it('allows transactions with the correct data', async () => { + const txs = mockTxs(3); + await expect(validator.validateTxs(txs)).resolves.toEqual([txs, []]); + }); + + 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].item.argsHash = Fr.random(); + badTxs[1].data.forPublic!.endNonRevertibleData.publicCallStack[1].item.contractAddress = AztecAddress.random(); + + await expect(validator.validateTxs([...goodTxs, ...badTxs])).resolves.toEqual([goodTxs, badTxs]); + }); + + it('rejects txs with mismatch revertible execution requests', async () => { + const goodTxs = mockTxs(3); + const badTxs = mockTxs(5); + badTxs[0].data.forPublic!.end.publicCallStack[0].item.callContext.msgSender = AztecAddress.random(); + badTxs[1].data.forPublic!.end.publicCallStack[1].item.callContext.storageContractAddress = AztecAddress.random(); + badTxs[2].data.forPublic!.end.publicCallStack[0].item.callContext.functionSelector = FunctionSelector.random(); + badTxs[3].data.forPublic!.end.publicCallStack[1].item.callContext.isDelegateCall = + !badTxs[3].enqueuedPublicFunctionCalls[1].callContext.isDelegateCall; + badTxs[4].data.forPublic!.end.publicCallStack[0].item.callContext.isStaticCall = + !badTxs[4].enqueuedPublicFunctionCalls[0].callContext.isStaticCall; + + await expect(validator.validateTxs([...badTxs, ...goodTxs])).resolves.toEqual([goodTxs, badTxs]); + }); + + it('rejects txs with mismatch teardown execution requests', async () => { + const goodTxs = mockTxs(3); + const badTxs = mockTxs(2); + badTxs[0].data.forPublic!.publicTeardownCallRequest.item.contractAddress = AztecAddress.random(); + badTxs[1].data.forPublic!.publicTeardownCallRequest.item.callContext.msgSender = AztecAddress.random(); + + await expect(validator.validateTxs([...goodTxs, ...badTxs])).resolves.toEqual([goodTxs, badTxs]); + }); + + it('rejects txs with mismatch number of execution requests', async () => { + const goodTxs = mockTxs(3); + const badTxs = mockTxs(2); + // Missing an enqueuedPublicFunctionCall. + const execRequest = badTxs[0].enqueuedPublicFunctionCalls.pop()!; + // Having an extra enqueuedPublicFunctionCall. + badTxs[1].enqueuedPublicFunctionCalls.push(execRequest); + + await expect(validator.validateTxs([...badTxs, ...goodTxs])).resolves.toEqual([goodTxs, badTxs]); + }); +}); diff --git a/yarn-project/sequencer-client/src/tx_validator/data_validator.ts b/yarn-project/sequencer-client/src/tx_validator/data_validator.ts new file mode 100644 index 000000000000..39731cbc08df --- /dev/null +++ b/yarn-project/sequencer-client/src/tx_validator/data_validator.ts @@ -0,0 +1,61 @@ +import { Tx, type TxValidator } from '@aztec/circuit-types'; +import { createDebugLogger } from '@aztec/foundation/log'; + +export class DataTxValidator implements TxValidator { + #log = createDebugLogger('aztec:sequencer:tx_validator:tx_data'); + + validateTxs(txs: Tx[]): Promise<[validTxs: Tx[], invalidTxs: Tx[]]> { + const validTxs: Tx[] = []; + const invalidTxs: Tx[] = []; + for (const tx of txs) { + if (!this.#hasCorrectExecutionRequests(tx)) { + invalidTxs.push(tx); + continue; + } + + validTxs.push(tx); + } + + return Promise.resolve([validTxs, invalidTxs]); + } + + #hasCorrectExecutionRequests(tx: Tx): boolean { + const callRequests = [ + ...tx.data.getRevertiblePublicCallRequests(), + ...tx.data.getNonRevertiblePublicCallRequests(), + ]; + if (callRequests.length !== tx.enqueuedPublicFunctionCalls.length) { + this.#log.warn( + `Rejecting tx ${Tx.getHash(tx)} because of mismatch number of execution requests for public calls. Expected ${ + callRequests.length + }. Got ${tx.enqueuedPublicFunctionCalls.length}.`, + ); + return false; + } + + const invalidExecutionRequestIndex = tx.enqueuedPublicFunctionCalls.findIndex( + (execRequest, i) => !execRequest.isForCallRequest(callRequests[i]), + ); + if (invalidExecutionRequestIndex !== -1) { + this.#log.warn( + `Rejecting tx ${Tx.getHash( + tx, + )} because of incorrect execution requests for public call at index ${invalidExecutionRequestIndex}.`, + ); + return false; + } + + const teardownCallRequest = tx.data.getTeardownPublicCallRequest(); + const isInvalidTeardownExecutionRequest = + (!teardownCallRequest && !tx.publicTeardownFunctionCall.isEmpty()) || + (teardownCallRequest && !tx.publicTeardownFunctionCall.isForCallRequest(teardownCallRequest)); + if (isInvalidTeardownExecutionRequest) { + this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} because of incorrect teardown execution requests.`); + return false; + } + + return true; + } + + // TODO: Check logs. +} diff --git a/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts b/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts index e1b47f095398..b3e1c6058124 100644 --- a/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts +++ b/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts @@ -60,7 +60,9 @@ export class GasTxValidator implements TxValidator { fn => fn.contractAddress.equals(this.#gasTokenAddress) && fn.callContext.msgSender.equals(this.#gasTokenAddress) && - fn.functionSelector.equals(GasTokenArtifact.functions.find(f => f.name === '_increase_public_balance')!) && + fn.callContext.functionSelector.equals( + GasTokenArtifact.functions.find(f => f.name === '_increase_public_balance')!, + ) && fn.args[0].equals(feePayer) && !fn.callContext.isStaticCall && !fn.callContext.isDelegateCall, diff --git a/yarn-project/sequencer-client/src/tx_validator/phases_validator.test.ts b/yarn-project/sequencer-client/src/tx_validator/phases_validator.test.ts index 55531324fd33..0b0ac76f8453 100644 --- a/yarn-project/sequencer-client/src/tx_validator/phases_validator.test.ts +++ b/yarn-project/sequencer-client/src/tx_validator/phases_validator.test.ts @@ -51,14 +51,14 @@ describe('PhasesTxValidator', () => { }); it('allows setup functions on the contracts allow list', async () => { - const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 2 }); + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 1 }); patchNonRevertibleFn(tx, 0, { address: allowedContract, selector: allowedSetupSelector1 }); await expect(txValidator.validateTxs([tx])).resolves.toEqual([[tx], []]); }); it('allows setup functions on the contracts class allow list', async () => { - const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 2 }); + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 1 }); const { address } = patchNonRevertibleFn(tx, 0, { selector: allowedSetupSelector1 }); contractDataSource.getContract.mockImplementationOnce(contractAddress => { @@ -81,7 +81,7 @@ describe('PhasesTxValidator', () => { }); it('rejects setup functions not on the contracts class list', async () => { - const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 2 }); + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 1 }); // good selector, bad contract class const { address } = patchNonRevertibleFn(tx, 0, { selector: allowedSetupSelector1 }); contractDataSource.getContract.mockImplementationOnce(contractAddress => { @@ -97,7 +97,7 @@ describe('PhasesTxValidator', () => { }); it('allows multiple setup functions on the allow list', async () => { - const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 3 }); + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 2 }); patchNonRevertibleFn(tx, 0, { address: allowedContract, selector: allowedSetupSelector1 }); patchNonRevertibleFn(tx, 1, { address: allowedContract, selector: allowedSetupSelector2 }); @@ -105,7 +105,7 @@ describe('PhasesTxValidator', () => { }); it('rejects if one setup functions is not on the allow list', async () => { - const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 3 }); + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 2 }); patchNonRevertibleFn(tx, 0, { address: allowedContract, selector: allowedSetupSelector1 }); await expect(txValidator.validateTxs([tx])).resolves.toEqual([[], [tx]]); diff --git a/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts b/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts index 537d646707ab..345fd066ef32 100644 --- a/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts +++ b/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts @@ -1,5 +1,10 @@ -import { type AllowedElement, PublicKernelType, Tx, type TxValidator } from '@aztec/circuit-types'; -import { type PublicCallRequest } from '@aztec/circuits.js'; +import { + type AllowedElement, + type PublicExecutionRequest, + PublicKernelType, + Tx, + type TxValidator, +} from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; import { AbstractPhaseManager, ContractsDataSourcePublicDB } from '@aztec/simulator'; import { type ContractDataSource } from '@aztec/types/contracts'; @@ -47,7 +52,7 @@ export class PhasesTxValidator implements TxValidator { this.#log.warn( `Rejecting tx ${Tx.getHash(tx)} because it calls setup function not on allow list: ${ setupFn.contractAddress - }:${setupFn.functionSelector}`, + }:${setupFn.callContext.functionSelector}`, ); return false; @@ -57,12 +62,15 @@ export class PhasesTxValidator implements TxValidator { return true; } - async isOnAllowList(publicCall: PublicCallRequest, allowList: AllowedElement[]): Promise { + async isOnAllowList(publicCall: PublicExecutionRequest, allowList: AllowedElement[]): Promise { if (publicCall.isEmpty()) { return true; } - const { contractAddress, functionSelector } = publicCall; + const { + contractAddress, + callContext: { functionSelector }, + } = publicCall; // do these checks first since they don't require the contract class for (const entry of allowList) { 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 9f40736db69a..76d620754d2e 100644 --- a/yarn-project/sequencer-client/src/tx_validator/test_utils.ts +++ b/yarn-project/sequencer-client/src/tx_validator/test_utils.ts @@ -1,5 +1,6 @@ import { type Tx } from '@aztec/circuit-types'; import { type AztecAddress, type Fr, type FunctionSelector } from '@aztec/circuits.js'; +import { computeVarArgsHash } from '@aztec/circuits.js/hash'; export function patchNonRevertibleFn( tx: Tx, @@ -25,13 +26,19 @@ function patchFn( ): { address: AztecAddress; selector: FunctionSelector } { const fn = tx.enqueuedPublicFunctionCalls.at(-1 * index - 1)!; fn.contractAddress = overrides.address ?? fn.contractAddress; - fn.functionSelector = overrides.selector; + fn.callContext.functionSelector = overrides.selector; fn.args = overrides.args ?? fn.args; fn.callContext.msgSender = overrides.msgSender ?? fn.callContext.msgSender; - tx.data.forPublic![where].publicCallStack[index] = fn.toCallRequest(); + tx.enqueuedPublicFunctionCalls[index] = fn; + + const request = tx.data.forPublic![where].publicCallStack[index]; + request.item.contractAddress = fn.contractAddress; + request.item.callContext = fn.callContext; + request.item.argsHash = computeVarArgsHash(fn.args); + tx.data.forPublic![where].publicCallStack[index] = request; return { address: fn.contractAddress, - selector: fn.functionSelector, + selector: fn.callContext.functionSelector, }; } diff --git a/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts b/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts index 6322ced853cc..38d44fdf7b27 100644 --- a/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts +++ b/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts @@ -6,6 +6,7 @@ import { type ContractDataSource } from '@aztec/types/contracts'; import { type MerkleTreeOperations } from '@aztec/world-state'; import { AggregateTxValidator } from './aggregate_tx_validator.js'; +import { DataTxValidator } from './data_validator.js'; import { DoubleSpendTxValidator } from './double_spend_validator.js'; import { GasTxValidator } from './gas_validator.js'; import { MetadataTxValidator } from './metadata_validator.js'; @@ -20,6 +21,7 @@ export class TxValidatorFactory { validatorForNewTxs(globalVariables: GlobalVariables, setupAllowList: AllowedElement[]): TxValidator { return new AggregateTxValidator( + new DataTxValidator(), new MetadataTxValidator(globalVariables), new DoubleSpendTxValidator(new WorldStateDB(this.merkleTreeDb)), new PhasesTxValidator(this.contractDataSource, setupAllowList), diff --git a/yarn-project/simulator/src/acvm/acvm.ts b/yarn-project/simulator/src/acvm/acvm.ts index 72f559da7436..b80b6b89c1fa 100644 --- a/yarn-project/simulator/src/acvm/acvm.ts +++ b/yarn-project/simulator/src/acvm/acvm.ts @@ -18,7 +18,7 @@ import { type ORACLE_NAMES } from './oracle/index.js'; */ type ACIRCallback = Record< ORACLE_NAMES, - (...args: ForeignCallInput[]) => void | ForeignCallOutput | Promise + (...args: ForeignCallInput[]) => void | Promise | ForeignCallOutput | Promise >; /** diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index bc7fedc2f141..2ebd3db21527 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -6,7 +6,7 @@ import { Fr, Point } from '@aztec/foundation/fields'; import { type ACVMField } from '../acvm_types.js'; import { frToBoolean, frToNumber, fromACVMField } from '../deserialize.js'; -import { toACVMField, toAcvmEnqueuePublicFunctionResult } from '../serialize.js'; +import { toACVMField } from '../serialize.js'; import { type TypedOracle } from './typed_oracle.js'; /** @@ -429,7 +429,7 @@ export class Oracle { [isStaticCall]: ACVMField[], [isDelegateCall]: ACVMField[], ): Promise { - const callStackItem = await this.typedOracle.callPrivateFunction( + const { endSideEffectCounter, returnsHash } = await this.typedOracle.callPrivateFunction( AztecAddress.fromField(fromACVMField(contractAddress)), FunctionSelector.fromField(fromACVMField(functionSelector)), fromACVMField(argsHash), @@ -437,7 +437,7 @@ export class Oracle { frToBoolean(fromACVMField(isStaticCall)), frToBoolean(fromACVMField(isDelegateCall)), ); - return callStackItem.toFields().map(toACVMField); + return [endSideEffectCounter, returnsHash].map(toACVMField); } async callPublicFunction( @@ -467,7 +467,7 @@ export class Oracle { [isStaticCall]: ACVMField[], [isDelegateCall]: ACVMField[], ) { - const enqueuedRequest = await this.typedOracle.enqueuePublicFunctionCall( + await this.typedOracle.enqueuePublicFunctionCall( AztecAddress.fromString(contractAddress), FunctionSelector.fromField(fromACVMField(functionSelector)), fromACVMField(argsHash), @@ -475,7 +475,6 @@ export class Oracle { frToBoolean(fromACVMField(isStaticCall)), frToBoolean(fromACVMField(isDelegateCall)), ); - return toAcvmEnqueuePublicFunctionResult(enqueuedRequest); } async setPublicTeardownFunctionCall( @@ -486,7 +485,7 @@ export class Oracle { [isStaticCall]: ACVMField[], [isDelegateCall]: ACVMField[], ) { - const teardownRequest = await this.typedOracle.setPublicTeardownFunctionCall( + await this.typedOracle.setPublicTeardownFunctionCall( AztecAddress.fromString(contractAddress), FunctionSelector.fromField(fromACVMField(functionSelector)), fromACVMField(argsHash), @@ -494,7 +493,6 @@ export class Oracle { frToBoolean(fromACVMField(isStaticCall)), frToBoolean(fromACVMField(isDelegateCall)), ); - return toAcvmEnqueuePublicFunctionResult(teardownRequest); } aes128Encrypt(input: ACVMField[], initializationVector: ACVMField[], key: ACVMField[]): ACVMField[] { diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 256e7bd30835..36a84e4963bb 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -9,13 +9,7 @@ import { type SiblingPath, type UnencryptedL2Log, } from '@aztec/circuit-types'; -import { - type Header, - type KeyValidationRequest, - type L1_TO_L2_MSG_TREE_HEIGHT, - type PrivateCallStackItem, - type PublicCallRequest, -} from '@aztec/circuits.js'; +import { type Header, type KeyValidationRequest, type L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js'; import { type FunctionSelector, type NoteSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; @@ -255,7 +249,7 @@ export abstract class TypedOracle { _sideEffectCounter: number, _isStaticCall: boolean, _isDelegateCall: boolean, - ): Promise { + ): Promise<{ endSideEffectCounter: Fr; returnsHash: Fr }> { throw new OracleMethodNotAvailableError('callPrivateFunction'); } @@ -277,7 +271,7 @@ export abstract class TypedOracle { _sideEffectCounter: number, _isStaticCall: boolean, _isDelegateCall: boolean, - ): Promise { + ): Promise { throw new OracleMethodNotAvailableError('enqueuePublicFunctionCall'); } @@ -288,7 +282,7 @@ export abstract class TypedOracle { _sideEffectCounter: number, _isStaticCall: boolean, _isDelegateCall: boolean, - ): Promise { + ): Promise { throw new OracleMethodNotAvailableError('setPublicTeardownFunctionCall'); } diff --git a/yarn-project/simulator/src/acvm/serialize.ts b/yarn-project/simulator/src/acvm/serialize.ts index 0175cfcb275e..4e84ccac128e 100644 --- a/yarn-project/simulator/src/acvm/serialize.ts +++ b/yarn-project/simulator/src/acvm/serialize.ts @@ -1,4 +1,3 @@ -import { ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH, type PublicCallRequest } from '@aztec/circuits.js'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { type EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; @@ -40,34 +39,6 @@ export function toACVMField( return `0x${adaptBufferSize(buffer).toString('hex')}`; } -// Utilities to write TS classes to ACVM Field arrays -// In the order that the ACVM expects them - -/** - * Converts a public call stack item with the request for executing a public function to - * a set of ACVM fields accepted by the enqueue_public_function_call_oracle Aztec.nr function. - * Note that only the fields related to the request are serialized: those related to the result - * are empty since this is just an execution request, so we don't send them to the circuit. - * @param item - The public call stack item to serialize to be passed onto Noir. - * @returns The fields expected by the enqueue_public_function_call_oracle Aztec.nr function. - * TODO(#4380): Nuke this and replace it with PublicCallRequest.toFields() - */ -export function toAcvmEnqueuePublicFunctionResult(item: PublicCallRequest): ACVMField[] { - const fields = [ - item.contractAddress.toField(), - item.functionSelector.toField(), - ...item.callContext.toFields(), - item.sideEffectCounter, - item.getArgsHash(), - ]; - if (fields.length !== ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH) { - throw new Error( - `Invalid length for EnqueuePublicFunctionResult (got ${fields.length} expected ${ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH})`, - ); - } - return fields.map(toACVMField); -} - /** * Inserts a list of ACVM fields to a witness. * @param witnessStartIndex - The index where to start inserting the fields. diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 304bc11528d3..49363be658ff 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -8,6 +8,7 @@ import { L1NotePayload, Note, type NoteStatus, + PublicExecutionRequest, TaggedLog, type UnencryptedL2Log, } from '@aztec/circuit-types'; @@ -17,7 +18,6 @@ import { type Header, type KeyValidationRequest, PrivateContextInputs, - PublicCallRequest, type TxContext, } from '@aztec/circuits.js'; import { Aes128 } from '@aztec/circuits.js/barretenberg'; @@ -38,7 +38,13 @@ import { type NoteData, toACVMWitness } from '../acvm/index.js'; import { type PackedValuesCache } from '../common/packed_values_cache.js'; import { type DBOracle } from './db_oracle.js'; import { type ExecutionNoteCache } from './execution_note_cache.js'; -import { CountedLog, CountedNoteLog, type ExecutionResult, type NoteAndSlot } from './execution_result.js'; +import { + CountedLog, + CountedNoteLog, + CountedPublicExecutionRequest, + type ExecutionResult, + type NoteAndSlot, +} from './execution_result.js'; import { pickNotes } from './pick_notes.js'; import { executePrivateFunction } from './private_execution.js'; import { ViewDataOracle } from './view_data_oracle.js'; @@ -70,8 +76,8 @@ export class ClientExecutionContext extends ViewDataOracle { private encryptedLogs: CountedLog[] = []; private unencryptedLogs: CountedLog[] = []; private nestedExecutions: ExecutionResult[] = []; - private enqueuedPublicFunctionCalls: PublicCallRequest[] = []; - private publicTeardownFunctionCall: PublicCallRequest = PublicCallRequest.empty(); + private enqueuedPublicFunctionCalls: CountedPublicExecutionRequest[] = []; + private publicTeardownFunctionCall: PublicExecutionRequest = PublicExecutionRequest.empty(); constructor( contractAddress: AztecAddress, @@ -528,7 +534,11 @@ export class ClientExecutionContext extends ViewDataOracle { this.nestedExecutions.push(childExecutionResult); - return childExecutionResult.callStackItem; + const publicInputs = childExecutionResult.callStackItem.publicInputs; + return { + endSideEffectCounter: publicInputs.endSideEffectCounter, + returnsHash: publicInputs.returnsHash, + }; } /** @@ -540,7 +550,7 @@ export class ClientExecutionContext extends ViewDataOracle { * @param isStaticCall - Whether the call is a static call. * @returns The public call stack item with the request information. */ - protected async createPublicCallRequest( + protected async createPublicExecutionRequest( callType: 'enqueued' | 'teardown', targetContractAddress: AztecAddress, functionSelector: FunctionSelector, @@ -548,9 +558,7 @@ export class ClientExecutionContext extends ViewDataOracle { sideEffectCounter: number, isStaticCall: boolean, isDelegateCall: boolean, - ): Promise { - isStaticCall = isStaticCall || this.callContext.isStaticCall; - + ) { const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector); const derivedCallContext = this.deriveCallContext( targetContractAddress, @@ -560,22 +568,21 @@ export class ClientExecutionContext extends ViewDataOracle { ); const args = this.packedValuesCache.unpack(argsHash); - // TODO($846): if enqueued public calls are associated with global - // side-effect counter, that will leak info about how many other private - // side-effects occurred in the TX. Ultimately the private kernel should - // just output everything in the proper order without any counters. this.log.verbose( - `Created PublicCallRequest of type [${callType}], side-effect counter [${sideEffectCounter}] to ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`, + `Created PublicExecutionRequest of type [${callType}], side-effect counter [${sideEffectCounter}] to ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`, ); - return PublicCallRequest.from({ + const request = PublicExecutionRequest.from({ args, callContext: derivedCallContext, - parentCallContext: this.callContext, - functionSelector, contractAddress: targetContractAddress, - sideEffectCounter, }); + + if (callType === 'enqueued') { + this.enqueuedPublicFunctionCalls.push(new CountedPublicExecutionRequest(request, sideEffectCounter)); + } else { + this.publicTeardownFunctionCall = request; + } } /** @@ -596,8 +603,8 @@ export class ClientExecutionContext extends ViewDataOracle { sideEffectCounter: number, isStaticCall: boolean, isDelegateCall: boolean, - ): Promise { - const enqueuedRequest = await this.createPublicCallRequest( + ) { + await this.createPublicExecutionRequest( 'enqueued', targetContractAddress, functionSelector, @@ -606,10 +613,6 @@ export class ClientExecutionContext extends ViewDataOracle { isStaticCall, isDelegateCall, ); - - this.enqueuedPublicFunctionCalls.push(enqueuedRequest); - - return enqueuedRequest; } /** @@ -630,8 +633,8 @@ export class ClientExecutionContext extends ViewDataOracle { sideEffectCounter: number, isStaticCall: boolean, isDelegateCall: boolean, - ): Promise { - const publicTeardownFunctionCall = await this.createPublicCallRequest( + ) { + await this.createPublicExecutionRequest( 'teardown', targetContractAddress, functionSelector, @@ -640,10 +643,6 @@ export class ClientExecutionContext extends ViewDataOracle { isStaticCall, isDelegateCall, ); - - this.publicTeardownFunctionCall = publicTeardownFunctionCall; - - return publicTeardownFunctionCall; } /** diff --git a/yarn-project/simulator/src/client/execution_result.test.ts b/yarn-project/simulator/src/client/execution_result.test.ts index 6b6ee3ed9133..87d83686b480 100644 --- a/yarn-project/simulator/src/client/execution_result.test.ts +++ b/yarn-project/simulator/src/client/execution_result.test.ts @@ -1,4 +1,5 @@ -import { PrivateCallStackItem, PublicCallRequest } from '@aztec/circuits.js'; +import { PublicExecutionRequest } from '@aztec/circuit-types'; +import { PrivateCallStackItem } from '@aztec/circuits.js'; import { type ExecutionResult, @@ -18,7 +19,7 @@ function emptyExecutionResult(): ExecutionResult { returnValues: [], nestedExecutions: [], enqueuedPublicFunctionCalls: [], - publicTeardownFunctionCall: PublicCallRequest.empty(), + publicTeardownFunctionCall: PublicExecutionRequest.empty(), noteEncryptedLogs: [], encryptedLogs: [], unencryptedLogs: [], diff --git a/yarn-project/simulator/src/client/execution_result.ts b/yarn-project/simulator/src/client/execution_result.ts index d804e08b3865..53ca908c8d1f 100644 --- a/yarn-project/simulator/src/client/execution_result.ts +++ b/yarn-project/simulator/src/client/execution_result.ts @@ -4,10 +4,11 @@ import { type EncryptedL2NoteLog, EncryptedNoteFunctionL2Logs, type Note, + PublicExecutionRequest, UnencryptedFunctionL2Logs, type UnencryptedL2Log, } from '@aztec/circuit-types'; -import { type IsEmpty, type PrivateCallStackItem, PublicCallRequest, sortByCounter } from '@aztec/circuits.js'; +import { type IsEmpty, type PrivateCallStackItem, sortByCounter } from '@aztec/circuits.js'; import { type NoteSelector } from '@aztec/foundation/abi'; import { type Fr } from '@aztec/foundation/fields'; @@ -38,6 +39,15 @@ export class CountedNoteLog extends CountedLog { super(log, counter); } } + +export class CountedPublicExecutionRequest { + constructor(public request: PublicExecutionRequest, public counter: number) {} + + isEmpty(): boolean { + return this.request.isEmpty() && !this.counter; + } +} + /** * The result of executing a private function. */ @@ -63,9 +73,9 @@ export interface ExecutionResult { /** The nested executions. */ nestedExecutions: this[]; /** Enqueued public function execution requests to be picked up by the sequencer. */ - enqueuedPublicFunctionCalls: PublicCallRequest[]; + enqueuedPublicFunctionCalls: CountedPublicExecutionRequest[]; /** Public function execution requested for teardown */ - publicTeardownFunctionCall: PublicCallRequest; + publicTeardownFunctionCall: PublicExecutionRequest; /** * Encrypted note logs emitted during execution of this function call. * Note: These are preimages to `noteEncryptedLogsHashes`. @@ -161,21 +171,26 @@ export function collectSortedUnencryptedLogs(execResult: ExecutionResult): Unenc return new UnencryptedFunctionL2Logs(sortedLogs.map(l => l.log)); } +function collectEnqueuedCountedPublicExecutionRequests(execResult: ExecutionResult): CountedPublicExecutionRequest[] { + return [ + ...execResult.enqueuedPublicFunctionCalls, + ...execResult.nestedExecutions.flatMap(collectEnqueuedCountedPublicExecutionRequests), + ]; +} + /** * Collect all enqueued public function calls across all nested executions. * @param execResult - The topmost execution result. * @returns All enqueued public function calls. */ -export function collectEnqueuedPublicFunctionCalls(execResult: ExecutionResult): PublicCallRequest[] { +export function collectEnqueuedPublicFunctionCalls(execResult: ExecutionResult): PublicExecutionRequest[] { + const countedRequests = collectEnqueuedCountedPublicExecutionRequests(execResult); // without the reverse sort, the logs will be in a queue like fashion which is wrong // as the kernel processes it like a stack, popping items off and pushing them to output - return [ - ...execResult.enqueuedPublicFunctionCalls, - ...execResult.nestedExecutions.flatMap(collectEnqueuedPublicFunctionCalls), - ].sort((a, b) => b.sideEffectCounter - a.sideEffectCounter); + return sortByCounter(countedRequests, false).map(r => r.request); } -export function collectPublicTeardownFunctionCall(execResult: ExecutionResult): PublicCallRequest { +export function collectPublicTeardownFunctionCall(execResult: ExecutionResult): PublicExecutionRequest { const teardownCalls = [ execResult.publicTeardownFunctionCall, ...execResult.nestedExecutions.flatMap(collectPublicTeardownFunctionCall), @@ -189,5 +204,5 @@ export function collectPublicTeardownFunctionCall(execResult: ExecutionResult): throw new Error('Multiple public teardown calls detected'); } - return PublicCallRequest.empty(); + return PublicExecutionRequest.empty(); } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 4c94b92b441f..e3047d7b861a 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -6,6 +6,7 @@ import { Note, PackedValues, PublicDataWitness, + PublicExecutionRequest, SiblingPath, TxExecutionRequest, } from '@aztec/circuit-types'; @@ -22,7 +23,6 @@ import { NOTE_HASH_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, PartialStateReference, - PublicCallRequest, PublicDataTreeLeafPreimage, StateReference, TxContext, @@ -68,7 +68,7 @@ import { MessageLoadOracleInputs } from '../acvm/index.js'; import { buildL1ToL2Message } from '../test/utils.js'; import { computeSlotForMapping } from '../utils.js'; import { type DBOracle } from './db_oracle.js'; -import { type ExecutionResult, collectSortedEncryptedLogs } from './execution_result.js'; +import { CountedPublicExecutionRequest, type ExecutionResult, collectSortedEncryptedLogs } from './execution_result.js'; import { AcirSimulator } from './simulator.js'; jest.setTimeout(60_000); @@ -875,38 +875,22 @@ describe('Private Execution test suite', () => { args, }); - // Alter function data to match the manipulated oracle - const functionSelector = FunctionSelector.fromNameAndParameters( - childContractArtifact.name, - childContractArtifact.parameters, - ); - - const publicCallRequest = PublicCallRequest.from({ - contractAddress: childAddress, - functionSelector, - args: [new Fr(42n)], - callContext: CallContext.from({ - msgSender: parentAddress, - storageContractAddress: childAddress, - functionSelector: childSelector, - isDelegateCall: false, - isStaticCall: false, - }), - parentCallContext: CallContext.from({ - msgSender: parentAddress, - storageContractAddress: parentAddress, - functionSelector: FunctionSelector.fromNameAndParameters(parentArtifact.name, parentArtifact.parameters), - isDelegateCall: false, - isStaticCall: false, + const request = new CountedPublicExecutionRequest( + PublicExecutionRequest.from({ + contractAddress: childAddress, + args: [new Fr(42n)], + callContext: CallContext.from({ + msgSender: parentAddress, + storageContractAddress: childAddress, + functionSelector: childSelector, + isDelegateCall: false, + isStaticCall: false, + }), }), - sideEffectCounter: 2, - }); - - const publicCallRequestHash = publicCallRequest.toPublicCallStackItem().getCompressed().hash(); + 2, // sideEffectCounter + ); - expect(result.enqueuedPublicFunctionCalls).toHaveLength(1); - expect(result.enqueuedPublicFunctionCalls[0]).toEqual(publicCallRequest); - expect(result.callStackItem.publicInputs.publicCallStackHashes[0]).toEqual(publicCallRequestHash); + expect(result.enqueuedPublicFunctionCalls).toEqual([request]); }); }); @@ -917,7 +901,7 @@ describe('Private Execution test suite', () => { oracle.getFunctionArtifact.mockImplementation(() => Promise.resolve({ ...teardown })); const result = await runSimulator({ artifact: entrypoint }); expect(result.publicTeardownFunctionCall.isEmpty()).toBeFalsy(); - expect(result.publicTeardownFunctionCall.functionSelector).toEqual( + expect(result.publicTeardownFunctionCall.callContext.functionSelector).toEqual( FunctionSelector.fromNameAndParameters(teardown.name, teardown.parameters), ); }); diff --git a/yarn-project/simulator/src/mocks/fixtures.ts b/yarn-project/simulator/src/mocks/fixtures.ts index 40667e111b72..00e0797123a6 100644 --- a/yarn-project/simulator/src/mocks/fixtures.ts +++ b/yarn-project/simulator/src/mocks/fixtures.ts @@ -1,4 +1,9 @@ -import { type FunctionCall, type SimulationError, UnencryptedFunctionL2Logs } from '@aztec/circuit-types'; +import { + type FunctionCall, + PublicExecutionRequest, + type SimulationError, + UnencryptedFunctionL2Logs, +} from '@aztec/circuit-types'; import { ARGS_LENGTH, AvmExecutionHints, @@ -8,13 +13,12 @@ import { type ContractStorageUpdateRequest, Fr, Gas, - type PublicCallRequest, } from '@aztec/circuits.js'; import { makeAztecAddress, makeSelector } from '@aztec/circuits.js/testing'; import { FunctionType } from '@aztec/foundation/abi'; import { padArrayEnd } from '@aztec/foundation/collection'; -import { type PublicExecutionRequest, type PublicExecutionResult } from '../public/execution.js'; +import { type PublicExecutionResult, resultToPublicCallRequest } from '../public/execution.js'; export class PublicExecutionResultBuilder { private _executionRequest: PublicExecutionRequest; @@ -29,7 +33,7 @@ export class PublicExecutionResultBuilder { this._executionRequest = executionRequest; } - static fromPublicCallRequest({ + static fromPublicExecutionRequest({ request, returnValues = [new Fr(1n)], nestedExecutions = [], @@ -37,7 +41,7 @@ export class PublicExecutionResultBuilder { contractStorageReads = [], revertReason = undefined, }: { - request: PublicCallRequest; + request: PublicExecutionRequest; returnValues?: Fr[]; nestedExecutions?: PublicExecutionResult[]; contractStorageUpdateRequests?: ContractStorageUpdateRequest[]; @@ -74,12 +78,9 @@ export class PublicExecutionResultBuilder { contractStorageReads?: ContractStorageRead[]; revertReason?: SimulationError; }) { - const builder = new PublicExecutionResultBuilder({ - callContext: new CallContext(from, tx.to, tx.selector, false, false), - contractAddress: tx.to, - functionSelector: tx.selector, - args: tx.args, - }); + const builder = new PublicExecutionResultBuilder( + new PublicExecutionRequest(tx.to, new CallContext(from, tx.to, tx.selector, false, false), tx.args), + ); builder.withNestedExecutions(...nestedExecutions); builder.withContractStorageUpdateRequest(...contractStorageUpdateRequests); @@ -122,6 +123,7 @@ export class PublicExecutionResultBuilder { return { executionRequest: this._executionRequest, nestedExecutions: this._nestedExecutions, + publicCallRequests: this._nestedExecutions.map(resultToPublicCallRequest), noteHashReadRequests: [], nullifierReadRequests: [], nullifierNonExistentReadRequests: [], diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.test.ts b/yarn-project/simulator/src/public/abstract_phase_manager.test.ts index d17cd896a4e6..b3282e8adbd9 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.test.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.test.ts @@ -1,4 +1,3 @@ -import { Fr } from '@aztec/circuits.js'; import { makePublicKernelCircuitPublicInputs } from '@aztec/circuits.js/testing'; import { AbstractPhaseManager } from './abstract_phase_manager.js'; @@ -13,7 +12,7 @@ describe('AbstractPhaseManager utils', () => { inputs.endNonRevertibleData.noteHashes.at(-1)!.counter = startingCounter + 1; expect(AbstractPhaseManager.getMaxSideEffectCounter(inputs)).toBe(startingCounter + 1); - inputs.endNonRevertibleData.publicCallStack.at(-1)!.startSideEffectCounter = new Fr(startingCounter + 2); + inputs.endNonRevertibleData.publicCallStack.at(-1)!.counter = startingCounter + 2; expect(AbstractPhaseManager.getMaxSideEffectCounter(inputs)).toBe(startingCounter + 2); inputs.end.noteHashes.at(-1)!.counter = startingCounter + 3; diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index 9610f906deac..fc89d685bc1b 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -3,6 +3,7 @@ import { type AvmProvingRequest, MerkleTreeId, type NestedProcessReturnValues, + type PublicExecutionRequest, type PublicKernelNonTailRequest, PublicKernelType, type PublicProvingRequest, @@ -13,7 +14,6 @@ import { import { type AvmExecutionHints, AztecAddress, - CallRequest, ClientIvcProof, ContractStorageRead, ContractStorageUpdateRequest, @@ -40,7 +40,7 @@ import { NoteHash, Nullifier, PublicCallData, - type PublicCallRequest, + PublicCallRequest, PublicCallStackItem, PublicCircuitPublicInputs, PublicKernelCircuitPrivateInputs, @@ -62,7 +62,6 @@ import { getVKSiblingPath, } from '@aztec/noir-protocol-circuits-types'; import { - type PublicExecutionRequest, type PublicExecutionResult, type PublicExecutor, accumulateReturnValues, @@ -165,76 +164,18 @@ export abstract class AbstractPhaseManager { previousKernelArtifact: ProtocolArtifact, ): Promise; - public static extractEnqueuedPublicCallsByPhase(tx: Tx): Record { - const data = tx.data.forPublic; - if (!data) { - return { - [PublicKernelType.NON_PUBLIC]: [], - [PublicKernelType.SETUP]: [], - [PublicKernelType.APP_LOGIC]: [], - [PublicKernelType.TEARDOWN]: [], - [PublicKernelType.TAIL]: [], - }; - } - const publicCallsStack = tx.enqueuedPublicFunctionCalls.slice().reverse(); - const nonRevertibleCallStack = data.endNonRevertibleData.publicCallStack.filter(i => !i.isEmpty()); - const revertibleCallStack = data.end.publicCallStack.filter(i => !i.isEmpty()); - - const callRequestsStack = publicCallsStack - .map(call => call.toCallRequest()) - .filter( - // filter out enqueued calls that are not in the public call stack - // TODO mitch left a question about whether this is only needed when unit testing - // with mock data - call => revertibleCallStack.find(p => p.equals(call)) || nonRevertibleCallStack.find(p => p.equals(call)), - ); - - const teardownCallStack = tx.publicTeardownFunctionCall.isEmpty() ? [] : [tx.publicTeardownFunctionCall]; - - if (callRequestsStack.length === 0) { - return { - [PublicKernelType.NON_PUBLIC]: [], - [PublicKernelType.SETUP]: [], - [PublicKernelType.APP_LOGIC]: [], - [PublicKernelType.TEARDOWN]: teardownCallStack, - [PublicKernelType.TAIL]: [], - }; - } - - // find the first call that is revertible - const firstRevertibleCallIndex = callRequestsStack.findIndex( - c => revertibleCallStack.findIndex(p => p.equals(c)) !== -1, - ); - - if (firstRevertibleCallIndex === 0) { - return { - [PublicKernelType.NON_PUBLIC]: [], - [PublicKernelType.SETUP]: [], - [PublicKernelType.APP_LOGIC]: publicCallsStack, - [PublicKernelType.TEARDOWN]: teardownCallStack, - [PublicKernelType.TAIL]: [], - }; - } else if (firstRevertibleCallIndex === -1) { - // there's no app logic, split the functions between setup (many) and teardown (just one function call) - return { - [PublicKernelType.NON_PUBLIC]: [], - [PublicKernelType.SETUP]: publicCallsStack, - [PublicKernelType.APP_LOGIC]: [], - [PublicKernelType.TEARDOWN]: teardownCallStack, - [PublicKernelType.TAIL]: [], - }; - } else { - return { - [PublicKernelType.NON_PUBLIC]: [], - [PublicKernelType.SETUP]: publicCallsStack.slice(0, firstRevertibleCallIndex), - [PublicKernelType.APP_LOGIC]: publicCallsStack.slice(firstRevertibleCallIndex), - [PublicKernelType.TEARDOWN]: teardownCallStack, - [PublicKernelType.TAIL]: [], - }; - } + public static extractEnqueuedPublicCallsByPhase(tx: Tx): Record { + const teardownRequest = tx.getPublicTeardownExecutionRequest(); + return { + [PublicKernelType.NON_PUBLIC]: [], + [PublicKernelType.SETUP]: tx.getNonRevertiblePublicExecutionRequests(), + [PublicKernelType.APP_LOGIC]: tx.getRevertiblePublicExecutionRequests(), + [PublicKernelType.TEARDOWN]: teardownRequest ? [teardownRequest] : [], + [PublicKernelType.TAIL]: [], + }; } - protected extractEnqueuedPublicCalls(tx: Tx): PublicCallRequest[] { + protected extractEnqueuedPublicCalls(tx: Tx): PublicExecutionRequest[] { const calls = AbstractPhaseManager.extractEnqueuedPublicCallsByPhase(tx)[this.phase]; return calls; @@ -245,7 +186,7 @@ export abstract class AbstractPhaseManager { previousPublicKernelOutput: PublicKernelCircuitPublicInputs, previousKernelArtifact: ProtocolArtifact, ): Promise { - const enqueuedCalls = this.extractEnqueuedPublicCalls(tx); + const enqueuedCalls = [...this.extractEnqueuedPublicCalls(tx)].reverse(); if (!enqueuedCalls || !enqueuedCalls.length) { return { @@ -299,7 +240,7 @@ export abstract class AbstractPhaseManager { // Sanity check for a current upstream assumption. // Consumers of the result seem to expect "reverted <=> revertReason !== undefined". - const functionSelector = result.executionRequest.functionSelector.toString(); + const functionSelector = result.executionRequest.callContext.functionSelector.toString(); if (result.reverted && !result.revertReason) { throw new Error( `Simulation of ${result.executionRequest.contractAddress.toString()}:${functionSelector}(${ @@ -460,13 +401,6 @@ export abstract class AbstractPhaseManager { const publicDataTreeInfo = await this.db.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE); this.historicalHeader.state.partial.publicDataTree.root = Fr.fromBuffer(publicDataTreeInfo.root); - const callStackPreimages = await this.getPublicCallStackPreimages(result); - const publicCallStackHashes = padArrayEnd( - callStackPreimages.map(c => c.getCompressed().hash()), - Fr.ZERO, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - ); - const publicCircuitPublicInputs = PublicCircuitPublicInputs.from({ callContext: result.executionRequest.callContext, proverAddress: AztecAddress.ZERO, @@ -507,7 +441,11 @@ export abstract class AbstractPhaseManager { ContractStorageUpdateRequest.empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ), - publicCallStackHashes, + publicCallRequests: padArrayEnd( + result.publicCallRequests, + PublicCallRequest.empty(), + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, + ), unencryptedLogsHashes: padArrayEnd(result.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_CALL), historicalHeader: this.historicalHeader, globalVariables: this.globalVariables, @@ -520,23 +458,12 @@ export abstract class AbstractPhaseManager { return new PublicCallStackItem( result.executionRequest.contractAddress, - new FunctionData(result.executionRequest.functionSelector, false), + new FunctionData(result.executionRequest.callContext.functionSelector, false), publicCircuitPublicInputs, isExecutionRequest, ); } - protected async getPublicCallStackPreimages(result: PublicExecutionResult): Promise { - const nested = result.nestedExecutions; - if (nested.length > MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL) { - throw new Error( - `Public call stack size exceeded (max ${MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL}, got ${nested.length})`, - ); - } - - return await Promise.all(nested.map(n => this.getPublicCallStackItem(n))); - } - /** * Looks at the side effects of a transaction and returns the highest counter * @param tx - A transaction @@ -562,10 +489,7 @@ export abstract class AbstractPhaseManager { let max = 0; for (const sideEffect of sideEffectCounters) { - if ('startSideEffectCounter' in sideEffect) { - // look at both start and end counters because for enqueued public calls start > 0 while end === 0 - max = Math.max(max, sideEffect.startSideEffectCounter.toNumber(), sideEffect.endSideEffectCounter.toNumber()); - } else if ('counter' in sideEffect) { + if ('counter' in sideEffect) { max = Math.max(max, sideEffect.counter); } else { throw new Error('Unknown side effect type'); @@ -593,10 +517,6 @@ export abstract class AbstractPhaseManager { protected async getPublicCallData(result: PublicExecutionResult, isExecutionRequest = false) { const bytecodeHash = await this.getBytecodeHash(result); const callStackItem = await this.getPublicCallStackItem(result, isExecutionRequest); - const publicCallRequests = (await this.getPublicCallStackPreimages(result)).map(c => - c.toCallRequest(callStackItem.publicInputs.callContext), - ); - const publicCallStack = padArrayEnd(publicCallRequests, CallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL); - return new PublicCallData(callStackItem, publicCallStack, makeEmptyProof(), bytecodeHash); + return new PublicCallData(callStackItem, makeEmptyProof(), bytecodeHash); } } diff --git a/yarn-project/simulator/src/public/execution.ts b/yarn-project/simulator/src/public/execution.ts index a95fee4bbb59..be5b4a516057 100644 --- a/yarn-project/simulator/src/public/execution.ts +++ b/yarn-project/simulator/src/public/execution.ts @@ -1,18 +1,26 @@ -import { type SimulationError, type UnencryptedFunctionL2Logs } from '@aztec/circuit-types'; +import { + type PublicExecutionRequest, + type SimulationError, + type UnencryptedFunctionL2Logs, +} from '@aztec/circuit-types'; import { type AvmExecutionHints, type ContractStorageRead, type ContractStorageUpdateRequest, type Fr, + Gas, type L2ToL1Message, type LogHash, type NoteHash, type Nullifier, - type PublicCallRequest, + PublicCallRequest, + PublicCallStackItemCompressed, type ReadRequest, + RevertCode, } from '@aztec/circuits.js'; +import { computeVarArgsHash } from '@aztec/circuits.js/hash'; -import { type Gas } from '../avm/avm_gas.js'; +import { type Gas as AvmGas } from '../avm/avm_gas.js'; /** * The public function execution result. @@ -26,9 +34,9 @@ export interface PublicExecutionResult { /** The side effect counter after executing this function call */ endSideEffectCounter: Fr; /** How much gas was available for this public execution. */ - startGasLeft: Gas; + startGasLeft: AvmGas; /** How much gas was left after this public execution. */ - endGasLeft: Gas; + endGasLeft: AvmGas; /** Transaction fee set for this tx. */ transactionFee: Fr; @@ -79,6 +87,8 @@ export interface PublicExecutionResult { // TODO(dbanks12): add contract instance read requests + /** The requests to call public functions made by this call. */ + publicCallRequests: PublicCallRequest[]; /** The results of nested calls. */ nestedExecutions: this[]; @@ -89,15 +99,6 @@ export interface PublicExecutionResult { functionName: string; } -/** - * The execution request of a public function. - * A subset of PublicCallRequest - */ -export type PublicExecutionRequest = Pick< - PublicCallRequest, - 'contractAddress' | 'functionSelector' | 'callContext' | 'args' ->; - /** * Returns if the input is a public execution result and not just a public execution. * @param input - Public execution or public execution result. @@ -131,3 +132,18 @@ export function checkValidStaticCall( throw new Error('Static call cannot update the state, emit L2->L1 messages or generate logs'); } } + +export function resultToPublicCallRequest(result: PublicExecutionResult) { + const request = result.executionRequest; + const item = new PublicCallStackItemCompressed( + request.contractAddress, + request.callContext, + computeVarArgsHash(request.args), + computeVarArgsHash(result.returnValues), + // TODO(@just-mitch): need better mapping from simulator to revert code. + result.reverted ? RevertCode.APP_LOGIC_REVERTED : RevertCode.OK, + Gas.from(result.startGasLeft), + Gas.from(result.endGasLeft), + ); + return new PublicCallRequest(item, result.startSideEffectCounter.toNumber()); +} diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 64f57d27d887..1e96f97c956e 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -1,3 +1,4 @@ +import { type PublicExecutionRequest } from '@aztec/circuit-types'; import { type AvmSimulationStats } from '@aztec/circuit-types/stats'; import { Fr, Gas, type GlobalVariables, type Header, type Nullifier, type TxContext } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -10,7 +11,7 @@ import { AvmSimulator } from '../avm/avm_simulator.js'; import { HostStorage } from '../avm/journal/host_storage.js'; import { AvmPersistableStateManager } from '../avm/journal/index.js'; import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db_interfaces.js'; -import { type PublicExecutionRequest, type PublicExecutionResult } from './execution.js'; +import { type PublicExecutionResult } from './execution.js'; import { PublicSideEffectTrace } from './side_effect_trace.js'; /** @@ -47,7 +48,7 @@ export class PublicExecutor { startSideEffectCounter: number = 0, ): Promise { const address = executionRequest.contractAddress; - const selector = executionRequest.functionSelector; + const selector = executionRequest.callContext.functionSelector; const fnName = (await this.contractsDb.getDebugFunctionName(address, selector)) ?? `${address}:${selector}`; PublicExecutor.log.verbose(`[AVM] Executing public external function ${fnName}.`); @@ -122,7 +123,7 @@ function createAvmExecutionEnvironment( executionRequest.contractAddress, executionRequest.callContext.storageContractAddress, executionRequest.callContext.msgSender, - executionRequest.functionSelector, + executionRequest.callContext.functionSelector, /*contractCallDepth=*/ Fr.zero(), transactionFee, header, diff --git a/yarn-project/simulator/src/public/index.ts b/yarn-project/simulator/src/public/index.ts index 6bbddcb71e63..cf32d4b4e191 100644 --- a/yarn-project/simulator/src/public/index.ts +++ b/yarn-project/simulator/src/public/index.ts @@ -1,6 +1,6 @@ export * from './abstract_phase_manager.js'; export * from './db_interfaces.js'; -export { isPublicExecutionResult, type PublicExecutionRequest, type PublicExecutionResult } from './execution.js'; +export { isPublicExecutionResult, type PublicExecutionResult } from './execution.js'; export { PublicExecutor } from './executor.js'; export * from './fee_payment.js'; export { HintsBuilder } from './hints_builder.js'; diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index b39fff577826..02f4bf004ad5 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -25,14 +25,13 @@ import { PUBLIC_DATA_TREE_HEIGHT, PartialStateReference, PublicAccumulatedDataBuilder, - PublicCallRequest, PublicDataTreeLeafPreimage, PublicDataUpdateRequest, RevertCode, StateReference, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; -import { fr, makeAztecAddress, makePublicCallRequest, makeSelector } from '@aztec/circuits.js/testing'; +import { fr, makeSelector } from '@aztec/circuits.js/testing'; import { arrayNonEmptyLength, times } from '@aztec/foundation/collection'; import { type FieldsOf } from '@aztec/foundation/types'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -99,10 +98,7 @@ describe('public_processor', () => { }); it('skips txs without public execution requests', async function () { - const tx = mockTx(1, { - numberOfNonRevertiblePublicCallRequests: 0, - numberOfRevertiblePublicCallRequests: 0, - }); + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 0 }); const hash = tx.getTxHash(); const [processed, failed] = await processor.process([tx], 1, prover); @@ -151,34 +147,6 @@ describe('public_processor', () => { let publicKernel: PublicKernelCircuitSimulator; let publicDataTree: AppendOnlyTree; - const mockTxWithPartialState = ( - { - hasLogs = false, - numberOfNonRevertiblePublicCallRequests = 0, - numberOfRevertiblePublicCallRequests = 0, - publicCallRequests = [], - publicTeardownCallRequest = PublicCallRequest.empty(), - feePayer = AztecAddress.ZERO, - }: { - hasLogs?: boolean; - numberOfNonRevertiblePublicCallRequests?: number; - numberOfRevertiblePublicCallRequests?: number; - publicCallRequests?: PublicCallRequest[]; - publicTeardownCallRequest?: PublicCallRequest; - feePayer?: AztecAddress; - } = {}, - seed = 1, - ) => { - return mockTx(seed, { - hasLogs, - numberOfNonRevertiblePublicCallRequests, - numberOfRevertiblePublicCallRequests, - publicCallRequests, - publicTeardownCallRequest, - feePayer, - }); - }; - beforeAll(async () => { publicDataTree = await newTree( StandardTree, @@ -210,6 +178,11 @@ describe('public_processor', () => { db.getPreviousValueIndex.mockResolvedValue({ index: 0n, alreadyPresent: true }); db.getLeafPreimage.mockResolvedValue(new PublicDataTreeLeafPreimage(new Fr(0), new Fr(0), new Fr(0), 0n)); + publicExecutor.simulate.mockImplementation(request => { + const result = PublicExecutionResultBuilder.fromPublicExecutionRequest({ request }).build(); + return Promise.resolve(result); + }); + publicKernel = new RealPublicKernelCircuitSimulator(new WASMSimulator()); processor = new PublicProcessor( db, @@ -224,20 +197,10 @@ describe('public_processor', () => { }); it('runs a tx with enqueued public calls', async function () { - const tx = mockTxWithPartialState({ - hasLogs: true, + const tx = mockTx(1, { + numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 2, - publicTeardownCallRequest: PublicCallRequest.empty(), - }); - - publicExecutor.simulate.mockImplementation(execution => { - for (const request of tx.enqueuedPublicFunctionCalls) { - if (execution.contractAddress.equals(request.contractAddress)) { - const result = PublicExecutionResultBuilder.fromPublicCallRequest({ request }).build(); - return Promise.resolve(result); - } - } - throw new Error(`Unexpected execution request: ${execution}`); + hasLogs: true, }); const [processed, failed] = await processor.process([tx], 1, prover); @@ -258,14 +221,14 @@ describe('public_processor', () => { }); it('runs a tx with an enqueued public call with nested execution', async function () { - const tx = mockTxWithPartialState({ numberOfRevertiblePublicCallRequests: 1 }); - const callRequest = tx.enqueuedPublicFunctionCalls[0]; + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 1 }); + const request = tx.getRevertiblePublicExecutionRequests()[0]; - const publicExecutionResult = PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequest, + const publicExecutionResult = PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request, nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequest.contractAddress, + from: request.contractAddress, tx: makeFunctionCall(), }).build(), ], @@ -291,23 +254,9 @@ describe('public_processor', () => { it('does not attempt to overfill a block', async function () { const txs = Array.from([1, 2, 3], index => - mockTxWithPartialState({ numberOfRevertiblePublicCallRequests: 1 }, index), + mockTx(index, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 1 }), ); - let txCount = 0; - - publicExecutor.simulate.mockImplementation(execution => { - const tx = txs[txCount++]; - for (const request of tx.enqueuedPublicFunctionCalls) { - if (execution.contractAddress.equals(request.contractAddress)) { - const result = PublicExecutionResultBuilder.fromPublicCallRequest({ request }).build(); - // result.unencryptedLogs = tx.unencryptedLogs.functionLogs[0]; - return Promise.resolve(result); - } - } - throw new Error(`Unexpected execution request: ${execution}`); - }); - // We are passing 3 txs but only 2 can fit in the block const [processed, failed] = await processor.process(txs, 2, prover); @@ -326,18 +275,7 @@ describe('public_processor', () => { }); it('does not send a transaction to the prover if validation fails', async function () { - const tx = mockTxWithPartialState({ numberOfRevertiblePublicCallRequests: 1 }); - - publicExecutor.simulate.mockImplementation(execution => { - for (const request of tx.enqueuedPublicFunctionCalls) { - if (execution.contractAddress.equals(request.contractAddress)) { - const result = PublicExecutionResultBuilder.fromPublicCallRequest({ request }).build(); - // result.unencryptedLogs = tx.unencryptedLogs.functionLogs[0]; - return Promise.resolve(result); - } - } - throw new Error(`Unexpected execution request: ${execution}`); - }); + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 1 }); const txValidator: MockProxy> = mock(); txValidator.validateTxs.mockRejectedValue([[], [tx]]); @@ -352,29 +290,21 @@ describe('public_processor', () => { }); it('rolls back app logic db updates on failed public execution, but persists setup', async function () { - const baseContractAddressSeed = 0x200; - const baseContractAddress = makeAztecAddress(baseContractAddressSeed); - const publicCallRequests: PublicCallRequest[] = [ - baseContractAddressSeed, - baseContractAddressSeed, - baseContractAddressSeed, - ].map(makePublicCallRequest); - publicCallRequests[0].sideEffectCounter = 2; - publicCallRequests[1].sideEffectCounter = 3; - publicCallRequests[2].sideEffectCounter = 4; - const teardown = publicCallRequests.pop()!; // Remove the last call request to test that the processor can handle this - - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { hasLogs: true, numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, - publicCallRequests, - publicTeardownCallRequest: teardown, + hasPublicTeardownCallRequest: true, }); + const nonRevertibleRequests = tx.getNonRevertiblePublicExecutionRequests(); + const revertibleRequests = tx.getRevertiblePublicExecutionRequests(); + const teardownRequest = tx.getPublicTeardownExecutionRequest()!; + const teardownGas = tx.data.constants.txContext.gasSettings.getTeardownLimits(); const teardownResultSettings = { startGasLeft: teardownGas, endGasLeft: teardownGas }; + const nestedContractAddress = AztecAddress.fromBigInt(112233n); const contractSlotA = fr(0x100); const contractSlotB = fr(0x150); const contractSlotC = fr(0x200); @@ -385,46 +315,44 @@ describe('public_processor', () => { let simulatorCallCount = 0; const simulatorResults: PublicExecutionResult[] = [ // Setup - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: publicCallRequests[0], - contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11, baseContractAddress), - ], + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: nonRevertibleRequests[0], + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11)], }).build(), // App Logic - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: publicCallRequests[1], + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: revertibleRequests[0], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: publicCallRequests[1].contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), + from: revertibleRequests[0].callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 13, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 14, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotC, fr(0x200), 15, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 13), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 14), + new ContractStorageUpdateRequest(contractSlotC, fr(0x200), 15), ], }).build(), PublicExecutionResultBuilder.fromFunctionCall({ - from: publicCallRequests[1].contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), + from: revertibleRequests[0].contractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), revertReason: new SimulationError('Simulation Failed', []), }).build(), ], }).build(), // Teardown - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: teardown, + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: teardownRequest, nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: teardown.contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), + from: teardownRequest.callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 16, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotD, fr(0x251), 17, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotE, fr(0x301), 18, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotF, fr(0x351), 19, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 16), + new ContractStorageUpdateRequest(contractSlotD, fr(0x251), 17), + new ContractStorageUpdateRequest(contractSlotE, fr(0x301), 18), + new ContractStorageUpdateRequest(contractSlotF, fr(0x351), 19), ], }).build(teardownResultSettings), ], @@ -460,22 +388,18 @@ describe('public_processor', () => { expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); const txEffect = toTxEffect(processed[0], GasFees.default()); - expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toEqual(5); - expect(txEffect.publicDataWrites[0]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x101)), - ); - expect(txEffect.publicDataWrites[1]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotF), fr(0x351)), - ); - expect(txEffect.publicDataWrites[2]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotD), fr(0x251)), - ); - expect(txEffect.publicDataWrites[3]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotE), fr(0x301)), - ); - expect(txEffect.publicDataWrites[4]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotC), fr(0x201)), - ); + const numPublicDataWrites = 5; + expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toBe(numPublicDataWrites); + expect(txEffect.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ + new PublicDataWrite( + computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.storageContractAddress, contractSlotA), + fr(0x101), + ), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotE), fr(0x301)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotC), fr(0x201)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotF), fr(0x351)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotD), fr(0x251)), + ]); // we keep the non-revertible logs expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(3); @@ -485,25 +409,17 @@ describe('public_processor', () => { }); it('fails a transaction that reverts in setup', async function () { - const baseContractAddressSeed = 0x200; - const baseContractAddress = makeAztecAddress(baseContractAddressSeed); - const publicCallRequests: PublicCallRequest[] = [ - baseContractAddressSeed, - baseContractAddressSeed, - baseContractAddressSeed, - ].map(makePublicCallRequest); - publicCallRequests[0].sideEffectCounter = 2; - publicCallRequests[1].sideEffectCounter = 3; - publicCallRequests[2].sideEffectCounter = 4; - const teardown = publicCallRequests.pop()!; - - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, - publicCallRequests, - publicTeardownCallRequest: teardown, + hasPublicTeardownCallRequest: true, }); + const nonRevertibleRequests = tx.getNonRevertiblePublicExecutionRequests(); + const revertibleRequests = tx.getRevertiblePublicExecutionRequests(); + const teardownRequest = tx.getPublicTeardownExecutionRequest()!; + + const nestedContractAddress = AztecAddress.fromBigInt(112233n); const contractSlotA = fr(0x100); const contractSlotB = fr(0x150); const contractSlotC = fr(0x200); @@ -511,43 +427,39 @@ describe('public_processor', () => { let simulatorCallCount = 0; const simulatorResults: PublicExecutionResult[] = [ // Setup - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: publicCallRequests[0], - contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11, baseContractAddress), - ], + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: nonRevertibleRequests[0], + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11)], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: publicCallRequests[1].contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), + from: nonRevertibleRequests[0].callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13), ], }).build(), PublicExecutionResultBuilder.fromFunctionCall({ - from: publicCallRequests[1].contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), + from: nonRevertibleRequests[0].callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), revertReason: new SimulationError('Simulation Failed', []), }).build(), ], }).build(), // App Logic - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: publicCallRequests[2], + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: revertibleRequests[0], }).build(), // Teardown - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: teardown, + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: teardownRequest, nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: teardown.contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16, baseContractAddress), - ], + from: teardownRequest.callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16)], }).build(), ], }).build(), @@ -585,29 +497,21 @@ describe('public_processor', () => { }); it('includes a transaction that reverts in teardown', async function () { - const baseContractAddressSeed = 0x200; - const baseContractAddress = makeAztecAddress(baseContractAddressSeed); - const publicCallRequests: PublicCallRequest[] = [ - baseContractAddressSeed, - baseContractAddressSeed, - baseContractAddressSeed, - ].map(makePublicCallRequest); - publicCallRequests[0].sideEffectCounter = 2; - publicCallRequests[1].sideEffectCounter = 3; - publicCallRequests[2].sideEffectCounter = 4; - const teardown = publicCallRequests.pop()!; - - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { hasLogs: true, numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, - publicCallRequests, - publicTeardownCallRequest: teardown, + hasPublicTeardownCallRequest: true, }); + const nonRevertibleRequests = tx.getNonRevertiblePublicExecutionRequests(); + const revertibleRequests = tx.getRevertiblePublicExecutionRequests(); + const teardownRequest = tx.getPublicTeardownExecutionRequest()!; + const teardownGas = tx.data.constants.txContext.gasSettings.getTeardownLimits(); const teardownResultSettings = { startGasLeft: teardownGas, endGasLeft: teardownGas }; + const nestedContractAddress = AztecAddress.fromBigInt(112233n); const contractSlotA = fr(0x100); const contractSlotB = fr(0x150); const contractSlotC = fr(0x200); @@ -615,49 +519,43 @@ describe('public_processor', () => { let simulatorCallCount = 0; const simulatorResults: PublicExecutionResult[] = [ // Setup - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: publicCallRequests[0], - contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11, baseContractAddress), - ], + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: nonRevertibleRequests[0], + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11)], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: publicCallRequests[0].contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), + from: nonRevertibleRequests[0].callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13), ], }).build(), ], }).build(), // App Logic - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: publicCallRequests[1], + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: revertibleRequests[0], contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotB, fr(0x152), 14, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 15, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotB, fr(0x152), 14), + new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 15), ], }).build(), // Teardown - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: teardown, + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: teardownRequest, nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: teardown.contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16, baseContractAddress), - ], + from: teardownRequest.callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16)], }).build(teardownResultSettings), PublicExecutionResultBuilder.fromFunctionCall({ - from: teardown.contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16, baseContractAddress), - ], + from: teardownRequest.callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16)], revertReason: new SimulationError('Simulation Failed', []), }).build(teardownResultSettings), ], @@ -693,13 +591,16 @@ describe('public_processor', () => { expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); const txEffect = toTxEffect(processed[0], GasFees.default()); - expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toEqual(2); - expect(txEffect.publicDataWrites[0]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotB), fr(0x151)), - ); - expect(txEffect.publicDataWrites[1]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x102)), - ); + const numPublicDataWrites = 3; + expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toBe(numPublicDataWrites); + expect(txEffect.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x151)), + new PublicDataWrite( + computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.storageContractAddress, contractSlotA), + fr(0x101), + ), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), fr(0x102)), + ]); // we keep the non-revertible logs expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(3); @@ -711,29 +612,21 @@ describe('public_processor', () => { }); it('includes a transaction that reverts in app logic and teardown', async function () { - const baseContractAddressSeed = 0x200; - const baseContractAddress = makeAztecAddress(baseContractAddressSeed); - const publicCallRequests: PublicCallRequest[] = [ - baseContractAddressSeed, - baseContractAddressSeed, - baseContractAddressSeed, - ].map(makePublicCallRequest); - publicCallRequests[0].sideEffectCounter = 2; - publicCallRequests[1].sideEffectCounter = 3; - publicCallRequests[2].sideEffectCounter = 4; - const teardown = publicCallRequests.pop()!; - - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { hasLogs: true, numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, - publicCallRequests, - publicTeardownCallRequest: teardown, + hasPublicTeardownCallRequest: true, }); + const nonRevertibleRequests = tx.getNonRevertiblePublicExecutionRequests(); + const revertibleRequests = tx.getRevertiblePublicExecutionRequests(); + const teardownRequest = tx.getPublicTeardownExecutionRequest()!; + const teardownGas = tx.data.constants.txContext.gasSettings.getTeardownLimits(); const teardownResultSettings = { startGasLeft: teardownGas, endGasLeft: teardownGas }; + const nestedContractAddress = AztecAddress.fromBigInt(112233n); const contractSlotA = fr(0x100); const contractSlotB = fr(0x150); const contractSlotC = fr(0x200); @@ -741,50 +634,44 @@ describe('public_processor', () => { let simulatorCallCount = 0; const simulatorResults: PublicExecutionResult[] = [ // Setup - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: publicCallRequests[0], - contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11, baseContractAddress), - ], + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: nonRevertibleRequests[0], + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11)], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: publicCallRequests[0].contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), + from: nonRevertibleRequests[0].callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13), ], }).build(), ], }).build(), // App Logic - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: publicCallRequests[1], + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: revertibleRequests[0], contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotB, fr(0x152), 14, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 15, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotB, fr(0x152), 14), + new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 15), ], revertReason: new SimulationError('Simulation Failed', []), }).build(), // Teardown - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: teardown, + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: teardownRequest, nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: teardown.contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16, baseContractAddress), - ], + from: teardownRequest.callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16)], }).build(teardownResultSettings), PublicExecutionResultBuilder.fromFunctionCall({ - from: teardown.contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16, baseContractAddress), - ], + from: teardownRequest.callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16)], revertReason: new SimulationError('Simulation Failed', []), }).build(teardownResultSettings), ], @@ -820,13 +707,16 @@ describe('public_processor', () => { expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); const txEffect = toTxEffect(processed[0], GasFees.default()); - expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toEqual(2); - expect(txEffect.publicDataWrites[0]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotB), fr(0x151)), - ); - expect(txEffect.publicDataWrites[1]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x102)), - ); + const numPublicDataWrites = 3; + expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toBe(numPublicDataWrites); + expect(txEffect.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x151)), + new PublicDataWrite( + computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.storageContractAddress, contractSlotA), + fr(0x101), + ), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), fr(0x102)), + ]); // we keep the non-revertible logs expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(3); @@ -838,25 +728,16 @@ describe('public_processor', () => { }); it('runs a tx with setup and teardown phases', async function () { - const baseContractAddressSeed = 0x200; - const baseContractAddress = makeAztecAddress(baseContractAddressSeed); - const publicCallRequests: PublicCallRequest[] = [ - baseContractAddressSeed, - baseContractAddressSeed, - baseContractAddressSeed, - ].map(makePublicCallRequest); - publicCallRequests[0].sideEffectCounter = 2; - publicCallRequests[1].sideEffectCounter = 3; - publicCallRequests[2].sideEffectCounter = 4; - const teardown = publicCallRequests.pop(); // Remove the last call request to test that the processor can handle this - - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, - publicCallRequests, - publicTeardownCallRequest: teardown, + hasPublicTeardownCallRequest: true, }); + const nonRevertibleRequests = tx.getNonRevertiblePublicExecutionRequests(); + const revertibleRequests = tx.getRevertiblePublicExecutionRequests(); + const teardownRequest = tx.getPublicTeardownExecutionRequest()!; + const gasLimits = Gas.from({ l2Gas: 1e9, daGas: 1e9 }); const teardownGas = Gas.from({ l2Gas: 1e7, daGas: 1e7 }); tx.data.constants.txContext.gasSettings = GasSettings.from({ @@ -876,6 +757,7 @@ describe('public_processor', () => { .withGasUsed(Gas.empty()) .build(); + const nestedContractAddress = revertibleRequests[0].callContext.storageContractAddress; const contractSlotA = fr(0x100); const contractSlotB = fr(0x150); const contractSlotC = fr(0x200); @@ -900,45 +782,45 @@ describe('public_processor', () => { const simulatorResults: PublicExecutionResult[] = [ // Setup - PublicExecutionResultBuilder.fromPublicCallRequest({ request: publicCallRequests[0] }).build({ + PublicExecutionResultBuilder.fromPublicExecutionRequest({ request: nonRevertibleRequests[0] }).build({ startGasLeft: initialGas, endGasLeft: afterSetupGas, }), // App Logic - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: publicCallRequests[1], + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: revertibleRequests[0], contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 10, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 11, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 10), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 11), ], - contractStorageReads: [new ContractStorageRead(contractSlotA, fr(0x100), 19, baseContractAddress)], + contractStorageReads: [new ContractStorageRead(contractSlotA, fr(0x100), 19)], }).build({ startGasLeft: afterSetupGas, endGasLeft: afterAppGas, }), // Teardown - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: teardown!, + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: teardownRequest, nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: teardown!.contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), + from: teardownRequest.callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x103), 16, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 17, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x103), 16), + new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 17), ], - contractStorageReads: [new ContractStorageRead(contractSlotA, fr(0x102), 15, baseContractAddress)], + contractStorageReads: [new ContractStorageRead(contractSlotA, fr(0x102), 15)], }).build({ startGasLeft: teardownGas, endGasLeft: teardownGas, transactionFee }), PublicExecutionResultBuilder.fromFunctionCall({ - from: teardown!.contractAddress, - tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), + from: teardownRequest.callContext.storageContractAddress, + tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 13, baseContractAddress), - new ContractStorageUpdateRequest(contractSlotB, fr(0x152), 14, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 13), + new ContractStorageUpdateRequest(contractSlotB, fr(0x152), 14), ], - contractStorageReads: [new ContractStorageRead(contractSlotA, fr(0x101), 12, baseContractAddress)], + contractStorageReads: [new ContractStorageRead(contractSlotA, fr(0x101), 12)], }).build({ startGasLeft: teardownGas, endGasLeft: teardownGas, transactionFee }), ], }).build({ @@ -1002,16 +884,13 @@ describe('public_processor', () => { expect(processed[0].gasUsed[PublicKernelType.NON_PUBLIC]).toBeUndefined(); const txEffect = toTxEffect(processed[0], GasFees.default()); - expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toEqual(3); - expect(txEffect.publicDataWrites[0]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotB), fr(0x152)), - ); - expect(txEffect.publicDataWrites[1]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x103)), - ); - expect(txEffect.publicDataWrites[2]).toEqual( - new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotC), fr(0x201)), - ); + const numPublicDataWrites = 3; + expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toEqual(numPublicDataWrites); + expect(txEffect.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), fr(0x103)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x152)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotC), fr(0x201)), + ]); expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(0); expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(0); @@ -1019,15 +898,14 @@ describe('public_processor', () => { }); it('runs a tx with only teardown', async function () { - const baseContractAddressSeed = 0x200; - const teardown = makePublicCallRequest(baseContractAddressSeed); - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 0, - publicCallRequests: [], - publicTeardownCallRequest: teardown, + hasPublicTeardownCallRequest: true, }); + const teardownRequest = tx.getPublicTeardownExecutionRequest()!; + const gasLimits = Gas.from({ l2Gas: 1e9, daGas: 1e9 }); const teardownGas = Gas.from({ l2Gas: 1e7, daGas: 1e7 }); tx.data.constants.txContext.gasSettings = GasSettings.from({ @@ -1055,8 +933,8 @@ describe('public_processor', () => { const simulatorResults: PublicExecutionResult[] = [ // Teardown - PublicExecutionResultBuilder.fromPublicCallRequest({ - request: teardown, + PublicExecutionResultBuilder.fromPublicExecutionRequest({ + request: teardownRequest, nestedExecutions: [], }).build({ startGasLeft: teardownGas, @@ -1097,9 +975,9 @@ describe('public_processor', () => { const feePayer = AztecAddress.random(); const initialBalance = BigInt(1e12); const inclusionFee = 100n; - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { + numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 0, - publicTeardownCallRequest: PublicCallRequest.empty(), feePayer, }); @@ -1137,9 +1015,9 @@ describe('public_processor', () => { const feePayer = AztecAddress.random(); const initialBalance = BigInt(1e12); const inclusionFee = 100n; - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { + numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 2, - publicTeardownCallRequest: PublicCallRequest.empty(), feePayer, }); @@ -1153,16 +1031,6 @@ describe('public_processor', () => { Promise.resolve(computePublicDataTreeLeafSlot(address, slot).toBigInt()), ); - publicExecutor.simulate.mockImplementation(execution => { - for (const request of tx.enqueuedPublicFunctionCalls) { - if (execution.contractAddress.equals(request.contractAddress)) { - const result = PublicExecutionResultBuilder.fromPublicCallRequest({ request }).build(); - return Promise.resolve(result); - } - } - throw new Error(`Unexpected execution request: ${execution}`); - }); - const [processed, failed] = await processor.process([tx], 1, prover); expect(failed.map(f => f.error)).toEqual([]); @@ -1189,9 +1057,9 @@ describe('public_processor', () => { const feePayer = AztecAddress.random(); const initialBalance = BigInt(1e12); const inclusionFee = 100n; - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { + numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 2, - publicTeardownCallRequest: PublicCallRequest.empty(), feePayer, }); @@ -1205,16 +1073,6 @@ describe('public_processor', () => { Promise.resolve(computePublicDataTreeLeafSlot(address, slot).toBigInt()), ); - publicExecutor.simulate.mockImplementation(execution => { - for (const request of tx.enqueuedPublicFunctionCalls) { - if (execution.contractAddress.equals(request.contractAddress)) { - const result = PublicExecutionResultBuilder.fromPublicCallRequest({ request }).build(); - return Promise.resolve(result); - } - } - throw new Error(`Unexpected execution request: ${execution}`); - }); - tx.data.publicInputs.end.publicDataUpdateRequests[0] = PublicDataUpdateRequest.from({ leafIndex: computeFeePayerBalanceLeafSlot(feePayer), newValue: new Fr(initialBalance), @@ -1247,9 +1105,9 @@ describe('public_processor', () => { const feePayer = AztecAddress.random(); const initialBalance = 1n; const inclusionFee = 100n; - const tx = mockTxWithPartialState({ + const tx = mockTx(1, { + numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 0, - publicTeardownCallRequest: PublicCallRequest.empty(), feePayer, }); diff --git a/yarn-project/simulator/src/public/setup_phase_manager.test.ts b/yarn-project/simulator/src/public/setup_phase_manager.test.ts index e6a53be713ac..41bfa9ea5a76 100644 --- a/yarn-project/simulator/src/public/setup_phase_manager.test.ts +++ b/yarn-project/simulator/src/public/setup_phase_manager.test.ts @@ -1,5 +1,5 @@ import { mockTx } from '@aztec/circuit-types'; -import { GlobalVariables, Header, PublicAccumulatedDataBuilder } from '@aztec/circuits.js'; +import { GlobalVariables, Header } from '@aztec/circuits.js'; import { type PublicExecutor } from '@aztec/simulator'; import { type MerkleTreeOperations, type TreeInfo } from '@aztec/world-state'; @@ -48,17 +48,7 @@ describe('setup_phase_manager', () => { }); it('does not extract non-revertible calls when none exist', function () { - const tx = mockTx(); - - tx.data.forPublic!.end = PublicAccumulatedDataBuilder.fromPublicAccumulatedData(tx.data.forPublic!.end) - .withPublicCallStack([]) - .build(); - - tx.data.forPublic!.endNonRevertibleData = PublicAccumulatedDataBuilder.fromPublicAccumulatedData( - tx.data.forPublic!.endNonRevertibleData, - ) - .withPublicCallStack([]) - .build(); + const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 0 }); const enqueuedNonRevertibleCalls = phaseManager.extractEnqueuedPublicCalls(tx); diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts index a42be29f898d..dbbe1c8ac370 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.ts @@ -1,4 +1,4 @@ -import { UnencryptedFunctionL2Logs, UnencryptedL2Log } from '@aztec/circuit-types'; +import { PublicExecutionRequest, UnencryptedFunctionL2Logs, UnencryptedL2Log } from '@aztec/circuit-types'; import { AvmContractInstanceHint, AvmExecutionHints, @@ -14,6 +14,7 @@ import { LogHash, NoteHash, Nullifier, + type PublicCallRequest, ReadRequest, } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; @@ -23,7 +24,7 @@ import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type AvmContractCallResult } from '../avm/avm_contract_call_result.js'; import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; import { createSimulationError } from '../common/errors.js'; -import { type PublicExecutionRequest, type PublicExecutionResult } from './execution.js'; +import { type PublicExecutionResult, resultToPublicCallRequest } from './execution.js'; import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js'; export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress; @@ -51,6 +52,8 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { private allUnencryptedLogs: UnencryptedL2Log[] = []; private unencryptedLogsHashes: LogHash[] = []; + private publicCallRequests: PublicCallRequest[] = []; + private gotContractInstances: ContractInstanceWithAddress[] = []; private nestedExecutions: PublicExecutionResult[] = []; @@ -247,6 +250,9 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { result.startGasLeft.daGas - result.endGasLeft.daGas, result.startGasLeft.l2Gas - result.endGasLeft.l2Gas, ); + + this.publicCallRequests.push(resultToPublicCallRequest(result)); + this.avmCircuitHints.externalCalls.items.push( new AvmExternalCallHint( /*success=*/ new Fr(result.reverted ? 0 : 1), @@ -305,6 +311,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { // TODO(dbanks12): process contract instance read requests in public kernel //gotContractInstances: this.gotContractInstances, + publicCallRequests: this.publicCallRequests, nestedExecutions: this.nestedExecutions, avmCircuitHints: this.avmCircuitHints, @@ -325,11 +332,10 @@ function createPublicExecutionRequest(avmEnvironment: AvmExecutionEnvironment): isDelegateCall: avmEnvironment.isDelegateCall, isStaticCall: avmEnvironment.isStaticCall, }); - return { - contractAddress: avmEnvironment.address, - functionSelector: avmEnvironment.functionSelector, + return new PublicExecutionRequest( + avmEnvironment.address, callContext, // execution request does not contain AvmContextInputs prefix - args: avmEnvironment.getCalldataWithoutPrefix(), - }; + avmEnvironment.getCalldataWithoutPrefix(), + ); } diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 7fcaebffdb95..474ba90cbe96 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -9,13 +9,13 @@ import { NullifierMembershipWitness, PublicDataWitness, PublicDataWrite, + PublicExecutionRequest, TaggedLog, type UnencryptedL2Log, } from '@aztec/circuit-types'; import { type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats'; import { CallContext, - FunctionData, Gas, GlobalVariables, Header, @@ -25,10 +25,8 @@ import { type NullifierLeafPreimage, PUBLIC_DATA_SUBTREE_HEIGHT, type PUBLIC_DATA_TREE_HEIGHT, - PrivateCallStackItem, PrivateCircuitPublicInputs, PrivateContextInputs, - PublicCallRequest, PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, TxContext, @@ -553,7 +551,7 @@ export class TXE implements TypedOracle { sideEffectCounter: number, isStaticCall: boolean, isDelegateCall: boolean, - ): Promise { + ) { this.logger.verbose( `Executing external function ${targetContractAddress}:${functionSelector}(${await this.getDebugFunctionName( targetContractAddress, @@ -609,13 +607,9 @@ export class TXE implements TypedOracle { appCircuitName: 'noname', } satisfies CircuitWitnessGenerationStats); - const callStackItem = new PrivateCallStackItem( - targetContractAddress, - new FunctionData(functionSelector, true), - publicInputs, - ); // Apply side effects - this.sideEffectsCounter = publicInputs.endSideEffectCounter.toNumber(); + const endSideEffectCounter = publicInputs.endSideEffectCounter; + this.sideEffectsCounter = endSideEffectCounter.toNumber(); await this.addNullifiers( targetContractAddress, @@ -627,7 +621,7 @@ export class TXE implements TypedOracle { publicInputs.noteHashes.filter(noteHash => !noteHash.isEmpty()).map(noteHash => noteHash.value), ); - return callStackItem; + return { endSideEffectCounter, returnsHash: publicInputs.returnsHash }; } finally { this.setContractAddress(currentContractAddress); this.setMsgSender(currentMessageSender); @@ -682,12 +676,7 @@ export class TXE implements TypedOracle { return `${artifact.name}:${f.name}`; } - async executePublicFunction( - targetContractAddress: AztecAddress, - functionSelector: FunctionSelector, - args: Fr[], - callContext: CallContext, - ) { + async executePublicFunction(targetContractAddress: AztecAddress, args: Fr[], callContext: CallContext) { const header = Header.empty(); header.state = await this.trees.getStateReference(true); header.globalVariables.blockNumber = new Fr(await this.getBlockNumber()); @@ -709,12 +698,7 @@ export class TXE implements TypedOracle { new WorldStateDB(this.trees.asLatest()), header, ); - const execution = { - contractAddress: targetContractAddress, - functionSelector, - args, - callContext, - }; + const execution = new PublicExecutionRequest(targetContractAddress, callContext, args); return executor.simulate( execution, @@ -748,12 +732,7 @@ export class TXE implements TypedOracle { callContext.isStaticCall = isStaticCall; callContext.isDelegateCall = isDelegateCall; - const executionResult = await this.executePublicFunction( - targetContractAddress, - functionSelector, - args, - callContext, - ); + const executionResult = await this.executePublicFunction(targetContractAddress, args, callContext); // Apply side effects if (!executionResult.reverted) { @@ -770,7 +749,7 @@ export class TXE implements TypedOracle { targetContractAddress: AztecAddress, functionSelector: FunctionSelector, argsHash: Fr, - sideEffectCounter: number, + _sideEffectCounter: number, isStaticCall: boolean, isDelegateCall: boolean, ): Promise { @@ -791,12 +770,7 @@ export class TXE implements TypedOracle { const args = this.packedValuesCache.unpack(argsHash); - const executionResult = await this.executePublicFunction( - targetContractAddress, - functionSelector, - args, - callContext, - ); + const executionResult = await this.executePublicFunction(targetContractAddress, args, callContext); // Apply side effects this.sideEffectsCounter = executionResult.endSideEffectCounter.toNumber(); @@ -811,10 +785,10 @@ export class TXE implements TypedOracle { targetContractAddress: AztecAddress, functionSelector: FunctionSelector, argsHash: Fr, - sideEffectCounter: number, + _sideEffectCounter: number, isStaticCall: boolean, isDelegateCall: boolean, - ): Promise { + ) { // Store and modify env const currentContractAddress = AztecAddress.fromField(this.contractAddress); const currentMessageSender = AztecAddress.fromField(this.msgSender); @@ -832,47 +806,26 @@ export class TXE implements TypedOracle { const args = this.packedValuesCache.unpack(argsHash); - const executionResult = await this.executePublicFunction( - targetContractAddress, - functionSelector, - args, - callContext, - ); + const executionResult = await this.executePublicFunction(targetContractAddress, args, callContext); // Apply side effects this.sideEffectsCounter += executionResult.endSideEffectCounter.toNumber(); this.setContractAddress(currentContractAddress); this.setMsgSender(currentMessageSender); this.setFunctionSelector(currentFunctionSelector); - - const parentCallContext = CallContext.empty(); - parentCallContext.msgSender = currentMessageSender; - parentCallContext.functionSelector = currentFunctionSelector; - parentCallContext.storageContractAddress = currentContractAddress; - parentCallContext.isStaticCall = isStaticCall; - parentCallContext.isDelegateCall = isDelegateCall; - - return PublicCallRequest.from({ - parentCallContext, - contractAddress: targetContractAddress, - functionSelector, - callContext, - sideEffectCounter, - args, - }); } - setPublicTeardownFunctionCall( + async setPublicTeardownFunctionCall( targetContractAddress: AztecAddress, functionSelector: FunctionSelector, argsHash: Fr, sideEffectCounter: number, isStaticCall: boolean, isDelegateCall: boolean, - ): Promise { + ) { // Definitely not right, in that the teardown should always be last. // But useful for executing flows. - return this.enqueuePublicFunctionCall( + await this.enqueuePublicFunctionCall( targetContractAddress, functionSelector, argsHash, diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 019e331d2bdb..45de5f2fe61e 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -638,7 +638,7 @@ export class TXEService { fromSingle(isStaticCall).toBool(), fromSingle(isDelegateCall).toBool(), ); - return toForeignCallResult([toArray(result.toFields())]); + return toForeignCallResult([toArray([result.endSideEffectCounter, result.returnsHash])]); } async getNullifierMembershipWitness(blockNumber: ForeignCallSingle, nullifier: ForeignCallSingle) { @@ -667,7 +667,7 @@ export class TXEService { isStaticCall: ForeignCallSingle, isDelegateCall: ForeignCallSingle, ) { - const publicCallRequest = await this.typedOracle.enqueuePublicFunctionCall( + await this.typedOracle.enqueuePublicFunctionCall( fromSingle(targetContractAddress), FunctionSelector.fromField(fromSingle(functionSelector)), fromSingle(argsHash), @@ -675,14 +675,7 @@ export class TXEService { fromSingle(isStaticCall).toBool(), fromSingle(isDelegateCall).toBool(), ); - const fields = [ - publicCallRequest.contractAddress.toField(), - publicCallRequest.functionSelector.toField(), - ...publicCallRequest.callContext.toFields(), - fromSingle(sideEffectCounter), - publicCallRequest.getArgsHash(), - ]; - return toForeignCallResult([toArray(fields)]); + return toForeignCallResult([]); } public async setPublicTeardownFunctionCall( @@ -693,7 +686,7 @@ export class TXEService { isStaticCall: ForeignCallSingle, isDelegateCall: ForeignCallSingle, ) { - const publicTeardownCallRequest = await this.typedOracle.setPublicTeardownFunctionCall( + await this.typedOracle.setPublicTeardownFunctionCall( fromSingle(targetContractAddress), FunctionSelector.fromField(fromSingle(functionSelector)), fromSingle(argsHash), @@ -701,16 +694,7 @@ export class TXEService { fromSingle(isStaticCall).toBool(), fromSingle(isDelegateCall).toBool(), ); - - const fields = [ - publicTeardownCallRequest.contractAddress.toField(), - publicTeardownCallRequest.functionSelector.toField(), - ...publicTeardownCallRequest.callContext.toFields(), - fromSingle(sideEffectCounter), - publicTeardownCallRequest.getArgsHash(), - ]; - - return toForeignCallResult([toArray(fields)]); + return toForeignCallResult([]); } async getChainId() {