diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index e28b20aa4a3..e0e162c8ce8 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -80,7 +80,7 @@ impl From for TranspiledContract { // TODO(4269): once functions are tagged for transpilation to AVM, check tag if function .custom_attributes - .contains(&"aztec(public-vm)".to_string()) + .contains(&"aztec(public)".to_string()) { info!( "Transpiling AVM function {} on contract {}", diff --git a/noir-projects/aztec-nr/aztec/src/context.nr b/noir-projects/aztec-nr/aztec/src/context.nr index c7d79f2e24b..b076711d2e1 100644 --- a/noir-projects/aztec-nr/aztec/src/context.nr +++ b/noir-projects/aztec-nr/aztec/src/context.nr @@ -3,40 +3,33 @@ mod inputs; mod private_context; mod public_context; -mod avm_context; mod interface; mod gas; use interface::{ ContextInterface, PrivateCallInterface, PublicCallInterface, PrivateVoidCallInterface, - PublicVoidCallInterface, AvmCallInterface, AvmVoidCallInterface + PublicVoidCallInterface }; use private_context::PrivateContext; use private_context::PackedReturns; use public_context::PublicContext; use public_context::FunctionReturns; -use avm_context::AvmContext; struct Context { private: Option<&mut PrivateContext>, public: Option<&mut PublicContext>, - avm: Option<&mut AvmContext>, } impl Context { pub fn private(context: &mut PrivateContext) -> Context { - Context { private: Option::some(context), public: Option::none(), avm: Option::none() } + Context { private: Option::some(context), public: Option::none() } } pub fn public(context: &mut PublicContext) -> Context { - Context { public: Option::some(context), private: Option::none(), avm: Option::none() } - } - - pub fn avm(context: &mut AvmContext) -> Context { - Context { avm: Option::some(context), public: Option::none(), private: Option::none() } + Context { public: Option::some(context), private: Option::none() } } pub fn none() -> Context { - Context { public: Option::none(), private: Option::none(), avm: Option::none() } + Context { public: Option::none(), private: Option::none() } } } diff --git a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr deleted file mode 100644 index d7180bd8338..00000000000 --- a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr +++ /dev/null @@ -1,281 +0,0 @@ -use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier}; -use dep::protocol_types::{ - address::{AztecAddress, EthAddress}, - constants::{L1_TO_L2_MESSAGE_LENGTH, NESTED_CALL_L2_GAS_BUFFER}, header::Header -}; -use dep::protocol_types::traits::Serialize; -use dep::protocol_types::abis::function_selector::FunctionSelector; -use dep::protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs; -use crate::context::inputs::avm_context_inputs::AvmContextInputs; -use crate::context::interface::ContextInterface; -use crate::context::interface::PublicContextInterface; -use crate::context::gas::GasOpts; -use crate::context::public_context::FunctionReturns; - -struct AvmContext { - inputs: AvmContextInputs, -} - -impl AvmContext { - pub fn new(inputs: AvmContextInputs) -> Self { - AvmContext { inputs } - } - - pub fn storage_address(self) -> AztecAddress { - storage_address() - } - pub fn fee_per_l2_gas(self) -> Field { - fee_per_l2_gas() - } - pub fn fee_per_da_gas(self) -> Field { - fee_per_da_gas() - } - /** - * Emit a log with the given event selector and message. - * - * @param event_selector The event selector for the log. - * @param message The message to emit in the log. - * Should be automatically convertible to [Field; N]. For example str works with - * one char per field. Otherwise you can use CompressedString. - */ - pub fn emit_unencrypted_log_with_selector(&mut self, event_selector: Field, log: T) { - emit_unencrypted_log(event_selector, log); - } - pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool { - note_hash_exists(note_hash, leaf_index) == 1 - } - pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool { - l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1 - } -} - -impl PublicContextInterface for AvmContext { - fn block_number(self) -> Field { - block_number() - } - - fn timestamp(self) -> u64 { - timestamp() - } - - fn coinbase(self) -> EthAddress { - assert(false, "'coinbase' not implemented!"); - EthAddress::zero() - } - - fn fee_recipient(self) -> AztecAddress { - assert(false, "'fee_recipient' not implemented!"); - AztecAddress::zero() - } - - fn fee_per_da_gas(self) -> Field { - assert(false, "'fee_per_da_gas' not implemented!"); - 0 - } - - fn fee_per_l2_gas(self) -> Field { - assert(false, "'fee_per_l2_gas' not implemented!"); - 0 - } - - fn transaction_fee(self) -> Field { - transaction_fee() - } - - fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool { - nullifier_exists(unsiloed_nullifier, address.to_field()) == 1 - } - - fn emit_unencrypted_log(&mut self, log: T) { - let event_selector = 5; // Matches current PublicContext. - self.emit_unencrypted_log_with_selector(event_selector, log); - } - - fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field) { - let secret_hash = compute_secret_hash(secret); - let message_hash = compute_message_hash( - sender, - self.chain_id(), - /*recipient=*/self.this_address(), - self.version(), - content, - secret_hash - ); - let nullifier = compute_message_nullifier(message_hash, secret, leaf_index); - - assert(!self.nullifier_exists(nullifier, self.this_address()), "L1-to-L2 message is already nullified"); - assert(self.l1_to_l2_msg_exists(message_hash, leaf_index), "Tried to consume nonexistent L1-to-L2 message"); - - // Push nullifier (and the "commitment" corresponding to this can be "empty") - self.push_new_nullifier(nullifier, 0); - } - - fn message_portal(&mut self, recipient: EthAddress, content: Field) { - send_l2_to_l1_msg(recipient, content); - } - - fn call_public_function( - self: &mut Self, - contract_address: AztecAddress, - temporary_function_selector: FunctionSelector, - args: [Field], - gas_opts: GasOpts - ) -> FunctionReturns { - let results = call( - gas_for_call(gas_opts), - contract_address, - args, - temporary_function_selector.to_field() - ); - let data_to_return: [Field; RETURNS_COUNT] = results.0; - let success: u8 = results.1; - assert(success == 1, "Nested call failed!"); - - FunctionReturns::new(data_to_return) - } - - fn static_call_public_function( - self: &mut Self, - contract_address: AztecAddress, - temporary_function_selector: FunctionSelector, - args: [Field], - gas_opts: GasOpts - ) -> FunctionReturns { - let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static( - gas_for_call(gas_opts), - contract_address, - args, - temporary_function_selector.to_field() - ); - - assert(success == 1, "Nested static call failed!"); - FunctionReturns::new(data_to_return) - } - - fn delegate_call_public_function( - self: &mut Self, - contract_address: AztecAddress, - function_selector: FunctionSelector, - args: [Field] - ) -> FunctionReturns { - assert(false, "'delegate_call_public_function' not implemented!"); - FunctionReturns::new([0; RETURNS_COUNT]) - } -} - -impl ContextInterface for AvmContext { - fn push_new_note_hash(&mut self, note_hash: Field) { - emit_note_hash(note_hash); - } - fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) { - // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used - emit_nullifier(nullifier); - } - fn msg_sender(self) -> AztecAddress { - sender() - } - fn this_address(self) -> AztecAddress { - address() - } - fn chain_id(self) -> Field { - chain_id() - } - fn version(self) -> Field { - version() - } - fn selector(self) -> FunctionSelector { - FunctionSelector::from_field(self.inputs.selector) - } - fn get_args_hash(self) -> Field { - self.inputs.args_hash - } -} - -// Helper functions -fn gas_for_call(user_gas: GasOpts) -> [Field; 2] { - [ - user_gas.l2_gas.unwrap_or_else(|| l2_gas_left() - NESTED_CALL_L2_GAS_BUFFER), - user_gas.da_gas.unwrap_or_else(|| da_gas_left()) - ] -} - -// AVM oracles (opcodes) follow, do not use directly. -#[oracle(avmOpcodeAddress)] -fn address() -> AztecAddress {} - -#[oracle(avmOpcodeStorageAddress)] -fn storage_address() -> AztecAddress {} - -#[oracle(avmOpcodeSender)] -fn sender() -> AztecAddress {} - -#[oracle(avmOpcodePortal)] -fn portal() -> EthAddress {} - -#[oracle(avmOpcodeFeePerL2Gas)] -fn fee_per_l2_gas() -> Field {} - -#[oracle(avmOpcodeFeePerDaGas)] -fn fee_per_da_gas() -> Field {} - -#[oracle(avmOpcodeTransactionFee)] -fn transaction_fee() -> Field {} - -#[oracle(avmOpcodeChainId)] -fn chain_id() -> Field {} - -#[oracle(avmOpcodeVersion)] -fn version() -> Field {} - -#[oracle(avmOpcodeBlockNumber)] -fn block_number() -> Field {} - -#[oracle(avmOpcodeTimestamp)] -fn timestamp() -> u64 {} - -#[oracle(avmOpcodeL2GasLeft)] -fn l2_gas_left() -> Field {} - -#[oracle(avmOpcodeDaGasLeft)] -fn da_gas_left() -> Field {} - -#[oracle(avmOpcodeNoteHashExists)] -fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {} - -#[oracle(avmOpcodeEmitNoteHash)] -fn emit_note_hash(note_hash: Field) {} - -#[oracle(avmOpcodeNullifierExists)] -fn nullifier_exists(nullifier: Field, address: Field) -> u8 {} - -#[oracle(avmOpcodeEmitNullifier)] -fn emit_nullifier(nullifier: Field) {} - -#[oracle(amvOpcodeEmitUnencryptedLog)] -fn emit_unencrypted_log(event_selector: Field, message: T) {} - -#[oracle(avmOpcodeL1ToL2MsgExists)] -fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {} - -#[oracle(avmOpcodeSendL2ToL1Msg)] -fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {} - -#[oracle(avmOpcodeCall)] -fn call( - gas: [Field; 2], // gas allocation: [l2_gas, da_gas] - address: AztecAddress, - args: [Field], - // TODO(5110): consider passing in calldata directly - temporary_function_selector: Field -) -> ([Field; RET_SIZE], u8) {} -// ^ return data ^ success - -#[oracle(avmOpcodeStaticCall)] -fn call_static( - gas: [Field; 2], // gas allocation: [l2_gas, da_gas] - address: AztecAddress, - args: [Field], - // TODO(5110): consider passing in calldata directly - temporary_function_selector: Field -) -> ([Field; RET_SIZE], u8) {} -// ^ return data ^ success diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs.nr index 86595969e1e..0d7c56574d5 100644 --- a/noir-projects/aztec-nr/aztec/src/context/inputs.nr +++ b/noir-projects/aztec-nr/aztec/src/context/inputs.nr @@ -1,7 +1,5 @@ mod private_context_inputs; mod public_context_inputs; -mod avm_context_inputs; use crate::context::inputs::private_context_inputs::PrivateContextInputs; use crate::context::inputs::public_context_inputs::PublicContextInputs; -use crate::context::inputs::avm_context_inputs::AvmContextInputs; diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs/avm_context_inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/avm_context_inputs.nr deleted file mode 100644 index ffd16b268ac..00000000000 --- a/noir-projects/aztec-nr/aztec/src/context/inputs/avm_context_inputs.nr +++ /dev/null @@ -1,4 +0,0 @@ -struct AvmContextInputs { - selector: Field, - args_hash: Field, -} diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr index a766cf9858a..7187cb542fb 100644 --- a/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr +++ b/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr @@ -16,7 +16,7 @@ struct PrivateContextInputs { impl Empty for PrivateContextInputs { fn empty() -> Self { PrivateContextInputs { - call_context : CallContext::empty(), + call_context: CallContext::empty(), historical_header: Header::empty(), tx_context: TxContext::empty(), start_side_effect_counter: 0 as u32, diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr index 3461315502d..c15ead73744 100644 --- a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr +++ b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr @@ -1,29 +1,15 @@ -use crate::context::globals::public_global_variables::PublicGlobalVariables; +use dep::protocol_types::traits::Empty; -use dep::protocol_types::{abis::call_context::CallContext, abis::gas::Gas, header::Header, traits::Empty}; - -// PublicContextInputs are expected to be provided to each public function -// docs:start:public-context-inputs struct PublicContextInputs { - call_context: CallContext, - historical_header: Header, - - public_global_variables: PublicGlobalVariables, - start_side_effect_counter: u32, - gas_left: Gas, - transaction_fee: Field, + selector: Field, + args_hash: Field, } -// docs:end:public-context-inputs impl Empty for PublicContextInputs { fn empty() -> Self { PublicContextInputs { - call_context: CallContext::empty(), - historical_header: Header::empty(), - public_global_variables: PublicGlobalVariables::empty(), - start_side_effect_counter: 0 as u32, - gas_left: Gas::empty(), - transaction_fee: 0, + selector: 0, + args_hash: 0, } } } diff --git a/noir-projects/aztec-nr/aztec/src/context/interface.nr b/noir-projects/aztec-nr/aztec/src/context/interface.nr index 7f72656252b..b57de5e16e4 100644 --- a/noir-projects/aztec-nr/aztec/src/context/interface.nr +++ b/noir-projects/aztec-nr/aztec/src/context/interface.nr @@ -3,7 +3,6 @@ use dep::protocol_types::{abis::function_selector::FunctionSelector, address::{A use crate::hash::hash_args; use crate::context::private_context::PrivateContext; use crate::context::public_context::PublicContext; -use crate::context::avm_context::AvmContext; use crate::context::gas::GasOpts; use crate::context::public_context::FunctionReturns; @@ -19,8 +18,8 @@ trait ContextInterface { } // TEMPORARY: This trait is to promote sharing of the current public context -// and the upcoming AvmContext. This will be removed once the AvmContext is the default. -// If you are adding something here, then you should also implement it in the AvmContext. +// and the upcoming PublicContext. This will be removed once the PublicContext is the default. +// If you are adding something here, then you should also implement it in the PublicContext. trait PublicContextInterface { fn block_number(self) -> Field; fn timestamp(self) -> u64; @@ -112,121 +111,29 @@ impl PrivateVoidCallInterface { } struct PublicCallInterface { - target_contract: AztecAddress, - selector: FunctionSelector, - args_hash: Field, -} - -impl PublicCallInterface { - - pub fn call(self, context: &mut PublicContext) -> T where T: Deserialize { - let returns = context.call_public_function_with_packed_args( - self.target_contract, - self.selector, - self.args_hash, - false, - false - ); - returns.deserialize_into() - } - - pub fn static_call(self, context: &mut PublicContext) -> T where T: Deserialize { - let returns = context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false); - returns.deserialize_into() - } - - pub fn delegate_call(self, context: &mut PublicContext) -> T where T: Deserialize { - let returns = context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true); - returns.deserialize_into() - } - - pub fn enqueue(self, context: &mut PrivateContext) { - context.call_public_function_with_packed_args( - self.target_contract, - self.selector, - self.args_hash, - false, - false - ) - } - - pub fn static_enqueue(self, context: &mut PrivateContext) { - context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false) - } - - pub fn delegate_enqueue(self, context: &mut PrivateContext) { - context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true) - } -} - -struct PublicVoidCallInterface { - target_contract: AztecAddress, - selector: FunctionSelector, - args_hash: Field -} - -impl PublicVoidCallInterface { - pub fn call(self, context: &mut PublicContext) { - context.call_public_function_with_packed_args( - self.target_contract, - self.selector, - self.args_hash, - false, - false - ).assert_empty() - } - - pub fn static_call(self, context: &mut PublicContext) { - context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty(); - } - - pub fn delegate_call(self, context: &mut PublicContext) { - context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true).assert_empty(); - } - - pub fn enqueue(self, context: &mut PrivateContext) { - context.call_public_function_with_packed_args( - self.target_contract, - self.selector, - self.args_hash, - false, - false - ) - } - - pub fn static_enqueue(self, context: &mut PrivateContext) { - context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false) - } - - pub fn delegate_enqueue(self, context: &mut PrivateContext) { - context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true) - } -} - -struct AvmCallInterface { target_contract: AztecAddress, selector: FunctionSelector, args: [Field], gas_opts: GasOpts, } -impl AvmCallInterface { +impl PublicCallInterface { pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self { self.gas_opts = gas_opts; self } - pub fn call(self, context: &mut AvmContext) -> T where T: Deserialize { + pub fn call(self, context: &mut PublicContext) -> T where T: Deserialize { let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts); returns.deserialize_into() } - pub fn static_call(self, context: &mut AvmContext) -> T where T: Deserialize { + pub fn static_call(self, context: &mut PublicContext) -> T where T: Deserialize { let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts); returns.deserialize_into() } - pub fn delegate_call(self, context: &mut AvmContext) -> T where T: Deserialize { + pub fn delegate_call(self, context: &mut PublicContext) -> T where T: Deserialize { let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args); returns.deserialize_into() } @@ -247,30 +154,30 @@ impl AvmCallInterface { } } -struct AvmVoidCallInterface { +struct PublicVoidCallInterface { target_contract: AztecAddress, selector: FunctionSelector, args: [Field], gas_opts: GasOpts, } -impl AvmVoidCallInterface { +impl PublicVoidCallInterface { pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self { self.gas_opts = gas_opts; self } - pub fn call(self, context: &mut AvmContext) { + pub fn call(self, context: &mut PublicContext) { let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts); returns.assert_empty() } - pub fn static_call(self, context: &mut AvmContext) { + pub fn static_call(self, context: &mut PublicContext) { let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts); returns.assert_empty() } - pub fn delegate_call(self, context: &mut AvmContext) { + pub fn delegate_call(self, context: &mut PublicContext) { let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args); returns.assert_empty() } 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 a410a4accb1..6d52f01f8bc 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -1,317 +1,154 @@ -use crate::{ - context::{ - inputs::PublicContextInputs, interface::ContextInterface, interface::PublicContextInterface, - gas::GasOpts -}, - messaging::process_l1_to_l2_message, - oracle::{arguments, public_call::call_public_function_internal, returns, logs_traits::ToBytesForUnencryptedLog}, - hash::{hash_args, ArgsHasher, compute_unencrypted_log_hash} -}; +use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier}; use dep::protocol_types::{ - abis::{ - global_variables::GlobalVariables, function_selector::FunctionSelector, - private_circuit_public_inputs::PrivateCircuitPublicInputs, - public_call_stack_item::PublicCallStackItem, - public_circuit_public_inputs::PublicCircuitPublicInputs, read_request::ReadRequest, - note_hash::NoteHash, nullifier::Nullifier, side_effect::SideEffect -}, - hash::silo_nullifier, address::{AztecAddress, EthAddress}, - constants::{ - MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL -}, - contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, header::Header, - messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{Deserialize, Empty} + address::{AztecAddress, EthAddress}, + constants::{L1_TO_L2_MESSAGE_LENGTH, NESTED_CALL_L2_GAS_BUFFER}, header::Header }; +use dep::protocol_types::traits::{Deserialize, Serialize, Empty}; +use dep::protocol_types::abis::function_selector::FunctionSelector; +use dep::protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs; +use crate::context::inputs::public_context_inputs::PublicContextInputs; +use crate::context::interface::ContextInterface; +use crate::context::interface::PublicContextInterface; +use crate::context::gas::GasOpts; struct PublicContext { inputs: PublicContextInputs, - side_effect_counter: u32, - - args_hash : Field, - return_hash : Field, - - nullifier_read_requests: BoundedVec, - nullifier_non_existent_read_requests: BoundedVec, - contract_storage_update_requests: BoundedVec, - contract_storage_reads: BoundedVec, - public_call_stack_hashes: BoundedVec, - - new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, - - new_l2_to_l1_msgs: BoundedVec, - - unencrypted_logs_hashes: BoundedVec, - unencrypted_log_preimages_length: Field, - - // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block - // previous to the one in which the tx is included. - historical_header: Header, - prover_address: AztecAddress, } impl PublicContext { - pub fn new(inputs: PublicContextInputs, args_hash: Field) -> PublicContext { - PublicContext { - inputs, - side_effect_counter: inputs.start_side_effect_counter, - args_hash, - return_hash: 0, - nullifier_read_requests: BoundedVec::new(), - nullifier_non_existent_read_requests: BoundedVec::new(), - contract_storage_update_requests: BoundedVec::new(), - contract_storage_reads: BoundedVec::new(), - public_call_stack_hashes: BoundedVec::new(), - new_note_hashes: BoundedVec::new(), - new_nullifiers: BoundedVec::new(), - new_l2_to_l1_msgs: BoundedVec::new(), - unencrypted_logs_hashes: BoundedVec::new(), - unencrypted_log_preimages_length: 0, - historical_header: inputs.historical_header, - prover_address: AztecAddress::zero() - } - } - - pub fn call_public_function_no_args( - self: &mut Self, - contract_address: AztecAddress, - function_selector: FunctionSelector - ) -> FunctionReturns { - self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false) - } - - pub fn static_call_public_function_no_args( - self: &mut Self, - contract_address: AztecAddress, - function_selector: FunctionSelector - ) -> FunctionReturns { - self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false) - } - - pub fn delegate_call_public_function_no_args( - self: &mut Self, - contract_address: AztecAddress, - function_selector: FunctionSelector - ) -> FunctionReturns { - self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true) - } - - pub fn call_public_function_with_packed_args( - self: &mut Self, - contract_address: AztecAddress, - function_selector: FunctionSelector, - args_hash: Field, - is_static_call: bool, - is_delegate_call: bool - ) -> FunctionReturns { - let side_effect_counter = self.side_effect_counter; - // TODO(6052): get next value from output of `call_public_function_internal` - self.side_effect_counter += 1; - - let raw_returns = call_public_function_internal( - contract_address, - function_selector, - args_hash, - side_effect_counter, - is_static_call, - is_delegate_call - ); - - FunctionReturns::new(raw_returns) - } - - pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) { - returns::pack_returns(returns_hasher.fields); - self.return_hash = returns_hasher.hash(); - } - - // Keep private or ask the AVM team if you want to change it. - fn push_nullifier_read_request(&mut self, nullifier: Field) { - let request = ReadRequest { value: nullifier, counter: self.side_effect_counter }; - self.nullifier_read_requests.push(request); - self.side_effect_counter = self.side_effect_counter + 1; - } - - // Keep private or ask the AVM team if you want to change it. - fn push_nullifier_non_existent_read_request(&mut self, nullifier: Field) { - let request = ReadRequest { value: nullifier, counter: self.side_effect_counter }; - self.nullifier_non_existent_read_requests.push(request); - self.side_effect_counter = self.side_effect_counter + 1; - } - - pub fn finish(self) -> PublicCircuitPublicInputs { - // Compute the public call stack hashes - let pub_circuit_pub_inputs = PublicCircuitPublicInputs { - call_context: self.inputs.call_context, // Done - args_hash: self.args_hash, // Done - nullifier_read_requests: self.nullifier_read_requests.storage, - nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests.storage, - contract_storage_update_requests: self.contract_storage_update_requests.storage, - contract_storage_reads: self.contract_storage_reads.storage, - returns_hash: self.return_hash, - new_note_hashes: self.new_note_hashes.storage, - new_nullifiers: self.new_nullifiers.storage, - public_call_stack_hashes: self.public_call_stack_hashes.storage, - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, - start_side_effect_counter: self.inputs.start_side_effect_counter, - end_side_effect_counter: self.side_effect_counter, - unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, - unencrypted_log_preimages_length: self.unencrypted_log_preimages_length + 4, - historical_header: self.inputs.historical_header, - global_variables: self.inputs.public_global_variables, - prover_address: self.prover_address, - revert_code: 0, - start_gas_left: self.inputs.gas_left, - end_gas_left: self.inputs.gas_left, // AVM should decrease this value - transaction_fee: self.inputs.transaction_fee - }; - pub_circuit_pub_inputs + pub fn new(inputs: PublicContextInputs) -> Self { + PublicContext { inputs } } -} -impl ContextInterface for PublicContext { - fn msg_sender(self) -> AztecAddress { - self.inputs.call_context.msg_sender - } - - fn this_address(self) -> AztecAddress { - self.inputs.call_context.storage_contract_address - } - - fn chain_id(self) -> Field { - self.inputs.public_global_variables.chain_id + pub fn storage_address(self) -> AztecAddress { + storage_address() } - - fn version(self) -> Field { - self.inputs.public_global_variables.version + pub fn fee_per_l2_gas(self) -> Field { + fee_per_l2_gas() } - - fn selector(self) -> FunctionSelector { - self.inputs.call_context.function_selector + pub fn fee_per_da_gas(self) -> Field { + fee_per_da_gas() } - - fn get_args_hash(self) -> Field { - self.args_hash + /** + * Emit a log with the given event selector and message. + * + * @param event_selector The event selector for the log. + * @param message The message to emit in the log. + * Should be automatically convertible to [Field; N]. For example str works with + * one char per field. Otherwise you can use CompressedString. + */ + pub fn emit_unencrypted_log_with_selector(&mut self, event_selector: Field, log: T) { + emit_unencrypted_log(event_selector, log); } - - fn push_new_note_hash(&mut self, note_hash: Field) { - self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.side_effect_counter }); - self.side_effect_counter = self.side_effect_counter + 1; + pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool { + note_hash_exists(note_hash, leaf_index) == 1 } - - fn push_new_nullifier(&mut self, nullifier: Field, _nullified_note_hash: Field) { - self.new_nullifiers.push(Nullifier { - value: nullifier, - note_hash: 0, // cannot nullify pending notes in public context - counter: self.side_effect_counter - }); - self.side_effect_counter = self.side_effect_counter + 1; + pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool { + l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1 } } impl PublicContextInterface for PublicContext { fn block_number(self) -> Field { - self.inputs.public_global_variables.block_number + block_number() } fn timestamp(self) -> u64 { - self.inputs.public_global_variables.timestamp + timestamp() } fn coinbase(self) -> EthAddress { - self.inputs.public_global_variables.coinbase + assert(false, "'coinbase' not implemented!"); + EthAddress::zero() } fn fee_recipient(self) -> AztecAddress { - self.inputs.public_global_variables.fee_recipient + assert(false, "'fee_recipient' not implemented!"); + AztecAddress::zero() } fn fee_per_da_gas(self) -> Field { - self.inputs.public_global_variables.gas_fees.fee_per_da_gas + assert(false, "'fee_per_da_gas' not implemented!"); + 0 } fn fee_per_l2_gas(self) -> Field { - self.inputs.public_global_variables.gas_fees.fee_per_l2_gas + assert(false, "'fee_per_l2_gas' not implemented!"); + 0 } fn transaction_fee(self) -> Field { - self.inputs.transaction_fee + transaction_fee() } fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool { - // Current public can only check for settled nullifiers, so we always silo. - let siloed_nullifier = silo_nullifier(address, unsiloed_nullifier); - nullifier_exists_oracle(siloed_nullifier) == 1 + nullifier_exists(unsiloed_nullifier, address.to_field()) == 1 } - fn message_portal(&mut self, recipient: EthAddress, content: Field) { - let message = L2ToL1Message { recipient, content }; - self.new_l2_to_l1_msgs.push(message); - } - - // We can consume message with a secret in public context because the message cannot be modified and therefore - // there is no front-running risk (e.g. somebody could front run you to claim your tokens to your address). - // Leaf index is not used in public context, but it is used in the AVMContext which will replace it. - fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, _leaf_index: Field) { - let this = (*self).this_address(); - let nullifier = process_l1_to_l2_message( - self.historical_header.state.l1_to_l2_message_tree.root, - this, + fn emit_unencrypted_log(&mut self, log: T) { + let event_selector = 5; // Matches current PublicContext. + self.emit_unencrypted_log_with_selector(event_selector, log); + } + + fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field) { + let secret_hash = compute_secret_hash(secret); + let message_hash = compute_message_hash( sender, self.chain_id(), + /*recipient=*/self.this_address(), self.version(), content, - secret + secret_hash ); + let nullifier = compute_message_nullifier(message_hash, secret, leaf_index); + assert(!self.nullifier_exists(nullifier, self.this_address()), "L1-to-L2 message is already nullified"); + assert(self.l1_to_l2_msg_exists(message_hash, leaf_index), "Tried to consume nonexistent L1-to-L2 message"); + // Push nullifier (and the "commitment" corresponding to this can be "empty") - self.push_new_nullifier(nullifier, 0) + self.push_new_nullifier(nullifier, 0); } - fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog { - let event_selector = 5; // TODO: compute actual event selector. - let contract_address = self.this_address(); - let log_slice = log.to_be_bytes_arr(); - let log_hash = compute_unencrypted_log_hash( - contract_address, - event_selector, - log - ); - let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; - self.unencrypted_logs_hashes.push(side_effect); - self.side_effect_counter = self.side_effect_counter + 1; - // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) - self.unencrypted_log_preimages_length = self.unencrypted_log_preimages_length + 44 + log_slice.len().to_field(); - // Call oracle to broadcast log - let _void = emit_unencrypted_log_oracle(contract_address, event_selector, log, side_effect.counter); + fn message_portal(&mut self, recipient: EthAddress, content: Field) { + send_l2_to_l1_msg(recipient, content); } fn call_public_function( self: &mut Self, contract_address: AztecAddress, - function_selector: FunctionSelector, + temporary_function_selector: FunctionSelector, args: [Field], - _gas: GasOpts - ) -> FunctionReturns { - let args_hash = hash_args(args); - assert(args_hash == arguments::pack_arguments(args)); - self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false) + gas_opts: GasOpts + ) -> FunctionReturns { + let results = call( + gas_for_call(gas_opts), + contract_address, + args, + temporary_function_selector.to_field() + ); + let data_to_return: [Field; RETURNS_COUNT] = results.0; + let success: u8 = results.1; + assert(success == 1, "Nested call failed!"); + + FunctionReturns::new(data_to_return) } fn static_call_public_function( self: &mut Self, contract_address: AztecAddress, - function_selector: FunctionSelector, + temporary_function_selector: FunctionSelector, args: [Field], - _gas: GasOpts + gas_opts: GasOpts ) -> FunctionReturns { - let args_hash = hash_args(args); - assert(args_hash == arguments::pack_arguments(args)); - self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false) + let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static( + gas_for_call(gas_opts), + contract_address, + args, + temporary_function_selector.to_field() + ); + + assert(success == 1, "Nested static call failed!"); + FunctionReturns::new(data_to_return) } fn delegate_call_public_function( @@ -320,45 +157,133 @@ impl PublicContextInterface for PublicContext { function_selector: FunctionSelector, args: [Field] ) -> FunctionReturns { - let args_hash = hash_args(args); - assert(args_hash == arguments::pack_arguments(args)); - self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true) + assert(false, "'delegate_call_public_function' not implemented!"); + FunctionReturns::new([0; RETURNS_COUNT]) + } +} + +impl ContextInterface for PublicContext { + fn push_new_note_hash(&mut self, note_hash: Field) { + emit_note_hash(note_hash); + } + fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) { + // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used + emit_nullifier(nullifier); + } + fn msg_sender(self) -> AztecAddress { + sender() + } + fn this_address(self) -> AztecAddress { + address() + } + fn chain_id(self) -> Field { + chain_id() + } + fn version(self) -> Field { + version() + } + fn selector(self) -> FunctionSelector { + FunctionSelector::from_field(self.inputs.selector) + } + fn get_args_hash(self) -> Field { + self.inputs.args_hash } } impl Empty for PublicContext { fn empty() -> Self { - PublicContext { - inputs: PublicContextInputs::empty(), - side_effect_counter: 0 as u32, - args_hash : 0, - return_hash : 0, - nullifier_read_requests: BoundedVec::new(), - nullifier_non_existent_read_requests: BoundedVec::new(), - contract_storage_update_requests: BoundedVec::new(), - contract_storage_reads: BoundedVec::new(), - public_call_stack_hashes: BoundedVec::new(), - new_note_hashes: BoundedVec::new(), - new_nullifiers: BoundedVec::new(), - new_l2_to_l1_msgs: BoundedVec::new(), - unencrypted_logs_hashes: BoundedVec::new(), - unencrypted_log_preimages_length: 0, - historical_header: Header::empty(), - prover_address: AztecAddress::zero(), - } + PublicContext::new(PublicContextInputs::empty()) } } -#[oracle(checkNullifierExists)] -fn nullifier_exists_oracle(nullifier: Field) -> Field {} +// Helper functions +fn gas_for_call(user_gas: GasOpts) -> [Field; 2] { + [ + user_gas.l2_gas.unwrap_or_else(|| l2_gas_left() - NESTED_CALL_L2_GAS_BUFFER), + user_gas.da_gas.unwrap_or_else(|| da_gas_left()) + ] +} + +// AVM oracles (opcodes) follow, do not use directly. +#[oracle(avmOpcodeAddress)] +fn address() -> AztecAddress {} + +#[oracle(avmOpcodeStorageAddress)] +fn storage_address() -> AztecAddress {} + +#[oracle(avmOpcodeSender)] +fn sender() -> AztecAddress {} + +#[oracle(avmOpcodePortal)] +fn portal() -> EthAddress {} + +#[oracle(avmOpcodeFeePerL2Gas)] +fn fee_per_l2_gas() -> Field {} + +#[oracle(avmOpcodeFeePerDaGas)] +fn fee_per_da_gas() -> Field {} + +#[oracle(avmOpcodeTransactionFee)] +fn transaction_fee() -> Field {} + +#[oracle(avmOpcodeChainId)] +fn chain_id() -> Field {} + +#[oracle(avmOpcodeVersion)] +fn version() -> Field {} + +#[oracle(avmOpcodeBlockNumber)] +fn block_number() -> Field {} + +#[oracle(avmOpcodeTimestamp)] +fn timestamp() -> u64 {} + +#[oracle(avmOpcodeL2GasLeft)] +fn l2_gas_left() -> Field {} + +#[oracle(avmOpcodeDaGasLeft)] +fn da_gas_left() -> Field {} + +#[oracle(avmOpcodeNoteHashExists)] +fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {} + +#[oracle(avmOpcodeEmitNoteHash)] +fn emit_note_hash(note_hash: Field) {} + +#[oracle(avmOpcodeNullifierExists)] +fn nullifier_exists(nullifier: Field, address: Field) -> u8 {} + +#[oracle(avmOpcodeEmitNullifier)] +fn emit_nullifier(nullifier: Field) {} + +#[oracle(amvOpcodeEmitUnencryptedLog)] +fn emit_unencrypted_log(event_selector: Field, message: T) {} + +#[oracle(avmOpcodeL1ToL2MsgExists)] +fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {} + +#[oracle(avmOpcodeSendL2ToL1Msg)] +fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {} + +#[oracle(avmOpcodeCall)] +fn call( + gas: [Field; 2], // gas allocation: [l2_gas, da_gas] + address: AztecAddress, + args: [Field], + // TODO(5110): consider passing in calldata directly + temporary_function_selector: Field +) -> ([Field; RET_SIZE], u8) {} +// ^ return data ^ success -#[oracle(emitUnencryptedLog)] -fn emit_unencrypted_log_oracle( - _contract_address: AztecAddress, - _event_selector: Field, - _message: T, - _counter: u32 -) -> Field {} +#[oracle(avmOpcodeStaticCall)] +fn call_static( + gas: [Field; 2], // gas allocation: [l2_gas, da_gas] + address: AztecAddress, + args: [Field], + // TODO(5110): consider passing in calldata directly + temporary_function_selector: Field +) -> ([Field; RET_SIZE], u8) {} +// ^ return data ^ success struct FunctionReturns { values: [Field; N] diff --git a/noir-projects/aztec-nr/aztec/src/initializer.nr b/noir-projects/aztec-nr/aztec/src/initializer.nr index f060fc14f1a..6da47905b83 100644 --- a/noir-projects/aztec-nr/aztec/src/initializer.nr +++ b/noir-projects/aztec-nr/aztec/src/initializer.nr @@ -4,7 +4,7 @@ use dep::protocol_types::{ }; use crate::{ - context::{PrivateContext, PublicContext, AvmContext, ContextInterface}, + context::{PrivateContext, PublicContext, ContextInterface}, oracle::get_contract_instance::get_contract_instance, oracle::get_contract_instance::get_contract_instance_avm, history::nullifier_inclusion::prove_nullifier_inclusion @@ -14,10 +14,6 @@ pub fn mark_as_initialized_public(context: &mut PublicContext) { mark_as_initialized(context); } -pub fn mark_as_initialized_avm(context: &mut AvmContext) { - mark_as_initialized(context); -} - pub fn mark_as_initialized_private(context: &mut PrivateContext) { mark_as_initialized(context); } @@ -32,11 +28,6 @@ pub fn assert_is_initialized_public(context: &mut PublicContext) { assert(context.nullifier_exists(init_nullifier, context.this_address()), "Not initialized"); } -pub fn assert_is_initialized_avm(context: &mut AvmContext) { - let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address()); - assert(context.nullifier_exists(init_nullifier, context.this_address()), "Not initialized"); -} - pub fn assert_is_initialized_private(context: &mut PrivateContext) { let init_nullifier = compute_contract_initialization_nullifier(context.this_address()); prove_nullifier_inclusion(init_nullifier, *context); @@ -54,10 +45,6 @@ fn compute_unsiloed_contract_initialization_nullifier(address: AztecAddress) -> } pub fn assert_initialization_matches_address_preimage_public(context: PublicContext) { - assert_initialization_matches_address_preimage(context); -} - -pub fn assert_initialization_matches_address_preimage_avm(context: AvmContext) { let address = context.this_address(); let instance = get_contract_instance_avm(address).unwrap(); let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash()); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr index 8ab974c7389..77ac5a9890f 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr @@ -130,7 +130,8 @@ mod test { Context::private(&mut private_context) } else { let mut public_context = PublicContext::empty(); - public_context.inputs.public_global_variables.block_number = block_number; + // FIXME + // public_context.inputs.public_global_variables.block_number = block_number; Context::public(&mut public_context) } } diff --git a/noir-projects/noir-contracts/bootstrap.sh b/noir-projects/noir-contracts/bootstrap.sh index b5bf4764cb2..880ef561f81 100755 --- a/noir-projects/noir-contracts/bootstrap.sh +++ b/noir-projects/noir-contracts/bootstrap.sh @@ -19,5 +19,5 @@ echo "Compiling contracts..." NARGO=${NARGO:-../../noir/noir-repo/target/release/nargo} $NARGO compile --silence-warnings -echo "Transpiling avm contracts... (only '#[aztec(public-vm)]')" +echo "Transpiling avm contracts..." scripts/transpile.sh \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/avm_acvm_interop_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_acvm_interop_test_contract/src/main.nr index fa459a62255..b9e6d458954 100644 --- a/noir-projects/noir-contracts/contracts/avm_acvm_interop_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_acvm_interop_test_contract/src/main.nr @@ -9,7 +9,7 @@ contract AvmAcvmInteropTest { use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; // Use the standard context interface to emit a new nullifier - #[aztec(public-vm)] + #[aztec(public)] fn new_nullifier(nullifier: Field) { context.push_new_nullifier(nullifier, 0); } @@ -22,7 +22,7 @@ contract AvmAcvmInteropTest { 123456 } - #[aztec(public-vm)] + #[aztec(public)] fn constant_field_avm() -> pub Field { 123456 } @@ -37,7 +37,7 @@ contract AvmAcvmInteropTest { assert(context.nullifier_exists(unsiloed_nullifier, context.this_address())); } - #[aztec(public-vm)] + #[aztec(public)] fn call_acvm_from_avm() -> pub Field { context.call_public_function( context.this_address(), @@ -57,7 +57,7 @@ contract AvmAcvmInteropTest { ).deserialize_into() } - #[aztec(public-vm)] + #[aztec(public)] fn avm_to_acvm_call(selector: FunctionSelector, args: Field) { context.call_public_function( context.this_address(), @@ -70,7 +70,7 @@ contract AvmAcvmInteropTest { /************************************************************************ * Authwit functions ************************************************************************/ - #[aztec(public-vm)] + #[aztec(public)] fn test_authwit_send_money(from: AztecAddress, _to: AztecAddress, _amount: Field) { assert_current_call_valid_authwit_public(&mut context, from); } diff --git a/noir-projects/noir-contracts/contracts/avm_initializer_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_initializer_test_contract/src/main.nr index a71cf2a1de4..6e075e89a3e 100644 --- a/noir-projects/noir-contracts/contracts/avm_initializer_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_initializer_test_contract/src/main.nr @@ -11,13 +11,13 @@ contract AvmInitializerTest { /************************************************************************ * Storage ************************************************************************/ - #[aztec(public-vm)] + #[aztec(public)] #[aztec(initializer)] fn constructor() { storage.immutable.initialize(42); } - #[aztec(public-vm)] + #[aztec(public)] fn read_storage_immutable() -> pub Field { storage.immutable.read() } diff --git a/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr index 1ebc736cc8d..d87294ed385 100644 --- a/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr @@ -16,24 +16,24 @@ contract AvmNestedCallsTest { /************************************************************************ * Storage ************************************************************************/ - #[aztec(public-vm)] + #[aztec(public)] fn set_storage_single(a: Field) { storage.single.write(a); } - #[aztec(public-vm)] + #[aztec(public)] fn add_args_return(arg_a: Field, arg_b: Field) -> pub Field { arg_a + arg_b } // Use the standard context interface to emit a new nullifier - #[aztec(public-vm)] + #[aztec(public)] fn new_nullifier(nullifier: Field) { context.push_new_nullifier(nullifier, 0); } // External call opcode to initiate a nested call to the add function with user-specified gas - #[aztec(public-vm)] + #[aztec(public)] fn nested_call_to_add_with_gas( arg_a: Field, arg_b: Field, @@ -44,30 +44,30 @@ contract AvmNestedCallsTest { } // Use the `call_public_function` wrapper to initiate a nested call to the add function - #[aztec(public-vm)] + #[aztec(public)] fn nested_call_to_add(arg_a: Field, arg_b: Field) -> pub Field { AvmNestedCallsTest::at(context.this_address()).add_args_return(arg_a, arg_b).call(&mut context) } // Indirectly call_static the external call opcode to initiate a nested call to the add function - #[aztec(public-vm)] + #[aztec(public)] fn nested_static_call_to_add(arg_a: Field, arg_b: Field) -> pub Field { AvmNestedCallsTest::at(context.this_address()).add_args_return(arg_a, arg_b).static_call(&mut context) } // Indirectly call_static `set_storage_single`. Should revert since it's accessing storage. - #[aztec(public-vm)] + #[aztec(public)] fn nested_static_call_to_set_storage() { AvmNestedCallsTest::at(context.this_address()).set_storage_single(20).static_call(&mut context); } - #[aztec(public-vm)] + #[aztec(public)] fn create_same_nullifier_in_nested_call(nestedAddress: AztecAddress, nullifier: Field) { context.push_new_nullifier(nullifier, 0); AvmNestedCallsTest::at(nestedAddress).new_nullifier(nullifier).call(&mut context); } - #[aztec(public-vm)] + #[aztec(public)] fn create_different_nullifier_in_nested_call(nestedAddress: AztecAddress, nullifier: Field) { context.push_new_nullifier(nullifier, 0); AvmNestedCallsTest::at(nestedAddress).new_nullifier(nullifier + 1).call(&mut context); diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index c26c4f2551a..50582d13c69 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -54,42 +54,42 @@ contract AvmTest { storage.map.at(address).read() } - #[aztec(public-vm)] + #[aztec(public)] fn set_storage_single(a: Field) { storage.single.write(a); } - #[aztec(public-vm)] + #[aztec(public)] fn read_storage_single() -> Field { storage.single.read() } // should still be able to use ` -> pub *` for return type even though macro forces `pub` - #[aztec(public-vm)] + #[aztec(public)] fn set_read_storage_single(a: Field) -> pub Field { storage.single.write(a); storage.single.read() } - #[aztec(public-vm)] + #[aztec(public)] fn set_storage_list(a: Field, b: Field) { storage.list.write(Note { a, b }); } - #[aztec(public-vm)] + #[aztec(public)] fn read_storage_list() -> [Field; 2] { let note: Note = storage.list.read(); note.serialize() } - #[aztec(public-vm)] + #[aztec(public)] fn set_storage_map(to: AztecAddress, amount: u32) -> Field { storage.map.at(to).write(amount); // returns storage slot for key dep::std::hash::pedersen_hash([storage.map.storage_slot, to.to_field()]) } - #[aztec(public-vm)] + #[aztec(public)] fn add_storage_map(to: AztecAddress, amount: u32) -> Field { let new_balance = storage.map.at(to).read().add(amount); storage.map.at(to).write(new_balance); @@ -97,12 +97,12 @@ contract AvmTest { dep::std::hash::pedersen_hash([storage.map.storage_slot, to.to_field()]) } - #[aztec(public-vm)] + #[aztec(public)] fn read_storage_map(address: AztecAddress) -> u32 { storage.map.at(address).read() } - #[aztec(public-vm)] + #[aztec(public)] fn add_args_return(arg_a: Field, arg_b: Field) -> Field { arg_a + arg_b } @@ -110,32 +110,32 @@ contract AvmTest { /************************************************************************ * General Opcodes ************************************************************************/ - #[aztec(public-vm)] + #[aztec(public)] fn set_opcode_u8() -> u8 { 8 as u8 } - #[aztec(public-vm)] + #[aztec(public)] fn set_opcode_u32() -> u32 { 1 << 30 as u8 } - #[aztec(public-vm)] + #[aztec(public)] fn set_opcode_u64() -> u64 { 1 << 60 as u8 } - #[aztec(public-vm)] + #[aztec(public)] fn set_opcode_small_field() -> Field { big_field_128_bits } - #[aztec(public-vm)] + #[aztec(public)] fn set_opcode_big_field() -> Field { big_field_136_bits } - #[aztec(public-vm)] + #[aztec(public)] fn add_u128(a: U128, b: U128) -> U128 { a + b } @@ -143,27 +143,27 @@ contract AvmTest { /************************************************************************ * Hashing functions ************************************************************************/ - #[aztec(public-vm)] + #[aztec(public)] fn keccak_hash(data: [u8; 10]) -> [u8; 32] { dep::std::hash::keccak256(data, data.len() as u32) } - #[aztec(public-vm)] + #[aztec(public)] fn poseidon2_hash(data: [Field; 10]) -> Field { dep::std::hash::poseidon2::Poseidon2::hash(data, data.len()) } - #[aztec(public-vm)] + #[aztec(public)] fn sha256_hash(data: [u8; 10]) -> [u8; 32] { dep::std::hash::sha256(data) } - #[aztec(public-vm)] + #[aztec(public)] fn pedersen_hash(data: [Field; 10]) -> Field { dep::std::hash::pedersen_hash(data) } - #[aztec(public-vm)] + #[aztec(public)] fn pedersen_hash_with_index(data: [Field; 10]) -> Field { dep::std::hash::pedersen_hash_with_separator(data, /*index=*/ 20) } @@ -171,7 +171,7 @@ contract AvmTest { /************************************************************************ * Contract instance ************************************************************************/ - #[aztec(public-vm)] + #[aztec(public)] fn test_get_contract_instance_raw() { let fields = get_contract_instance_internal_avm(context.this_address()); // The values here should match those in `avm_simulator.test.ts>Contract>GETCONTRACTINSTANCE deserializes correctly` @@ -184,7 +184,7 @@ contract AvmTest { assert(fields[5] == 0x161718); } - #[aztec(public-vm)] + #[aztec(public)] fn test_get_contract_instance() { let ci = get_contract_instance_avm(context.this_address()); assert(ci.is_some(), "Contract instance not found!"); @@ -193,74 +193,74 @@ contract AvmTest { /************************************************************************ * AvmContext functions ************************************************************************/ - #[aztec(public-vm)] + #[aztec(public)] fn get_address() -> AztecAddress { context.this_address() } - #[aztec(public-vm)] + #[aztec(public)] fn get_storage_address() -> AztecAddress { context.storage_address() } - #[aztec(public-vm)] + #[aztec(public)] fn get_sender() -> AztecAddress { context.msg_sender() } - #[aztec(public-vm)] + #[aztec(public)] fn get_fee_per_l2_gas() -> Field { context.fee_per_l2_gas() } - #[aztec(public-vm)] + #[aztec(public)] fn get_fee_per_da_gas() -> Field { context.fee_per_da_gas() } - #[aztec(public-vm)] + #[aztec(public)] fn get_transaction_fee() -> Field { context.transaction_fee() } - #[aztec(public-vm)] + #[aztec(public)] fn get_chain_id() -> Field { context.chain_id() } - #[aztec(public-vm)] + #[aztec(public)] fn get_version() -> Field { context.version() } - #[aztec(public-vm)] + #[aztec(public)] fn get_block_number() -> Field { context.block_number() } - #[aztec(public-vm)] + #[aztec(public)] fn get_timestamp() -> u64 { context.timestamp() } - // #[aztec(public-vm)] + // #[aztec(public)] // fn get_contract_call_depth() -> Field { // context.contract_call_depth() // } - #[aztec(public-vm)] + #[aztec(public)] fn check_selector() { assert( context.selector() == FunctionSelector::from_signature("check_selector()"), "Unexpected selector!" ); } - #[aztec(public-vm)] + #[aztec(public)] fn get_args_hash(_a: u8, _fields: [Field; 3]) -> Field { context.get_args_hash() } - #[aztec(public-vm)] + #[aztec(public)] fn emit_unencrypted_log() { context.emit_unencrypted_log_with_selector(/*event_selector=*/ 5, /*message=*/ [10, 20, 30]); context.emit_unencrypted_log_with_selector(/*event_selector=*/ 8, /*message=*/ "Hello, world!"); @@ -268,36 +268,36 @@ contract AvmTest { context.emit_unencrypted_log_with_selector(/*event_selector=*/ 10, /*message=*/ s); } - #[aztec(public-vm)] + #[aztec(public)] fn note_hash_exists(note_hash: Field, leaf_index: Field) -> bool { context.note_hash_exists(note_hash, leaf_index) } // Use the standard context interface to emit a new note hash - #[aztec(public-vm)] + #[aztec(public)] fn new_note_hash(note_hash: Field) { context.push_new_note_hash(note_hash); } // Use the standard context interface to emit a new nullifier - #[aztec(public-vm)] + #[aztec(public)] fn new_nullifier(nullifier: Field) { context.push_new_nullifier(nullifier, 0); } // Use the standard context interface to check for a nullifier - #[aztec(public-vm)] + #[aztec(public)] fn nullifier_exists(nullifier: Field) -> bool { context.nullifier_exists(nullifier, context.this_address()) } - #[aztec(public-vm)] + #[aztec(public)] fn assert_nullifier_exists(nullifier: Field) { assert(context.nullifier_exists(nullifier, context.this_address()), "Nullifier doesn't exist!"); } // Use the standard context interface to emit a new nullifier - #[aztec(public-vm)] + #[aztec(public)] fn emit_nullifier_and_check(nullifier: Field) { context.push_new_nullifier(nullifier, 0); let exists = context.nullifier_exists(nullifier, context.this_address()); @@ -305,19 +305,19 @@ contract AvmTest { } // Create the same nullifier twice (shouldn't work!) - #[aztec(public-vm)] + #[aztec(public)] fn nullifier_collision(nullifier: Field) { context.push_new_nullifier(nullifier, 0); // Can't do this twice! context.push_new_nullifier(nullifier, 0); } - #[aztec(public-vm)] + #[aztec(public)] fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> bool { context.l1_to_l2_msg_exists(msg_hash, msg_leaf_index) } - #[aztec(public-vm)] + #[aztec(public)] fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) { context.message_portal(recipient, content) } diff --git a/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr b/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr index 0cfbb45b596..4dc3734e87a 100644 --- a/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/reader_contract/src/main.nr @@ -1,6 +1,8 @@ contract Reader { use dep::aztec::prelude::{AztecAddress, FunctionSelector, Deserialize}; + use dep::aztec::context::gas::GasOpts; + use dep::compressed_string::FieldCompressedString; #[aztec(private)] @@ -9,7 +11,7 @@ contract Reader { #[aztec(public)] fn check_name_public(who: AztecAddress, what: str<31>) { let selector = FunctionSelector::from_signature("public_get_name()"); - let name: FieldCompressedString = context.call_public_function_no_args(who, selector).deserialize_into(); + let name: FieldCompressedString = context.call_public_function(who, selector, &[], GasOpts::default()).deserialize_into(); let _what = FieldCompressedString::from_string(what); assert(name.is_eq(_what)); } @@ -30,7 +32,7 @@ contract Reader { #[aztec(public)] fn check_symbol_public(who: AztecAddress, what: str<31>) { let selector = FunctionSelector::from_signature("public_get_symbol()"); - let symbol: FieldCompressedString = context.call_public_function_no_args(who, selector).deserialize_into(); + let symbol: FieldCompressedString = context.call_public_function(who, selector, &[], GasOpts::default()).deserialize_into(); let _what = FieldCompressedString::from_string(what); assert(symbol.is_eq(_what)); } @@ -51,7 +53,7 @@ contract Reader { #[aztec(public)] fn check_decimals_public(who: AztecAddress, what: u8) { let selector = FunctionSelector::from_signature("public_get_decimals()"); - let ret: u8 = context.call_public_function_no_args(who, selector).deserialize_into(); + let ret: u8 = context.call_public_function(who, selector, &[], GasOpts::default()).deserialize_into(); assert(ret == what); } diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr index 9ab011d9e0e..afacb220568 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -223,7 +223,7 @@ contract Uniswap { token.eq(TokenBridge::at(token_bridge).get_token().static_call(&mut context)), "input_asset address is not the same as seen in the bridge contract" ); } - + // /// Unconstrained /// // this method exists solely for e2e tests to test that nonce gets incremented each time. @@ -231,5 +231,4 @@ contract Uniswap { storage.nonce_for_burn_approval.read() } // docs:end:assert_token_is_same - } diff --git a/noir/noir-repo/aztec_macros/src/lib.rs b/noir/noir-repo/aztec_macros/src/lib.rs index 17ae999fb8f..37ca374b6a7 100644 --- a/noir/noir-repo/aztec_macros/src/lib.rs +++ b/noir/noir-repo/aztec_macros/src/lib.rs @@ -128,7 +128,6 @@ fn transform_module( for func in module.functions.iter_mut() { let mut is_private = false; let mut is_public = false; - let mut is_public_vm = false; let mut is_initializer = false; let mut is_internal = false; let mut insert_init_check = has_initializer; @@ -145,20 +144,12 @@ fn transform_module( is_internal = true; } else if is_custom_attribute(&secondary_attribute, "aztec(public)") { is_public = true; - } else if is_custom_attribute(&secondary_attribute, "aztec(public-vm)") { - is_public_vm = true; } } // Apply transformations to the function based on collected attributes - if is_private || is_public || is_public_vm { - let fn_type = if is_private { - "Private" - } else if is_public_vm { - "Avm" - } else { - "Public" - }; + if is_private || is_public { + let fn_type = if is_private { "Private" } else { "Public" }; stubs.push(stub_function(fn_type, func)); export_fn_abi(&mut module.types, func)?; diff --git a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs index 1afe0a30068..bc0a849b7cf 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs @@ -85,7 +85,7 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction) -> String { }) .collect::>() .join(""); - if aztec_visibility != "Avm" { + if aztec_visibility != "Public" { let args_hash = if !parameters.is_empty() { format!( "let mut args_acc: [Field] = &[]; @@ -122,7 +122,7 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction) -> String { ); let fn_body = format!( "{} - dep::aztec::context::Avm{}CallInterface {{ + dep::aztec::context::Public{}CallInterface {{ target_contract: self.target_contract, selector: {}, args: args_acc, @@ -131,7 +131,7 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction) -> String { args, is_void, fn_selector, ); format!( - "pub fn {}(self, {}) -> dep::aztec::context::Avm{}CallInterface{} {{ + "pub fn {}(self, {}) -> dep::aztec::context::Public{}CallInterface{} {{ {} }}", fn_name, fn_parameters, is_void, return_type_hint, fn_body diff --git a/noir/noir-repo/aztec_macros/src/transforms/functions.rs b/noir/noir-repo/aztec_macros/src/transforms/functions.rs index 90563c6085c..ba4d0a077b7 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/functions.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/functions.rs @@ -37,7 +37,7 @@ pub fn transform_function( let context_name = format!("{}Context", ty); let inputs_name = format!("{}ContextInputs", ty); let return_type_name = format!("{}CircuitPublicInputs", ty); - let is_avm = ty == "Avm"; + let is_avm = ty == "Public"; let is_private = ty == "Private"; // Add check that msg sender equals this address and flag function as internal @@ -108,7 +108,7 @@ pub fn transform_function( } // Public functions should have unconstrained auto-inferred - func.def.is_unconstrained = matches!(ty, "Public" | "Avm"); + func.def.is_unconstrained = is_avm; // Private functions need to be recursive if is_private { @@ -446,25 +446,29 @@ fn create_context(ty: &str, params: &[Param]) -> Result, AztecMac /// /// The replaced code: /// ```noir -/// #[aztec(public-vm)] -/// fn foo(inputs: AvmContextInputs, ...) -> Field { -/// let mut context = AvmContext::new(inputs); +/// #[aztec(public)] +/// fn foo(inputs: PublicContextInputs, ...) -> Field { +/// let mut context = PublicContext::new(inputs); /// } /// ``` fn create_context_avm() -> Result, AztecMacroError> { let mut injected_expressions: Vec = vec![]; // Create the inputs to the context - let ty = "AvmContext"; let inputs_expression = variable("inputs"); - let path_snippet = ty.to_case(Case::Snake); // e.g. private_context // let mut context = {ty}::new(inputs, hash); let let_context = mutable_assignment( "context", // Assigned to call( - variable_path(chained_dep!("aztec", "context", &path_snippet, ty, "new")), // Path - vec![inputs_expression], // args + variable_path(chained_dep!( + "aztec", + "context", + "public_context", + "PublicContext", + "new" + )), // Path + vec![inputs_expression], // args ), ); injected_expressions.push(let_context);