diff --git a/docs/docs/_protocol-specs/transactions/local-execution.md b/docs/docs/_protocol-specs/transactions/local-execution.md index 70170bdb720..01ed56e5867 100644 --- a/docs/docs/_protocol-specs/transactions/local-execution.md +++ b/docs/docs/_protocol-specs/transactions/local-execution.md @@ -8,7 +8,6 @@ Mike review: - (We should probably adopt this approach throughout the protocol specs) - Link to any types / fields which are defined on some other page of the protocol specs (e.g. `AuthWitness`). - Is the hash used to compute `argsHash` protocol-defined or app-defined? If the former, we should define it (in a way which is consistent with all other hash definitions). -- How are the packed arguments packed? What's the encoding? Or is it app-specific and hence out-of-protocol? - "Entrypoint" is such an important term, perhaps it needs to be a subheading (with the text rearranged to accommodate such a subheading), for easier referencing and searching? - Do we need to describe how public functions will be simulated? (I'm not sure the sandbox does such simulation yet, but it ought to, eventually). - Where we link to definitions (such as "transaction"), if that definition is actually a specific struct, we should use the exact name of the struct, wrapped in backticks, to a subheading whose name exactly matches the name of the struct. @@ -25,12 +24,12 @@ A transaction execution request has the following structure. Note that, since Az | `functionSelector` | u32 | Selector (identifier) of the function to be called as entrypoint in the origin contract. | | `argsHash` | `Field` | Hash of the arguments to be used for calling the entrypoint function. | | `txContext` | `TxContext` | Includes chain id, protocol version, and gas settings. | -| `packedArguments` | `PackedValues[]` | Preimages for argument hashes. When executing a function call with the hash of the arguments, the PXE will look for the preimage of that hash in this list, and expand the arguments to execute the call. | +| `hashedArguments` | `HashedValues[]` | Preimages for argument hashes. When executing a function call with the hash of the arguments, the PXE will look for the preimage of that hash in this list, and expand the arguments to execute the call. | | `authWitnesses` | `AuthWitness[]` | Authorization witnesses. When authorizing an action identified by a hash, the PXE will look for the authorization witness identified by that hash and provide that value to the account contract. | ## Simulation step -Upon receiving a transaction execution request to _simulate_, the PXE will locally execute the function identified by the given `functionSelector` in the given `origin` contract with the arguments committed to by `argsHash`. We refer to this function as the _entrypoint_. During execution, contracts may request authorization witnesses or expanded arguments from the _execution oracle_ , which are answered with the `packedArguments` and `authWitnesses` from the request. +Upon receiving a transaction execution request to _simulate_, the PXE will locally execute the function identified by the given `functionSelector` in the given `origin` contract with the arguments committed to by `argsHash`. We refer to this function as the _entrypoint_. During execution, contracts may request authorization witnesses or expanded arguments from the _execution oracle_ , which are answered with the `hashedArguments` and `authWitnesses` from the request. The _entrypoint_ may enqueue additional function calls, either private or public. The simulation step will always execute all private functions in the call stack until emptied. The result of the simulation is a [_transaction_](./tx-object.md) object without an associated _proof_ which is returned to the application that requested the simulation. diff --git a/noir-projects/aztec-nr/authwit/src/auth.nr b/noir-projects/aztec-nr/authwit/src/auth.nr index 6c21bfaecdb..40e5d9e850a 100644 --- a/noir-projects/aztec-nr/authwit/src/auth.nr +++ b/noir-projects/aztec-nr/authwit/src/auth.nr @@ -232,7 +232,7 @@ pub fn assert_inner_hash_valid_authwit( comptime { FunctionSelector::from_signature("verify_private_authwit(Field)") }, [inner_hash], ) - .unpack_into(); + .get_preimage(); assert(result == IS_VALID_SELECTOR, "Message not authorized by account"); // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version. // Those should already be handled in the verification, so we just need something to nullify, that allows the same inner_hash for multiple actors. diff --git a/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr b/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr index 2733c736842..a909fe2261c 100644 --- a/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr +++ b/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr @@ -59,14 +59,14 @@ impl AppPayload { for call in self.function_calls { if !call.target_address.is_zero() { if call.is_public { - context.call_public_function_with_packed_args( + context.call_public_function_with_args_hash( call.target_address, call.function_selector, call.args_hash, call.is_static, ); } else { - let _result = context.call_private_function_with_packed_args( + let _result = context.call_private_function_with_args_hash( call.target_address, call.function_selector, call.args_hash, diff --git a/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr b/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr index 9647cf05067..3825b1dc673 100644 --- a/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr +++ b/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr @@ -58,14 +58,14 @@ impl FeePayload { for call in self.function_calls { if !call.target_address.is_zero() { if call.is_public { - context.call_public_function_with_packed_args( + context.call_public_function_with_args_hash( call.target_address, call.function_selector, call.args_hash, call.is_static, ); } else { - let _result = context.call_private_function_with_packed_args( + let _result = context.call_private_function_with_args_hash( call.target_address, call.function_selector, call.args_hash, diff --git a/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr b/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr index 6c15183e91d..84fca8e2da7 100644 --- a/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr +++ b/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr @@ -5,7 +5,7 @@ use dep::protocol_types::{ use crate::context::{gas::GasOpts, private_context::PrivateContext, public_context::PublicContext}; use crate::hash::hash_args; -use crate::oracle::arguments::pack_arguments; +use crate::oracle::execution_cache; pub trait CallInterface { fn get_args(self) -> [Field]; @@ -30,29 +30,29 @@ impl PrivateCallInterface { where T: Deserialize, { - pack_arguments(self.args); - let returns = context.call_private_function_with_packed_args( + execution_cache::store(self.args); + let returns_hash = context.call_private_function_with_args_hash( self.target_contract, self.selector, self.args_hash, false, ); - let unpacked: T = returns.unpack_into(); - unpacked + let returns: T = returns_hash.get_preimage(); + returns } pub fn view(self, context: &mut PrivateContext) -> T where T: Deserialize, { - pack_arguments(self.args); - let returns = context.call_private_function_with_packed_args( + execution_cache::store(self.args); + let returns_hash = context.call_private_function_with_args_hash( self.target_contract, self.selector, self.args_hash, true, ); - returns.unpack_into() + returns_hash.get_preimage() } } @@ -90,9 +90,9 @@ pub struct PrivateVoidCallInterface { impl PrivateVoidCallInterface { pub fn call(self, context: &mut PrivateContext) { - pack_arguments(self.args); + execution_cache::store(self.args); context - .call_private_function_with_packed_args( + .call_private_function_with_args_hash( self.target_contract, self.selector, self.args_hash, @@ -102,9 +102,9 @@ impl PrivateVoidCallInterface { } pub fn view(self, context: &mut PrivateContext) { - pack_arguments(self.args); + execution_cache::store(self.args); context - .call_private_function_with_packed_args( + .call_private_function_with_args_hash( self.target_contract, self.selector, self.args_hash, @@ -151,14 +151,14 @@ impl PrivateStaticCallInterface { where T: Deserialize, { - pack_arguments(self.args); - let returns = context.call_private_function_with_packed_args( + execution_cache::store(self.args); + let returns = context.call_private_function_with_args_hash( self.target_contract, self.selector, self.args_hash, true, ); - returns.unpack_into() + returns.get_preimage() } } @@ -196,9 +196,9 @@ pub struct PrivateStaticVoidCallInterface { impl PrivateStaticVoidCallInterface { pub fn view(self, context: &mut PrivateContext) { - pack_arguments(self.args); + execution_cache::store(self.args); context - .call_private_function_with_packed_args( + .call_private_function_with_args_hash( self.target_contract, self.selector, self.args_hash, @@ -274,8 +274,8 @@ impl PublicCallInterface { pub fn enqueue(self, context: &mut PrivateContext) { let args_hash = hash_args(self.args); - pack_arguments(self.args); - context.call_public_function_with_packed_args( + execution_cache::store(self.args); + context.call_public_function_with_args_hash( self.target_contract, self.selector, args_hash, @@ -286,8 +286,8 @@ impl PublicCallInterface { pub fn enqueue_view(self, context: &mut PrivateContext) { let args_hash = hash_args(self.args); - pack_arguments(self.args); - context.call_public_function_with_packed_args( + execution_cache::store(self.args); + context.call_public_function_with_args_hash( self.target_contract, self.selector, args_hash, @@ -357,8 +357,8 @@ impl PublicVoidCallInterface { pub fn enqueue(self, context: &mut PrivateContext) { let args_hash = hash_args(self.args); - pack_arguments(self.args); - context.call_public_function_with_packed_args( + execution_cache::store(self.args); + context.call_public_function_with_args_hash( self.target_contract, self.selector, args_hash, @@ -369,8 +369,8 @@ impl PublicVoidCallInterface { pub fn enqueue_view(self, context: &mut PrivateContext) { let args_hash = hash_args(self.args); - pack_arguments(self.args); - context.call_public_function_with_packed_args( + execution_cache::store(self.args); + context.call_public_function_with_args_hash( self.target_contract, self.selector, args_hash, @@ -433,8 +433,8 @@ impl PublicStaticCallInterface { pub fn enqueue_view(self, context: &mut PrivateContext) { let args_hash = hash_args(self.args); - pack_arguments(self.args); - context.call_public_function_with_packed_args( + execution_cache::store(self.args); + context.call_public_function_with_args_hash( self.target_contract, self.selector, args_hash, @@ -494,8 +494,8 @@ impl PublicStaticVoidCallInterface { pub fn enqueue_view(self, context: &mut PrivateContext) { let args_hash = hash_args(self.args); - pack_arguments(self.args); - context.call_public_function_with_packed_args( + execution_cache::store(self.args); + context.call_public_function_with_args_hash( self.target_contract, self.selector, args_hash, diff --git a/noir-projects/aztec-nr/aztec/src/context/mod.nr b/noir-projects/aztec-nr/aztec/src/context/mod.nr index 77db0e0e6a8..ee3d755abc2 100644 --- a/noir-projects/aztec-nr/aztec/src/context/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/context/mod.nr @@ -1,7 +1,7 @@ pub mod globals; pub mod inputs; -pub mod packed_returns; +pub mod returns_hash; pub mod private_context; pub mod public_context; pub mod unconstrained_context; @@ -14,7 +14,7 @@ pub use call_interfaces::{ PrivateVoidCallInterface, PublicCallInterface, PublicStaticCallInterface, PublicStaticVoidCallInterface, PublicVoidCallInterface, }; -pub use packed_returns::PackedReturns; pub use private_context::PrivateContext; pub use public_context::PublicContext; +pub use returns_hash::ReturnsHash; pub use unconstrained_context::UnconstrainedContext; diff --git a/noir-projects/aztec-nr/aztec/src/context/packed_returns.nr b/noir-projects/aztec-nr/aztec/src/context/packed_returns.nr deleted file mode 100644 index ebb86a9621f..00000000000 --- a/noir-projects/aztec-nr/aztec/src/context/packed_returns.nr +++ /dev/null @@ -1,36 +0,0 @@ -use crate::{hash::hash_args_array, oracle::returns::unpack_returns}; -use dep::protocol_types::traits::Deserialize; - -pub struct PackedReturns { - packed_returns: Field, -} - -impl PackedReturns { - pub fn new(packed_returns: Field) -> Self { - PackedReturns { packed_returns } - } - - pub fn assert_empty(self) { - assert_eq(self.packed_returns, 0); - } - - pub fn raw(self) -> Field { - self.packed_returns - } - - pub fn unpack(self) -> [Field; N] { - // We verify that the value returned by `unpack_returns` is the preimage of `packed_returns`, fully constraining - // it. - let unpacked: [Field; N] = unsafe { unpack_returns(self.packed_returns) }; - assert_eq(self.packed_returns, hash_args_array(unpacked)); - unpacked - } - - pub fn unpack_into(self) -> T - where - T: Deserialize, - { - let unpacked: [Field; N] = self.unpack(); - Deserialize::deserialize(unpacked) - } -} 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 e0ea249df30..38fc05b8ae2 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -1,20 +1,19 @@ use dep::protocol_types::debug_log::debug_log_format; use crate::{ - context::{inputs::PrivateContextInputs, packed_returns::PackedReturns}, + context::{inputs::PrivateContextInputs, returns_hash::ReturnsHash}, hash::{ArgsHasher, hash_args_array}, keys::constants::{NULLIFIER_INDEX, NUM_KEY_TYPES, OUTGOING_INDEX, sk_generators}, messaging::process_l1_to_l2_message, oracle::{ - arguments, block_header::get_block_header_at, call_private_function::call_private_function_internal, enqueue_public_function_call::{ enqueue_public_function_call_internal, notify_set_min_revertible_side_effect_counter, set_public_teardown_function_call_internal, }, + execution_cache, key_validation_request::get_key_validation_request, - returns::pack_returns, }, }; use dep::protocol_types::{ @@ -176,7 +175,7 @@ impl PrivateContext { } pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) { - pack_returns(returns_hasher.fields); + execution_cache::store(returns_hasher.fields); self.return_hash = returns_hasher.hash(); } @@ -332,10 +331,10 @@ impl PrivateContext { contract_address: AztecAddress, function_selector: FunctionSelector, args: [Field; ARGS_COUNT], - ) -> PackedReturns { + ) -> ReturnsHash { let args_hash = hash_args_array(args); - arguments::pack_arguments_array(args); - self.call_private_function_with_packed_args( + execution_cache::store_array(args); + self.call_private_function_with_args_hash( contract_address, function_selector, args_hash, @@ -348,10 +347,10 @@ impl PrivateContext { contract_address: AztecAddress, function_selector: FunctionSelector, args: [Field; ARGS_COUNT], - ) -> PackedReturns { + ) -> ReturnsHash { let args_hash = hash_args_array(args); - arguments::pack_arguments_array(args); - self.call_private_function_with_packed_args( + execution_cache::store_array(args); + self.call_private_function_with_args_hash( contract_address, function_selector, args_hash, @@ -363,25 +362,25 @@ impl PrivateContext { &mut self, contract_address: AztecAddress, function_selector: FunctionSelector, - ) -> PackedReturns { - self.call_private_function_with_packed_args(contract_address, function_selector, 0, false) + ) -> ReturnsHash { + self.call_private_function_with_args_hash(contract_address, function_selector, 0, false) } pub fn static_call_private_function_no_args( &mut self, contract_address: AztecAddress, function_selector: FunctionSelector, - ) -> PackedReturns { - self.call_private_function_with_packed_args(contract_address, function_selector, 0, true) + ) -> ReturnsHash { + self.call_private_function_with_args_hash(contract_address, function_selector, 0, true) } - pub fn call_private_function_with_packed_args( + pub fn call_private_function_with_args_hash( &mut self, contract_address: AztecAddress, function_selector: FunctionSelector, args_hash: Field, is_static_call: bool, - ) -> PackedReturns { + ) -> ReturnsHash { let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call; let start_side_effect_counter = self.side_effect_counter; @@ -427,7 +426,7 @@ impl PrivateContext { // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter; // } self.side_effect_counter = end_side_effect_counter + 1; - PackedReturns::new(returns_hash) + ReturnsHash::new(returns_hash) } pub fn call_public_function( @@ -437,8 +436,8 @@ impl PrivateContext { args: [Field; ARGS_COUNT], ) { let args_hash = hash_args_array(args); - arguments::pack_arguments_array(args); - self.call_public_function_with_packed_args( + execution_cache::store_array(args); + self.call_public_function_with_args_hash( contract_address, function_selector, args_hash, @@ -453,8 +452,8 @@ impl PrivateContext { args: [Field; ARGS_COUNT], ) { let args_hash = hash_args_array(args); - arguments::pack_arguments_array(args); - self.call_public_function_with_packed_args( + execution_cache::store_array(args); + self.call_public_function_with_args_hash( contract_address, function_selector, args_hash, @@ -467,7 +466,7 @@ impl PrivateContext { contract_address: AztecAddress, function_selector: FunctionSelector, ) { - self.call_public_function_with_packed_args(contract_address, function_selector, 0, false) + self.call_public_function_with_args_hash(contract_address, function_selector, 0, false) } pub fn static_call_public_function_no_args( @@ -475,10 +474,10 @@ impl PrivateContext { contract_address: AztecAddress, function_selector: FunctionSelector, ) { - self.call_public_function_with_packed_args(contract_address, function_selector, 0, true) + self.call_public_function_with_args_hash(contract_address, function_selector, 0, true) } - pub fn call_public_function_with_packed_args( + pub fn call_public_function_with_args_hash( &mut self, contract_address: AztecAddress, function_selector: FunctionSelector, @@ -490,7 +489,7 @@ impl PrivateContext { let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this. // WARNING: This is insecure and should be temporary! - // The oracle repacks the arguments and returns a new args_hash. + // The oracle hashes the arguments and returns a new args_hash. // new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function. // We don't validate or compute it in the circuit because a) it's harder to do with slices, and // b) this is only temporary. @@ -525,8 +524,8 @@ impl PrivateContext { args: [Field; ARGS_COUNT], ) { let args_hash = hash_args_array(args); - arguments::pack_arguments_array(args); - self.set_public_teardown_function_with_packed_args( + execution_cache::store_array(args); + self.set_public_teardown_function_with_args_hash( contract_address, function_selector, args_hash, @@ -534,7 +533,7 @@ impl PrivateContext { ) } - pub fn set_public_teardown_function_with_packed_args( + pub fn set_public_teardown_function_with_args_hash( &mut self, contract_address: AztecAddress, function_selector: FunctionSelector, @@ -546,7 +545,7 @@ impl PrivateContext { let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this. // WARNING: This is insecure and should be temporary! - // The oracle repacks the arguments and returns a new args_hash. + // The oracle hashes the arguments and returns a new args_hash. // new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function. // We don't validate or compute it in the circuit because a) it's harder to do with slices, and // b) this is only temporary. diff --git a/noir-projects/aztec-nr/aztec/src/context/returns_hash.nr b/noir-projects/aztec-nr/aztec/src/context/returns_hash.nr new file mode 100644 index 00000000000..79cee30fb51 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/context/returns_hash.nr @@ -0,0 +1,33 @@ +use crate::{hash::hash_args_array, oracle::execution_cache}; +use dep::protocol_types::traits::Deserialize; + +pub struct ReturnsHash { + hash: Field, +} + +impl ReturnsHash { + pub fn new(hash: Field) -> Self { + ReturnsHash { hash } + } + + pub fn assert_empty(self) { + assert_eq(self.hash, 0); + } + + pub fn raw(self) -> Field { + self.hash + } + + /// This is only used during private execution, since in public it is the VM itself that keeps track of return + /// values. + pub fn get_preimage(self) -> T + where + T: Deserialize, + { + /// Safety: We verify that the value returned by `load` is the preimage of `hash`, fully constraining it. + let preimage: [Field; N] = unsafe { execution_cache::load(self.hash) }; + assert_eq(self.hash, hash_args_array(preimage)); + + Deserialize::deserialize(preimage) + } +} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr b/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr deleted file mode 100644 index 8321bccc27a..00000000000 --- a/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr +++ /dev/null @@ -1,30 +0,0 @@ -/// Notifies the simulator that `args` will later be used at some point during execution, referenced by their hash. This -/// allows the simulator to know how to respond to this future request. -/// -/// This is only used during private execution, since in public it is the VM itself that keeps track of arguments. -pub fn pack_arguments(args: [Field]) { - // This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call. When - // unpacking however the caller must check that the returned value is indeed the preimage. - unsafe { pack_arguments_oracle_wrapper(args) }; -} - -/// Same as `pack_arguments`, but using arrays instead of slices. -pub fn pack_arguments_array(args: [Field; N]) { - // This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call. When - // unpacking however the caller must check that the returned value is indeed the preimage. - unsafe { pack_arguments_array_oracle_wrapper(args) }; -} - -unconstrained fn pack_arguments_oracle_wrapper(args: [Field]) { - let _ = pack_arguments_oracle(args); -} - -unconstrained fn pack_arguments_array_oracle_wrapper(args: [Field; N]) { - let _ = pack_arguments_array_oracle(args); -} - -#[oracle(packArguments)] -unconstrained fn pack_arguments_oracle(_args: [Field]) -> Field {} - -#[oracle(packArgumentsArray)] -unconstrained fn pack_arguments_array_oracle(_args: [Field; N]) -> Field {} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr b/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr new file mode 100644 index 00000000000..3da3faca655 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr @@ -0,0 +1,34 @@ +/// Stores values represented as slice in execution cache to be later obtained by its hash. +pub fn store(values: [Field]) { + /// Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe + /// to call. When loading the values, however, the caller must check that the values are indeed the preimage. + unsafe { store_in_execution_cache_oracle_wrapper(values) }; +} + +/// Stores values represented as array in execution cache to be later obtained by its hash. +pub fn store_array(values: [Field; N]) { + /// Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe + /// to call. When loading the values, however, the caller must check that the values are indeed the preimage. + unsafe { store_array_in_execution_cache_oracle_wrapper(values) }; +} + +pub unconstrained fn store_in_execution_cache_oracle_wrapper(values: [Field]) { + let _ = store_in_execution_cache_oracle(values); +} + +pub unconstrained fn store_array_in_execution_cache_oracle_wrapper(values: [Field; N]) { + let _ = store_array_in_execution_cache_oracle(values); +} + +pub unconstrained fn load(hash: Field) -> [Field; N] { + load_from_execution_cache_oracle(hash) +} + +#[oracle(storeInExecutionCache)] +unconstrained fn store_in_execution_cache_oracle(_values: [Field]) -> Field {} + +#[oracle(storeArrayInExecutionCache)] +unconstrained fn store_array_in_execution_cache_oracle(_args: [Field; N]) -> Field {} + +#[oracle(loadFromExecutionCache)] +unconstrained fn load_from_execution_cache_oracle(_hash: Field) -> [Field; N] {} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/mod.nr b/noir-projects/aztec-nr/aztec/src/oracle/mod.nr index dfbc4d3139b..642cde6b960 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/mod.nr @@ -2,7 +2,6 @@ /// Oracles module // docs:end:oracles-module -pub mod arguments; pub mod call_private_function; pub mod execution; pub mod get_contract_instance; @@ -19,7 +18,7 @@ pub mod notes; pub mod storage; pub mod logs; pub mod pxe_db; -pub mod returns; +pub mod execution_cache; // debug_log oracle is used by both noir-protocol-circuits and this crate and for this reason we just re-export it // here from protocol circuits. diff --git a/noir-projects/aztec-nr/aztec/src/oracle/returns.nr b/noir-projects/aztec-nr/aztec/src/oracle/returns.nr deleted file mode 100644 index b12009e6313..00000000000 --- a/noir-projects/aztec-nr/aztec/src/oracle/returns.nr +++ /dev/null @@ -1,23 +0,0 @@ -/// Notifies the simulator that `returns` will be later fetched once the function return is processed, referenced by -/// their hash. This allows the simulator to know how to respond to this future request. -/// -/// This is only used during private execution, since in public it is the VM itself that keeps track of return values. -pub fn pack_returns(returns: [Field]) { - // This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call. When - // unpacking however the caller must check that the returned value is indeed the preimage. - unsafe { pack_returns_oracle_wrapper(returns) }; -} - -pub unconstrained fn pack_returns_oracle_wrapper(returns: [Field]) { - let _ = pack_returns_oracle(returns); -} - -pub unconstrained fn unpack_returns(return_hash: Field) -> [Field; N] { - unpack_returns_oracle(return_hash) -} - -#[oracle(packReturns)] -unconstrained fn pack_returns_oracle(_returns: [Field]) -> Field {} - -#[oracle(unpackReturns)] -unconstrained fn unpack_returns_oracle(_return_hash: Field) -> [Field; N] {} diff --git a/noir-projects/aztec-nr/aztec/src/prelude.nr b/noir-projects/aztec-nr/aztec/src/prelude.nr index 861ef71f2ba..4365663e0b3 100644 --- a/noir-projects/aztec-nr/aztec/src/prelude.nr +++ b/noir-projects/aztec-nr/aztec/src/prelude.nr @@ -1,6 +1,6 @@ // docs:start:prelude pub use crate::{ - context::{PackedReturns, PrivateContext, PublicContext}, + context::{PrivateContext, PublicContext, ReturnsHash}, note::{ note_getter_options::NoteGetterOptions, note_header::NoteHeader, diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr index d8a68388962..eacf34d3914 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr @@ -11,8 +11,8 @@ use crate::test::helpers::cheatcodes; use crate::context::gas::GasOpts; use crate::hash::hash_args; -use crate::oracle::arguments::pack_arguments; use crate::oracle::execution::get_block_number; +use crate::oracle::execution_cache; pub struct Deployer { pub path: str, @@ -40,8 +40,8 @@ impl Deployer { let mut private_context = PrivateContext::new(inputs, 0); let args = call_interface.get_args(); let args_hash = if args.len() > 0 { hash_args(args) } else { 0 }; - pack_arguments(args); - let _ = private_context.call_private_function_with_packed_args( + execution_cache::store(args); + let _ = private_context.call_private_function_with_args_hash( instance.to_address(), call_interface.get_selector(), args_hash, diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/dapp_payload.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/dapp_payload.nr index 00e01f9b70d..c4524a1fa22 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/dapp_payload.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/dapp_payload.nr @@ -60,14 +60,14 @@ impl DAppPayload { // whitelist the calls that the user can do only go to the expected Dapp contract assert(call.target_address == target_address); if call.is_public { - context.call_public_function_with_packed_args( + context.call_public_function_with_args_hash( call.target_address, call.function_selector, call.args_hash, call.is_static, ); } else { - let _result = context.call_private_function_with_packed_args( + let _result = context.call_private_function_with_args_hash( call.target_address, call.function_selector, call.args_hash, diff --git a/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr b/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr index 1f7757239d7..c20c913caa6 100644 --- a/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr @@ -9,7 +9,7 @@ contract Parent { #[private] fn entry_point(target_contract: AztecAddress, target_selector: FunctionSelector) -> Field { // Call the target private function - context.call_private_function(target_contract, target_selector, [0]).unpack_into() + context.call_private_function(target_contract, target_selector, [0]).get_preimage() } // Public function to directly call another public function to the target_contract using the selector and value provided #[public] @@ -146,7 +146,7 @@ contract Parent { args: [Field; 2], ) -> Field { // Call the target private function - context.static_call_private_function(target_contract, target_selector, args).unpack_into() + context.static_call_private_function(target_contract, target_selector, args).get_preimage() } #[private] fn private_call( @@ -155,7 +155,7 @@ contract Parent { args: [Field; 2], ) -> Field { // Call the target private function - context.call_private_function(target_contract, target_selector, args).unpack_into() + context.call_private_function(target_contract, target_selector, args).get_preimage() } // Private function to set a static context and verify correct propagation for nested private calls #[private] @@ -174,7 +174,7 @@ contract Parent { private_call_selector, [target_contract.to_field(), target_selector.to_field(), args[0], args[1]], ) - .unpack_into(); + .get_preimage(); // Copy the return value from the call to this function's return values return_value } diff --git a/noir-projects/noir-contracts/contracts/static_parent_contract/src/main.nr b/noir-projects/noir-contracts/contracts/static_parent_contract/src/main.nr index ef606854b3c..fb3df27bc88 100644 --- a/noir-projects/noir-contracts/contracts/static_parent_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/static_parent_contract/src/main.nr @@ -29,7 +29,7 @@ contract StaticParent { target_selector: FunctionSelector, args: [Field; 2], ) -> Field { - context.call_private_function(target_contract, target_selector, args).unpack_into() + context.call_private_function(target_contract, target_selector, args).get_preimage() } // Just like function above but with 3 args. @@ -39,7 +39,7 @@ contract StaticParent { target_selector: FunctionSelector, args: [Field; 3], ) -> Field { - context.call_private_function(target_contract, target_selector, args).unpack_into() + context.call_private_function(target_contract, target_selector, args).get_preimage() } // Private function to enqueue a call to a public function of another contract, passing the target arguments provided @@ -58,7 +58,7 @@ contract StaticParent { target_selector: FunctionSelector, args: [Field; 2], ) -> Field { - context.static_call_private_function(target_contract, target_selector, args).unpack_into() + context.static_call_private_function(target_contract, target_selector, args).get_preimage() } // Private function to statically call another private function to the target_contract using the selector and values provided @@ -68,7 +68,7 @@ contract StaticParent { target_selector: FunctionSelector, args: [Field; 3], ) -> Field { - context.static_call_private_function(target_contract, target_selector, args).unpack_into() + context.static_call_private_function(target_contract, target_selector, args).get_preimage() } // Same as above but using a specific function from the interface diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr index 155471c7962..c84653d848f 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr @@ -19,12 +19,12 @@ pub struct BaseOrMergeRollupPublicInputs { pub(crate) start: PartialStateReference, pub(crate) end: PartialStateReference, - // A poseidon sponge of all tx effects to be unpacked in block root, then added to blob(s) + // A poseidon sponge of all tx effects to be opened in block root, then added to blob(s) // In sponge form so we can check left.end == right.start, rather than recreate a tree later pub(crate) start_sponge_blob: SpongeBlob, pub(crate) end_sponge_blob: SpongeBlob, - // We hash public inputs to make them constant-sized (to then be unpacked on-chain) + // We hash public inputs to make them constant-sized (to then be opened on-chain) // U128 isn't safe if it's an input to the circuit (it won't automatically constrain the witness) // So we want to constrain it when casting these fields to U128 diff --git a/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts b/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts index 57d10fa67a4..0407f1b43a6 100644 --- a/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts +++ b/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts @@ -48,7 +48,7 @@ export class DeployAccountMethod extends DeployMethod { protected override async getInitializeFunctionCalls( options: DeployOptions, - ): Promise> { + ): Promise> { const exec = await super.getInitializeFunctionCalls(options); if (options.fee && this.#feePaymentArtifact) { @@ -71,14 +71,14 @@ export class DeployAccountMethod extends DeployMethod { }); exec.authWitnesses ??= []; - exec.packedArguments ??= []; + exec.hashedArguments ??= []; exec.authWitnesses.push( await this.#authWitnessProvider.createAuthWit(computeCombinedPayloadHash(emptyAppPayload, feePayload)), ); - exec.packedArguments.push(...emptyAppPayload.packedArguments); - exec.packedArguments.push(...feePayload.packedArguments); + exec.hashedArguments.push(...emptyAppPayload.hashedArguments); + exec.hashedArguments.push(...feePayload.hashedArguments); } return exec; diff --git a/yarn-project/aztec.js/src/contract/deploy_method.ts b/yarn-project/aztec.js/src/contract/deploy_method.ts index 869981308a7..91fa60e78c0 100644 --- a/yarn-project/aztec.js/src/contract/deploy_method.ts +++ b/yarn-project/aztec.js/src/contract/deploy_method.ts @@ -110,10 +110,10 @@ export class DeployMethod extends Bas const calls = [...deployment.calls, ...bootstrap.calls]; const authWitnesses = [...(deployment.authWitnesses ?? []), ...(bootstrap.authWitnesses ?? [])]; - const packedArguments = [...(deployment.packedArguments ?? []), ...(bootstrap.packedArguments ?? [])]; + const hashedArguments = [...(deployment.hashedArguments ?? []), ...(bootstrap.hashedArguments ?? [])]; const { cancellable, nonce, fee: userFee } = options; - const request = { calls, authWitnesses, packedArguments, cancellable, fee: userFee, nonce }; + const request = { calls, authWitnesses, hashedArguments, cancellable, fee: userFee, nonce }; const fee = await this.getFeeOptions(request); return { ...request, fee }; @@ -136,7 +136,7 @@ export class DeployMethod extends Bas */ protected async getDeploymentFunctionCalls( options: DeployOptions = {}, - ): Promise> { + ): Promise> { const calls: FunctionCall[] = []; // Set contract instance object so it's available for populating the DeploySendTx object @@ -180,7 +180,7 @@ export class DeployMethod extends Bas */ protected getInitializeFunctionCalls( options: DeployOptions, - ): Promise> { + ): Promise> { const { address } = this.getInstance(options); const calls: FunctionCall[] = []; if (this.constructorArtifact && !options.skipInitialization) { diff --git a/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts b/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts index 6b221c302d1..82c9fd3c758 100644 --- a/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts +++ b/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts @@ -1,4 +1,4 @@ -import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; +import { HashedValues, TxExecutionRequest } from '@aztec/circuit-types'; import { TxContext } from '@aztec/circuits.js'; import { FunctionType } from '@aztec/foundation/abi'; @@ -11,7 +11,7 @@ export class DefaultEntrypoint implements EntrypointInterface { constructor(private chainId: number, private protocolVersion: number) {} createTxExecutionRequest(exec: ExecutionRequestInit): Promise { - const { fee, calls, authWitnesses = [], packedArguments = [] } = exec; + const { fee, calls, authWitnesses = [], hashedArguments = [] } = exec; if (calls.length > 1) { throw new Error(`Expected a single call, got ${calls.length}`); @@ -23,15 +23,15 @@ export class DefaultEntrypoint implements EntrypointInterface { throw new Error('Public entrypoints are not allowed'); } - const entrypointPackedValues = PackedValues.fromValues(call.args); + const entrypointHashedValues = HashedValues.fromValues(call.args); const txContext = new TxContext(this.chainId, this.protocolVersion, fee.gasSettings); return Promise.resolve( new TxExecutionRequest( call.to, call.selector, - entrypointPackedValues.hash, + entrypointHashedValues.hash, txContext, - [...packedArguments, entrypointPackedValues], + [...hashedArguments, entrypointHashedValues], authWitnesses, ), ); diff --git a/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts b/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts index de68c922b80..df27e73f2c0 100644 --- a/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts +++ b/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts @@ -1,5 +1,5 @@ import { type EntrypointInterface, EntrypointPayload, type ExecutionRequestInit } from '@aztec/aztec.js/entrypoint'; -import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; +import { HashedValues, TxExecutionRequest } from '@aztec/circuit-types'; import { type AztecAddress, TxContext } from '@aztec/circuits.js'; import { type FunctionAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; @@ -15,17 +15,17 @@ export class DefaultMultiCallEntrypoint implements EntrypointInterface { ) {} createTxExecutionRequest(executions: ExecutionRequestInit): Promise { - const { fee, calls, authWitnesses = [], packedArguments = [] } = executions; + const { fee, calls, authWitnesses = [], hashedArguments = [] } = executions; const payload = EntrypointPayload.fromAppExecution(calls); const abi = this.getEntrypointAbi(); - const entrypointPackedArgs = PackedValues.fromValues(encodeArguments(abi, [payload])); + const entrypointHashedArgs = HashedValues.fromValues(encodeArguments(abi, [payload])); const txRequest = TxExecutionRequest.from({ - firstCallArgsHash: entrypointPackedArgs.hash, + firstCallArgsHash: entrypointHashedArgs.hash, origin: this.address, functionSelector: FunctionSelector.fromNameAndParameters(abi.name, abi.parameters), txContext: new TxContext(this.chainId, this.version, fee.gasSettings), - argsOfCalls: [...payload.packedArguments, ...packedArguments, entrypointPackedArgs], + argsOfCalls: [...payload.hashedArguments, ...hashedArguments, entrypointHashedArgs], authWitnesses, }); diff --git a/yarn-project/aztec.js/src/entrypoint/entrypoint.ts b/yarn-project/aztec.js/src/entrypoint/entrypoint.ts index 49b7fafa7c1..1afe6c0061a 100644 --- a/yarn-project/aztec.js/src/entrypoint/entrypoint.ts +++ b/yarn-project/aztec.js/src/entrypoint/entrypoint.ts @@ -1,4 +1,4 @@ -import { type AuthWitness, type FunctionCall, type PackedValues, type TxExecutionRequest } from '@aztec/circuit-types'; +import { type AuthWitness, type FunctionCall, type HashedValues, type TxExecutionRequest } from '@aztec/circuit-types'; import { type Fr } from '@aztec/circuits.js'; import { EntrypointPayload, type FeeOptions, computeCombinedPayloadHash } from './payload.js'; @@ -14,8 +14,8 @@ export type ExecutionRequestInit = { calls: FunctionCall[]; /** Any transient auth witnesses needed for this execution */ authWitnesses?: AuthWitness[]; - /** Any transient packed arguments for this execution */ - packedArguments?: PackedValues[]; + /** Any transient hashed arguments for this execution */ + hashedArguments?: HashedValues[]; /** How the fee is going to be payed */ fee: FeeOptions; /** An optional nonce. Used to repeat a previous tx with a higher fee so that the first one is cancelled */ diff --git a/yarn-project/aztec.js/src/entrypoint/payload.ts b/yarn-project/aztec.js/src/entrypoint/payload.ts index 8f76aa0e06f..eef9009f3e1 100644 --- a/yarn-project/aztec.js/src/entrypoint/payload.ts +++ b/yarn-project/aztec.js/src/entrypoint/payload.ts @@ -1,4 +1,4 @@ -import { FunctionCall, PackedValues } from '@aztec/circuit-types'; +import { FunctionCall, HashedValues } from '@aztec/circuit-types'; import { type AztecAddress, Fr, type GasSettings, GeneratorIndex } from '@aztec/circuits.js'; import { FunctionType } from '@aztec/foundation/abi'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -54,19 +54,19 @@ type EncodedFunctionCall = { /** Assembles an entrypoint payload */ export abstract class EntrypointPayload { - #packedArguments: PackedValues[] = []; + #hashedArguments: HashedValues[] = []; #functionCalls: EncodedFunctionCall[] = []; #nonce: Fr; #generatorIndex: number; protected constructor(functionCalls: FunctionCall[], generatorIndex: number, nonce = Fr.random()) { for (const call of functionCalls) { - this.#packedArguments.push(PackedValues.fromValues(call.args)); + this.#hashedArguments.push(HashedValues.fromValues(call.args)); } /* eslint-disable camelcase */ this.#functionCalls = functionCalls.map((call, index) => ({ - args_hash: this.#packedArguments[index].hash, + args_hash: this.#hashedArguments[index].hash, function_selector: call.selector.toField(), target_address: call.to.toField(), is_public: call.type == FunctionType.PUBLIC, @@ -97,10 +97,10 @@ export abstract class EntrypointPayload { } /** - * The packed arguments for the function calls + * The hashed arguments for the function calls */ - get packedArguments() { - return this.#packedArguments; + get hashedArguments() { + return this.#hashedArguments; } /** diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index be601cc31ac..e17f3436d24 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -109,7 +109,7 @@ export { LogId, MerkleTreeId, Note, - PackedValues, + HashedValues, SiblingPath, Tx, TxExecutionRequest, diff --git a/yarn-project/aztec.js/src/utils/authwit.ts b/yarn-project/aztec.js/src/utils/authwit.ts index 51c62370891..11d640ba749 100644 --- a/yarn-project/aztec.js/src/utils/authwit.ts +++ b/yarn-project/aztec.js/src/utils/authwit.ts @@ -1,4 +1,4 @@ -import { type FunctionCall, PackedValues } from '@aztec/circuit-types'; +import { type FunctionCall, HashedValues } from '@aztec/circuit-types'; import { type AztecAddress, Fr, GeneratorIndex } from '@aztec/circuits.js'; import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto'; @@ -70,7 +70,7 @@ export const computeAuthWitMessageHash = (intent: IntentInnerHash | IntentAction // docs:end:authwit_computeAuthWitMessageHash export const computeInnerAuthWitHashFromAction = (caller: AztecAddress, action: FunctionCall) => - computeInnerAuthWitHash([caller.toField(), action.selector.toField(), PackedValues.fromValues(action.args).hash]); + computeInnerAuthWitHash([caller.toField(), action.selector.toField(), HashedValues.fromValues(action.args).hash]); /** * Compute the inner hash for an authentication witness. diff --git a/yarn-project/circuit-types/src/hashed_values.test.ts b/yarn-project/circuit-types/src/hashed_values.test.ts new file mode 100644 index 00000000000..a7cbd07094b --- /dev/null +++ b/yarn-project/circuit-types/src/hashed_values.test.ts @@ -0,0 +1,11 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; + +import { HashedValues } from './hashed_values.js'; + +describe('HashedValues', () => { + it('serializes and deserializes', () => { + const values = HashedValues.random(); + const json = jsonStringify(values); + expect(HashedValues.schema.parse(JSON.parse(json))).toEqual(values); + }); +}); diff --git a/yarn-project/circuit-types/src/packed_values.ts b/yarn-project/circuit-types/src/hashed_values.ts similarity index 64% rename from yarn-project/circuit-types/src/packed_values.ts rename to yarn-project/circuit-types/src/hashed_values.ts index 4dfbcea863c..5fd26da5fb5 100644 --- a/yarn-project/circuit-types/src/packed_values.ts +++ b/yarn-project/circuit-types/src/hashed_values.ts @@ -6,9 +6,9 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { z } from 'zod'; /** - * Packs a set of values into a hash. + * A container for storing a list of values and their hash. */ -export class PackedValues { +export class HashedValues { private constructor( /** * Raw values. @@ -21,7 +21,7 @@ export class PackedValues { ) {} static get schema() { - return z.array(schemas.Fr).transform(PackedValues.fromValues); + return z.array(schemas.Fr).transform(HashedValues.fromValues); } toJSON() { @@ -29,19 +29,19 @@ export class PackedValues { } static random() { - return PackedValues.fromValues([Fr.random(), Fr.random()]); + return HashedValues.fromValues([Fr.random(), Fr.random()]); } static fromValues(values: Fr[]) { - return new PackedValues(values, computeVarArgsHash(values)); + return new HashedValues(values, computeVarArgsHash(values)); } toBuffer() { return serializeToBuffer(new Vector(this.values), this.hash); } - static fromBuffer(buffer: Buffer | BufferReader): PackedValues { + static fromBuffer(buffer: Buffer | BufferReader): HashedValues { const reader = BufferReader.asReader(buffer); - return new PackedValues(reader.readVector(Fr), Fr.fromBuffer(reader)); + return new HashedValues(reader.readVector(Fr), Fr.fromBuffer(reader)); } } diff --git a/yarn-project/circuit-types/src/index.ts b/yarn-project/circuit-types/src/index.ts index 87db2e5e2dd..a6dd1955cf7 100644 --- a/yarn-project/circuit-types/src/index.ts +++ b/yarn-project/circuit-types/src/index.ts @@ -13,7 +13,7 @@ export * from './messaging/index.js'; export * from './mocks.js'; export * from './notes/index.js'; export * from './p2p/index.js'; -export * from './packed_values.js'; +export * from './hashed_values.js'; export * from './prover_coordination/index.js'; export * from './public_data_witness.js'; export * from './public_execution_request.js'; diff --git a/yarn-project/circuit-types/src/packed_values.test.ts b/yarn-project/circuit-types/src/packed_values.test.ts deleted file mode 100644 index cd957019295..00000000000 --- a/yarn-project/circuit-types/src/packed_values.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { jsonStringify } from '@aztec/foundation/json-rpc'; - -import { PackedValues } from './packed_values.js'; - -describe('PackedValues', () => { - it('serializes and deserializes', () => { - const values = PackedValues.random(); - const json = jsonStringify(values); - expect(PackedValues.schema.parse(JSON.parse(json))).toEqual(values); - }); -}); diff --git a/yarn-project/circuit-types/src/tx_execution_request.ts b/yarn-project/circuit-types/src/tx_execution_request.ts index bdd90e28550..e554bc62bde 100644 --- a/yarn-project/circuit-types/src/tx_execution_request.ts +++ b/yarn-project/circuit-types/src/tx_execution_request.ts @@ -8,7 +8,7 @@ import { inspect } from 'util'; import { z } from 'zod'; import { AuthWitness } from './auth_witness.js'; -import { PackedValues } from './packed_values.js'; +import { HashedValues } from './hashed_values.js'; /** * Request to execute a transaction. Similar to TxRequest, but has the full args. @@ -37,7 +37,7 @@ export class TxExecutionRequest { * @dev These arguments are accessed in Noir via oracle and constrained against the args hash. The length of * the array is equal to the number of function calls in the transaction (1 args per 1 call). */ - public argsOfCalls: PackedValues[], + public argsOfCalls: HashedValues[], /** * Transient authorization witnesses for authorizing the execution of one or more actions during this tx. * These witnesses are not expected to be stored in the local witnesses database of the PXE. @@ -52,7 +52,7 @@ export class TxExecutionRequest { functionSelector: schemas.FunctionSelector, firstCallArgsHash: schemas.Fr, txContext: TxContext.schema, - argsOfCalls: z.array(PackedValues.schema), + argsOfCalls: z.array(HashedValues.schema), authWitnesses: z.array(AuthWitness.schema), }) .transform(TxExecutionRequest.from); @@ -118,7 +118,7 @@ export class TxExecutionRequest { reader.readObject(FunctionSelector), Fr.fromBuffer(reader), reader.readObject(TxContext), - reader.readVector(PackedValues), + reader.readVector(HashedValues), reader.readVector(AuthWitness), ); } @@ -138,7 +138,7 @@ export class TxExecutionRequest { FunctionSelector.random(), Fr.random(), TxContext.empty(), - [PackedValues.random()], + [HashedValues.random()], [AuthWitness.random()], ); } diff --git a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts index 1d9611e1c67..cc2947d9834 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts @@ -42,7 +42,7 @@ export class BaseOrMergeRollupPublicInputs { */ public endSpongeBlob: SpongeBlob, /** - * SHA256 hash of outhash. Used to make public inputs constant-sized (to then be unpacked on-chain). + * SHA256 hash of L2 to L1 messages. Used to make public inputs constant-sized (to then be opened on-chain). * Note: Truncated to 31 bytes to fit in Fr. */ public outHash: Fr, diff --git a/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts index 0731d0869c2..56bd636c6ef 100644 --- a/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts @@ -40,7 +40,7 @@ export class BlockRootOrBlockMergePublicInputs { */ public endGlobalVariables: GlobalVariables, /** - * SHA256 hash of outhash. Used to make public inputs constant-sized (to then be unpacked on-chain). + * SHA256 hash of L2 to L1 messages. Used to make public inputs constant-sized (to then be opened on-chain). * Note: Truncated to 31 bytes to fit in Fr. */ public outHash: Fr, diff --git a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts index a56390821d8..210fccee475 100644 --- a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts +++ b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts @@ -4,9 +4,9 @@ import { type AztecNode, type CheatCodes, Fr, + HashedValues, type Logger, type PXE, - PackedValues, TxExecutionRequest, type UniqueNote, deriveKeys, @@ -336,14 +336,14 @@ describe('e2e_crowdfunding_and_claim', () => { // Instead, we construct a call and impersonate operator by skipping the usual account contract entrypoint... const call = crowdfundingContract.withWallet(donorWallets[1]).methods.withdraw(donationAmount).request(); // ...using the withdraw fn as our entrypoint - const entrypointPackedValues = PackedValues.fromValues(call.args); + const entrypointHashedValues = HashedValues.fromValues(call.args); const maxFeesPerGas = await pxe.getCurrentBaseFees(); const request = new TxExecutionRequest( call.to, call.selector, - entrypointPackedValues.hash, + entrypointHashedValues.hash, new TxContext(donorWallets[1].getChainId(), donorWallets[1].getVersion(), GasSettings.default({ maxFeesPerGas })), - [entrypointPackedValues], + [entrypointHashedValues], [], ); // NB: Removing the msg_sender assertion from private_init will still result in a throw, as we are using diff --git a/yarn-project/entrypoints/src/account_entrypoint.ts b/yarn-project/entrypoints/src/account_entrypoint.ts index 15002e020a2..83c96533a90 100644 --- a/yarn-project/entrypoints/src/account_entrypoint.ts +++ b/yarn-project/entrypoints/src/account_entrypoint.ts @@ -5,7 +5,7 @@ import { type ExecutionRequestInit, computeCombinedPayloadHash, } from '@aztec/aztec.js/entrypoint'; -import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; +import { HashedValues, TxExecutionRequest } from '@aztec/circuit-types'; import { type AztecAddress, TxContext } from '@aztec/circuits.js'; import { type FunctionAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; @@ -29,18 +29,18 @@ export class DefaultAccountEntrypoint implements EntrypointInterface { const feePayload = await EntrypointPayload.fromFeeOptions(this.address, fee); const abi = this.getEntrypointAbi(); - const entrypointPackedArgs = PackedValues.fromValues(encodeArguments(abi, [appPayload, feePayload, !!cancellable])); + const entrypointHashedArgs = HashedValues.fromValues(encodeArguments(abi, [appPayload, feePayload, !!cancellable])); const combinedPayloadAuthWitness = await this.auth.createAuthWit( computeCombinedPayloadHash(appPayload, feePayload), ); const txRequest = TxExecutionRequest.from({ - firstCallArgsHash: entrypointPackedArgs.hash, + firstCallArgsHash: entrypointHashedArgs.hash, origin: this.address, functionSelector: FunctionSelector.fromNameAndParameters(abi.name, abi.parameters), txContext: new TxContext(this.chainId, this.version, fee.gasSettings), - argsOfCalls: [...appPayload.packedArguments, ...feePayload.packedArguments, entrypointPackedArgs], + argsOfCalls: [...appPayload.hashedArguments, ...feePayload.hashedArguments, entrypointHashedArgs], authWitnesses: [combinedPayloadAuthWitness], }); diff --git a/yarn-project/entrypoints/src/dapp_entrypoint.ts b/yarn-project/entrypoints/src/dapp_entrypoint.ts index 569715d3630..d093ff495e9 100644 --- a/yarn-project/entrypoints/src/dapp_entrypoint.ts +++ b/yarn-project/entrypoints/src/dapp_entrypoint.ts @@ -1,7 +1,7 @@ import { computeAuthWitMessageHash, computeInnerAuthWitHash } from '@aztec/aztec.js'; import { type AuthWitnessProvider } from '@aztec/aztec.js/account'; import { type EntrypointInterface, EntrypointPayload, type ExecutionRequestInit } from '@aztec/aztec.js/entrypoint'; -import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; +import { HashedValues, TxExecutionRequest } from '@aztec/circuit-types'; import { type AztecAddress, Fr, TxContext } from '@aztec/circuits.js'; import { type FunctionAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; @@ -29,13 +29,13 @@ export class DefaultDappEntrypoint implements EntrypointInterface { const payload = EntrypointPayload.fromFunctionCalls(calls); const abi = this.getEntrypointAbi(); - const entrypointPackedArgs = PackedValues.fromValues(encodeArguments(abi, [payload, this.userAddress])); + const entrypointHashedArgs = HashedValues.fromValues(encodeArguments(abi, [payload, this.userAddress])); const functionSelector = FunctionSelector.fromNameAndParameters(abi.name, abi.parameters); // Default msg_sender for entrypoints is now Fr.max_value rather than 0 addr (see #7190 & #7404) const innerHash = computeInnerAuthWitHash([ Fr.MAX_FIELD_VALUE, functionSelector.toField(), - entrypointPackedArgs.hash, + entrypointHashedArgs.hash, ]); const outerHash = computeAuthWitMessageHash( { consumer: this.dappEntrypointAddress, innerHash }, @@ -45,11 +45,11 @@ export class DefaultDappEntrypoint implements EntrypointInterface { const authWitness = await this.userAuthWitnessProvider.createAuthWit(outerHash); const txRequest = TxExecutionRequest.from({ - firstCallArgsHash: entrypointPackedArgs.hash, + firstCallArgsHash: entrypointHashedArgs.hash, origin: this.dappEntrypointAddress, functionSelector, txContext: new TxContext(this.chainId, this.version, fee.gasSettings), - argsOfCalls: [...payload.packedArguments, entrypointPackedArgs], + argsOfCalls: [...payload.hashedArguments, entrypointHashedArgs], authWitnesses: [authWitness], }); diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 2e16f58535c..9f9ec982555 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -22,25 +22,20 @@ export class Oracle { return toACVMField(val); } - async packArgumentsArray(args: ACVMField[]): Promise { - const packed = await this.typedOracle.packArgumentsArray(args.map(fromACVMField)); - return toACVMField(packed); - } - - async packArguments(_length: ACVMField[], values: ACVMField[]): Promise { - const packed = await this.typedOracle.packArgumentsArray(values.map(fromACVMField)); - return toACVMField(packed); + async storeArrayInExecutionCache(values: ACVMField[]): Promise { + const hash = await this.typedOracle.storeArrayInExecutionCache(values.map(fromACVMField)); + return toACVMField(hash); } // Since the argument is a slice, noir automatically adds a length field to oracle call. - async packReturns(_length: ACVMField[], values: ACVMField[]): Promise { - const packed = await this.typedOracle.packReturns(values.map(fromACVMField)); - return toACVMField(packed); + async storeInExecutionCache(_length: ACVMField[], values: ACVMField[]): Promise { + const hash = await this.typedOracle.storeInExecutionCache(values.map(fromACVMField)); + return toACVMField(hash); } - async unpackReturns([returnsHash]: ACVMField[]): Promise { - const unpacked = await this.typedOracle.unpackReturns(fromACVMField(returnsHash)); - return unpacked.map(toACVMField); + async loadFromExecutionCache([returnsHash]: ACVMField[]): Promise { + const values = await this.typedOracle.loadFromExecutionCache(fromACVMField(returnsHash)); + return values.map(toACVMField); } async getBlockNumber(): Promise { diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index d228db9776f..a8f6915e17f 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -56,16 +56,16 @@ export abstract class TypedOracle { return Fr.random(); } - packArgumentsArray(_args: Fr[]): Promise { - throw new OracleMethodNotAvailableError('packArgumentsArray'); + storeArrayInExecutionCache(_args: Fr[]): Promise { + throw new OracleMethodNotAvailableError('storeArrayInExecutionCache'); } - packReturns(_returns: Fr[]): Promise { - throw new OracleMethodNotAvailableError('packReturns'); + storeInExecutionCache(_values: Fr[]): Promise { + throw new OracleMethodNotAvailableError('storeInExecutionCache'); } - unpackReturns(_returnsHash: Fr): Promise { - throw new OracleMethodNotAvailableError('unpackReturns'); + loadFromExecutionCache(_hash: Fr): Promise { + throw new OracleMethodNotAvailableError('loadFromExecutionCache'); } getBlockNumber(): Promise { diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 3c2c761f356..d3ce233ab89 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -26,7 +26,7 @@ import { Fr } from '@aztec/foundation/fields'; import { createLogger } from '@aztec/foundation/log'; import { type NoteData, toACVMWitness } from '../acvm/index.js'; -import { type PackedValuesCache } from '../common/packed_values_cache.js'; +import { type HashedValuesCache } from '../common/hashed_values_cache.js'; import { type SimulationProvider } from '../server.js'; import { type DBOracle } from './db_oracle.js'; import { type ExecutionNoteCache } from './execution_note_cache.js'; @@ -70,7 +70,7 @@ export class ClientExecutionContext extends ViewDataOracle { protected readonly historicalHeader: BlockHeader, /** List of transient auth witnesses to be used during this simulation */ authWitnesses: AuthWitness[], - private readonly packedValuesCache: PackedValuesCache, + private readonly executionCache: HashedValuesCache, private readonly noteCache: ExecutionNoteCache, db: DBOracle, private node: AztecNode, @@ -92,7 +92,7 @@ export class ClientExecutionContext extends ViewDataOracle { public getInitialWitness(abi: FunctionAbi) { const argumentsSize = countArgumentsSize(abi); - const args = this.packedValuesCache.unpack(this.argsHash); + const args = this.executionCache.getPreimage(this.argsHash); if (args.length !== argumentsSize) { throw new Error('Invalid arguments size'); @@ -161,27 +161,29 @@ export class ClientExecutionContext extends ViewDataOracle { } /** - * Pack the given array of arguments. - * @param args - Arguments to pack + * Store values in the execution cache. + * @param values - Values to store. */ - public override packArgumentsArray(args: Fr[]): Promise { - return Promise.resolve(this.packedValuesCache.pack(args)); + public override storeArrayInExecutionCache(args: Fr[]): Promise { + return Promise.resolve(this.executionCache.store(args)); } /** - * Pack the given returns. - * @param returns - Returns to pack + * Store values in the execution cache. + * @param values - Values to store. + * @returns The hash of the values. */ - public override packReturns(returns: Fr[]): Promise { - return Promise.resolve(this.packedValuesCache.pack(returns)); + public override storeInExecutionCache(values: Fr[]): Promise { + return Promise.resolve(this.executionCache.store(values)); } /** - * Unpack the given returns. - * @param returnsHash - Returns hash to unpack + * Gets values from the execution cache. + * @param hash - Hash of the values. + * @returns The values. */ - public override unpackReturns(returnsHash: Fr): Promise { - return Promise.resolve(this.packedValuesCache.unpack(returnsHash)); + public override loadFromExecutionCache(hash: Fr): Promise { + return Promise.resolve(this.executionCache.getPreimage(hash)); } /** @@ -341,7 +343,7 @@ export class ClientExecutionContext extends ViewDataOracle { * Calls a private function as a nested execution. * @param targetContractAddress - The address of the contract to call. * @param functionSelector - The function selector of the function to call. - * @param argsHash - The packed arguments to pass to the function. + * @param argsHash - The arguments hash to pass to the function. * @param sideEffectCounter - The side effect counter at the start of the call. * @param isStaticCall - Whether the call is a static call. * @returns The execution result. @@ -371,7 +373,7 @@ export class ClientExecutionContext extends ViewDataOracle { derivedCallContext, this.historicalHeader, this.authWitnesses, - this.packedValuesCache, + this.executionCache, this.noteCache, this.db, this.node, @@ -406,7 +408,7 @@ export class ClientExecutionContext extends ViewDataOracle { * Creates a PublicExecutionRequest object representing the request to call a public function. * @param targetContractAddress - The address of the contract to call. * @param functionSelector - The function selector of the function to call. - * @param argsHash - The packed arguments to pass to the function. + * @param argsHash - The arguments hash to pass to the function. * @param sideEffectCounter - The side effect counter at the start of the call. * @param isStaticCall - Whether the call is a static call. * @returns The public call stack item with the request information. @@ -421,7 +423,7 @@ export class ClientExecutionContext extends ViewDataOracle { ) { const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector); const derivedCallContext = this.deriveCallContext(targetContractAddress, targetArtifact, isStaticCall); - const args = this.packedValuesCache.unpack(argsHash); + const args = this.executionCache.getPreimage(argsHash); this.log.verbose( `Created ${callType} public execution request to ${targetArtifact.name}@${targetContractAddress}`, @@ -452,7 +454,7 @@ export class ClientExecutionContext extends ViewDataOracle { * of the execution are empty. * @param targetContractAddress - The address of the contract to call. * @param functionSelector - The function selector of the function to call. - * @param argsHash - The packed arguments to pass to the function. + * @param argsHash - The arguments hash to pass to the function. * @param sideEffectCounter - The side effect counter at the start of the call. * @param isStaticCall - Whether the call is a static call. * @returns The public call stack item with the request information. @@ -466,13 +468,13 @@ export class ClientExecutionContext extends ViewDataOracle { ): Promise { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this. // WARNING: This is insecure and should be temporary! - // The oracle repacks the arguments and returns a new args_hash. + // The oracle re-hashes the arguments and returns a new args_hash. // new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function. // We don't validate or compute it in the circuit because a) it's harder to do with slices, and // b) this is only temporary. - const newArgsHash = this.packedValuesCache.pack([ + const newArgsHash = this.executionCache.store([ functionSelector.toField(), - ...this.packedValuesCache.unpack(argsHash), + ...this.executionCache.getPreimage(argsHash), ]); await this.createPublicExecutionRequest( 'enqueued', @@ -491,7 +493,7 @@ export class ClientExecutionContext extends ViewDataOracle { * of the execution are empty. * @param targetContractAddress - The address of the contract to call. * @param functionSelector - The function selector of the function to call. - * @param argsHash - The packed arguments to pass to the function. + * @param argsHash - The arguments hash to pass to the function. * @param sideEffectCounter - The side effect counter at the start of the call. * @param isStaticCall - Whether the call is a static call. * @returns The public call stack item with the request information. @@ -505,13 +507,13 @@ export class ClientExecutionContext extends ViewDataOracle { ): Promise { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this. // WARNING: This is insecure and should be temporary! - // The oracle repacks the arguments and returns a new args_hash. + // The oracle rehashes the arguments and returns a new args_hash. // new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function. // We don't validate or compute it in the circuit because a) it's harder to do with slices, and // b) this is only temporary. - const newArgsHash = this.packedValuesCache.pack([ + const newArgsHash = this.executionCache.store([ functionSelector.toField(), - ...this.packedValuesCache.unpack(argsHash), + ...this.executionCache.getPreimage(argsHash), ]); await this.createPublicExecutionRequest( 'teardown', diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 57d751c6151..29c38af525e 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -1,10 +1,10 @@ import { type AztecNode, CountedPublicExecutionRequest, + HashedValues, type L1ToL2Message, type L2BlockNumber, Note, - PackedValues, PublicExecutionRequest, TxExecutionRequest, } from '@aztec/circuit-types'; @@ -121,13 +121,13 @@ describe('Private Execution test suite', () => { args?: any[]; txContext?: Partial>; }) => { - const packedArguments = PackedValues.fromValues(encodeArguments(artifact, args)); + const hashedArguments = HashedValues.fromValues(encodeArguments(artifact, args)); const txRequest = TxExecutionRequest.from({ origin: contractAddress, - firstCallArgsHash: packedArguments.hash, + firstCallArgsHash: hashedArguments.hash, functionSelector: FunctionSelector.fromNameAndParameters(artifact.name, artifact.parameters), txContext: TxContext.from({ ...txContextFields, ...txContext }), - argsOfCalls: [packedArguments], + argsOfCalls: [hashedArguments], authWitnesses: [], }); diff --git a/yarn-project/simulator/src/client/private_execution.ts b/yarn-project/simulator/src/client/private_execution.ts index 2e7a6cbef7d..72dca650012 100644 --- a/yarn-project/simulator/src/client/private_execution.ts +++ b/yarn-project/simulator/src/client/private_execution.ts @@ -65,7 +65,7 @@ export async function executePrivateFunction( const contractClassLogs = context.getContractClassLogs(); - const rawReturnValues = await context.unpackReturns(publicInputs.returnsHash); + const rawReturnValues = await context.loadFromExecutionCache(publicInputs.returnsHash); const noteHashLeafIndexMap = context.getNoteHashLeafIndexMap(); const newNotes = context.getNewNotes(); diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index bc0bb302540..62873365f77 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -13,7 +13,7 @@ import { Fr } from '@aztec/foundation/fields'; import { type Logger, createLogger } from '@aztec/foundation/log'; import { createSimulationError } from '../common/errors.js'; -import { PackedValuesCache } from '../common/packed_values_cache.js'; +import { HashedValuesCache } from '../common/hashed_values_cache.js'; import { type SimulationProvider } from '../common/simulation_provider.js'; import { ClientExecutionContext } from './client_execution_context.js'; import { type DBOracle } from './db_oracle.js'; @@ -78,7 +78,7 @@ export class AcirSimulator { callContext, header, request.authWitnesses, - PackedValuesCache.create(request.argsOfCalls), + HashedValuesCache.create(request.argsOfCalls), new ExecutionNoteCache(txHash), this.db, this.node, diff --git a/yarn-project/simulator/src/common/hashed_values_cache.ts b/yarn-project/simulator/src/common/hashed_values_cache.ts new file mode 100644 index 00000000000..34b7b545b28 --- /dev/null +++ b/yarn-project/simulator/src/common/hashed_values_cache.ts @@ -0,0 +1,55 @@ +import { HashedValues } from '@aztec/circuit-types'; +import { Fr } from '@aztec/circuits.js'; + +/** + * A cache for hashed values (arguments, returns) during transaction execution. + */ +export class HashedValuesCache { + private cache: Map; + + constructor(initialArguments: HashedValues[] = []) { + this.cache = new Map(); + for (const initialArg of initialArguments) { + this.cache.set(initialArg.hash.toBigInt(), initialArg.values); + } + } + + /** + * Creates a new hashed values cache. + * @param initialArguments - The initial arguments to add to the cache. + * @returns The new hashed values cache. + */ + public static create(initialArguments: HashedValues[] = []) { + return new HashedValuesCache(initialArguments); + } + + /** + * Gets preimage of a hash. + * @param hash - The hash to get the preimage of. + * @returns The preimage. + */ + public getPreimage(hash: Fr): Fr[] { + if (hash.equals(Fr.ZERO)) { + return []; + } + const hashedValues = this.cache.get(hash.value); + if (!hashedValues) { + throw new Error(`Preimage for hash ${hash.toString()} not found in cache`); + } + return hashedValues; + } + + /** + * Stores values in cache and returns its hash. + * @param values - The values to store. + * @returns The hash of the values. + */ + public store(values: Fr[]) { + if (values.length === 0) { + return Fr.ZERO; + } + const hashedValues = HashedValues.fromValues(values); + this.cache.set(hashedValues.hash.value, hashedValues.values); + return hashedValues.hash; + } +} diff --git a/yarn-project/simulator/src/common/index.ts b/yarn-project/simulator/src/common/index.ts index c1da4735a9f..9b4950ade3c 100644 --- a/yarn-project/simulator/src/common/index.ts +++ b/yarn-project/simulator/src/common/index.ts @@ -1,2 +1,2 @@ -export * from './packed_values_cache.js'; +export * from './hashed_values_cache.js'; export * from './errors.js'; diff --git a/yarn-project/simulator/src/common/packed_values_cache.ts b/yarn-project/simulator/src/common/packed_values_cache.ts deleted file mode 100644 index 47a8281b330..00000000000 --- a/yarn-project/simulator/src/common/packed_values_cache.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { PackedValues } from '@aztec/circuit-types'; -import { Fr } from '@aztec/circuits.js'; - -/** - * A cache for packed values (arguments, returns) during transaction execution. - */ -export class PackedValuesCache { - private cache: Map; - - constructor(initialArguments: PackedValues[] = []) { - this.cache = new Map(); - for (const initialArg of initialArguments) { - this.cache.set(initialArg.hash.toBigInt(), initialArg.values); - } - } - - /** - * Creates a new packed values cache. - * @param initialArguments - The initial arguments to add to the cache. - * @returns The new packed values cache. - */ - public static create(initialArguments: PackedValues[] = []) { - return new PackedValuesCache(initialArguments); - } - - /** - * Unpacks packed values. - * @param hash - The hash of the packed values. - * @returns The unpacked values. - */ - public unpack(hash: Fr): Fr[] { - if (hash.equals(Fr.ZERO)) { - return []; - } - const packedValues = this.cache.get(hash.value); - if (!packedValues) { - throw new Error(`Packed values for hash ${hash.toString()} not found in cache`); - } - return packedValues; - } - - /** - * Packs values. - * @param values - The values to pack. - * @returns The hash of the packed values. - */ - public pack(values: Fr[]) { - if (values.length === 0) { - return Fr.ZERO; - } - const packedValues = PackedValues.fromValues(values); - this.cache.set(packedValues.hash.value, packedValues.values); - return packedValues.hash; - } -} diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index de0e7be647d..054194b096e 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -78,7 +78,7 @@ import { import { createTxForPublicCalls } from '@aztec/simulator/public/fixtures'; import { ExecutionError, - type PackedValuesCache, + type HashedValuesCache, type PublicTxResult, PublicTxSimulator, createSimulationError, @@ -125,7 +125,7 @@ export class TXE implements TypedOracle { constructor( private logger: Logger, private trees: MerkleTrees, - private packedValuesCache: PackedValuesCache, + private executionCache: HashedValuesCache, private noteCache: ExecutionNoteCache, private keyStore: KeyStore, private txeDatabase: TXEDatabase, @@ -374,16 +374,16 @@ export class TXE implements TypedOracle { return Fr.random(); } - packArgumentsArray(args: Fr[]) { - return Promise.resolve(this.packedValuesCache.pack(args)); + storeArrayInExecutionCache(values: Fr[]) { + return Promise.resolve(this.executionCache.store(values)); } - packReturns(returns: Fr[]) { - return Promise.resolve(this.packedValuesCache.pack(returns)); + storeInExecutionCache(values: Fr[]) { + return Promise.resolve(this.executionCache.store(values)); } - unpackReturns(returnsHash: Fr) { - return Promise.resolve(this.packedValuesCache.unpack(returnsHash)); + loadFromExecutionCache(returnsHash: Fr) { + return Promise.resolve(this.executionCache.getPreimage(returnsHash)); } getKeyValidationRequest(pkMHash: Fr): Promise { @@ -778,7 +778,7 @@ export class TXE implements TypedOracle { async getInitialWitness(abi: FunctionAbi, argsHash: Fr, sideEffectCounter: number, isStaticCall: boolean) { const argumentsSize = countArgumentsSize(abi); - const args = this.packedValuesCache.unpack(argsHash); + const args = this.executionCache.getPreimage(argsHash); if (args.length !== argumentsSize) { throw new Error('Invalid arguments size'); @@ -889,8 +889,8 @@ export class TXE implements TypedOracle { isStaticCall, ); - const args = [this.functionSelector.toField(), ...this.packedValuesCache.unpack(argsHash)]; - const newArgsHash = this.packedValuesCache.pack(args); + const args = [this.functionSelector.toField(), ...this.executionCache.getPreimage(argsHash)]; + const newArgsHash = this.executionCache.store(args); const executionResult = await this.executePublicFunction(args, callContext, isTeardown); diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 0164be15d6e..ed14655697c 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -19,7 +19,7 @@ import { protocolContractNames } from '@aztec/protocol-contracts'; import { getCanonicalProtocolContract } from '@aztec/protocol-contracts/bundle'; import { enrichPublicSimulationError } from '@aztec/pxe'; import { ExecutionNoteCache, type TypedOracle } from '@aztec/simulator/client'; -import { PackedValuesCache } from '@aztec/simulator/server'; +import { HashedValuesCache } from '@aztec/simulator/server'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { MerkleTrees } from '@aztec/world-state'; @@ -43,7 +43,7 @@ export class TXEService { static async init(logger: Logger) { const store = openTmpStore(true); const trees = await MerkleTrees.new(store, new NoopTelemetryClient(), logger); - const packedValuesCache = new PackedValuesCache(); + const executionCache = new HashedValuesCache(); const txHash = new Fr(1); // The txHash is used for computing the revertible nullifiers for non-revertible note hashes. It can be any value for testing. const noteCache = new ExecutionNoteCache(txHash); const keyStore = new KeyStore(store); @@ -55,7 +55,7 @@ export class TXEService { await txeDatabase.addContractInstance(instance); } logger.debug(`TXE service initialized`); - const txe = new TXE(logger, trees, packedValuesCache, noteCache, keyStore, txeDatabase); + const txe = new TXE(logger, trees, executionCache, noteCache, keyStore, txeDatabase); const service = new TXEService(logger, txe); await service.advanceBlocksBy(toSingle(new Fr(1n))); return service; @@ -273,25 +273,20 @@ export class TXEService { return toForeignCallResult([toSingle(new Fr(blockNumber))]); } - async packArgumentsArray(args: ForeignCallArray) { - const packed = await this.typedOracle.packArgumentsArray(fromArray(args)); - return toForeignCallResult([toSingle(packed)]); - } - - async packArguments(_length: ForeignCallSingle, values: ForeignCallArray) { - const packed = await this.typedOracle.packArgumentsArray(fromArray(values)); - return toForeignCallResult([toSingle(packed)]); + async storeArrayInExecutionCache(args: ForeignCallArray) { + const hash = await this.typedOracle.storeArrayInExecutionCache(fromArray(args)); + return toForeignCallResult([toSingle(hash)]); } // Since the argument is a slice, noir automatically adds a length field to oracle call. - async packReturns(_length: ForeignCallSingle, values: ForeignCallArray) { - const packed = await this.typedOracle.packReturns(fromArray(values)); - return toForeignCallResult([toSingle(packed)]); + async storeInExecutionCache(_length: ForeignCallSingle, values: ForeignCallArray) { + const returnsHash = await this.typedOracle.storeInExecutionCache(fromArray(values)); + return toForeignCallResult([toSingle(returnsHash)]); } - async unpackReturns(returnsHash: ForeignCallSingle) { - const unpacked = await this.typedOracle.unpackReturns(fromSingle(returnsHash)); - return toForeignCallResult([toArray(unpacked)]); + async loadFromExecutionCache(hash: ForeignCallSingle) { + const returns = await this.typedOracle.loadFromExecutionCache(fromSingle(hash)); + return toForeignCallResult([toArray(returns)]); } // Since the argument is a slice, noir automatically adds a length field to oracle call.