From 4d8b51caf477ff83390ec6b40f11b0768e57903f Mon Sep 17 00:00:00 2001 From: just-mitch <68168980+just-mitch@users.noreply.github.com> Date: Fri, 3 May 2024 15:35:09 -0600 Subject: [PATCH] feat: expose set_public_teardown_function in private context (#6199) See [spec](https://docs.aztec.network/protocol-specs/gas-and-fees/tx-setup-and-teardown) No additional business logic here, just exposing the planned interface. --- .github/workflows/ci.yml | 4 +- .../src/core/libraries/ConstantsGen.sol | 2 +- .../aztec/src/context/private_context.nr | 146 ++++++++++-------- .../oracle/enqueue_public_function_call.nr | 85 +++++++++- .../types/src/abis/private_call_stack_item.nr | 2 +- .../src/abis/private_circuit_public_inputs.nr | 6 +- .../crates/types/src/constants.nr | 2 +- .../private_circuit_public_inputs_builder.nr | 4 + yarn-project/circuits.js/src/constants.gen.ts | 1 + .../private_call_stack_item.test.ts.snap | 4 +- ...private_circuit_public_inputs.test.ts.snap | 4 +- .../structs/private_circuit_public_inputs.ts | 9 ++ .../circuits.js/src/tests/factories.ts | 1 + .../src/type_conversion.ts | 1 + 14 files changed, 196 insertions(+), 75 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad0e789d6ca..cc7fa5753ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -192,7 +192,7 @@ jobs: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" concurrency_key: yarn-project-test-${{ github.actor }}-x86 - name: "Yarn Project Tests" - timeout-minutes: 25 + timeout-minutes: 30 run: earthly-ci --no-output ./yarn-project/+test prover-client-test: @@ -292,7 +292,7 @@ jobs: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" concurrency_key: docs-preview-${{ inputs.username || github.actor }}-x86 - name: "Docs Preview" - timeout-minutes: 25 + timeout-minutes: 30 run: earthly --no-output ./docs/+deploy-preview --PR=${{ github.event.number }} --AZTEC_BOT_COMMENTER_GITHUB_TOKEN=${{ secrets.AZTEC_BOT_GITHUB_TOKEN }} --NETLIFY_AUTH_TOKEN=${{ secrets.NETLIFY_AUTH_TOKEN }} --NETLIFY_SITE_ID=${{ secrets.NETLIFY_SITE_ID }} # push benchmarking binaries to dockerhub registry diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 3e5ec74866d..8a9200aaee6 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -137,7 +137,7 @@ library Constants { + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL - + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; 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 b5d5621bd10..0411ba566a0 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -4,34 +4,32 @@ use crate::{ hash::{hash_args_array, ArgsHasher, compute_encrypted_log_hash, compute_unencrypted_log_hash}, oracle::{ arguments, returns, call_private_function::call_private_function_internal, - enqueue_public_function_call::enqueue_public_function_call_internal, header::get_header_at, - logs::emit_encrypted_log, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, + enqueue_public_function_call::{ + enqueue_public_function_call_internal, set_public_teardown_function_call_internal, + parse_public_call_stack_item_from_oracle +}, + header::get_header_at, logs::emit_encrypted_log, + logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, nullifier_key::{get_nullifier_keys, NullifierKeys} } }; use dep::protocol_types::{ abis::{ - global_variables::GlobalVariables, gas::Gas, call_context::CallContext, function_data::FunctionData, function_selector::FunctionSelector, max_block_number::MaxBlockNumber, nullifier_key_validation_request::NullifierKeyValidationRequest, - private_call_stack_item::PrivateCallStackItem, private_circuit_public_inputs::PrivateCircuitPublicInputs, - public_call_stack_item::PublicCallStackItem, - public_circuit_public_inputs::PublicCircuitPublicInputs, read_request::ReadRequest, - note_hash::NoteHash, nullifier::Nullifier, side_effect::SideEffect + public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash, + nullifier::Nullifier, side_effect::SideEffect }, address::{AztecAddress, EthAddress}, constants::{ MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, - MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, + MAX_UNENCRYPTED_LOGS_PER_CALL }, - contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, - grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header, - messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, + grumpkin_point::GrumpkinPoint, header::Header, messaging::l2_to_l1_message::L2ToL1Message, traits::{is_empty, Deserialize, Empty} }; @@ -57,6 +55,7 @@ struct PrivateContext { private_call_stack_hashes : BoundedVec, public_call_stack_hashes : BoundedVec, + public_teardown_function_hash: Field, new_l2_to_l1_msgs : BoundedVec, // docs:end:private-context @@ -129,6 +128,7 @@ impl PrivateContext { historical_header: inputs.historical_header, private_call_stack_hashes: BoundedVec::new(), public_call_stack_hashes: BoundedVec::new(), + public_teardown_function_hash: 0, new_l2_to_l1_msgs: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), @@ -169,6 +169,7 @@ impl PrivateContext { new_nullifiers: self.new_nullifiers.storage, private_call_stack_hashes: self.private_call_stack_hashes.storage, public_call_stack_hashes: self.public_call_stack_hashes.storage, + public_teardown_function_hash: self.public_teardown_function_hash, new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, start_side_effect_counter: self.inputs.start_side_effect_counter, end_side_effect_counter: self.side_effect_counter, @@ -257,11 +258,7 @@ impl PrivateContext { let event_selector = 5; // TODO: compute actual event selector. let contract_address = self.this_address(); let log_slice = log.to_be_bytes_arr(); - let log_hash = compute_unencrypted_log_hash( - contract_address, - event_selector, - log, - ); + let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log); let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; self.unencrypted_logs_hashes.push(side_effect); self.side_effect_counter = self.side_effect_counter + 1; @@ -281,12 +278,7 @@ impl PrivateContext { pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) { let event_selector = 5; // TODO: compute actual event selector. let contract_address = self.this_address(); - let log_hash = emit_contract_class_unencrypted_log_private_internal( - contract_address, - event_selector, - log, - self.side_effect_counter - ); + let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, self.side_effect_counter); let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; self.unencrypted_logs_hashes.push(side_effect); self.side_effect_counter = self.side_effect_counter + 1; @@ -316,7 +308,7 @@ impl PrivateContext { let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; self.encrypted_logs_hashes.push(side_effect); self.side_effect_counter = self.side_effect_counter + 1; - let encrypted_log_byte_len = 112 + 32*(N + 3); + let encrypted_log_byte_len = 112 + 32 * (N + 3); // + processed log len (4) self.encrypted_log_preimages_length += encrypted_log_byte_len + 4; } @@ -516,47 +508,77 @@ impl PrivateContext { is_delegate_call ); - 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! - let item = PublicCallStackItem { - contract_address: AztecAddress::from_field(reader.read()), - function_data: reader.read_struct(FunctionData::deserialize), - public_inputs: PublicCircuitPublicInputs { - call_context: reader.read_struct(CallContext::deserialize), - args_hash: reader.read(), - returns_hash: 0, - 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], - 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], - new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL], - new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL], - new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], - start_side_effect_counter: 0, - end_side_effect_counter: 0, - unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], - unencrypted_log_preimages_length: 0, - 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(); + let item = parse_public_call_stack_item_from_oracle(fields); + self.validate_call_stack_item_from_oracle( + item, + 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.hash()); + } + + pub fn set_public_teardown_function( + &mut self, + contract_address: AztecAddress, + function_selector: FunctionSelector, + args: [Field; ARGS_COUNT] + ) { + let args_hash = hash_args_array(args); + assert(args_hash == arguments::pack_arguments_array(args)); + self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false) + } + + pub fn set_public_teardown_function_with_packed_args( + &mut self, + contract_address: AztecAddress, + function_selector: FunctionSelector, + args_hash: Field, + is_static_call: bool, + is_delegate_call: bool + ) { + let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call; + let fields = set_public_teardown_function_call_internal( + contract_address, + function_selector, + args_hash, + self.side_effect_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, + 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.hash(); + } + + fn validate_call_stack_item_from_oracle( + 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.call_context.side_effect_counter, self.side_effect_counter); // We increment the sideffect counter by one, to account for the call itself being a side effect. - self.side_effect_counter = self.side_effect_counter + 1; assert(args_hash == item.public_inputs.args_hash); @@ -577,8 +599,6 @@ impl PrivateContext { item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address) ); } - - self.public_call_stack_hashes.push(item.hash()); } } @@ -598,6 +618,7 @@ impl Empty for PrivateContext { new_nullifiers: BoundedVec::new(), private_call_stack_hashes : BoundedVec::new(), public_call_stack_hashes : BoundedVec::new(), + public_teardown_function_hash: 0, new_l2_to_l1_msgs : BoundedVec::new(), historical_header: Header::empty(), encrypted_logs_hashes: BoundedVec::new(), @@ -663,7 +684,6 @@ fn emit_contract_class_unencrypted_log_private( counter: u32 ) -> Field {} - unconstrained pub fn emit_contract_class_unencrypted_log_private_internal( contract_address: AztecAddress, event_selector: Field, 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 28bcb331240..65341ba396a 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,6 +1,20 @@ use dep::protocol_types::{ - abis::function_selector::FunctionSelector, address::AztecAddress, - constants::ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH + 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, + side_effect::SideEffect, 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_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_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 +} }; #[oracle(enqueuePublicFunctionCall)] @@ -30,3 +44,70 @@ unconstrained pub fn enqueue_public_function_call_internal( is_delegate_call ) } + +#[oracle(setPublicTeardownFunctionCall)] +fn set_public_teardown_function_call_oracle( + _contract_address: AztecAddress, + _function_selector: FunctionSelector, + _args_hash: Field, + _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, + function_selector: FunctionSelector, + args_hash: Field, + 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, + args_hash, + 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! + let item = PublicCallStackItem { + contract_address: AztecAddress::from_field(reader.read()), + function_data: reader.read_struct(FunctionData::deserialize), + public_inputs: PublicCircuitPublicInputs { + call_context: reader.read_struct(CallContext::deserialize), + args_hash: reader.read(), + returns_hash: 0, + 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], + 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], + new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL], + new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL], + new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], + start_side_effect_counter: 0, + end_side_effect_counter: 0, + unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], + unencrypted_log_preimages_length: 0, + 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/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index 7fc8c7a86c0..652bceb0fe1 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 = 0x17fd6ffcb3394b845069dc87e055c37ac50599f274130fac69c6fe919bfe382e; + let test_data_empty_hash = 0x2485b8cfe671417410382ba6dfc803de70d9d45008a1b30c31b34d7c4de92106; 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 e4dc6851f99..e48226fa1f4 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 @@ -35,6 +35,7 @@ struct PrivateCircuitPublicInputs { new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL], private_call_stack_hashes: [Field; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL], public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + public_teardown_function_hash: Field, new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter : u32, @@ -109,6 +110,7 @@ impl Serialize for PrivateCircuitPublicInp } fields.extend_from_array(self.private_call_stack_hashes); fields.extend_from_array(self.public_call_stack_hashes); + fields.push(self.public_teardown_function_hash); for i in 0..self.new_l2_to_l1_msgs.len() { fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize()); } @@ -148,6 +150,7 @@ impl Deserialize for PrivateCircuitPublicI new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]), private_call_stack_hashes: reader.read_array([0; 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(), new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]), start_side_effect_counter: reader.read() as u32, end_side_effect_counter: reader.read() as u32, @@ -185,6 +188,7 @@ impl Empty for PrivateCircuitPublicInputs { new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL], private_call_stack_hashes: [0; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL], public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], + public_teardown_function_hash: 0, new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter : 0 as u32, end_side_effect_counter : 0 as u32, @@ -211,6 +215,6 @@ 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 = 0x29129c06414f4ac73bf889692c7011f91727d4cdbfe4fe143e6adee69b565cc8; + let test_data_empty_hash = 0x249d46b5a3e35f6489e793cd604e375634d4bfdac762ec06b5f8f03016bb4257; 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 ba2fc9ab0f0..ad82df9c822 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -169,7 +169,7 @@ global STATE_REFERENCE_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_ global TX_CONTEXT_LENGTH: u64 = 2 + GAS_SETTINGS_LENGTH; global TX_REQUEST_LENGTH: u64 = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; global HEADER_LENGTH: u64 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; -global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 3 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; +global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 3 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_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_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr index 2f4ed8d08e7..a8cc18978b8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr @@ -39,6 +39,7 @@ struct PrivateCircuitPublicInputsBuilder { private_call_stack_hashes: BoundedVec, public_call_stack_hashes: BoundedVec, + public_teardown_function_hash: Field, new_l2_to_l1_msgs: BoundedVec, encrypted_logs_hashes: BoundedVec, @@ -81,6 +82,7 @@ impl PrivateCircuitPublicInputsBuilder { public_inputs.chain_id = 0; public_inputs.version = 1; public_inputs.gas_settings = GasSettings::default(); + public_inputs.public_teardown_function_hash = 0; public_inputs } @@ -103,6 +105,7 @@ impl PrivateCircuitPublicInputsBuilder { new_nullifiers: self.new_nullifiers.storage, private_call_stack_hashes: self.private_call_stack_hashes.storage, public_call_stack_hashes: self.public_call_stack_hashes.storage, + public_teardown_function_hash: self.public_teardown_function_hash, new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, start_side_effect_counter: self.call_context.side_effect_counter, end_side_effect_counter: 10, @@ -131,6 +134,7 @@ impl Empty for PrivateCircuitPublicInputsBuilder { new_nullifiers: BoundedVec::new(), private_call_stack_hashes: BoundedVec::new(), public_call_stack_hashes: BoundedVec::new(), + public_teardown_function_hash: 0, new_l2_to_l1_msgs: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 094991c36b0..70d3975bfea 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -124,6 +124,7 @@ export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + + 1 + L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL + 2 + SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL + 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 0a6b285dc0c..36a5ad79d94 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<0x17fd6ffcb3394b845069dc87e055c37ac50599f274130fac69c6fe919bfe382e>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x2485b8cfe671417410382ba6dfc803de70d9d45008a1b30c31b34d7c4de92106>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x07e0e054d39be2aab72d74cc72ef8adc61016744fd985c6736e14e710d14c875>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x0efad8edafef07ee5165f01a51dec26edc7fd28f55eff90478d86f8a95a5352b>`; 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 72ffed28cf3..a01d735ecb7 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<0x29129c06414f4ac73bf889692c7011f91727d4cdbfe4fe143e6adee69b565cc8>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x249d46b5a3e35f6489e793cd604e375634d4bfdac762ec06b5f8f03016bb4257>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0ab17c0893be4023ff61f8c2df5a0106c1709f7b10c2fadd53581da7a7d799d6>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x2f33953d4e47a0ebbe6ae3f4785ada5d107383e82038e7caf27cc37fdb69a088>`; 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 ef3b61190ed..8697c01cbdd 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 @@ -94,6 +94,10 @@ export class PrivateCircuitPublicInputs { * Public call stack at the current kernel iteration. */ public publicCallStackHashes: Tuple, + /** + * Hash of the public teardown function. + */ + public publicTeardownFunctionHash: Fr, /** * New L2 to L1 messages created by the corresponding function call. */ @@ -169,6 +173,7 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NEW_NULLIFIERS_PER_CALL, Nullifier), reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, Fr), reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, Fr), + reader.readObject(Fr), reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), reader.readObject(Fr), @@ -196,6 +201,7 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NEW_NULLIFIERS_PER_CALL, Nullifier), reader.readFieldArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL), reader.readFieldArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL), + reader.readField(), reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), reader.readField(), @@ -226,6 +232,7 @@ export class PrivateCircuitPublicInputs { makeTuple(MAX_NEW_NULLIFIERS_PER_CALL, Nullifier.empty), makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, Fr.zero), makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, Fr.zero), + Fr.ZERO, makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, Fr.ZERO, @@ -253,6 +260,7 @@ export class PrivateCircuitPublicInputs { isEmptyArray(this.newNullifiers) && isZeroArray(this.privateCallStackHashes) && isZeroArray(this.publicCallStackHashes) && + this.publicTeardownFunctionHash.isZero() && isEmptyArray(this.newL2ToL1Msgs) && isEmptyArray(this.encryptedLogsHashes) && isEmptyArray(this.unencryptedLogsHashes) && @@ -282,6 +290,7 @@ export class PrivateCircuitPublicInputs { fields.newNullifiers, fields.privateCallStackHashes, fields.publicCallStackHashes, + fields.publicTeardownFunctionHash, fields.newL2ToL1Msgs, fields.startSideEffectCounter, fields.endSideEffectCounter, diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 1e43ed44ebc..2f48780c24f 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -843,6 +843,7 @@ export function makePrivateCircuitPublicInputs(seed = 0): PrivateCircuitPublicIn newNullifiers: makeTuple(MAX_NEW_NULLIFIERS_PER_CALL, makeNullifier, seed + 0x500), privateCallStackHashes: makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, fr, seed + 0x600), publicCallStackHashes: makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, fr, seed + 0x700), + publicTeardownFunctionHash: fr(seed + 0x800), newL2ToL1Msgs: makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x800), startSideEffectCounter: fr(seed + 0x849), endSideEffectCounter: fr(seed + 0x850), 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 e641b21559a..a891b6c775c 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -748,6 +748,7 @@ export function mapPrivateCircuitPublicInputsToNoir( new_nullifiers: mapTuple(privateCircuitPublicInputs.newNullifiers, mapNullifierToNoir), private_call_stack_hashes: mapTuple(privateCircuitPublicInputs.privateCallStackHashes, mapFieldToNoir), public_call_stack_hashes: mapTuple(privateCircuitPublicInputs.publicCallStackHashes, mapFieldToNoir), + public_teardown_function_hash: mapFieldToNoir(privateCircuitPublicInputs.publicTeardownFunctionHash), new_l2_to_l1_msgs: mapTuple(privateCircuitPublicInputs.newL2ToL1Msgs, mapL2ToL1MessageToNoir), start_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.startSideEffectCounter), end_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.endSideEffectCounter),