diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index 718f61220a59..b571e5ffbd49 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -317,6 +317,7 @@ dependencies = [ name = "aztec_macros" version = "0.23.0" dependencies = [ + "convert_case", "iter-extended", "noirc_frontend", ] @@ -550,6 +551,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -1775,6 +1785,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + [[package]] name = "unicode-width" version = "0.1.11" diff --git a/boxes/blank-react/src/contracts/src/main.nr b/boxes/blank-react/src/contracts/src/main.nr index 84750a2da700..89c803065290 100644 --- a/boxes/blank-react/src/contracts/src/main.nr +++ b/boxes/blank-react/src/contracts/src/main.nr @@ -1,12 +1,11 @@ contract Blank { use dep::aztec::{ - abi, oracle::{ get_public_key::get_public_key, }, protocol_types::address::AztecAddress }; - + #[aztec(private)] fn constructor() {} diff --git a/boxes/blank/src/contracts/src/main.nr b/boxes/blank/src/contracts/src/main.nr index 28647415a6bc..c5ccfa0ff444 100644 --- a/boxes/blank/src/contracts/src/main.nr +++ b/boxes/blank/src/contracts/src/main.nr @@ -1,12 +1,11 @@ contract Blank { use dep::aztec::{ - abi, oracle::{ get_public_key::get_public_key, }, protocol_types::address::AztecAddress }; - + #[aztec(private)] fn constructor() {} diff --git a/boxes/token/src/contracts/src/main.nr b/boxes/token/src/contracts/src/main.nr index a6c67b253ed0..6bef8316beaa 100644 --- a/boxes/token/src/contracts/src/main.nr +++ b/boxes/token/src/contracts/src/main.nr @@ -21,7 +21,6 @@ contract Token { note_header::NoteHeader, utils as note_utils, }, - context::{PrivateContext, PublicContext, Context}, hash::{compute_secret_hash}, state_vars::{map::Map, public_state::PublicState, set::Set}, protocol_types::{ @@ -328,7 +327,11 @@ contract Token { ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); if (storage_slot == storage.pending_shields.get_storage_slot()) { - note_utils::compute_note_hash_and_nullifier(TransparentNote::deserialize_content, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier( + TransparentNote::deserialize_content, + note_header, + serialized_note + ) } else { note_utils::compute_note_hash_and_nullifier(TokenNote::deserialize_content, note_header, serialized_note) } diff --git a/boxes/token/src/contracts/src/types/balances_map.nr b/boxes/token/src/contracts/src/types/balances_map.nr index 3b4c06075285..286a7825645a 100644 --- a/boxes/token/src/contracts/src/types/balances_map.nr +++ b/boxes/token/src/contracts/src/types/balances_map.nr @@ -1,7 +1,7 @@ use dep::std::option::Option; use dep::safe_math::SafeU120; use dep::aztec::{ - context::{PrivateContext, PublicContext, Context}, + context::Context, hash::pedersen_hash, protocol_types::{ address::AztecAddress, diff --git a/docs/docs/developers/contracts/portals/main.md b/docs/docs/developers/contracts/portals/main.md index 71e5bd40751a..69142288e6d5 100644 --- a/docs/docs/developers/contracts/portals/main.md +++ b/docs/docs/developers/contracts/portals/main.md @@ -42,7 +42,7 @@ To consume the message, we can use the `consume_l1_to_l2_message` function withi Note that while the `secret` and the `content` are both hashed, they are actually hashed with different hash functions! ::: -#include_code context_consume_l1_to_l2_message /yarn-project/aztec-nr/aztec/src/context/private.nr rust +#include_code context_consume_l1_to_l2_message /yarn-project/aztec-nr/aztec/src/context/private_context.nr rust Computing the `content` must be done manually in its current form, as we are still adding a number of bytes utilities. A good example exists within the [Token bridge example](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/noir-contracts/contracts/token_bridge_contract/src/util.nr). @@ -78,7 +78,7 @@ The portal must ensure that the sender is as expected. One way to do this is to To send a message to L1 from your Aztec contract, you must use the `message_portal` function on the `context`. When messaging to L1, only the `content` is required (as a `Field`). -#include_code context_message_portal /yarn-project/aztec-nr/aztec/src/context/private.nr rust +#include_code context_message_portal /yarn-project/aztec-nr/aztec/src/context/private_context.nr rust When sending a message from L2 to L1 we don't need to pass recipient, deadline, secret nor fees. Recipient is populated with the attached portal and the remaining values are not needed as the message is inserted into the outbox at the same time as it was included in a block (for the inbox it could be inserted and then only included in rollup block later). diff --git a/docs/docs/developers/contracts/syntax/context.md b/docs/docs/developers/contracts/syntax/context.md index 291940586413..eea03e8eb0f4 100644 --- a/docs/docs/developers/contracts/syntax/context.md +++ b/docs/docs/developers/contracts/syntax/context.md @@ -34,7 +34,7 @@ The following section will cover both contexts. ## The Private Context The code snippet below shows what is contained within the private context. -#include_code private-context /yarn-project/aztec-nr/aztec/src/context/private.nr rust +#include_code private-context /yarn-project/aztec-nr/aztec/src/context/private_context.nr rust ### Private Context Broken Down @@ -42,7 +42,7 @@ The code snippet below shows what is contained within the private context. The context inputs includes all of the information that is passed from the kernel circuit into the application circuit. It contains the following values. -#include_code private-context-inputs /yarn-project/aztec-nr/aztec/src/abi.nr rust +#include_code private-context-inputs /yarn-project/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr rust As shown in the snippet, the application context is made up of 4 main structures. The call context, the block header, the contract deployment data and the private global variables. @@ -89,7 +89,7 @@ Just like with the `is_contract_deployment` flag mentioned earlier. This data wi In the private execution context, we only have access to a subset of the total global variables, we are restricted to those which can be reliably proven by the kernel circuits. -#include_code private-global-variables /yarn-project/aztec-nr/aztec/src/abi.nr rust +#include_code private-global-variables /yarn-project/aztec-nr/aztec/src/context/globals/private_global_variables.nr rust ### Args Hash @@ -141,10 +141,10 @@ The Public Context includes all of the information passed from the `Public VM` i In the current version of the system, the public context is almost a clone of the private execution context. It contains the same call context data, access to the same historical tree roots, however it does NOT have access to contract deployment data, this is due to traditional contract deployments only currently being possible from private transactions. -#include_code public-context-inputs /yarn-project/aztec-nr/aztec/src/abi.nr rust +#include_code public-context-inputs /yarn-project/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr rust ### Public Global Variables The public global variables are provided by the rollup sequencer and consequently contain some more values than the private global variables. -#include_code public-global-variables /yarn-project/aztec-nr/aztec/src/abi.nr rust +#include_code global-variables /yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr rust diff --git a/docs/docs/developers/contracts/syntax/globals.md b/docs/docs/developers/contracts/syntax/globals.md index 1778c75e56db..4f66ff577a6e 100644 --- a/docs/docs/developers/contracts/syntax/globals.md +++ b/docs/docs/developers/contracts/syntax/globals.md @@ -9,7 +9,7 @@ For developers coming from solidity, this concept will be similar to how the glo `Aztec` has two execution environments, Private and Public. Each execution environment contains a different global variables object. ## Private Global Variables -#include_code private-global-variables /yarn-project/aztec-nr/aztec/src/abi.nr rust +#include_code private-global-variables /yarn-project/aztec-nr/aztec/src/context/globals/private_global_variables.nr rust The private global variables contain: ### Chain Id @@ -27,7 +27,7 @@ context.version(); ## Public Global Variables -#include_code public-global-variables /yarn-project/aztec-nr/aztec/src/abi.nr rust +#include_code global-variables /yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr rust The public global variables contain the values present in the `private global variables` described above, with the addition of: diff --git a/noir/Cargo.lock b/noir/Cargo.lock index 93f1d25fc76b..291ac30336ca 100644 --- a/noir/Cargo.lock +++ b/noir/Cargo.lock @@ -418,6 +418,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" name = "aztec_macros" version = "0.23.0" dependencies = [ + "convert_case 0.6.0", "iter-extended", "noirc_frontend", ] @@ -1003,6 +1004,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -1368,7 +1378,7 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", + "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", diff --git a/noir/aztec_macros/Cargo.toml b/noir/aztec_macros/Cargo.toml index 04f74d3b022c..5e908b2e672d 100644 --- a/noir/aztec_macros/Cargo.toml +++ b/noir/aztec_macros/Cargo.toml @@ -12,3 +12,4 @@ repository.workspace = true [dependencies] noirc_frontend.workspace = true iter-extended.workspace = true +convert_case = "0.6.0" diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index 138bcafb1d61..2143fbf6e3d8 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -1,6 +1,7 @@ use std::borrow::{Borrow, BorrowMut}; use std::vec; +use convert_case::{Case, Casing}; use iter_extended::vecmap; use noirc_frontend::macros_api::FieldElement; use noirc_frontend::macros_api::{ @@ -1049,7 +1050,10 @@ fn generate_selector_impl(structure: &NoirStruct) -> TypeImpl { fn create_inputs(ty: &str) -> Param { let context_ident = ident("inputs"); let context_pattern = Pattern::Identifier(context_ident); - let type_path = chained_path!("aztec", "abi", ty); + + let path_snippet = ty.to_case(Case::Snake); // e.g. private_context_inputs + let type_path = chained_path!("aztec", "context", "inputs", &path_snippet, ty); + let context_type = make_type(UnresolvedTypeData::Named(type_path, vec![])); let visibility = Visibility::Private; @@ -1088,8 +1092,8 @@ fn create_context(ty: &str, params: &[Param]) -> Result, AztecMac let let_hasher = mutable_assignment( "hasher", // Assigned to call( - variable_path(chained_path!("aztec", "abi", "Hasher", "new")), // Path - vec![], // args + variable_path(chained_path!("aztec", "hasher", "Hasher", "new")), // Path + vec![], // args ), ); @@ -1148,12 +1152,14 @@ fn create_context(ty: &str, params: &[Param]) -> Result, AztecMac vec![], // args ); + 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_path!("aztec", "context", ty, "new")), // Path - vec![inputs_expression, hash_call], // args + variable_path(chained_path!("aztec", "context", &path_snippet, ty, "new")), // Path + vec![inputs_expression, hash_call], // args ), ); injected_expressions.push(let_context); @@ -1200,7 +1206,7 @@ fn create_avm_context() -> Result { /// ```noir /// /// Before /// #[aztec(private)] -/// fn foo() -> abi::PrivateCircuitPublicInputs { +/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { /// // ... /// let my_return_value: Field = 10; /// context.return_values.push(my_return_value); @@ -1376,8 +1382,8 @@ fn make_castable_return_type(expression: Expression) -> Statement { /// Create Return Type /// -/// Public functions return abi::PublicCircuitPublicInputs while -/// private functions return abi::PrivateCircuitPublicInputs +/// Public functions return protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs while +/// private functions return protocol_types::abis::private_circuit_public_inputs::::PrivateCircuitPublicInputs /// /// This call constructs an ast token referencing the above types /// The name is set in the function above `transform`, hence the @@ -1387,7 +1393,7 @@ fn make_castable_return_type(expression: Expression) -> Statement { /// ```noir /// /// /// Before -/// fn foo() -> abi::PrivateCircuitPublicInputs { +/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { /// // ... /// } /// @@ -1397,7 +1403,8 @@ fn make_castable_return_type(expression: Expression) -> Statement { /// // ... /// } fn create_return_type(ty: &str) -> FunctionReturnType { - let return_path = chained_path!("aztec", "abi", ty); + let path_snippet = ty.to_case(Case::Snake); // e.g. private_circuit_public_inputs or public_circuit_public_inputs + let return_path = chained_path!("aztec", "protocol_types", "abis", &path_snippet, ty); return_type(return_path) } @@ -1409,7 +1416,7 @@ fn create_return_type(ty: &str) -> FunctionReturnType { /// The replaced code: /// ```noir /// /// Before -/// fn foo() -> abi::PrivateCircuitPublicInputs { +/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { /// // ... /// context.finish() /// } diff --git a/yarn-project/aztec-nr/aztec/src/abi.nr b/yarn-project/aztec-nr/aztec/src/abi.nr deleted file mode 100644 index d9de304de0c7..000000000000 --- a/yarn-project/aztec-nr/aztec/src/abi.nr +++ /dev/null @@ -1,95 +0,0 @@ -use dep::protocol_types::{ - abis::{ - call_context::CallContext, - private_circuit_public_inputs::PrivateCircuitPublicInputs, - public_circuit_public_inputs::PublicCircuitPublicInputs, - }, - address::{AztecAddress, EthAddress}, - contrakt::deployment_data::ContractDeploymentData, - hash::hash_args, - traits::{Hash, Serialize}, - header::Header, -}; - -// docs:start:private-global-variables -struct PrivateGlobalVariables { - chain_id: Field, - version: Field, -} -// docs:end:private-global-variables - -impl Serialize<2> for PrivateGlobalVariables { - fn serialize(self) -> [Field; 2] { - [self.chain_id, self.version] - } -} - -// docs:start:public-global-variables -struct PublicGlobalVariables { - chain_id: Field, - version: Field, - block_number: Field, - timestamp: Field, - coinbase: EthAddress, - fee_recipient: AztecAddress, -} -// docs:end:public-global-variables - -impl Serialize<6> for PublicGlobalVariables { - fn serialize(self) -> [Field; 6] { - [ - self.chain_id, - self.version, - self.block_number, - self.timestamp, - self.coinbase.to_field(), - self.fee_recipient.to_field(), - ] - } -} - -// PrivateContextInputs are expected to be provided to each private function -// docs:start:private-context-inputs -struct PrivateContextInputs { - call_context : CallContext, - historical_header: Header, - contract_deployment_data: ContractDeploymentData, - private_global_variables: PrivateGlobalVariables, -} -// docs:end:private-context-inputs - -// 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, -} -// docs:end:public-context-inputs - -struct Hasher { - fields: [Field], -} - -impl Hash for Hasher { - fn hash(self) -> Field { - hash_args(self.fields) - } -} - -impl Hasher { - pub fn new()-> Self { - Self { fields: [] } - } - - pub fn add(&mut self, field: Field) { - self.fields = self.fields.push_back(field); - } - - pub fn add_multiple(&mut self, fields: [Field; N]) { - for i in 0..N { - self.fields = self.fields.push_back(fields[i]); - } - } -} diff --git a/yarn-project/aztec-nr/aztec/src/context.nr b/yarn-project/aztec-nr/aztec/src/context.nr index 911ee98f17c2..8cc2c2a22c24 100644 --- a/yarn-project/aztec-nr/aztec/src/context.nr +++ b/yarn-project/aztec-nr/aztec/src/context.nr @@ -1,9 +1,12 @@ -mod private; -mod public; +mod globals; +mod inputs; + +mod private_context; +mod public_context; mod avm; -use public::PublicContext; -use private::PrivateContext; +use private_context::PrivateContext; +use public_context::PublicContext; use avm::AVMContext; struct Context { diff --git a/yarn-project/aztec-nr/aztec/src/context/globals.nr b/yarn-project/aztec-nr/aztec/src/context/globals.nr new file mode 100644 index 000000000000..8b50aa87a592 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/context/globals.nr @@ -0,0 +1,2 @@ +mod private_global_variables; +mod public_global_variables; diff --git a/yarn-project/aztec-nr/aztec/src/context/globals/private_global_variables.nr b/yarn-project/aztec-nr/aztec/src/context/globals/private_global_variables.nr new file mode 100644 index 000000000000..012db96d33c5 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/context/globals/private_global_variables.nr @@ -0,0 +1,16 @@ +use dep::protocol_types::traits::Serialize; + +global PRIVATE_GLOBAL_VARIABLES_LENGTH: Field = 2; + +// docs:start:private-global-variables +struct PrivateGlobalVariables { + chain_id: Field, + version: Field, +} +// docs:end:private-global-variables + +impl Serialize for PrivateGlobalVariables { + fn serialize(self) -> [Field; PRIVATE_GLOBAL_VARIABLES_LENGTH] { + [self.chain_id, self.version] + } +} diff --git a/yarn-project/aztec-nr/aztec/src/context/globals/public_global_variables.nr b/yarn-project/aztec-nr/aztec/src/context/globals/public_global_variables.nr new file mode 100644 index 000000000000..de68887afa86 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/context/globals/public_global_variables.nr @@ -0,0 +1,2 @@ +// protocl global vars are equal to the private ones so we just re-export them here under a different name +use dep::protocol_types::abis::global_variables::GlobalVariables as PublicGlobalVariables; diff --git a/yarn-project/aztec-nr/aztec/src/context/inputs.nr b/yarn-project/aztec-nr/aztec/src/context/inputs.nr new file mode 100644 index 000000000000..0d7c56574d52 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/context/inputs.nr @@ -0,0 +1,5 @@ +mod private_context_inputs; +mod public_context_inputs; + +use crate::context::inputs::private_context_inputs::PrivateContextInputs; +use crate::context::inputs::public_context_inputs::PublicContextInputs; diff --git a/yarn-project/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr b/yarn-project/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr new file mode 100644 index 000000000000..b96f62e6e50e --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr @@ -0,0 +1,16 @@ +use dep::protocol_types::{ + abis::call_context::CallContext, + contrakt::deployment_data::ContractDeploymentData, + header::Header, +}; +use crate::context::globals::private_global_variables::PrivateGlobalVariables; + +// PrivateContextInputs are expected to be provided to each private function +// docs:start:private-context-inputs +struct PrivateContextInputs { + call_context : CallContext, + historical_header: Header, + contract_deployment_data: ContractDeploymentData, + private_global_variables: PrivateGlobalVariables, +} +// docs:end:private-context-inputs \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr b/yarn-project/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr new file mode 100644 index 000000000000..6fefcfed3b73 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr @@ -0,0 +1,16 @@ +use crate::context::globals::public_global_variables::PublicGlobalVariables; + +use dep::protocol_types::{ + abis::call_context::CallContext, + header::Header, +}; + +// 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, +} +// docs:end:public-context-inputs diff --git a/yarn-project/aztec-nr/aztec/src/context/private.nr b/yarn-project/aztec-nr/aztec/src/context/private_context.nr similarity index 99% rename from yarn-project/aztec-nr/aztec/src/context/private.nr rename to yarn-project/aztec-nr/aztec/src/context/private_context.nr index 1692808fbdbf..1fdad5a141a9 100644 --- a/yarn-project/aztec-nr/aztec/src/context/private.nr +++ b/yarn-project/aztec-nr/aztec/src/context/private_context.nr @@ -1,5 +1,5 @@ use crate::{ - abi::PrivateContextInputs, + context::inputs::PrivateContextInputs, key::nullifier_key::validate_nullifier_key_against_address, messaging::process_l1_to_l2_message, oracle::{ @@ -40,9 +40,7 @@ use dep::protocol_types::{ NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH, }, - contract_class::ContractClassId, contrakt::{ - deployment_data::ContractDeploymentData, storage_read::StorageRead, storage_update_request::StorageUpdateRequest, }, diff --git a/yarn-project/aztec-nr/aztec/src/context/public.nr b/yarn-project/aztec-nr/aztec/src/context/public_context.nr similarity index 99% rename from yarn-project/aztec-nr/aztec/src/context/public.nr rename to yarn-project/aztec-nr/aztec/src/context/public_context.nr index 19bb51c6bb9e..2309a906d22d 100644 --- a/yarn-project/aztec-nr/aztec/src/context/public.nr +++ b/yarn-project/aztec-nr/aztec/src/context/public_context.nr @@ -1,5 +1,5 @@ use crate::{ - abi::PublicContextInputs, + context::inputs::PublicContextInputs, messaging::process_l1_to_l2_message, oracle::{ arguments, diff --git a/yarn-project/aztec-nr/aztec/src/hasher.nr b/yarn-project/aztec-nr/aztec/src/hasher.nr new file mode 100644 index 000000000000..fcfd27a74ac2 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/hasher.nr @@ -0,0 +1,30 @@ +use dep::protocol_types::{ + hash::hash_args, + traits::Hash, +}; + +struct Hasher { + fields: [Field], +} + +impl Hash for Hasher { + fn hash(self) -> Field { + hash_args(self.fields) + } +} + +impl Hasher { + pub fn new()-> Self { + Self { fields: [] } + } + + pub fn add(&mut self, field: Field) { + self.fields = self.fields.push_back(field); + } + + pub fn add_multiple(&mut self, fields: [Field; N]) { + for i in 0..N { + self.fields = self.fields.push_back(fields[i]); + } + } +} diff --git a/yarn-project/aztec-nr/aztec/src/lib.nr b/yarn-project/aztec-nr/aztec/src/lib.nr index 88866fb2fbcf..4b02952d76a1 100644 --- a/yarn-project/aztec-nr/aztec/src/lib.nr +++ b/yarn-project/aztec-nr/aztec/src/lib.nr @@ -1,7 +1,7 @@ -mod abi; mod avm; mod context; mod hash; +mod hasher; mod history; mod key; mod log; diff --git a/yarn-project/noir-contracts/contracts/card_game_contract/src/main.nr b/yarn-project/noir-contracts/contracts/card_game_contract/src/main.nr index 46461faf1fba..0b4424ac9b53 100644 --- a/yarn-project/noir-contracts/contracts/card_game_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/card_game_contract/src/main.nr @@ -25,15 +25,9 @@ contract CardGame { }, }; - use dep::aztec::{ - abi, - abi::{ - Hasher, PrivateContextInputs, - }, - note::{ - note_header::NoteHeader, - utils as note_utils, - }, + use dep::aztec::note::{ + note_header::NoteHeader, + utils as note_utils, }; use crate::cards::{ diff --git a/yarn-project/noir-contracts/contracts/child_contract/src/main.nr b/yarn-project/noir-contracts/contracts/child_contract/src/main.nr index 1298819f326f..a830f36be2b8 100644 --- a/yarn-project/noir-contracts/contracts/child_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/child_contract/src/main.nr @@ -3,13 +3,15 @@ contract Child { use dep::std::option::Option; use dep::aztec::{ - abi::CallContext, context::{PrivateContext, PublicContext, Context}, log::emit_unencrypted_log, state_vars::public_state::PublicState, }; use dep::aztec::protocol_types::{ - abis::function_selector::FunctionSelector, + abis::{ + call_context::CallContext, + function_selector::FunctionSelector, + }, address::AztecAddress, }; diff --git a/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr b/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr index 7182013b426d..d884a56a40fd 100644 --- a/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -244,10 +244,10 @@ contract DocsExample { } /// Macro equivalence section - use dep::aztec::abi; - use dep::aztec::abi::Hasher; - use dep::aztec::abi::PrivateContextInputs; - use dep::aztec::abi::PrivateCircuitPublicInputs; + use dep::aztec::hasher::Hasher; + + use dep::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs; + use dep::aztec::context::inputs::PrivateContextInputs; // docs:start:simple_macro_example #[aztec(private)] @@ -270,7 +270,7 @@ contract DocsExample { b: Field // The actual return type of our circuit is the PrivateCircuitPublicInputs struct, this will be the // input to our kernel! // docs:start:context-example-return - ) -> distinct pub abi::PrivateCircuitPublicInputs { + ) -> distinct pub PrivateCircuitPublicInputs { // docs:end:context-example-return // ************************************************************ // The hasher is a structure used to generate a hash of the circuits inputs. diff --git a/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/main.nr b/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/main.nr index d343f255f0a8..b94b576b364c 100644 --- a/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/main.nr @@ -3,11 +3,13 @@ mod ecdsa_public_key_note; // Account contract that uses ECDSA signatures for authentication on the same curve as Ethereum. // The signing key is stored in an immutable private note and should be different from the signing key. contract EcdsaAccount { - use dep::aztec::protocol_types::address::AztecAddress; + use dep::aztec::protocol_types::{ + abis::call_context::CallContext, + address::AztecAddress, + }; use dep::std; use dep::std::option::Option; use dep::aztec::{ - abi::CallContext, context::{PrivateContext, PublicContext, Context}, note::{ note_header::NoteHeader, diff --git a/yarn-project/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr b/yarn-project/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr index 6226024e39f4..ce0c13a9844e 100644 --- a/yarn-project/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr @@ -2,10 +2,7 @@ // Account contract that uses Schnorr signatures for authentication using a hardcoded public key. contract SchnorrHardcodedAccount { use dep::std; - use dep::aztec::{ - abi::{ PrivateCircuitPublicInputs, PrivateContextInputs, Hasher }, - context::PrivateContext, - }; + use dep::aztec::context::PrivateContext; use dep::authwit:: { entrypoint::{ EntrypointPayload, ENTRYPOINT_PAYLOAD_SIZE }, diff --git a/yarn-project/noir-contracts/contracts/test_contract/src/main.nr b/yarn-project/noir-contracts/contracts/test_contract/src/main.nr index f2eaa8511c66..05158e604d5e 100644 --- a/yarn-project/noir-contracts/contracts/test_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/test_contract/src/main.nr @@ -2,6 +2,7 @@ contract Test { use dep::std::option::Option; use dep::aztec::protocol_types::{ + abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, address::{ AztecAddress, EthAddress, @@ -9,7 +10,8 @@ contract Test { constants::{ MAX_READ_REQUESTS_PER_CALL, MAX_NOTES_PER_PAGE - } + }, + hash::hash_args, }; // The following import is here in order to make the event macro work because the macro doesn't add the import. // It doesn't add the import because in the future we will re-export all the types via aztec-nr and aztec-nr is @@ -21,9 +23,10 @@ contract Test { // docs:end:unencrypted_import use dep::aztec::{ - context::Context, - abi, - abi::PrivateContextInputs, + context::{ + Context, + inputs::private_context_inputs::PrivateContextInputs, + }, hash::pedersen_hash, context::PrivateContext, note::{ @@ -191,7 +194,7 @@ contract Test { an_array: [Field; 2], a_struct: DummyNote, a_deep_struct: DeepStruct - ) -> distinct pub abi::PrivateCircuitPublicInputs { + ) -> distinct pub PrivateCircuitPublicInputs { let mut args: BoundedVec = BoundedVec::new(0); args.push(a_field); args.push(a_bool as Field); @@ -207,7 +210,7 @@ contract Test { args.push(note.amount); args.push(note.secret_hash); } - let args_hash = abi::hash_args(args.storage); + let args_hash = hash_args(args.storage); let mut context = PrivateContext::new(inputs, args_hash); context.return_values.push(args_hash); context.finish() @@ -298,14 +301,27 @@ contract Test { storage.example_constant.initialize(&mut note, false); } - #[aztec(public)] - fn assert_coinbase(coinbase: EthAddress) { - assert(context.coinbase().eq(coinbase), "Invalid coinbase"); + #[aztec(private)] + fn assert_private_global_vars(chain_id: Field, version: Field) { + assert(context.chain_id() == chain_id, "Invalid chain id"); + assert(context.version() == version, "Invalid version"); } #[aztec(public)] - fn assert_fee_recipient(fee_recipient: AztecAddress) { - assert(context.fee_recipient().eq(fee_recipient), "Invalid fee recipient"); + fn assert_public_global_vars( + chain_id: Field, + version: Field, + block_number: Field, + timestamp: Field, + coinbase: EthAddress, + fee_recipient: AztecAddress + ) { + assert(context.chain_id() == chain_id, "Invalid chain id"); + assert(context.version() == version, "Invalid version"); + assert(context.block_number() == block_number, "Invalid block number"); + assert(context.timestamp() == timestamp, "Invalid timestamp"); + assert(context.coinbase() == coinbase, "Invalid coinbase"); + assert(context.fee_recipient() == fee_recipient, "Invalid fee recipient"); } unconstrained fn get_constant() -> pub Field { diff --git a/yarn-project/noir-contracts/contracts/token_contract/src/main.nr b/yarn-project/noir-contracts/contracts/token_contract/src/main.nr index 01af0454f6a1..1c21fd1f95a5 100644 --- a/yarn-project/noir-contracts/contracts/token_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/token_contract/src/main.nr @@ -22,7 +22,6 @@ contract Token { note_header::NoteHeader, utils as note_utils, }, - context::{PrivateContext, PublicContext, Context}, hash::{compute_secret_hash}, state_vars::{map::Map, public_state::PublicState, stable_public_state::StablePublicState, set::Set}, protocol_types::{ diff --git a/yarn-project/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/yarn-project/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 3b4c06075285..8452ba327a70 100644 --- a/yarn-project/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/yarn-project/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -1,8 +1,7 @@ use dep::std::option::Option; use dep::safe_math::SafeU120; use dep::aztec::{ - context::{PrivateContext, PublicContext, Context}, - hash::pedersen_hash, + context::Context, protocol_types::{ address::AztecAddress, constants::MAX_READ_REQUESTS_PER_CALL, diff --git a/yarn-project/noir-contracts/contracts/uniswap_contract/src/interfaces.nr b/yarn-project/noir-contracts/contracts/uniswap_contract/src/interfaces.nr index 1d9c2985eb91..3db1354766b8 100644 --- a/yarn-project/noir-contracts/contracts/uniswap_contract/src/interfaces.nr +++ b/yarn-project/noir-contracts/contracts/uniswap_contract/src/interfaces.nr @@ -7,7 +7,7 @@ use dep::aztec::protocol_types::{ }, }; use dep::aztec::{ - context::{ PrivateContext, PublicContext, Context }, + context::{ PrivateContext, PublicContext }, }; struct Token { diff --git a/yarn-project/noir-contracts/contracts/uniswap_contract/src/main.nr b/yarn-project/noir-contracts/contracts/uniswap_contract/src/main.nr index 65f9a8ea5904..b389f1b3413a 100644 --- a/yarn-project/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -14,7 +14,6 @@ contract Uniswap { }, }; use dep::aztec::{ - context::{PrivateContext, PublicContext, Context}, oracle::{context::get_portal_address}, state_vars::{map::Map, public_state::PublicState}, }; diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr index c7d9ef97d10f..81c040a246bd 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/global_variables.nr @@ -16,6 +16,7 @@ use crate::{ }, }; +// docs:start:global-variables struct GlobalVariables { chain_id : Field, version : Field, @@ -24,6 +25,7 @@ struct GlobalVariables { coinbase : EthAddress, fee_recipient : AztecAddress, } +// docs:end:global-variables impl Serialize for GlobalVariables { fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] { diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 63ae8f7c4108..2ea03803d01c 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -1129,4 +1129,41 @@ describe('Private Execution test suite', () => { expect(result.returnValues).toEqual(portalContractAddress.toField().value); }); }); + + describe('Private global variables', () => { + let chainId: Fr; + let version: Fr; + let args: any[]; + let artifact: FunctionArtifact; + + beforeAll(() => { + chainId = Fr.random(); + version = Fr.random(); + args = [chainId, version]; + + artifact = getFunctionArtifact(TestContractArtifact, 'assert_private_global_vars'); + oracle.getFunctionArtifact.mockImplementation(() => Promise.resolve(artifact)); + }); + + it('Private global vars are correctly set', () => { + // Chain id and version set in tx context is the same as the ones we pass via args so this should not throw + expect(() => runSimulator({ artifact, msgSender: owner, args, txContext: { chainId, version } })).not.toThrow(); + }); + + it('Throws when chainId is incorrectly set', async () => { + // We set the chainId in the tx context to a different value than the one we pass via args so the simulator should throw + const unexpectedChainId = Fr.random(); + await expect( + runSimulator({ artifact, msgSender: owner, args, txContext: { chainId: unexpectedChainId, version } }), + ).rejects.toThrowError('Invalid chain id'); + }); + + it('Throws when version is incorrectly set', async () => { + // We set the version in the tx context to a different value than the one we pass via args so the simulator should throw + const unexpectedVersion = Fr.random(); + await expect( + runSimulator({ artifact, msgSender: owner, args, txContext: { chainId, version: unexpectedVersion } }), + ).rejects.toThrowError('Invalid version'); + }); + }); }); diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index c2c625dda911..1d1a6a7b2e06 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -231,11 +231,7 @@ describe('ACIR public execution simulator', () => { const initialValue = 3n; const functionData = new FunctionData(parentEntryPointFnSelector, isInternal ?? false, false, false); - const args = encodeArguments(parentEntryPointFn, [ - childContractAddress.toField(), - childValueFnSelector.toField(), - initialValue, - ]); + const args = encodeArguments(parentEntryPointFn, [childContractAddress, childValueFnSelector, initialValue]); const callContext = CallContext.from({ msgSender: AztecAddress.random(), @@ -311,7 +307,7 @@ describe('ACIR public execution simulator', () => { const msgSender = AztecAddress.random(); const secretHash = Fr.random(); - const args = encodeArguments(shieldArtifact, [msgSender.toField(), amount, secretHash, Fr.ZERO]); + const args = encodeArguments(shieldArtifact, [msgSender, amount, secretHash, Fr.ZERO]); const callContext = CallContext.from({ msgSender: msgSender, @@ -436,9 +432,9 @@ describe('ACIR public execution simulator', () => { const computeArgs = () => encodeArguments(mintPublicArtifact, [ - tokenRecipient.toField(), + tokenRecipient, bridgedAmount, - canceller.toField(), + canceller, messageKey ?? preimage.hash(), secret, ]); @@ -636,6 +632,14 @@ describe('ACIR public execution simulator', () => { describe('Global variables in public context', () => { let contractAddress: AztecAddress; let callContext: CallContext; + let assertGlobalVarsArtifact: FunctionArtifact; + let functionData: FunctionData; + + const modifyGlobalVariables = (globalVariables: GlobalVariables, propertyIndex: number, value: any) => { + const globalVariablesFields = GlobalVariables.getFields(globalVariables) as unknown as any[]; + globalVariablesFields[propertyIndex] = value; + return GlobalVariables.fromFields(globalVariablesFields); + }; beforeAll(() => { contractAddress = AztecAddress.random(); @@ -649,92 +653,68 @@ describe('ACIR public execution simulator', () => { isStaticCall: false, startSideEffectCounter: 0, }); + assertGlobalVarsArtifact = TestContractArtifact.functions.find(f => f.name === 'assert_public_global_vars')!; + functionData = FunctionData.fromAbi(assertGlobalVarsArtifact); }); - const computeGlobalVariables = (coinbase: EthAddress, feeRecipient: AztecAddress) => - new GlobalVariables(new Fr(1), new Fr(2), Fr.ZERO, Fr.ZERO, coinbase, feeRecipient); - - describe('Coinbase', () => { - let expectedCoinbase: EthAddress; - let globalVariables: GlobalVariables; - let assertCoinbaseArtifact: FunctionArtifact; - let functionData: FunctionData; - - beforeAll(() => { - expectedCoinbase = EthAddress.random(); - globalVariables = computeGlobalVariables(expectedCoinbase, AztecAddress.random()); - - assertCoinbaseArtifact = TestContractArtifact.functions.find(f => f.name === 'assert_coinbase')!; - functionData = FunctionData.fromAbi(assertCoinbaseArtifact); - }); - - beforeEach(() => { - publicContracts.getBytecode.mockResolvedValue(Buffer.from(assertCoinbaseArtifact.bytecode, 'base64')); - }); - - it('Valid', () => { - // We set the coinbase function arg to one we set in global vars - const args = encodeArguments(assertCoinbaseArtifact, [expectedCoinbase]); - - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; - executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); - - // Now we check that the global vars value was correctly set by checking if the assert func throws - expect(() => executor.simulate(execution, globalVariables)).not.toThrow(); - }); - - it('Invalid', async () => { - // We set the coinbase function arg to a random invalid value - const invalidCoinbase = EthAddress.random(); - const args = encodeArguments(assertCoinbaseArtifact, [invalidCoinbase]); - - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; - executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); - - // Now we check that the function throws in case of invalid coinbase - await expect(executor.simulate(execution, globalVariables)).rejects.toThrowError('Invalid coinbase'); - }); + beforeEach(() => { + publicContracts.getBytecode.mockResolvedValue(Buffer.from(assertGlobalVarsArtifact.bytecode, 'base64')); }); - describe('Fee recipient', () => { - let expectedFeeRecipient: AztecAddress; - let globalVariables: GlobalVariables; - let assertFeeRecipientArtifact: FunctionArtifact; - let functionData: FunctionData; + // Note: Order here has to match the order of the properties in GlobalVariables.getFields(...) function. + const testCases = [ + { value: new Fr(1), invalidValue: Fr.random(), description: 'Chain ID' }, + { value: new Fr(1), invalidValue: Fr.random(), description: 'Version' }, + { value: new Fr(1), invalidValue: Fr.random(), description: 'Block number' }, + { value: new Fr(1), invalidValue: Fr.random(), description: 'Timestamp' }, + { value: EthAddress.random(), invalidValue: EthAddress.random(), description: 'Coinbase' }, + { + value: AztecAddress.random(), + invalidValue: AztecAddress.random(), + description: 'Fee recipient', + }, + ]; - beforeAll(() => { - expectedFeeRecipient = AztecAddress.random(); - globalVariables = computeGlobalVariables(EthAddress.random(), expectedFeeRecipient); + testCases.forEach(({ value, invalidValue, description }, i: number) => { + describe(`${description}`, () => { + let globalVariables: GlobalVariables; - assertFeeRecipientArtifact = TestContractArtifact.functions.find(f => f.name === 'assert_fee_recipient')!; - functionData = FunctionData.fromAbi(assertFeeRecipientArtifact); - }); - - beforeEach(() => { - publicContracts.getBytecode.mockResolvedValue(Buffer.from(assertFeeRecipientArtifact.bytecode, 'base64')); - }); + beforeAll(() => { + // We create a new global variables object containing non-zero value in place of the tested property + globalVariables = modifyGlobalVariables(GlobalVariables.empty(), i, value); + }); - it('Valid', () => { - // We set the fee recipient function arg to one we set in global vars - const args = encodeArguments(assertFeeRecipientArtifact, [expectedFeeRecipient]); + it('Valid', () => { + let args: Fr[]; + { + // We create the args by just serializing the reference global variables object + const rawArgs = GlobalVariables.getFields(globalVariables) as unknown as any[]; + args = encodeArguments(assertGlobalVarsArtifact, rawArgs); + } - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; - executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); + const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); - // Now we check that the global vars value was correctly set by checking if the assert func throws - expect(() => executor.simulate(execution, globalVariables)).not.toThrow(); - }); + expect(() => executor.simulate(execution, globalVariables)).not.toThrow(); + }); - it('Invalid', async () => { - // We set the fee recipient function arg to a random invalid value - const invalidFeeRecipient = AztecAddress.random(); - const args = encodeArguments(assertFeeRecipientArtifact, [invalidFeeRecipient]); + it('Invalid', async () => { + let args: Fr[]; + { + // We create the args by modifying the global variables object to contain an invalid value in place of + // the tested property + const modifiedGlobalVariables = modifyGlobalVariables(globalVariables, i, invalidValue); + const rawArgs = GlobalVariables.getFields(modifiedGlobalVariables) as unknown as any[]; + args = encodeArguments(assertGlobalVarsArtifact, rawArgs); + } - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; - executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); + const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); - // Now we check that the function throws in case of invalid fee recipient - await expect(executor.simulate(execution, globalVariables)).rejects.toThrowError('Invalid fee recipient'); + await expect(executor.simulate(execution, globalVariables)).rejects.toThrowError( + `Invalid ${description.toLowerCase()}`, + ); + }); }); }); });