From 663806b144e8dfd85327aa67289baa231f22d9bf Mon Sep 17 00:00:00 2001 From: benesjan <13470840+benesjan@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:47:16 +0000 Subject: [PATCH] refactor: call args as an array instead of a slice Usage of slices is now discouraged and for this reason I am dropping their use from calls. This made me drop the `hash_args` function and rename `hash_args_array` to just `hash_args` as the original was no longer in use. Also `poseidon2_hash_with_separator_slice` got dropped due to lack of use. --- avm-transpiler/src/transpile.rs | 22 ++++--- .../aztec-nr/aztec/src/authwit/auth.nr | 10 +-- .../aztec-nr/aztec/src/context/calls.nr | 61 +++++++++---------- .../aztec/src/context/private_context.nr | 8 +-- .../aztec/src/context/public_context.nr | 40 +++++++----- .../aztec/src/context/returns_hash.nr | 16 ++--- .../aztec-nr/aztec/src/contract_self.nr | 26 +++++--- noir-projects/aztec-nr/aztec/src/hash.nr | 26 +------- .../external_functions_stubs.nr | 42 +++++++------ .../external/private.nr | 2 +- .../external/public.nr | 2 +- .../aztec/src/oracle/execution_cache.nr | 9 ++- .../aztec/src/test/helpers/authwit.nr | 12 ++-- .../src/test/helpers/test_environment.nr | 32 ++++++---- .../aztec/src/test/helpers/txe_oracles.nr | 30 ++++----- .../aztec-nr/aztec/src/test/helpers/utils.nr | 20 +++--- .../app/simple_token_contract/src/main.nr | 2 +- .../contracts/app/token_contract/src/main.nr | 2 +- .../docs/docs_example_contract/src/main.nr | 2 +- .../src/fake_public_context.nr | 14 +++-- .../test/avm_test_contract/src/main.nr | 14 ++--- .../test/parent_contract/src/main.nr | 10 +-- .../test/static_parent_contract/src/main.nr | 4 +- .../crates/types/src/hash.nr | 16 ----- .../oracle/oracle.ts | 3 +- yarn-project/txe/src/rpc_translator.ts | 10 +-- 26 files changed, 208 insertions(+), 227 deletions(-) diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index b03be8c5b879..39f089b57c1d 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -580,10 +580,12 @@ fn handle_foreign_call( /// (an external 'call' brillig foreign call was encountered) /// Adds the new instruction to the avm instructions list. // #[oracle(avmOpcodeCall)] -// unconstrained fn call_opcode( -// gas: [Field; 2], // gas allocation: [l2_gas, da_gas] +// unconstrained fn call_opcode( +// l2_gas_allocation: u32, +// da_gas_allocation: u32, // address: AztecAddress, -// args: [Field], +// length: u32, +// args: [Field; N], // ) {} fn handle_external_call( avm_instrs: &mut Vec, @@ -611,14 +613,14 @@ fn handle_external_call( ValueOrArray::MemoryAddress(offset) => offset, _ => panic!("Call instruction's target address input should be a basic MemoryAddress",), }; - // The args are a slice, and this is represented as a (Field, HeapVector). - // The field is the length (memory address) and the HeapVector has the data and length again. - // This is an ACIR internal representation detail that leaks to the SSA. - // Observe that below, we use `inputs[4]` and therefore skip the length field. + let args_size_offset = match &inputs[3] { + ValueOrArray::MemoryAddress(offset) => offset, + _ => panic!("Call instruction's length input should be a basic MemoryAddress"), + }; let args = &inputs[4]; - let (args_offset_ptr, args_size_offset) = match args { - ValueOrArray::HeapVector(HeapVector { pointer, size }) => (pointer, size), - _ => panic!("Call instruction's args input should be a HeapVector input"), + let args_offset_ptr = match args { + ValueOrArray::HeapArray(HeapArray { pointer, size: _ }) => pointer, + _ => panic!("Call instruction's args input should be a HeapArray input"), }; avm_instrs.push(AvmInstruction { diff --git a/noir-projects/aztec-nr/aztec/src/authwit/auth.nr b/noir-projects/aztec-nr/aztec/src/authwit/auth.nr index 1dfad1146522..9be62ef1336f 100644 --- a/noir-projects/aztec-nr/aztec/src/authwit/auth.nr +++ b/noir-projects/aztec-nr/aztec/src/authwit/auth.nr @@ -4,7 +4,7 @@ use crate::{ authorization_selector::AuthorizationSelector, }, context::{gas::GasOpts, PrivateContext, PublicContext}, - hash::hash_args_array, + hash::hash_args, macros::authorization::authorization, oracle::{execution_cache::load, offchain_effect::emit_offchain_effect}, }; @@ -344,7 +344,7 @@ pub unconstrained fn assert_inner_hash_valid_authwit_public( let results: [Field] = context.call_public_function( CANONICAL_AUTH_REGISTRY_ADDRESS, comptime { FunctionSelector::from_signature("consume((Field),Field)") }, - [on_behalf_of.to_field(), inner_hash].as_slice(), + [on_behalf_of.to_field(), inner_hash], GasOpts::default(), ); assert(results.len() == 1, "Invalid response from registry"); @@ -373,7 +373,7 @@ pub fn compute_authwit_message_hash_from_call( selector: FunctionSelector, args: [Field; N], ) -> Field { - let args_hash = hash_args_array(args); + let args_hash = hash_args(args); let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]); compute_authwit_message_hash(consumer, chain_id, version, inner_hash) @@ -438,7 +438,7 @@ pub unconstrained fn set_authorized(context: PublicContext, message_hash: Field, let res = context.call_public_function( CANONICAL_AUTH_REGISTRY_ADDRESS, comptime { FunctionSelector::from_signature("set_authorized(Field,bool)") }, - [message_hash, authorize as Field].as_slice(), + [message_hash, authorize as Field], GasOpts::default(), ); assert(res.len() == 0); @@ -455,7 +455,7 @@ pub unconstrained fn set_reject_all(context: PublicContext, reject: bool) { let res = context.call_public_function( CANONICAL_AUTH_REGISTRY_ADDRESS, comptime { FunctionSelector::from_signature("set_reject_all(bool)") }, - [context.this_address().to_field(), reject as Field].as_slice(), + [context.this_address().to_field(), reject as Field], GasOpts::default(), ); assert(res.len() == 0); diff --git a/noir-projects/aztec-nr/aztec/src/context/calls.nr b/noir-projects/aztec-nr/aztec/src/context/calls.nr index fc20118fbcbe..9d23532a4c17 100644 --- a/noir-projects/aztec-nr/aztec/src/context/calls.nr +++ b/noir-projects/aztec-nr/aztec/src/context/calls.nr @@ -5,34 +5,34 @@ use dep::protocol_types::{ }; use crate::context::{gas::GasOpts, private_context::PrivateContext, public_context::PublicContext}; -use crate::hash::{hash_args, hash_calldata}; +use crate::hash::{hash_args, hash_calldata_array}; use crate::oracle::execution_cache; // PrivateCall #[must_use = "Your private call needs to be passed into the `self.call(...)` method to be executed (e.g. `self.call(MyContract::at(address).my_private_function(...args))`"] -pub struct PrivateCall { +pub struct PrivateCall { pub target_contract: AztecAddress, pub selector: FunctionSelector, pub name: str, args_hash: Field, - pub args: [Field], + pub args: [Field; N], return_type: T, } -impl PrivateCall { +impl PrivateCall { pub fn new( target_contract: AztecAddress, selector: FunctionSelector, name: str, - args: [Field], + args: [Field; N], ) -> Self { let args_hash = hash_args(args); Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() } } } -impl PrivateCall +impl PrivateCall where T: Deserialize, { @@ -58,21 +58,21 @@ where // PrivateStaticCall #[must_use = "Your private static call needs to be passed into the `self.view(...)` method to be executed (e.g. `self.view(MyContract::at(address).my_private_static_function(...args))`"] -pub struct PrivateStaticCall { +pub struct PrivateStaticCall { pub target_contract: AztecAddress, pub selector: FunctionSelector, pub name: str, args_hash: Field, - pub args: [Field], + pub args: [Field; N], return_type: T, } -impl PrivateStaticCall { +impl PrivateStaticCall { pub fn new( target_contract: AztecAddress, selector: FunctionSelector, name: str, - args: [Field], + args: [Field; N], ) -> Self { let args_hash = hash_args(args); Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() } @@ -100,22 +100,21 @@ impl PrivateStaticCall { // PublicCall #[must_use = "Your public call needs to be passed into the `self.call(...)`, `self.enqueue(...)` or `self.enqueue_incognito(...)` method to be executed (e.g. `self.call(MyContract::at(address).my_public_function(...args))`"] -pub struct PublicCall { +pub struct PublicCall { pub target_contract: AztecAddress, pub selector: FunctionSelector, pub name: str, - // TODO(F-131): Determine the length at comptime and drop the use of slices. - pub args: [Field], + pub args: [Field; N], gas_opts: GasOpts, return_type: T, } -impl PublicCall { +impl PublicCall { pub fn new( target_contract: AztecAddress, selector: FunctionSelector, name: str, - args: [Field], + args: [Field; N], ) -> Self { Self { target_contract, @@ -173,8 +172,8 @@ impl PublicCall { is_static_call: bool, hide_msg_sender: bool, ) { - let calldata = self.args.push_front(self.selector.to_field()); - let calldata_hash = hash_calldata(calldata); + let calldata = [self.selector.to_field()].concat(self.args); + let calldata_hash = hash_calldata_array(calldata); execution_cache::store(calldata, calldata_hash); context.call_public_function_with_calldata_hash( self.target_contract, @@ -201,8 +200,8 @@ impl PublicCall { } fn set_as_teardown_impl(self, context: &mut PrivateContext, hide_msg_sender: bool) { - let calldata = self.args.push_front(self.selector.to_field()); - let calldata_hash = hash_calldata(calldata); + let calldata = [self.selector.to_field()].concat(self.args); + let calldata_hash = hash_calldata_array(calldata); execution_cache::store(calldata, calldata_hash); context.set_public_teardown_function_with_calldata_hash( self.target_contract, @@ -216,21 +215,21 @@ impl PublicCall { // PublicStaticCall #[must_use = "Your public static call needs to be passed into the `self.view(...)`, `self.enqueue_view(...)` or `self.enqueue_view_incognito(...)` method to be executed (e.g. `self.view(MyContract::at(address).my_public_static_function(...args))`"] -pub struct PublicStaticCall { +pub struct PublicStaticCall { pub target_contract: AztecAddress, pub selector: FunctionSelector, pub name: str, - pub args: [Field], + pub args: [Field; N], return_type: T, gas_opts: GasOpts, } -impl PublicStaticCall { +impl PublicStaticCall { pub fn new( target_contract: AztecAddress, selector: FunctionSelector, name: str, - args: [Field], + args: [Field; N], ) -> Self { Self { target_contract, @@ -269,8 +268,8 @@ impl PublicStaticCall { /// `self.enqueue_view(MyContract::at(address).my_public_static_function(...args))` /// instead of manually constructing and calling `PublicStaticCall`. pub fn enqueue_view(self, context: &mut PrivateContext) { - let calldata = self.args.push_front(self.selector.to_field()); - let calldata_hash = hash_calldata(calldata); + let calldata = [self.selector.to_field()].concat(self.args); + let calldata_hash = hash_calldata_array(calldata); execution_cache::store(calldata, calldata_hash); context.call_public_function_with_calldata_hash( self.target_contract, @@ -286,8 +285,8 @@ impl PublicStaticCall { /// `self.enqueue_view_incognito(MyContract::at(address).my_public_static_function(...args))` /// instead of manually constructing and calling `PublicStaticCall`. pub fn enqueue_view_incognito(self, context: &mut PrivateContext) { - let calldata = self.args.push_front(self.selector.to_field()); - let calldata_hash = hash_calldata(calldata); + let calldata = [self.selector.to_field()].concat(self.args); + let calldata_hash = hash_calldata_array(calldata); execution_cache::store(calldata, calldata_hash); context.call_public_function_with_calldata_hash( self.target_contract, @@ -301,21 +300,21 @@ impl PublicStaticCall { // UtilityCall -pub struct UtilityCall { +pub struct UtilityCall { pub target_contract: AztecAddress, pub selector: FunctionSelector, pub name: str, args_hash: Field, - pub args: [Field], + pub args: [Field; N], return_type: T, } -impl UtilityCall { +impl UtilityCall { pub fn new( target_contract: AztecAddress, selector: FunctionSelector, name: str, - args: [Field], + args: [Field; N], ) -> Self { let args_hash = hash_args(args); Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() } 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 43fb28aabc76..a8cb074f3847 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -2,7 +2,7 @@ use crate::{ context::{ inputs::PrivateContextInputs, note_hash_read::NoteHashRead, returns_hash::ReturnsHash, }, - hash::{hash_args_array, hash_calldata_array}, + hash::{hash_args, hash_calldata_array}, keys::constants::{NULLIFIER_INDEX, NUM_KEY_TYPES, OUTGOING_INDEX, sk_generators}, messaging::process_l1_to_l2_message, oracle::{ @@ -572,7 +572,7 @@ impl PrivateContext { /// * `serialized_return_values` - The serialized return values as a field array /// pub fn set_return_hash(&mut self, serialized_return_values: [Field; N]) { - let return_hash = hash_args_array(serialized_return_values); + let return_hash = hash_args(serialized_return_values); self.return_hash = return_hash; execution_cache::store(serialized_return_values, return_hash); } @@ -1263,7 +1263,7 @@ impl PrivateContext { function_selector: FunctionSelector, args: [Field; ArgsCount], ) -> ReturnsHash { - let args_hash = hash_args_array(args); + let args_hash = hash_args(args); execution_cache::store(args, args_hash); self.call_private_function_with_args_hash( contract_address, @@ -1297,7 +1297,7 @@ impl PrivateContext { function_selector: FunctionSelector, args: [Field; ArgsCount], ) -> ReturnsHash { - let args_hash = hash_args_array(args); + let args_hash = hash_args(args); execution_cache::store(args, args_hash); self.call_private_function_with_args_hash( contract_address, diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 3abe703f5792..bc58539bc467 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -287,14 +287,14 @@ impl PublicContext { /// # Returns /// * `[Field]` - Return data from the called function /// - pub unconstrained fn call_public_function( + pub unconstrained fn call_public_function( _self: Self, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field], + args: [Field; N], gas_opts: GasOpts, ) -> [Field] { - let calldata = args.push_front(function_selector.to_field()); + let calldata = [function_selector.to_field()].concat(args); call( gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE), @@ -332,14 +332,14 @@ impl PublicContext { /// # Returns /// * `[Field]` - Return data from the called function /// - pub unconstrained fn static_call_public_function( + pub unconstrained fn static_call_public_function( _self: Self, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field], + args: [Field; N], gas_opts: GasOpts, ) -> [Field] { - let calldata = args.push_front(function_selector.to_field()); + let calldata = [function_selector.to_field()].concat(args); call_static( gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE), @@ -861,22 +861,22 @@ unconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) { send_l2_to_l1_msg_opcode(recipient, content) } -unconstrained fn call( +unconstrained fn call( l2_gas_allocation: u32, da_gas_allocation: u32, address: AztecAddress, - args: [Field], + args: [Field; N], ) { - call_opcode(l2_gas_allocation, da_gas_allocation, address, args) + call_opcode(l2_gas_allocation, da_gas_allocation, address, N, args) } -unconstrained fn call_static( +unconstrained fn call_static( l2_gas_allocation: u32, da_gas_allocation: u32, address: AztecAddress, - args: [Field], + args: [Field; N], ) { - call_static_opcode(l2_gas_allocation, da_gas_allocation, address, args) + call_static_opcode(l2_gas_allocation, da_gas_allocation, address, N, args) } pub unconstrained fn calldata_copy(cdoffset: u32, copy_size: u32) -> [Field; N] { @@ -1001,20 +1001,28 @@ unconstrained fn return_opcode(returndata: [Field]) {} #[oracle(avmOpcodeRevert)] unconstrained fn revert_opcode(revertdata: [Field]) {} +// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode +// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take that +// route. #[oracle(avmOpcodeCall)] -unconstrained fn call_opcode( +unconstrained fn call_opcode( l2_gas_allocation: u32, da_gas_allocation: u32, address: AztecAddress, - args: [Field], + length: u32, + args: [Field; N], ) {} +// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode +// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take that +// route. #[oracle(avmOpcodeStaticCall)] -unconstrained fn call_static_opcode( +unconstrained fn call_static_opcode( l2_gas_allocation: u32, da_gas_allocation: u32, address: AztecAddress, - args: [Field], + length: u32, + args: [Field; N], ) {} #[oracle(avmOpcodeSuccessCopy)] diff --git a/noir-projects/aztec-nr/aztec/src/context/returns_hash.nr b/noir-projects/aztec-nr/aztec/src/context/returns_hash.nr index b42a69d72a6c..6e3e8af8d098 100644 --- a/noir-projects/aztec-nr/aztec/src/context/returns_hash.nr +++ b/noir-projects/aztec-nr/aztec/src/context/returns_hash.nr @@ -1,4 +1,4 @@ -use crate::{hash::hash_args_array, oracle::execution_cache}; +use crate::{hash::hash_args, oracle::execution_cache}; use dep::protocol_types::traits::Deserialize; /// A hash that represents a private contract function call's return value. Call `get_preimage` to get the underlying @@ -24,10 +24,10 @@ impl ReturnsHash { { // Safety: We verify that the value returned by `load` is the preimage of `hash`, fully constraining it. If `T` // is `()`, then `preimage` must be an array of length 0 (since that is `()`'s deserialization length). - // `hash_args_array` handles empty arrays following the protocol rules (i.e. an empty args array is signaled + // `hash_args` handles empty arrays following the protocol rules (i.e. an empty args array is signaled // with a zero hash), correctly constraining `self.hash`. let preimage = unsafe { execution_cache::load(self.hash) }; - assert_eq(self.hash, hash_args_array(preimage), "Preimage mismatch"); + assert_eq(self.hash, hash_args(preimage), "Preimage mismatch"); Deserialize::deserialize(preimage) } @@ -35,7 +35,7 @@ impl ReturnsHash { mod test { use crate::{ - hash::hash_args_array, + hash::hash_args, oracle::execution_cache, test::{helpers::test_environment::TestEnvironment, mocks::mock_struct::MockStruct}, }; @@ -50,7 +50,7 @@ mod test { let value = MockStruct::new(4, 7); let serialized = value.serialize(); - let hash = hash_args_array(serialized); + let hash = hash_args(serialized); execution_cache::store(serialized, hash); assert_eq(ReturnsHash::new(hash).get_preimage(), value); @@ -64,7 +64,7 @@ mod test { let value = (); let serialized = []; - let hash = hash_args_array(serialized); + let hash = hash_args(serialized); execution_cache::store(serialized, hash); assert_eq(ReturnsHash::new(hash).get_preimage(), value); @@ -79,7 +79,7 @@ mod test { let mut bad_serialized = serialized; bad_serialized[0] += 1; - let hash = hash_args_array(serialized); + let hash = hash_args(serialized); let _ = OracleMock::mock("privateLoadFromExecutionCache").returns(bad_serialized); assert_eq(ReturnsHash::new(hash).get_preimage(), value); @@ -91,7 +91,7 @@ mod test { // let value = (); // let serialized = []; - // let hash = hash_args_array(serialized); + // let hash = hash_args(serialized); // let _ = OracleMock::mock("privateLoadFromExecutionCache").returns([1]); // assert_eq(ReturnsHash::new(hash).get_preimage(), value); diff --git a/noir-projects/aztec-nr/aztec/src/contract_self.nr b/noir-projects/aztec-nr/aztec/src/contract_self.nr index 2312c7970032..cc8142e3efc1 100644 --- a/noir-projects/aztec-nr/aztec/src/contract_self.nr +++ b/noir-projects/aztec-nr/aztec/src/contract_self.nr @@ -262,7 +262,7 @@ impl(&mut self, call: PrivateCall) -> T + pub fn call(&mut self, call: PrivateCall) -> T where T: Deserialize, { @@ -285,7 +285,7 @@ impl(&mut self, call: PrivateStaticCall) -> T + pub fn view(&mut self, call: PrivateStaticCall) -> T where T: Deserialize, { @@ -323,7 +323,7 @@ impl(&mut self, call: PublicCall) + pub fn enqueue(&mut self, call: PublicCall) where T: Deserialize, { @@ -347,7 +347,7 @@ impl(&mut self, call: PublicStaticCall) + pub fn enqueue_view(&mut self, call: PublicStaticCall) where T: Deserialize, { @@ -400,7 +400,7 @@ impl(&mut self, call: PublicCall) + pub fn enqueue_incognito(&mut self, call: PublicCall) where T: Deserialize, { @@ -425,7 +425,10 @@ impl(&mut self, call: PublicStaticCall) + pub fn enqueue_view_incognito( + &mut self, + call: PublicStaticCall, + ) where T: Deserialize, { @@ -464,7 +467,7 @@ impl(&mut self, call: PublicCall) + pub fn set_as_teardown(&mut self, call: PublicCall) where T: Deserialize, { @@ -483,7 +486,10 @@ impl(&mut self, call: PublicCall) + pub fn set_as_teardown_incognito( + &mut self, + call: PublicCall, + ) where T: Deserialize, { @@ -584,7 +590,7 @@ impl ContractSelf(self, call: PublicCall) -> T + pub unconstrained fn call(self, call: PublicCall) -> T where T: Deserialize, { @@ -610,7 +616,7 @@ impl ContractSelf(self, call: PublicStaticCall) -> T + pub unconstrained fn view(self, call: PublicStaticCall) -> T where T: Deserialize, { diff --git a/noir-projects/aztec-nr/aztec/src/hash.nr b/noir-projects/aztec-nr/aztec/src/hash.nr index b794913567d6..fedc714978bd 100644 --- a/noir-projects/aztec-nr/aztec/src/hash.nr +++ b/noir-projects/aztec-nr/aztec/src/hash.nr @@ -5,10 +5,7 @@ use dep::protocol_types::{ GENERATOR_INDEX__PUBLIC_BYTECODE, GENERATOR_INDEX__PUBLIC_CALLDATA, GENERATOR_INDEX__SECRET_HASH, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, }, - hash::{ - poseidon2_hash_subarray, poseidon2_hash_with_separator, poseidon2_hash_with_separator_slice, - sha256_to_field, - }, + hash::{poseidon2_hash_subarray, poseidon2_hash_with_separator, sha256_to_field}, point::Point, traits::ToField, }; @@ -60,7 +57,7 @@ pub fn compute_l1_to_l2_message_nullifier(message_hash: Field, secret: Field) -> } // Computes the hash of input arguments or return values for private functions, or for authwit creation. -pub fn hash_args_array(args: [Field; N]) -> Field { +pub fn hash_args(args: [Field; N]) -> Field { if args.len() == 0 { 0 } else { @@ -68,25 +65,11 @@ pub fn hash_args_array(args: [Field; N]) -> Field { } } -// Same as `hash_args_array`, but takes a slice instead of an array. -pub fn hash_args(args: [Field]) -> Field { - if args.len() == 0 { - 0 - } else { - poseidon2_hash_with_separator_slice(args, GENERATOR_INDEX__FUNCTION_ARGS) - } -} - // Computes the hash of calldata for public functions. pub fn hash_calldata_array(calldata: [Field; N]) -> Field { poseidon2_hash_with_separator(calldata, GENERATOR_INDEX__PUBLIC_CALLDATA) } -// Same as `hash_calldata_array`, but takes a slice instead of an array. -pub fn hash_calldata(calldata: [Field]) -> Field { - poseidon2_hash_with_separator_slice(calldata, GENERATOR_INDEX__PUBLIC_CALLDATA) -} - /** * Computes the public bytecode commitment for a contract class. * The commitment is `hash([separator, ...bytecode])` where bytecode omits the length prefix present @@ -127,7 +110,7 @@ unconstrained fn compute_var_args_hash() { for i in 0..100 { input[i] = i as Field; } - let hash = hash_args_array(input); + let hash = hash_args(input); dep::std::println(hash); // Used in yarn-project/stdlib test snapshots: assert(hash == 0x19b0d74feb06ebde19edd85a28986c97063e84b3b351a8b666c7cac963ce655f); @@ -140,9 +123,6 @@ unconstrained fn compute_calldata_hash() { input[i] = i as Field; } let hash = hash_calldata_array(input); - dep::std::println(hash); - let hash_check = hash_calldata(input.as_slice()); - assert(hash == hash_check); // Used in cpp vm2 tests: assert(hash == 0x191383c9f8964afd3ea8879a03b7dda65d6724773966d18dcf80e452736fc1f3); } diff --git a/noir-projects/aztec-nr/aztec/src/macros/calls_generation/external_functions_stubs.nr b/noir-projects/aztec-nr/aztec/src/macros/calls_generation/external_functions_stubs.nr index 761f662b9ac4..c60c3fb7fe1a 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/calls_generation/external_functions_stubs.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/calls_generation/external_functions_stubs.nr @@ -21,7 +21,7 @@ comptime global FROM_FIELD: TypedExpr = { /// Utility function creating stubs used by all the stub functions in this file. comptime fn create_stub_base( f: FunctionDefinition, -) -> (Quoted, Quoted, Quoted, Quoted, Quoted, u32, Field) { +) -> (Quoted, Quoted, Quoted, Quoted, u32, Quoted, u32, Field) { // Dear privacy adventurer, // Chances are, you've command+clicked on the name of an external function // call -- seeking to view that function -- only to end up here. @@ -43,8 +43,10 @@ comptime fn create_stub_base( let fn_parameters_list = fn_parameters.map(|(name, typ): (Quoted, Type)| quote { $name: $typ }).join(quote {,}); - let (serialized_args_array_construction, _, serialized_args_array_name) = + let (serialized_args_array_construction, serialized_args_array_len_quote, serialized_args_array_name) = derive_serialization_quotes(fn_parameters, false); + let serialized_args_array_len: u32 = + unquote!(quote { ($serialized_args_array_len_quote) as u32 }); let (fn_name_str, _) = fn_name.as_str_quote(); let fn_name_len: u32 = unquote!(quote { $fn_name_str.as_bytes().len()}); @@ -52,17 +54,17 @@ comptime fn create_stub_base( ( fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, - fn_name_str, fn_name_len, fn_selector, + serialized_args_array_len, fn_name_str, fn_name_len, fn_selector, ) } pub(crate) comptime fn create_private_stub(f: FunctionDefinition) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, serialized_args_array_len, fn_name_str, fn_name_len, fn_selector) = create_stub_base(f); let fn_return_type = f.return_type(); quote { - pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::PrivateCall<$fn_name_len, $fn_return_type> { + pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::PrivateCall<$fn_name_len, $serialized_args_array_len, $fn_return_type> { $serialized_args_array_construction let selector = $FROM_FIELD($fn_selector); dep::aztec::context::calls::PrivateCall::new( @@ -76,12 +78,12 @@ pub(crate) comptime fn create_private_stub(f: FunctionDefinition) -> Quoted { } pub(crate) comptime fn create_private_static_stub(f: FunctionDefinition) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, serialized_args_array_len, fn_name_str, fn_name_len, fn_selector) = create_stub_base(f); let fn_return_type = f.return_type(); quote { - pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::PrivateStaticCall<$fn_name_len, $fn_return_type> { + pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::PrivateStaticCall<$fn_name_len, $serialized_args_array_len, $fn_return_type> { $serialized_args_array_construction let selector = $FROM_FIELD($fn_selector); dep::aztec::context::calls::PrivateStaticCall::new( @@ -95,12 +97,12 @@ pub(crate) comptime fn create_private_static_stub(f: FunctionDefinition) -> Quot } pub(crate) comptime fn create_public_stub(f: FunctionDefinition) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, serialized_args_array_len, fn_name_str, fn_name_len, fn_selector) = create_stub_base(f); let fn_return_type = f.return_type(); quote { - pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::PublicCall<$fn_name_len, $fn_return_type> { + pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::PublicCall<$fn_name_len, $serialized_args_array_len, $fn_return_type> { $serialized_args_array_construction let selector = $FROM_FIELD($fn_selector); dep::aztec::context::calls::PublicCall::new( @@ -114,12 +116,12 @@ pub(crate) comptime fn create_public_stub(f: FunctionDefinition) -> Quoted { } pub(crate) comptime fn create_public_static_stub(f: FunctionDefinition) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, serialized_args_array_len, fn_name_str, fn_name_len, fn_selector) = create_stub_base(f); let fn_return_type = f.return_type(); quote { - pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::PublicStaticCall<$fn_name_len, $fn_return_type> { + pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::PublicStaticCall<$fn_name_len, $serialized_args_array_len, $fn_return_type> { $serialized_args_array_construction let selector = $FROM_FIELD($fn_selector); dep::aztec::context::calls::PublicStaticCall::new( @@ -133,12 +135,12 @@ pub(crate) comptime fn create_public_static_stub(f: FunctionDefinition) -> Quote } pub(crate) comptime fn create_utility_stub(f: FunctionDefinition) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, serialized_args_array_len, fn_name_str, fn_name_len, fn_selector) = create_stub_base(f); let fn_return_type = f.return_type(); quote { - pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::UtilityCall<$fn_name_len, $fn_return_type> { + pub fn $fn_name(self, $fn_parameters_list) -> dep::aztec::context::calls::UtilityCall<$fn_name_len, $serialized_args_array_len, $fn_return_type> { $serialized_args_array_construction let selector = $FROM_FIELD($fn_selector); dep::aztec::context::calls::UtilityCall::new( @@ -160,7 +162,7 @@ pub(crate) comptime fn create_utility_stub(f: FunctionDefinition) -> Quoted { /// Creates a stub for calling a private function (or static private function if `is_static` is true) from private /// context (for CallSelf<&mut PrivateContext> and CallSelfStatic<&mut PrivateContext>). pub comptime fn create_private_self_call_stub(f: FunctionDefinition, is_static: bool) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, _, _, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, _, _, _, fn_selector) = create_stub_base(f); let fn_return_type = f.return_type(); @@ -189,7 +191,7 @@ pub comptime fn create_private_self_call_stub(f: FunctionDefinition, is_static: /// Creates a stub for calling a public function from public context (for CallSelf) pub comptime fn create_public_self_call_stub(f: FunctionDefinition) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, _, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, _, fn_name_str, _, fn_selector) = create_stub_base(f); let fn_return_type = f.return_type(); @@ -211,7 +213,7 @@ pub comptime fn create_public_self_call_stub(f: FunctionDefinition) -> Quoted { /// Creates a static stub for calling a public view function from public context (for CallSelfStatic) pub comptime fn create_public_self_call_static_stub(f: FunctionDefinition) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, _, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, _, fn_name_str, _, fn_selector) = create_stub_base(f); let fn_return_type = f.return_type(); @@ -233,14 +235,14 @@ pub comptime fn create_public_self_call_static_stub(f: FunctionDefinition) -> Qu /// Creates a static stub for enqueuing a public view function from private context (for EnqueueSelfStatic<&mut PrivateContext>) pub comptime fn create_public_self_enqueue_static_stub(f: FunctionDefinition) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, serialized_args_array_len, fn_name_str, fn_name_len, fn_selector) = create_stub_base(f); quote { pub fn $fn_name(self, $fn_parameters_list) { $serialized_args_array_construction let selector = $FROM_FIELD($fn_selector); - let interface: aztec::context::calls::PublicStaticCall<$fn_name_len, ()> = aztec::context::calls::PublicStaticCall::new( + let interface: aztec::context::calls::PublicStaticCall<$fn_name_len, $serialized_args_array_len, ()> = aztec::context::calls::PublicStaticCall::new( self.address, selector, $fn_name_str, @@ -253,14 +255,14 @@ pub comptime fn create_public_self_enqueue_static_stub(f: FunctionDefinition) -> /// Creates a stub for enqueuing a public function from private context (for EnqueueSelf<&mut PrivateContext>) pub comptime fn create_public_self_enqueue_stub(f: FunctionDefinition) -> Quoted { - let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, fn_name_str, fn_name_len, fn_selector) = + let (fn_name, fn_parameters_list, serialized_args_array_construction, serialized_args_array_name, serialized_args_array_len, fn_name_str, fn_name_len, fn_selector) = create_stub_base(f); quote { pub fn $fn_name(self, $fn_parameters_list) { $serialized_args_array_construction let selector = $FROM_FIELD($fn_selector); - let interface: aztec::context::calls::PublicCall<$fn_name_len, ()> = aztec::context::calls::PublicCall::new( + let interface: aztec::context::calls::PublicCall<$fn_name_len, $serialized_args_array_len, ()> = aztec::context::calls::PublicCall::new( self.address, selector, $fn_name_str, diff --git a/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/private.nr b/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/private.nr index 1627c6cdebb3..19ae22416ed4 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/private.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/private.nr @@ -52,7 +52,7 @@ pub(crate) comptime fn generate_private_external(f: FunctionDefinition) -> Quote #[allow(unused_variables)] let mut self = { $args_serialization - let args_hash = aztec::hash::hash_args_array($serialized_args_name); + let args_hash = aztec::hash::hash_args($serialized_args_name); let mut context = aztec::context::private_context::PrivateContext::new(inputs, args_hash); $storage_init let self_address = context.this_address(); diff --git a/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr b/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr index bd2eb9a516d5..1295796bdcfb 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr @@ -50,7 +50,7 @@ pub(crate) comptime fn generate_public_external(f: FunctionDefinition) -> Quoted let context = dep::aztec::context::public_context::PublicContext::new(|| { // We start from 1 because we skip the selector for the dispatch function. let serialized_args : [Field; $args_len_quote] = dep::aztec::context::public_context::calldata_copy(1, $args_len_quote); - dep::aztec::hash::hash_args_array(serialized_args) + dep::aztec::hash::hash_args(serialized_args) }); $storage_init let self_address = context.this_address(); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr b/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr index 9e625be253e5..5152f7ce6dd4 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr @@ -1,11 +1,14 @@ /// Stores values represented as slice in execution cache to be later obtained by its hash. -pub fn store(values: [Field], hash: Field) { +pub fn store(values: [Field; N], hash: 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, hash) }; } -unconstrained fn store_in_execution_cache_oracle_wrapper(values: [Field], hash: Field) { +unconstrained fn store_in_execution_cache_oracle_wrapper( + values: [Field; N], + hash: Field, +) { store_in_execution_cache_oracle(values, hash); } @@ -14,7 +17,7 @@ pub unconstrained fn load(hash: Field) -> [Field; N] { } #[oracle(privateStoreInExecutionCache)] -unconstrained fn store_in_execution_cache_oracle(_values: [Field], _hash: Field) {} +unconstrained fn store_in_execution_cache_oracle(_values: [Field; N], _hash: Field) {} #[oracle(privateLoadFromExecutionCache)] unconstrained fn load_from_execution_cache_oracle(_hash: Field) -> [Field; N] {} diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/authwit.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/authwit.nr index 4e3d125d16b0..bc8dde463218 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/authwit.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/authwit.nr @@ -10,11 +10,11 @@ use protocol_types::{ constants::CANONICAL_AUTH_REGISTRY_ADDRESS, traits::ToField, }; -pub unconstrained fn add_private_authwit_from_call( +pub unconstrained fn add_private_authwit_from_call( env: TestEnvironment, on_behalf_of: AztecAddress, caller: AztecAddress, - call: PrivateCall, + call: PrivateCall, ) { // The creation of this utility context results in the TXE session needing to keep track of authwits over its // lifetime, as we'd otherwise be unable to store more than one authwit due to them getting reset when restoring the @@ -33,11 +33,11 @@ pub unconstrained fn add_private_authwit_from_call( txe_oracles::add_authwit(on_behalf_of, message_hash); } -pub unconstrained fn add_public_authwit_from_call( +pub unconstrained fn add_public_authwit_from_call( env: TestEnvironment, on_behalf_of: AztecAddress, caller: AztecAddress, - call: PublicCall, + call: PublicCall, ) { let (chain_id, version) = env.utility_context(|context| (context.chain_id(), context.version())); @@ -52,11 +52,11 @@ pub unconstrained fn add_public_authwit_from_call( env.call_public( on_behalf_of, - PublicCall::<_, ()>::new( + PublicCall::<_, _, ()>::new( CANONICAL_AUTH_REGISTRY_ADDRESS, comptime { FunctionSelector::from_signature("set_authorized(Field,bool)") }, "set_authorized", - [message_hash, true as Field].as_slice(), + [message_hash, true as Field], ), ); } diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index 23ef0fdb5a89..70c62fd5b558 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -398,7 +398,7 @@ impl TestEnvironment { let _ = self.call_private( AztecAddress::zero(), - PrivateCall::<_, ()>::new( + PrivateCall::<_, _, ()>::new( address, comptime { FunctionSelector::from_signature("constructor(Field,Field)") }, "constructor", @@ -494,10 +494,10 @@ impl TestEnvironment { /// let contract_addr = env.deploy("SampleContract").without_initializer(); /// let return_value = env.call_private(caller, SampleContract::at(contract_addr).sample_private_function()); /// ``` - pub unconstrained fn call_private( + pub unconstrained fn call_private( _self: Self, from: AztecAddress, - call: PrivateCall, + call: PrivateCall, ) -> T where T: Deserialize, @@ -518,9 +518,9 @@ impl TestEnvironment { /// /// Unlike `call_private`, no transaction is created and no block is mined (since `#[view]` functions are only /// executable in a static context, and these produce no side effects). - pub unconstrained fn view_private( + pub unconstrained fn view_private( _self: Self, - call: PrivateStaticCall, + call: PrivateStaticCall, ) -> T where T: Deserialize, @@ -546,7 +546,10 @@ impl TestEnvironment { /// let contract_addr = env.deploy("SampleContract").without_initializer(); /// let return_value = env.simulate_utility(SampleContract::at(contract_addr).sample_utility_function()); /// ``` - pub unconstrained fn simulate_utility(_self: Self, call: UtilityCall) -> T + pub unconstrained fn simulate_utility( + _self: Self, + call: UtilityCall, + ) -> T where T: Deserialize, { @@ -574,10 +577,10 @@ impl TestEnvironment { /// let contract_addr = env.deploy("SampleContract").without_initializer(); /// let return_value = env.call_public(caller, SampleContract::at(contract_addr).sample_public_function()); /// ``` - pub unconstrained fn call_public( + pub unconstrained fn call_public( _self: Self, from: AztecAddress, - call: PublicCall, + call: PublicCall, ) -> T where T: Deserialize, @@ -595,10 +598,10 @@ impl TestEnvironment { /// Performs a public contract function call, including the processing of any nested public calls. Returns the /// result of the called function. /// Variant of `call_public`, but the `from` address (`msg_sender`) is set to "null". - pub unconstrained fn call_public_incognito( + pub unconstrained fn call_public_incognito( _self: Self, from: AztecAddress, - call: PublicCall, + call: PublicCall, ) -> T where T: Deserialize, @@ -618,7 +621,10 @@ impl TestEnvironment { /// /// Unlike `call_public`, no transaction is created and no block is mined (since `#[view]` functions are only /// executable in a static context, and these produce no side effects). - pub unconstrained fn view_public(_self: Self, call: PublicStaticCall) -> T + pub unconstrained fn view_public( + _self: Self, + call: PublicStaticCall, + ) -> T where T: Deserialize, { @@ -637,9 +643,9 @@ impl TestEnvironment { /// /// Unlike `call_public`, no transaction is created and no block is mined (since `#[view]` functions are only /// executable in a static context, and these produce no side effects). - pub unconstrained fn view_public_incognito( + pub unconstrained fn view_public_incognito( _self: Self, - call: PublicStaticCall, + call: PublicStaticCall, ) -> T where T: Deserialize, diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr index f29aab636d60..1380b819b9eb 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr @@ -11,21 +11,21 @@ use protocol_types::{ traits::{Deserialize, ToField}, }; -pub unconstrained fn deploy( +pub unconstrained fn deploy( path: str, initializer: str

, - args: [Field], + args: [Field; M], secret: Field, ) -> ContractInstance { let instance_fields = deploy_oracle(path, initializer, args, secret); ContractInstance::deserialize(instance_fields) } -pub unconstrained fn private_call_new_flow( +pub unconstrained fn private_call_new_flow( from: AztecAddress, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field], + args: [Field; M], args_hash: Field, is_static_call: bool, ) -> [Field; N] { @@ -39,24 +39,24 @@ pub unconstrained fn private_call_new_flow( ) } -pub unconstrained fn public_call_new_flow( +pub unconstrained fn public_call_new_flow( from: Option, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field], + args: [Field; M], is_static_call: bool, ) -> [Field; N] { - let calldata = args.push_front(function_selector.to_field()); + let calldata = [function_selector.to_field()].concat(args); let from = from.unwrap_or(NULL_MSG_SENDER_CONTRACT_ADDRESS); public_call_new_flow_oracle(from, contract_address, calldata, is_static_call) } -pub unconstrained fn simulate_utility_function( +pub unconstrained fn simulate_utility_function( contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field], + args: [Field; M], ) -> [Field; N] { simulate_utility_function_oracle(contract_address, function_selector, args) } @@ -97,28 +97,28 @@ pub unconstrained fn add_account(secret: Field) -> TestAccount {} pub unconstrained fn add_authwit(address: AztecAddress, message_hash: Field) {} #[oracle(txePrivateCallNewFlow)] -unconstrained fn private_call_new_flow_oracle( +unconstrained fn private_call_new_flow_oracle( _from: AztecAddress, _contract_address: AztecAddress, _function_selector: FunctionSelector, - _args: [Field], + _args: [Field; M], _args_hash: Field, _is_static_call: bool, ) -> [Field; N] {} #[oracle(txePublicCallNewFlow)] -unconstrained fn public_call_new_flow_oracle( +unconstrained fn public_call_new_flow_oracle( from: AztecAddress, contract_address: AztecAddress, - calldata: [Field], + calldata: [Field; M], is_static_call: bool, ) -> [Field; N] {} #[oracle(txeSimulateUtilityFunction)] -unconstrained fn simulate_utility_function_oracle( +unconstrained fn simulate_utility_function_oracle( contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field], + args: [Field; M], ) -> [Field; N] {} #[oracle(txeSetTopLevelTXEContext)] 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 de4252e99eff..8025fc1ca138 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr @@ -9,13 +9,13 @@ use protocol_types::{ }; use std::meta::derive; -pub struct ContractDeployment { +pub struct ContractDeployment { pub env: TestEnvironment, - pub path: str, + pub path: str, pub secret: Field, } -impl ContractDeployment { +impl ContractDeployment { /// Finalizes a contract deployment prepared via `TestEnvironment::deploy` by calling a private initializer function /// from the `from` account. /// @@ -34,10 +34,10 @@ impl ContractDeployment { /// MyContract::interface().init_fn(owner) /// ); /// } - pub unconstrained fn with_private_initializer( + pub unconstrained fn with_private_initializer( self, from: AztecAddress, - initializer_call: PrivateCall, + initializer_call: PrivateCall, ) -> AztecAddress where T: Deserialize, @@ -52,7 +52,7 @@ impl ContractDeployment { // a contract at an unknown address. Now that we've deployed the contract We can crate a new call interface with // the address and perform the call. // We probably want to introduce an intermediate struct to represent this, if we're going to keep this API. - let _ = self.env.call_private::( + let _ = self.env.call_private::<_, _, T>( from, PrivateCall::new(instance.to_address(), selector, name, args), ); @@ -78,10 +78,10 @@ impl ContractDeployment { /// MyContract::interface().init_fn(owner) /// ); /// } - pub unconstrained fn with_public_initializer( + pub unconstrained fn with_public_initializer( self, from: AztecAddress, - initializer_call: PublicCall, + initializer_call: PublicCall, ) -> AztecAddress where T: Deserialize, @@ -96,7 +96,7 @@ impl ContractDeployment { // a contract at an unknown address. Now that we've deployed the contract We can crate a new call interface with // the address and perform the call. // We probably want to introduce an intermediate struct to represent this, if we're going to keep this API. - let _ = self.env.call_public::( + let _ = self.env.call_public::<_, _, T>( from, PublicCall::new(instance.to_address(), selector, name, args), ); @@ -110,7 +110,7 @@ impl ContractDeployment { /// contains a commitment to the lack of initialization arguments as per the protocol rules. Initializers can only /// be invoked by using the `with_private_initializer` or `with_public_initializer` functions. pub unconstrained fn without_initializer(self) -> AztecAddress { - txe_oracles::deploy(self.path, "", &[], self.secret).to_address() + txe_oracles::deploy(self.path, "", [], self.secret).to_address() } } diff --git a/noir-projects/noir-contracts/contracts/app/simple_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app/simple_token_contract/src/main.nr index b54dbfe86b47..5f1a061ed14c 100644 --- a/noir-projects/noir-contracts/contracts/app/simple_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app/simple_token_contract/src/main.nr @@ -298,7 +298,7 @@ pub contract SimpleToken { context: PrivateContext, account: AztecAddress, remaining: u128, - ) -> PrivateCall<25, u128> { + ) -> PrivateCall<25, 2, u128> { SimpleToken::at(context.this_address())._recurse_subtract_balance(account, remaining) } diff --git a/noir-projects/noir-contracts/contracts/app/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app/token_contract/src/main.nr index 920aaeba64b5..ed50117d9672 100644 --- a/noir-projects/noir-contracts/contracts/app/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app/token_contract/src/main.nr @@ -283,7 +283,7 @@ pub contract Token { context: PrivateContext, account: AztecAddress, remaining: u128, - ) -> PrivateCall<25, u128> { + ) -> PrivateCall<25, 2, u128> { Token::at(context.this_address())._recurse_subtract_balance(account, remaining) } diff --git a/noir-projects/noir-contracts/contracts/docs/docs_example_contract/src/main.nr b/noir-projects/noir-contracts/contracts/docs/docs_example_contract/src/main.nr index b39443f99659..b69b48609c7f 100644 --- a/noir-projects/noir-contracts/contracts/docs/docs_example_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/docs/docs_example_contract/src/main.nr @@ -154,7 +154,7 @@ pub contract DocsExample { // docs:start:contract_self_creation let mut self = { let serialized_args = [a, b]; - let args_hash = dep::aztec::hash::hash_args_array(serialized_args); + let args_hash = dep::aztec::hash::hash_args(serialized_args); let mut context = PrivateContext::new(inputs, args_hash); let storage = Storage::init(&mut context); // The call_self, enqueue_self, call_self_static and enqueue_self_static are structs generated by the diff --git a/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/fake_public_context.nr b/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/fake_public_context.nr index 1be8a85834ad..35cc9d33565b 100644 --- a/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/fake_public_context.nr +++ b/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/fake_public_context.nr @@ -1,12 +1,12 @@ use dep::aztec::protocol_types::address::AztecAddress; -pub unconstrained fn call( +pub unconstrained fn call( l2_gas_allocation: u32, da_gas_allocation: u32, address: AztecAddress, - args: [Field], + args: [Field; N], ) { - call_opcode(l2_gas_allocation, da_gas_allocation, address, args) + call_opcode(l2_gas_allocation, da_gas_allocation, address, N, args) } pub unconstrained fn success_copy() -> bool { @@ -29,12 +29,16 @@ pub unconstrained fn avm_revert(revertdata: [Field]) { revert_opcode(revertdata) } +// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode +// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take that +// route. #[oracle(avmOpcodeCall)] -unconstrained fn call_opcode( +unconstrained fn call_opcode( l2_gas_allocation: u32, da_gas_allocation: u32, address: AztecAddress, - args: [Field], + length: u32, + args: [Field; N], ) {} #[oracle(avmOpcodeSuccessCopy)] diff --git a/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/main.nr index f2a561a1a721..dfb9f90a17e7 100644 --- a/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test/avm_test_contract/src/main.nr @@ -352,7 +352,7 @@ pub contract AvmTest { l2_gas_left - 200_000, da_gas_left - 200_000, self.address, - &[selector.to_field(), 0], + [selector.to_field(), 0], ); // Use SUCCESSCOPY to get the success status @@ -764,7 +764,7 @@ pub contract AvmTest { #[external("public")] fn nested_call_to_nothing_recovers() { let garbageAddress = AztecAddress::from_field(42); - call(1, 1, garbageAddress, &[]); + call(1, 1, garbageAddress, []); let success = success_copy(); assert( !success, @@ -829,12 +829,8 @@ pub contract AvmTest { ) -> Field { let selector = comptime { FunctionSelector::from_signature("add_args_return(Field,Field)") }; - context.static_call_public_function( - address, - selector, - [arg_a, arg_b].as_slice(), - GasOpts::default(), - )[0] + context.static_call_public_function(address, selector, [arg_a, arg_b], GasOpts::default()) + [0] } // Indirectly call_static `set_storage_single`. Should revert since it's accessing self.storage. @@ -845,7 +841,7 @@ pub contract AvmTest { let _ = self.context.static_call_public_function( self.address, selector, - args.as_slice(), + args, GasOpts::default(), ); } diff --git a/noir-projects/noir-contracts/contracts/test/parent_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test/parent_contract/src/main.nr index cb3187922ebb..a17361b42601 100644 --- a/noir-projects/noir-contracts/contracts/test/parent_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test/parent_contract/src/main.nr @@ -24,7 +24,7 @@ pub contract Parent { self.context.call_public_function( target_contract, target_selector, - [init_value].as_slice(), + [init_value], GasOpts::default(), )[0] } @@ -38,13 +38,13 @@ pub contract Parent { let return_value: Field = self.context.call_public_function( target_contract, target_selector, - [init_value].as_slice(), + [init_value], GasOpts::default(), )[0]; self.context.call_public_function( target_contract, target_selector, - [return_value].as_slice(), + [return_value], GasOpts::default(), )[0] } @@ -218,7 +218,7 @@ pub contract Parent { self.context.static_call_public_function( target_contract, target_selector, - args.as_slice(), + args, GasOpts::default(), )[0] } @@ -235,7 +235,7 @@ pub contract Parent { self.context.static_call_public_function( self.address, pub_entry_point_selector, - [target_contract.to_field(), target_selector.to_field(), args[0]].as_slice(), + [target_contract.to_field(), target_selector.to_field(), args[0]], GasOpts::default(), )[0] } diff --git a/noir-projects/noir-contracts/contracts/test/static_parent_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test/static_parent_contract/src/main.nr index 8d4c8a30eadc..3d05530e741b 100644 --- a/noir-projects/noir-contracts/contracts/test/static_parent_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test/static_parent_contract/src/main.nr @@ -20,7 +20,7 @@ pub contract StaticParent { self.context.call_public_function( target_contract, target_selector, - [arg].as_slice(), + [arg], GasOpts::default(), )[0] } @@ -136,7 +136,7 @@ pub contract StaticParent { self.context.static_call_public_function( target_contract, target_selector, - args.as_slice(), + args, GasOpts::default(), )[0] } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index 65305501f30c..26df569e0db9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -261,22 +261,6 @@ pub fn poseidon2_cheaper_variable_hash(input: [Field; N], in_len: u3 sponge.squeeze() } -pub fn poseidon2_hash_with_separator_slice(inputs: [Field], separator: T) -> Field -where - T: ToField, -{ - let in_len = inputs.len() + 1; - let iv: Field = (in_len as Field) * TWO_POW_64; - let mut sponge = Poseidon2Sponge::new(iv); - sponge.absorb(separator.to_field()); - - for i in 0..inputs.len() { - sponge.absorb(inputs[i]); - } - - sponge.squeeze() -} - // This function is unconstrained because it is intended to be used in unconstrained context only as // in constrained contexts it would be too inefficient. pub unconstrained fn poseidon2_hash_with_separator_bounded_vec( diff --git a/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts b/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts index ed7a8b842fc7..3025c8a76a34 100644 --- a/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts +++ b/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts @@ -100,8 +100,7 @@ export class Oracle { return Promise.resolve([toACVMField(val)]); } - // Since the argument is a slice, noir automatically adds a length field to oracle call. - privateStoreInExecutionCache(_length: ACVMField[], values: ACVMField[], [hash]: ACVMField[]): Promise { + privateStoreInExecutionCache(values: ACVMField[], [hash]: ACVMField[]): Promise { this.handlerAsPrivate().privateStoreInExecutionCache(values.map(Fr.fromString), Fr.fromString(hash)); return Promise.resolve([]); } diff --git a/yarn-project/txe/src/rpc_translator.ts b/yarn-project/txe/src/rpc_translator.ts index b893d2eb0c21..2cfb740f5f20 100644 --- a/yarn-project/txe/src/rpc_translator.ts +++ b/yarn-project/txe/src/rpc_translator.ts @@ -266,12 +266,7 @@ export class RPCTranslator { ]); } - // Since the argument is a slice, noir automatically adds a length field to oracle call. - privateStoreInExecutionCache( - _foreignLength: ForeignCallSingle, - foreignValues: ForeignCallArray, - foreignHash: ForeignCallSingle, - ) { + privateStoreInExecutionCache(foreignValues: ForeignCallArray, foreignHash: ForeignCallSingle) { const values = fromArray(foreignValues); const hash = fromSingle(foreignHash); @@ -927,7 +922,6 @@ export class RPCTranslator { foreignFrom: ForeignCallSingle, foreignTargetContractAddress: ForeignCallSingle, foreignFunctionSelector: ForeignCallSingle, - _foreignArgsLength: ForeignCallSingle, foreignArgs: ForeignCallArray, foreignArgsHash: ForeignCallSingle, foreignIsStaticCall: ForeignCallSingle, @@ -954,7 +948,6 @@ export class RPCTranslator { async txeSimulateUtilityFunction( foreignTargetContractAddress: ForeignCallSingle, foreignFunctionSelector: ForeignCallSingle, - _foreignArgsLength: ForeignCallSingle, foreignArgs: ForeignCallArray, ) { const targetContractAddress = addressFromSingle(foreignTargetContractAddress); @@ -973,7 +966,6 @@ export class RPCTranslator { async txePublicCallNewFlow( foreignFrom: ForeignCallSingle, foreignAddress: ForeignCallSingle, - _foreignLength: ForeignCallSingle, foreignCalldata: ForeignCallArray, foreignIsStaticCall: ForeignCallSingle, ) {