From f83b3c30d2075b56123694e0e98a1877a0fe46cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Thu, 15 Feb 2024 00:56:28 +0000 Subject: [PATCH 01/17] Add new trait fn, fails to find all impls --- avm-transpiler/Cargo.lock | 1 + noir/Cargo.lock | 1 + noir/aztec_macros/Cargo.toml | 1 + noir/aztec_macros/src/lib.rs | 107 +++++++++++++++++- .../src/hir/def_collector/dc_crate.rs | 8 ++ noir/compiler/noirc_frontend/src/lib.rs | 10 ++ noir/noirc_macros/src/lib.rs | 12 ++ yarn-project/noir-contracts.js/package.json | 2 +- .../noir-protocol-circuits-types/package.json | 2 +- yarn-project/package.json | 2 +- 10 files changed, 137 insertions(+), 9 deletions(-) diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index 7f2f7804f42..2a7ac18c9c2 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -319,6 +319,7 @@ version = "0.24.0" dependencies = [ "convert_case", "iter-extended", + "noirc_errors", "noirc_frontend", ] diff --git a/noir/Cargo.lock b/noir/Cargo.lock index a7d721ef097..84d7f5052db 100644 --- a/noir/Cargo.lock +++ b/noir/Cargo.lock @@ -420,6 +420,7 @@ version = "0.24.0" dependencies = [ "convert_case 0.6.0", "iter-extended", + "noirc_errors", "noirc_frontend", ] diff --git a/noir/aztec_macros/Cargo.toml b/noir/aztec_macros/Cargo.toml index 5e908b2e672..ed9821fabcf 100644 --- a/noir/aztec_macros/Cargo.toml +++ b/noir/aztec_macros/Cargo.toml @@ -11,5 +11,6 @@ repository.workspace = true [dependencies] noirc_frontend.workspace = true +noirc_errors.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 0f054c262bf..f1fdd70487e 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -3,6 +3,8 @@ use std::vec; use convert_case::{Case, Casing}; use iter_extended::vecmap; +use noirc_frontend::hir::def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl}; +use noirc_frontend::hir::def_map::{LocalModuleId, ModuleId}; use noirc_frontend::macros_api::FieldElement; use noirc_frontend::macros_api::{ BlockExpression, CallExpression, CastExpression, Distinctness, Expression, ExpressionKind, @@ -18,6 +20,8 @@ use noirc_frontend::macros_api::{MacroError, MacroProcessor}; use noirc_frontend::macros_api::{ModuleDefId, NodeInterner, SortedModule, StructId}; use noirc_frontend::node_interner::{TraitId, TraitImplKind}; use noirc_frontend::Lambda; +use noirc_frontend::macros_api::parse_program; +use noirc_errors::Location; pub struct AztecMacro; @@ -31,6 +35,16 @@ impl MacroProcessor for AztecMacro { transform(ast, crate_id, context) } + fn process_unresolved_traits_impls( + &self, + crate_id: &CrateId, + context: &mut HirContext, + unresolved_traits_impls: &Vec, + collected_functions: &mut Vec, + ) -> Result<(), (MacroError, FileId)> { + inject_compute_note_hash_and_nullifier(crate_id, context, unresolved_traits_impls, collected_functions) + } + fn process_typed_ast( &self, crate_id: &CrateId, @@ -40,6 +54,87 @@ impl MacroProcessor for AztecMacro { } } +fn inject_compute_note_hash_and_nullifier( + crate_id: &CrateId, + context: &mut HirContext, + unresolved_traits_impls: &Vec, + collected_functions: &mut Vec, + ) -> Result<(), (MacroError, FileId)> { + // First we need to fetch all of the different note types a contract might use. These are all of the types that + // implement the NoteInterface trait, which provides the get_note_type_id() function. + + let note_types: Vec = unresolved_traits_impls.iter() + .filter(|trait_impl| trait_impl.trait_path.segments.last().unwrap().0.contents == "NoteInterface") + .filter_map(|trait_impl| match &trait_impl.object_type.typ { + UnresolvedTypeData::Named(path, _, _) => Some(path.segments.last().unwrap().0.contents.clone()), + _ => None, + }) + .collect(); + + dbg!(¬e_types); + + // We can now generate a version of compute_note_hash_and_nullifier tailored for the contracts in this crate. + let fn_compute_note_hash_and_nullifier = generate_compute_note_hash_and_nullifier(¬e_types); + + // Then we fetch all of the modules which correspond to contracts + let contract_module_file_ids: Vec<(LocalModuleId, FileId)> = context.def_map(crate_id).unwrap().modules().iter() + .filter(|(_, module)| module.is_contract) + .map(|(idx, module)| (LocalModuleId(idx), module.location.file)) + .collect(); + + // And inject the newly created function into each of them. We perform two separate loops as def_map does not allow + // for mutable iteration. + for (module_id, file_id) in contract_module_file_ids { + // We don't have a reasonable location for the source code of this autogenerated function, but it should not + // result in errors anyway so this should not matter. + let location = Location::new(fn_compute_note_hash_and_nullifier.span(), file_id); + + dbg!(&module_id); + dbg!(&file_id); + + // This is the same thing the ModCollector does when collecting functions. The only part we are not doing is we + // are skipping the declaration of the function (i.e. adding it to the scope/namespace of the module) because we + // can't mutate the modules. This should not be an issue, since this function will not be called by any other + // contract function. + let func_id = context.def_interner.push_empty_fn(); + context.def_interner.push_function(func_id, &fn_compute_note_hash_and_nullifier.def, ModuleId { krate: *crate_id, local_id: module_id }, location); + + collected_functions.iter_mut().find(|fns| fns.file_id == file_id).unwrap().push_fn(module_id, func_id, fn_compute_note_hash_and_nullifier.clone()); + } + + Ok(()) +} + +fn generate_compute_note_hash_and_nullifier(_note_types: &Vec) -> NoirFunction { + let unformatted_source = " + unconstrained fn compute_note_hash_and_nullifier( + contract_address: AztecAddress, + nonce: Field, + storage_slot: Field, + note_type_id: Field, + serialized_note: [Field; TOKEN_NOTE_LEN] + ) -> pub [Field; 4] { + let note_header = NoteHeader::new(contract_address, nonce, storage_slot); + + if (note_type_id == TransparentNote::get_note_type_id()) { + note_utils::compute_note_hash_and_nullifier(TransparentNote::deserialize_content, note_header, serialized_note) + } else if (note_type_id == FieldNote::get_note_type_id()) { + note_utils::compute_note_hash_and_nullifier(FieldNote::deserialize_content, note_header, serialized_note) + } else { + note_utils::compute_note_hash_and_nullifier(TokenNote::deserialize_content, note_header, serialized_note) + } + }"; + + let (function_ast, errors) = parse_program(unformatted_source); + if !errors.is_empty() { + dbg!(errors.clone()); + } + assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); + + let mut function_ast = function_ast.into_sorted(); + function_ast.functions.remove(0) +} + const FUNCTION_TREE_HEIGHT: u32 = 5; const MAX_CONTRACT_FUNCTIONS: usize = 2_usize.pow(FUNCTION_TREE_HEIGHT); @@ -401,12 +496,12 @@ fn transform_module( generate_storage_implementation(module).map_err(|err| (err, crate_graph.root_file_id))?; } - if storage_defined && !check_for_compute_note_hash_and_nullifier_definition(module) { - return Err(( - AztecMacroError::ComputeNoteHashAndNullifierNotFound { span: Span::default() }, - crate_graph.root_file_id, - )); - } + // if storage_defined && !check_for_compute_note_hash_and_nullifier_definition(module) { + // return Err(( + // AztecMacroError::ComputeNoteHashAndNullifierNotFound { span: Span::default() }, + // crate_graph.root_file_id, + // )); + // } for structure in module.types.iter() { if structure.attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { diff --git a/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 0d1dd1b4337..95f9a71a9b6 100644 --- a/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -256,6 +256,14 @@ impl DefCollector { // Add the current crate to the collection of DefMaps context.def_maps.insert(crate_id, def_collector.def_map); + for macro_processor in ¯o_processors { + macro_processor.process_unresolved_traits_impls(&crate_id, context, &def_collector.collected_traits_impls, &mut def_collector.collected_functions).unwrap_or_else( + |(macro_err, file_id)| { + errors.push((macro_err.into(), file_id)); + }, + ); + } + inject_prelude(crate_id, context, crate_root, &mut def_collector.collected_imports); for submodule in submodules { inject_prelude( diff --git a/noir/compiler/noirc_frontend/src/lib.rs b/noir/compiler/noirc_frontend/src/lib.rs index eb00a61adf6..c92801439a0 100644 --- a/noir/compiler/noirc_frontend/src/lib.rs +++ b/noir/compiler/noirc_frontend/src/lib.rs @@ -45,6 +45,7 @@ pub mod macros_api { pub use noirc_errors::Span; pub use crate::graph::CrateId; + use crate::hir::def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl}; pub use crate::hir::def_collector::errors::MacroError; pub use crate::hir_def::expr::{HirExpression, HirLiteral}; pub use crate::hir_def::stmt::HirStatement; @@ -74,6 +75,15 @@ pub mod macros_api { crate_id: &CrateId, context: &HirContext, ) -> Result; + + fn process_unresolved_traits_impls( + &self, + _crate_id: &CrateId, + _context: &mut HirContext, + _unresolved_traits_impls: &Vec, + _collected_functions: &mut Vec, + ) -> Result<(), (MacroError, FileId)>; + /// Function to manipulate the AST after type checking has been completed. /// The AST after type checking has been done is called the HIR. fn process_typed_ast( diff --git a/noir/noirc_macros/src/lib.rs b/noir/noirc_macros/src/lib.rs index 4337214d69f..55109dbfba0 100644 --- a/noir/noirc_macros/src/lib.rs +++ b/noir/noirc_macros/src/lib.rs @@ -1,3 +1,5 @@ +use noirc_frontend::hir::def_collector::dc_crate::UnresolvedFunctions; +use noirc_frontend::hir::def_collector::dc_crate::UnresolvedTraitImpl; use noirc_frontend::macros_api::parse_program; use noirc_frontend::macros_api::HirContext; use noirc_frontend::macros_api::SortedModule; @@ -16,6 +18,16 @@ impl MacroProcessor for AssertMessageMacro { transform(ast, crate_id) } + fn process_unresolved_traits_impls( + &self, + _crate_id: &CrateId, + _context: &mut HirContext, + _unresolevd_traits_impls: &Vec, + _collected_functions: &mut Vec, + ) -> Result<(), (MacroError, FileId)> { + Ok(()) + } + // This macro does not need to process any information after name resolution fn process_typed_ast( &self, diff --git a/yarn-project/noir-contracts.js/package.json b/yarn-project/noir-contracts.js/package.json index df827fc8e0f..10195fd680b 100644 --- a/yarn-project/noir-contracts.js/package.json +++ b/yarn-project/noir-contracts.js/package.json @@ -49,4 +49,4 @@ "engines": { "node": ">=18" } -} \ No newline at end of file +} diff --git a/yarn-project/noir-protocol-circuits-types/package.json b/yarn-project/noir-protocol-circuits-types/package.json index eec6ca314b6..a580039ebca 100644 --- a/yarn-project/noir-protocol-circuits-types/package.json +++ b/yarn-project/noir-protocol-circuits-types/package.json @@ -57,4 +57,4 @@ "engines": { "node": ">=18" } -} \ No newline at end of file +} diff --git a/yarn-project/package.json b/yarn-project/package.json index c83a0292d4b..06f7739b380 100644 --- a/yarn-project/package.json +++ b/yarn-project/package.json @@ -72,4 +72,4 @@ "@noir-lang/noir_wasm": "portal:../noir/packages/noir_wasm", "@noir-lang/noir_js": "portal:../noir/packages/noir_js" } -} \ No newline at end of file +} From aaeba3ca4baf8f0fa95160e03d3a7fcb94b2b122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 13:24:39 +0000 Subject: [PATCH 02/17] Use new note type search mechanism, remove compute_note_hash impls --- boxes/token/src/contracts/src/main.nr | 25 -- .../contracts/avm_test_contract/src/main.nr | 12 - .../benchmarking_contract/src/main.nr | 11 - .../contracts/card_game_contract/src/main.nr | 14 - .../contracts/child_contract/src/main.nr | 11 - .../contracts/counter_contract/src/main.nr | 13 - .../docs_example_contract/src/main.nr | 12 - .../easy_private_token_contract/src/main.nr | 14 - .../easy_private_voting_contract/src/main.nr | 11 - .../ecdsa_account_contract/src/main.nr | 19 -- .../contracts/escrow_contract/src/main.nr | 12 - .../inclusion_proofs_contract/src/main.nr | 14 - .../contracts/lending_contract/src/main.nr | 11 - .../pending_commitments_contract/src/main.nr | 15 - .../contracts/price_feed_contract/src/main.nr | 11 - .../schnorr_account_contract/src/main.nr | 19 -- .../src/main.nr | 2 +- .../src/main.nr | 2 +- .../contracts/slow_tree_contract/src/main.nr | 10 - .../stateful_test_contract/src/main.nr | 11 - .../contracts/test_contract/src/main.nr | 20 -- .../token_blacklist_contract/src/main.nr | 21 -- .../token_bridge_contract/src/main.nr | 13 - .../contracts/token_contract/src/main.nr | 25 -- .../contracts/uniswap_contract/src/main.nr | 11 - noir/aztec_macros/src/lib.rs | 256 +++++++++++------- .../noirc_frontend/src/hir/def_map/mod.rs | 5 + noir/compiler/noirc_frontend/src/hir/mod.rs | 4 + .../noirc_frontend/src/node_interner.rs | 2 +- 29 files changed, 163 insertions(+), 443 deletions(-) diff --git a/boxes/token/src/contracts/src/main.nr b/boxes/token/src/contracts/src/main.nr index f48b637ef6d..5a5177de3f6 100644 --- a/boxes/token/src/contracts/src/main.nr +++ b/boxes/token/src/contracts/src/main.nr @@ -379,30 +379,5 @@ contract Token { storage.public_balances.at(owner).read().value } // docs:end:balance_of_public - - // docs:start:compute_note_hash_and_nullifier - // Computes note hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; TOKEN_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - - if (note_type_id == TransparentNote::get_note_type_id()) { - 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) - } - } - // docs:end:compute_note_hash_and_nullifier } // docs:end:token_all 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 8f2d554a811..64fe1644489 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 @@ -113,20 +113,8 @@ contract AvmTest { fn getTimestamp() -> pub Field { context.timestamp() } - // #[aztec(public-vm)] // fn getContractCallDepth() -> pub Field { // context.contract_call_depth() // } - - // Function required for all contracts - unconstrained fn compute_note_hash_and_nullifier( - _contract_address: AztecAddress, - _nonce: Field, - _storage_slot: Field, - _note_type_id: Field, - _serialized_note: [Field; 1] - ) -> pub [Field; 4] { - [0, 0, 0, 0] - } } diff --git a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr index 5cdbbe83d5f..fb102d14266 100644 --- a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr @@ -60,15 +60,4 @@ contract Benchmarking { fn broadcast(owner: AztecAddress) { emit_unencrypted_log(&mut context, storage.balances.at(owner).read()); } - - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; VALUE_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize_content, note_header, serialized_note) - } } diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr index ef3b161cfdd..8af2576846a 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr @@ -148,18 +148,4 @@ contract CardGame { unconstrained fn view_game(game: u32) -> pub Game { storage.games.at(game as Field).read() } - - // Computes note hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; VALUE_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize_content, note_header, serialized_note) - } } diff --git a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr index f557d06bb50..ec0587d581a 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -94,15 +94,4 @@ contract Child { let pubSetValueSelector = FunctionSelector::from_signature("pubSetValue(Field)"); let _ret = context.call_public_function(context.this_address(), pubSetValueSelector, [10]); } - - // TODO: remove this placeholder once https://github.com/AztecProtocol/aztec-packages/issues/2918 is implemented - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 0] - ) -> pub [Field; 4] { - [0, 0, 0, 0] - } } diff --git a/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr b/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr index 02059ef0d3f..a61f276d070 100644 --- a/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr @@ -47,17 +47,4 @@ contract Counter { balance_utils::get_balance(counters.at(owner).set) } // docs:end:get_counter - - // docs:start:nullifier - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; VALUE_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize_content, note_header, serialized_note) - } - // docs:end:nullifier } diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr index 86c91046462..534e51bb3c1 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -232,18 +232,6 @@ contract DocsExample { storage.imm_singleton.is_initialized() } - // TODO: remove this placeholder once https://github.com/AztecProtocol/aztec-packages/issues/2918 is implemented - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; CARD_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(CardNote::deserialize_content, note_header, serialized_note) - } - /// Macro equivalence section use dep::aztec::hasher::Hasher; diff --git a/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr index 29137e82834..db812da9538 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr @@ -57,19 +57,5 @@ contract EasyPrivateToken { // Return the sum of all notes in the set. balance_utils::get_balance(balances.at(owner).set) } - - // Computes note hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; VALUE_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize_content, note_header, serialized_note) - } } // docs:end:easy_private_token_contract diff --git a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr index ea919f4eb7d..f53586132a0 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr @@ -66,15 +66,4 @@ contract EasyPrivateVoting { storage.tally.at(candidate).read() } // docs:end:get_vote - // docs:start:compute_note_hash_and_nullifier - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 0] - ) -> pub [Field; 4] { - [0, 0, 0, 0] - } - // docs:end:compute_note_hash_and_nullifier } diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr index dfe804c0fa3..22fb70e0475 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr @@ -78,23 +78,4 @@ contract EcdsaAccount { true } - - // Computes note hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; ECDSA_PUBLIC_KEY_NOTE_LEN] - ) -> pub [Field; 4] { - assert(storage_slot == storage.public_key.get_storage_slot()); - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier( - EcdsaPublicKeyNote::deserialize_content, - note_header, - serialized_note - ) - } } diff --git a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr index 1bc3de696df..d04a1599aea 100644 --- a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr @@ -48,16 +48,4 @@ contract Escrow { [this.to_field(), recipient.to_field(), amount, 0] ); } - - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; ADDRESS_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - assert(storage_slot == storage.owners.get_storage_slot()); - note_utils::compute_note_hash_and_nullifier(AddressNote::deserialize_content, note_header, serialized_note) - } } diff --git a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 913a0a5b161..db765d6d28b 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -250,18 +250,4 @@ contract InclusionProofs { ); // Here typically the factory would add the contract address to its internal map of deployed contracts. } - - // Computes note hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; VALUE_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize_content, note_header, serialized_note) - } } diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr index 64bab5a6e72..0ecaa4f7dbe 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr @@ -306,15 +306,4 @@ contract Lending { unconstrained fn get_assets() -> pub [AztecAddress; 2] { [storage.collateral_asset.read(), storage.stable_coin.read()] } - - // TODO: remove this placeholder once https://github.com/AztecProtocol/aztec-packages/issues/2918 is implemented - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 0] - ) -> pub [Field; 4] { - [0, 0, 0, 0] - } } diff --git a/noir-projects/noir-contracts/contracts/pending_commitments_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_commitments_contract/src/main.nr index 6c09247b61a..69b504d2c6d 100644 --- a/noir-projects/noir-contracts/contracts/pending_commitments_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_commitments_contract/src/main.nr @@ -244,7 +244,6 @@ contract PendingCommitments { [owner.to_field()] ); } - // Confirm cannot get/read a pending commitment in a nested call // that is created/inserted later in execution but in the parent. // NOTE: This test is especially important in an end-to-end context because the parent call @@ -259,18 +258,4 @@ contract PendingCommitments { // get_then_nullify_fn_selector: FunctionSelector, //) { //} - - // Computes note hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; VALUE_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize_content, note_header, serialized_note) - } } diff --git a/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr b/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr index 5d2ef98e196..a86fcc73bfd 100644 --- a/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/price_feed_contract/src/main.nr @@ -34,15 +34,4 @@ contract PriceFeed { unconstrained fn fetch_price(assetId: Field) -> pub Asset { storage.assets.at(assetId).read() } - - // TODO: remove this placeholder once https://github.com/AztecProtocol/aztec-packages/issues/2918 is implemented - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 0] - ) -> pub [Field; 4] { - [0, 0, 0, 0] - } } diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr index 9eb15c3f691..1539c038b4a 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr @@ -88,23 +88,4 @@ contract SchnorrAccount { // docs:end:entrypoint true } - - // Computes notes hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; PUBLIC_KEY_NOTE_LEN] - ) -> pub [Field; 4] { - assert(storage_slot == storage.signing_public_key.get_storage_slot()); - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier( - PublicKeyNote::deserialize_content, - note_header, - serialized_note - ) - } } diff --git a/noir-projects/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr index c5293bac24c..88f6b7cf5e7 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr @@ -2,7 +2,7 @@ // Account contract that uses Schnorr signatures for authentication using a hardcoded public key. contract SchnorrHardcodedAccount { use dep::std; - use dep::aztec::context::PrivateContext; + use dep::aztec::{context::PrivateContext, protocol_types::address::AztecAddress}; use dep::authwit::{ entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions, diff --git a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr index f01b3237bfe..b5633b70009 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr @@ -3,7 +3,7 @@ mod auth_oracle; contract SchnorrSingleKeyAccount { use dep::std::{option::Option}; - use dep::aztec::context::{PrivateContext, PublicContext, Context}; + use dep::aztec::{context::{PrivateContext, PublicContext, Context}, protocol_types::address::AztecAddress}; use dep::authwit::{entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions}; diff --git a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr index b8a0d2525d8..268f2a433ce 100644 --- a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr @@ -140,14 +140,4 @@ contract SlowTree { unconstrained fn un_read_root(address: AztecAddress) -> pub Leaf { storage.trees.at(address.to_field()).read_root() } - - unconstrained fn compute_note_hash_and_nullifier( - _contract_address: AztecAddress, - _nonce: Field, - _storage_slot: Field, - _note_type_id: Field, - _serialized_note: [Field; 4] - ) -> pub [Field; 4] { - [0x0d, 0x0e, 0x0a, 0x0d] - } } diff --git a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr index 8c00312a3b7..b276253718f 100644 --- a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr @@ -55,15 +55,4 @@ contract StatefulTest { unconstrained fn get_public_value(owner: AztecAddress) -> pub Field { storage.public_values.at(owner).read() } - - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; VALUE_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize_content, note_header, serialized_note) - } } diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 8aa168448b4..f20fa454926 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -341,24 +341,4 @@ contract Test { a_note: DummyNote, many_notes: [DummyNote; 3], } - - // Computes note hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; VALUE_NOTE_LEN] // must fit either a FieldNote or a ValueNote - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - - if (note_type_id == FieldNote::get_note_type_id()) { - note_utils::compute_note_hash_and_nullifier(FieldNote::deserialize_content, note_header, serialized_note) - } else { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize_content, note_header, serialized_note) - } - } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index 0a0394289a1..39530b29f0f 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -333,25 +333,4 @@ contract TokenBlacklist { unconstrained fn balance_of_public(owner: AztecAddress) -> pub u120 { storage.public_balances.at(owner).read().value } - - // Computes note hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - preimage: [Field; TOKEN_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - - if (note_type_id == TransparentNote::get_note_type_id()) { - note_utils::compute_note_hash_and_nullifier(TransparentNote::deserialize_content, note_header, preimage) - } else if (note_type_id == FieldNote::get_note_type_id()) { - note_utils::compute_note_hash_and_nullifier(FieldNote::deserialize_content, note_header, preimage) - } else { - note_utils::compute_note_hash_and_nullifier(TokenNote::deserialize_content, note_header, preimage) - } - } } diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index bf03277ee1a..49f192b8386 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -154,17 +154,4 @@ contract TokenBridge { assert(storage.token.read().eq(token), "Token address is not the same as seen in storage"); } // docs:end:assert_token_is_same - - // TODO: remove this placeholder once https://github.com/AztecProtocol/aztec-packages/issues/2918 is implemented - // docs:start:compute_note_hash_and_nullifier_placeholder - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 0] - ) -> pub [Field; 4] { - [0, 0, 0, 0] - } - // docs:end:compute_note_hash_and_nullifier_placeholder } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index f48b637ef6d..5a5177de3f6 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -379,30 +379,5 @@ contract Token { storage.public_balances.at(owner).read().value } // docs:end:balance_of_public - - // docs:start:compute_note_hash_and_nullifier - // Computes note hash and nullifier. - // Note 1: Needs to be defined by every contract producing logs. - // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; TOKEN_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - - if (note_type_id == TransparentNote::get_note_type_id()) { - 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) - } - } - // docs:end:compute_note_hash_and_nullifier } // docs:end:token_all 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 061250c8d2a..9d351ac9b73 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -227,15 +227,4 @@ contract Uniswap { unconstrained fn nonce_for_burn_approval() -> pub Field { storage.nonce_for_burn_approval.read() } - - // TODO: remove this placeholder once https://github.com/AztecProtocol/aztec-packages/issues/2918 is implemented - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 0] - ) -> pub [Field; 4] { - [0, 0, 0, 0] - } } diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index f1fdd70487e..48e394ec316 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -18,11 +18,10 @@ use noirc_frontend::macros_api::{ use noirc_frontend::macros_api::{CrateId, FileId}; use noirc_frontend::macros_api::{MacroError, MacroProcessor}; use noirc_frontend::macros_api::{ModuleDefId, NodeInterner, SortedModule, StructId}; -use noirc_frontend::node_interner::{TraitId, TraitImplKind}; +use noirc_frontend::node_interner::{FuncId, TraitId, TraitImplId, TraitImplKind}; use noirc_frontend::Lambda; use noirc_frontend::macros_api::parse_program; use noirc_errors::Location; - pub struct AztecMacro; impl MacroProcessor for AztecMacro { @@ -52,87 +51,7 @@ impl MacroProcessor for AztecMacro { ) -> Result<(), (MacroError, FileId)> { transform_hir(crate_id, context).map_err(|(err, file_id)| (err.into(), file_id)) } -} - -fn inject_compute_note_hash_and_nullifier( - crate_id: &CrateId, - context: &mut HirContext, - unresolved_traits_impls: &Vec, - collected_functions: &mut Vec, - ) -> Result<(), (MacroError, FileId)> { - // First we need to fetch all of the different note types a contract might use. These are all of the types that - // implement the NoteInterface trait, which provides the get_note_type_id() function. - let note_types: Vec = unresolved_traits_impls.iter() - .filter(|trait_impl| trait_impl.trait_path.segments.last().unwrap().0.contents == "NoteInterface") - .filter_map(|trait_impl| match &trait_impl.object_type.typ { - UnresolvedTypeData::Named(path, _, _) => Some(path.segments.last().unwrap().0.contents.clone()), - _ => None, - }) - .collect(); - - dbg!(¬e_types); - - // We can now generate a version of compute_note_hash_and_nullifier tailored for the contracts in this crate. - let fn_compute_note_hash_and_nullifier = generate_compute_note_hash_and_nullifier(¬e_types); - - // Then we fetch all of the modules which correspond to contracts - let contract_module_file_ids: Vec<(LocalModuleId, FileId)> = context.def_map(crate_id).unwrap().modules().iter() - .filter(|(_, module)| module.is_contract) - .map(|(idx, module)| (LocalModuleId(idx), module.location.file)) - .collect(); - - // And inject the newly created function into each of them. We perform two separate loops as def_map does not allow - // for mutable iteration. - for (module_id, file_id) in contract_module_file_ids { - // We don't have a reasonable location for the source code of this autogenerated function, but it should not - // result in errors anyway so this should not matter. - let location = Location::new(fn_compute_note_hash_and_nullifier.span(), file_id); - - dbg!(&module_id); - dbg!(&file_id); - - // This is the same thing the ModCollector does when collecting functions. The only part we are not doing is we - // are skipping the declaration of the function (i.e. adding it to the scope/namespace of the module) because we - // can't mutate the modules. This should not be an issue, since this function will not be called by any other - // contract function. - let func_id = context.def_interner.push_empty_fn(); - context.def_interner.push_function(func_id, &fn_compute_note_hash_and_nullifier.def, ModuleId { krate: *crate_id, local_id: module_id }, location); - - collected_functions.iter_mut().find(|fns| fns.file_id == file_id).unwrap().push_fn(module_id, func_id, fn_compute_note_hash_and_nullifier.clone()); - } - - Ok(()) -} - -fn generate_compute_note_hash_and_nullifier(_note_types: &Vec) -> NoirFunction { - let unformatted_source = " - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; TOKEN_NOTE_LEN] - ) -> pub [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - - if (note_type_id == TransparentNote::get_note_type_id()) { - note_utils::compute_note_hash_and_nullifier(TransparentNote::deserialize_content, note_header, serialized_note) - } else if (note_type_id == FieldNote::get_note_type_id()) { - note_utils::compute_note_hash_and_nullifier(FieldNote::deserialize_content, note_header, serialized_note) - } else { - note_utils::compute_note_hash_and_nullifier(TokenNote::deserialize_content, note_header, serialized_note) - } - }"; - - let (function_ast, errors) = parse_program(unformatted_source); - if !errors.is_empty() { - dbg!(errors.clone()); - } - assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); - - let mut function_ast = function_ast.into_sorted(); - function_ast.functions.remove(0) } const FUNCTION_TREE_HEIGHT: u32 = 5; @@ -141,7 +60,6 @@ const MAX_CONTRACT_FUNCTIONS: usize = 2_usize.pow(FUNCTION_TREE_HEIGHT); #[derive(Debug, Clone)] pub enum AztecMacroError { AztecDepNotFound, - ComputeNoteHashAndNullifierNotFound { span: Span }, ContractHasTooManyFunctions { span: Span }, ContractConstructorMissing { span: Span }, UnsupportedFunctionArgumentType { span: Span, typ: UnresolvedTypeData }, @@ -158,11 +76,6 @@ impl From for MacroError { secondary_message: None, span: None, }, - AztecMacroError::ComputeNoteHashAndNullifierNotFound { span } => MacroError { - primary_message: "compute_note_hash_and_nullifier function not found. Define it in your contract. For more information go to https://docs.aztec.network/developers/debugging/aztecnr-errors#compute_note_hash_and_nullifier-function-not-found-define-it-in-your-contract".to_owned(), - secondary_message: None, - span: Some(span), - }, AztecMacroError::ContractHasTooManyFunctions { span } => MacroError { primary_message: format!("Contract can only have a maximum of {} functions", MAX_CONTRACT_FUNCTIONS), secondary_message: None, @@ -433,27 +346,27 @@ fn check_for_storage_implementation(module: &SortedModule) -> bool { } // Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,Field,[Field; N]) -> [Field; 4]" is defined -fn check_for_compute_note_hash_and_nullifier_definition(module: &SortedModule) -> bool { - module.functions.iter().any(|func| { - func.def.name.0.contents == "compute_note_hash_and_nullifier" - && func.def.parameters.len() == 5 - && match &func.def.parameters[0].typ.typ { +fn check_for_compute_note_hash_and_nullifier_definition(functions_data: &Vec<(LocalModuleId, FuncId, NoirFunction)>, module_id: LocalModuleId) -> bool { + functions_data.iter().filter(|func_data| func_data.0 == module_id).any(|func_data| { + func_data.2.def.name.0.contents == "compute_note_hash_and_nullifier" + && func_data.2.def.parameters.len() == 5 + && match &func_data.2.def.parameters[0].typ.typ { UnresolvedTypeData::Named(path, _, _) => path.segments.last().unwrap().0.contents == "AztecAddress", _ => false, } - && func.def.parameters[1].typ.typ == UnresolvedTypeData::FieldElement - && func.def.parameters[2].typ.typ == UnresolvedTypeData::FieldElement - && func.def.parameters[3].typ.typ == UnresolvedTypeData::FieldElement + && func_data.2.def.parameters[1].typ.typ == UnresolvedTypeData::FieldElement + && func_data.2.def.parameters[2].typ.typ == UnresolvedTypeData::FieldElement + && func_data.2.def.parameters[3].typ.typ == UnresolvedTypeData::FieldElement // checks if the 5th parameter is an array and the Box in // Array(Option, Box) contains only fields - && match &func.def.parameters[4].typ.typ { + && match &func_data.2.def.parameters[4].typ.typ { UnresolvedTypeData::Array(_, inner_type) => { matches!(inner_type.typ, UnresolvedTypeData::FieldElement) }, _ => false, } // We check the return type the same way as we did the 5th parameter - && match &func.def.return_type { + && match &func_data.2.def.return_type { FunctionReturnType::Default(_) => false, FunctionReturnType::Ty(unresolved_type) => { match &unresolved_type.typ { @@ -496,13 +409,6 @@ fn transform_module( generate_storage_implementation(module).map_err(|err| (err, crate_graph.root_file_id))?; } - // if storage_defined && !check_for_compute_note_hash_and_nullifier_definition(module) { - // return Err(( - // AztecMacroError::ComputeNoteHashAndNullifierNotFound { span: Span::default() }, - // crate_graph.root_file_id, - // )); - // } - for structure in module.types.iter() { if structure.attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { module.impls.push(generate_selector_impl(structure)); @@ -1696,3 +1602,143 @@ fn event_signature(event: &StructType) -> String { let fields = vecmap(event.get_fields(&[]), |(_, typ)| signature_of_type(&typ)); format!("{}({})", event.name.0.contents, fields.join(",")) } + +fn inject_compute_note_hash_and_nullifier( + crate_id: &CrateId, + context: &mut HirContext, + unresolved_traits_impls: &Vec, + collected_functions: &mut Vec, +) -> Result<(), (MacroError, FileId)> { + // We first fetch modules in this crate which correspond to contracts, along with their file id. + let mut contract_module_file_ids: Vec<(LocalModuleId, FileId)> = context.def_map(crate_id).unwrap().modules().iter() + .filter(|(_, module)| module.is_contract) + .map(|(idx, module)| (LocalModuleId(idx), module.location.file)) + .collect(); + + // If the current crate does not contain a contract module we simply skip it. + if contract_module_file_ids.len() == 0 { + return Ok(()); + } else if contract_module_file_ids.len() != 1 { + panic!("Found multiple contracts in the same crate"); + } + + let (module_id, file_id) = contract_module_file_ids.pop().unwrap(); + + // If compute_note_hash_and_nullifier is already defined by the user, we skip autogeneration in order to provide an + // escape hatch for this mechanism. + if collected_functions.iter().any(|coll_funcs_data| check_for_compute_note_hash_and_nullifier_definition(&coll_funcs_data.functions, module_id)) { + return Ok(()); + } + + // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the + // contract might use. These are the types that implement the NoteInterface trait, which provides the + // get_note_type_id function. + + let mut note_types: Vec = Vec::new(); + + // These note types can be declared in either external crates, or the contract's own crate. External crates have + // already been processed and resolved, but are available here via the NodeInterner. This is because the contract's + // crate is the last crate to be processed, after all of its dependencies. + for trait_impl_id in 0..(&context.def_interner.next_trait_impl_id()).0 { + let trait_impl = &context.def_interner.get_trait_implementation(TraitImplId(trait_impl_id)); + + if trait_impl.borrow().ident.0.contents == "NoteInterface" { + if let Type::Struct(s, _) = &trait_impl.borrow().typ { + note_types.push(s.borrow().name.0.contents.clone()); + } else { + panic!("Found impl for NoteInterface on non-Struct"); + } + } + } + + // This crate's traits and impls have not yet been resolved, so we look for impls in unresolved_trait_impls. + note_types.extend(unresolved_traits_impls.iter() + .filter(|trait_impl| trait_impl.trait_path.segments.last().unwrap().0.contents == "NoteInterface") + .filter_map(|trait_impl| match &trait_impl.object_type.typ { + UnresolvedTypeData::Named(path, _, _) => Some(path.segments.last().unwrap().0.contents.clone()), + _ => None, + })); + + // We can now generate a version of compute_note_hash_and_nullifier tailored for the contract in this crate. + let func = generate_compute_note_hash_and_nullifier(¬e_types); + + // And inject the newly created function into the contract. + + // We don't have a reasonable location for the source code of this autogenerated function, but it should not + // result in errors anyway so this should not matter. + let location = Location::new(func.span(), file_id); + + // These are the same things the ModCollector does when collecting functions: we push the function to the + // NodeInterner, declare it in the module (which checks for duplicate definitions), and finally add it to the list + // on collected but unresolved functions. + + let func_id = context.def_interner.push_empty_fn(); + context.def_interner.push_function(func_id, &func.def, ModuleId { krate: *crate_id, local_id: module_id }, location); + + let Ok(_) = context.def_map_mut(crate_id).unwrap() + .modules_mut()[module_id.0] + .declare_function( + func.name_ident().clone(), func_id + ) + else { + panic!("Failed to declare the autogenerated compute_note_hash_and_nullifier function, likely due to a duplicate definition. This should not happen"); + }; + + collected_functions.iter_mut().find(|fns| fns.file_id == file_id).unwrap().push_fn(module_id, func_id, func.clone()); + + Ok(()) +} + +fn generate_compute_note_hash_and_nullifier(note_types: &Vec) -> NoirFunction { + let function_source = generate_compute_note_hash_and_nullifier_source(note_types); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors.clone()); + } + assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); + + let mut function_ast = function_ast.into_sorted(); + function_ast.functions.remove(0) +} + +fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> String { + if note_types.len() == 0 { + " + unconstrained fn compute_note_hash_and_nullifier( + contract_address: AztecAddress, + nonce: Field, + storage_slot: Field, + note_type_id: Field, + serialized_note: [Field; 12] + ) -> pub [Field; 4] { + [0, 0, 0, 0] + }".to_string() + } else { + let if_statements: Vec = note_types.iter().map(|note_type| format!( + "if (note_type_id == {0}::get_note_type_id()) {{ + note_utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note) + }}" + , note_type)).collect(); + + // TODO(#4520): error out on the else instead of returning a zero array + let full_if_statement = if_statements.join(" else ") + " + else { + [0, 0, 0, 0] + }"; + + format!(" + unconstrained fn compute_note_hash_and_nullifier( + contract_address: AztecAddress, + nonce: Field, + storage_slot: Field, + note_type_id: Field, + serialized_note: [Field; 12] + ) -> pub [Field; 4] {{ + let note_header = NoteHeader::new(contract_address, nonce, storage_slot); + + {} + }}", full_if_statement) +} + +} \ No newline at end of file diff --git a/noir/compiler/noirc_frontend/src/hir/def_map/mod.rs b/noir/compiler/noirc_frontend/src/hir/def_map/mod.rs index 8c985e88e0b..0372edfd031 100644 --- a/noir/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/noir/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -135,6 +135,11 @@ impl CrateDefMap { pub fn modules(&self) -> &Arena { &self.modules } + + pub fn modules_mut(&mut self) -> &mut Arena { + &mut self.modules + } + pub fn krate(&self) -> CrateId { self.krate } diff --git a/noir/compiler/noirc_frontend/src/hir/mod.rs b/noir/compiler/noirc_frontend/src/hir/mod.rs index 4d3800f1a50..00bcb0cdebf 100644 --- a/noir/compiler/noirc_frontend/src/hir/mod.rs +++ b/noir/compiler/noirc_frontend/src/hir/mod.rs @@ -91,6 +91,10 @@ impl Context<'_, '_> { self.def_maps.get(crate_id) } + pub fn def_map_mut(&mut self, crate_id: &CrateId) -> Option<&mut CrateDefMap> { + self.def_maps.get_mut(crate_id) + } + /// Return the CrateId for each crate that has been compiled /// successfully pub fn crates(&self) -> impl Iterator + '_ { diff --git a/noir/compiler/noirc_frontend/src/node_interner.rs b/noir/compiler/noirc_frontend/src/node_interner.rs index 0051c1b4f5f..1841c4b790c 100644 --- a/noir/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/compiler/noirc_frontend/src/node_interner.rs @@ -371,7 +371,7 @@ impl TraitId { } #[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)] -pub struct TraitImplId(usize); +pub struct TraitImplId(pub usize); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct TraitMethodId { From 390e5f858dbd1a1243589b38d77ada2cd5868e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 13:54:28 +0000 Subject: [PATCH 03/17] use empty span, trim whitespace --- noir/aztec_macros/src/lib.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index 48e394ec316..926187a560c 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -51,7 +51,7 @@ impl MacroProcessor for AztecMacro { ) -> Result<(), (MacroError, FileId)> { transform_hir(crate_id, context).map_err(|(err, file_id)| (err.into(), file_id)) } - + } const FUNCTION_TREE_HEIGHT: u32 = 5; @@ -597,7 +597,7 @@ fn generate_storage_implementation(module: &mut SortedModule) -> Result<(), Azte /// If it does, it will insert the following things: /// - A new Input that is provided for a kernel app circuit, named: {Public/Private}ContextInputs /// - Hashes all of the function input variables -/// - This instantiates a helper function +/// - This instantiates a helper function fn transform_function( ty: &str, func: &mut NoirFunction, @@ -1614,7 +1614,7 @@ fn inject_compute_note_hash_and_nullifier( .filter(|(_, module)| module.is_contract) .map(|(idx, module)| (LocalModuleId(idx), module.location.file)) .collect(); - + // If the current crate does not contain a contract module we simply skip it. if contract_module_file_ids.len() == 0 { return Ok(()); @@ -1630,8 +1630,8 @@ fn inject_compute_note_hash_and_nullifier( return Ok(()); } - // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the - // contract might use. These are the types that implement the NoteInterface trait, which provides the + // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the + // contract might use. These are the types that implement the NoteInterface trait, which provides the // get_note_type_id function. let mut note_types: Vec = Vec::new(); @@ -1664,17 +1664,17 @@ fn inject_compute_note_hash_and_nullifier( // And inject the newly created function into the contract. - // We don't have a reasonable location for the source code of this autogenerated function, but it should not - // result in errors anyway so this should not matter. - let location = Location::new(func.span(), file_id); - - // These are the same things the ModCollector does when collecting functions: we push the function to the + // We don't have a reasonable location for the source code of this autogenerated function, so we simply pass an + // empty span. This function should not produce errors anyway so this should not matter. + let location = Location::new(Span::empty(0), file_id); + + // These are the same things the ModCollector does when collecting functions: we push the function to the // NodeInterner, declare it in the module (which checks for duplicate definitions), and finally add it to the list // on collected but unresolved functions. - + let func_id = context.def_interner.push_empty_fn(); context.def_interner.push_function(func_id, &func.def, ModuleId { krate: *crate_id, local_id: module_id }, location); - + let Ok(_) = context.def_map_mut(crate_id).unwrap() .modules_mut()[module_id.0] .declare_function( @@ -1691,7 +1691,7 @@ fn inject_compute_note_hash_and_nullifier( fn generate_compute_note_hash_and_nullifier(note_types: &Vec) -> NoirFunction { let function_source = generate_compute_note_hash_and_nullifier_source(note_types); - + let (function_ast, errors) = parse_program(&function_source); if !errors.is_empty() { dbg!(errors.clone()); @@ -1721,13 +1721,13 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> }}" , note_type)).collect(); - // TODO(#4520): error out on the else instead of returning a zero array + // TODO(#4520): error out on the else instead of returning a zero array let full_if_statement = if_statements.join(" else ") + " else { [0, 0, 0, 0] }"; - format!(" + format!(" unconstrained fn compute_note_hash_and_nullifier( contract_address: AztecAddress, nonce: Field, From 762ad4297020ad0f0bed049e2c22b00e171ec4d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 14:14:13 +0000 Subject: [PATCH 04/17] Update class registerer address --- yarn-project/protocol-contracts/src/class-registerer/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/protocol-contracts/src/class-registerer/index.ts b/yarn-project/protocol-contracts/src/class-registerer/index.ts index a4885c7d975..217b158aff4 100644 --- a/yarn-project/protocol-contracts/src/class-registerer/index.ts +++ b/yarn-project/protocol-contracts/src/class-registerer/index.ts @@ -13,5 +13,5 @@ export function getCanonicalClassRegisterer(): ProtocolContract { * @remarks This should not change often, hence we hardcode it to save from having to recompute it every time. */ export const ClassRegistererAddress = AztecAddress.fromString( - '0x29c0cd0000951bba8af520ad5513cc53d9f0413c5a24a72a4ba8c17894c0bef9', + '0x29bd3a9a50dd4bdd13c53fc6dd881964be32c04022e8d7cc696e1948b8327cd8', ); From 785ba342ef103340bf285386dd7d298553600fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 15:30:17 +0000 Subject: [PATCH 05/17] Update canonical protocol contracts --- .../__snapshots__/index.test.ts.snap | 314 +++++++++--------- .../__snapshots__/index.test.ts.snap | 288 ++++++++-------- .../src/instance-deployer/index.ts | 2 +- 3 files changed, 302 insertions(+), 302 deletions(-) diff --git a/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap index 1e0c5fe95d3..779c773780e 100644 --- a/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap @@ -3,122 +3,122 @@ exports[`ClassRegisterer returns canonical protocol contract 1`] = ` { "address": AztecAddress { - "asBigInt": 18885476286413803383198269230770707720385495724494788057562984154330701020921n, + "asBigInt": 18879165348792956523849879261898633134630135415990944739426750248408667290840n, "asBuffer": { "data": [ 41, - 192, - 205, - 0, - 0, - 149, - 27, - 186, - 138, - 245, - 32, - 173, - 85, - 19, - 204, - 83, - 217, - 240, - 65, - 60, - 90, - 36, - 167, - 42, + 189, + 58, + 154, + 80, + 221, 75, - 168, - 193, - 120, - 148, - 192, + 221, + 19, + 197, + 63, + 198, + 221, + 136, + 25, + 100, 190, - 249, + 50, + 192, + 64, + 34, + 232, + 215, + 204, + 105, + 110, + 25, + 72, + 184, + 50, + 124, + 216, ], "type": "Buffer", }, }, "contractClass": { "artifactHash": Fr { - "asBigInt": 12987763002449886210249343009930617501836480764589027470816200726753333386077n, + "asBigInt": 10026203357347043763857861630754166863011605093072915309439432122921172595525n, "asBuffer": { "data": [ - 28, - 182, - 208, - 56, - 31, - 162, - 181, - 120, - 194, - 173, - 145, - 119, - 205, - 23, - 92, - 17, - 148, - 169, - 179, - 132, - 128, - 198, - 168, - 109, - 135, - 242, - 101, - 160, - 56, - 218, - 155, - 93, + 22, + 42, + 161, + 71, + 156, + 116, + 4, + 138, + 117, + 195, + 180, + 196, + 124, + 146, + 98, + 97, + 12, + 147, + 67, + 131, + 237, + 163, + 102, + 130, + 82, + 161, + 229, + 206, + 150, + 103, + 243, + 69, ], "type": "Buffer", }, }, "id": Fr { - "asBigInt": 15610368298223903406763887747663253144646438360806401290390854210044956890867n, + "asBigInt": 15988644104676201200192077242461419082767909218193816497369696704044361007906n, "asBuffer": { "data": [ - 34, - 131, - 39, - 197, - 16, - 11, + 35, + 89, + 64, + 122, + 138, + 203, + 191, + 140, + 115, + 72, + 106, 210, - 53, - 13, - 80, - 129, - 233, - 196, - 47, - 124, - 112, - 85, - 229, - 146, - 176, - 58, - 247, - 80, - 38, - 80, - 100, - 198, - 59, - 105, - 209, - 214, - 243, + 158, + 215, + 154, + 180, + 169, + 216, + 155, + 63, + 82, + 29, + 101, + 244, + 7, + 217, + 56, + 5, + 41, + 123, + 67, + 34, ], "type": "Buffer", }, @@ -403,81 +403,81 @@ exports[`ClassRegisterer returns canonical protocol contract 1`] = ` }, "instance": { "address": AztecAddress { - "asBigInt": 18885476286413803383198269230770707720385495724494788057562984154330701020921n, + "asBigInt": 18879165348792956523849879261898633134630135415990944739426750248408667290840n, "asBuffer": { "data": [ 41, - 192, - 205, - 0, - 0, - 149, - 27, - 186, - 138, - 245, - 32, - 173, - 85, - 19, - 204, - 83, - 217, - 240, - 65, - 60, - 90, - 36, - 167, - 42, + 189, + 58, + 154, + 80, + 221, 75, - 168, - 193, - 120, - 148, - 192, + 221, + 19, + 197, + 63, + 198, + 221, + 136, + 25, + 100, 190, - 249, + 50, + 192, + 64, + 34, + 232, + 215, + 204, + 105, + 110, + 25, + 72, + 184, + 50, + 124, + 216, ], "type": "Buffer", }, }, "contractClassId": Fr { - "asBigInt": 15610368298223903406763887747663253144646438360806401290390854210044956890867n, + "asBigInt": 15988644104676201200192077242461419082767909218193816497369696704044361007906n, "asBuffer": { "data": [ - 34, - 131, - 39, - 197, - 16, - 11, + 35, + 89, + 64, + 122, + 138, + 203, + 191, + 140, + 115, + 72, + 106, 210, - 53, - 13, - 80, - 129, - 233, - 196, - 47, - 124, - 112, - 85, - 229, - 146, - 176, - 58, - 247, - 80, - 38, - 80, - 100, - 198, - 59, - 105, - 209, - 214, - 243, + 158, + 215, + 154, + 180, + 169, + 216, + 155, + 63, + 82, + 29, + 101, + 244, + 7, + 217, + 56, + 5, + 41, + 123, + 67, + 34, ], "type": "Buffer", }, diff --git a/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap index 3ca5288c62a..7de5c7e63f2 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap @@ -3,122 +3,122 @@ exports[`InstanceDeployer returns canonical protocol contract 1`] = ` { "address": AztecAddress { - "asBigInt": 10674890382018500410451173831129216683967953609468942304388116555335197334423n, + "asBigInt": 6114335376419651312789291039592727379508607669159505474839878685584297937951n, "asBuffer": { "data": [ - 23, - 153, - 198, + 13, + 132, + 151, + 87, + 219, + 22, + 170, + 125, + 24, + 214, 26, - 161, - 4, - 48, + 196, + 234, + 97, + 72, + 134, + 120, + 220, + 253, + 85, 191, - 111, - 236, - 70, - 103, - 156, - 76, + 9, 183, + 18, 108, - 62, - 209, - 44, - 216, - 182, + 92, + 238, + 191, 231, - 62, - 215, - 56, - 157, - 90, - 226, - 150, - 173, - 27, - 151, + 81, + 204, + 31, ], "type": "Buffer", }, }, "contractClass": { "artifactHash": Fr { - "asBigInt": 1546915255081493429210407932347415325264105027406908683791229627179136590869n, + "asBigInt": 19070479700791057827478396638125001777177091043307328607370134174275317261568n, "asBuffer": { "data": [ - 3, - 107, - 133, - 227, - 201, - 147, - 91, - 223, - 147, - 254, - 104, - 143, - 129, - 46, - 252, - 227, - 185, - 74, - 0, - 254, - 227, - 11, - 162, - 57, - 80, 42, - 239, + 41, + 130, + 78, + 6, + 255, + 160, + 186, + 166, + 49, + 54, 244, - 210, - 18, - 36, + 6, + 126, + 146, + 222, + 76, + 236, + 179, + 56, + 209, 21, + 19, + 124, + 178, + 51, + 251, + 148, + 238, + 47, + 229, + 0, ], "type": "Buffer", }, }, "id": Fr { - "asBigInt": 9040462806880011027940587321357143576447825874691049241890511565119666681463n, + "asBigInt": 19003838234876564894705716440306205769025681419911568720344156830131976536513n, "asBuffer": { "data": [ - 19, - 252, - 184, - 122, - 123, - 192, + 42, + 3, + 202, + 144, + 172, + 187, + 17, + 134, + 95, 60, - 228, - 9, - 114, - 248, 85, - 174, - 199, - 235, - 168, - 55, - 50, - 74, - 245, - 238, - 197, - 231, - 41, - 29, + 167, + 206, 105, - 17, + 217, + 58, + 252, + 171, + 186, + 10, + 178, + 43, + 98, + 100, + 166, 105, - 36, - 126, - 118, - 119, + 57, + 35, + 50, + 234, + 1, + 193, ], "type": "Buffer", }, @@ -311,81 +311,81 @@ exports[`InstanceDeployer returns canonical protocol contract 1`] = ` }, "instance": { "address": AztecAddress { - "asBigInt": 10674890382018500410451173831129216683967953609468942304388116555335197334423n, + "asBigInt": 6114335376419651312789291039592727379508607669159505474839878685584297937951n, "asBuffer": { "data": [ - 23, - 153, - 198, + 13, + 132, + 151, + 87, + 219, + 22, + 170, + 125, + 24, + 214, 26, - 161, - 4, - 48, + 196, + 234, + 97, + 72, + 134, + 120, + 220, + 253, + 85, 191, - 111, - 236, - 70, - 103, - 156, - 76, + 9, 183, + 18, 108, - 62, - 209, - 44, - 216, - 182, + 92, + 238, + 191, 231, - 62, - 215, - 56, - 157, - 90, - 226, - 150, - 173, - 27, - 151, + 81, + 204, + 31, ], "type": "Buffer", }, }, "contractClassId": Fr { - "asBigInt": 9040462806880011027940587321357143576447825874691049241890511565119666681463n, + "asBigInt": 19003838234876564894705716440306205769025681419911568720344156830131976536513n, "asBuffer": { "data": [ - 19, - 252, - 184, - 122, - 123, - 192, + 42, + 3, + 202, + 144, + 172, + 187, + 17, + 134, + 95, 60, - 228, - 9, - 114, - 248, 85, - 174, - 199, - 235, - 168, - 55, - 50, - 74, - 245, - 238, - 197, - 231, - 41, - 29, + 167, + 206, 105, - 17, + 217, + 58, + 252, + 171, + 186, + 10, + 178, + 43, + 98, + 100, + 166, 105, - 36, - 126, - 118, - 119, + 57, + 35, + 50, + 234, + 1, + 193, ], "type": "Buffer", }, diff --git a/yarn-project/protocol-contracts/src/instance-deployer/index.ts b/yarn-project/protocol-contracts/src/instance-deployer/index.ts index 9605acf2def..b6f5aa9e3cc 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/index.ts +++ b/yarn-project/protocol-contracts/src/instance-deployer/index.ts @@ -9,5 +9,5 @@ export function getCanonicalInstanceDeployer(): ProtocolContract { } export const InstanceDeployerAddress = AztecAddress.fromString( - '0x1799c61aa10430bf6fec46679c4cb76c3ed12cd8b6e73ed7389d5ae296ad1b97', + '0x0d849757db16aa7d18d61ac4ea61488678dcfd55bf09b7126c5ceebfe751cc1f', ); From 276f2891d74bdde8e29a855dd38ec45fe993c28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 16:04:03 +0000 Subject: [PATCH 06/17] Fix simulator tests --- yarn-project/simulator/src/client/simulator.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 0449969d275..48220f7119b 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -42,7 +42,7 @@ describe('Simulator', () => { const contractAddress = AztecAddress.random(); const nonce = Fr.random(); const storageSlot = Fr.random(); - const noteTypeId = Fr.random(); + const noteTypeId = new Fr(8411110710111078111116101n); // TokenNote const createNote = (amount = 123n) => new Note([new Fr(amount), owner.toField(), Fr.random()]); @@ -50,8 +50,8 @@ describe('Simulator', () => { oracle.getFunctionArtifactByName.mockResolvedValue(artifact); const note = createNote(); - const valueNoteHash = hashFields(note.items); - const innerNoteHash = hashFields([storageSlot, valueNoteHash]); + const tokenNoteHash = hashFields(note.items); + const innerNoteHash = hashFields([storageSlot, tokenNoteHash]); const siloedNoteHash = siloCommitment(contractAddress, innerNoteHash); const uniqueSiloedNoteHash = computeUniqueCommitment(nonce, siloedNoteHash); const innerNullifier = hashFields([ From 9688e2cab3b22cbd615f75d15bc24d2ceaecc8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 16:15:37 +0000 Subject: [PATCH 07/17] Extend serialized_note to 20 --- noir/aztec_macros/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index 926187a560c..b3e612ea626 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -51,7 +51,6 @@ impl MacroProcessor for AztecMacro { ) -> Result<(), (MacroError, FileId)> { transform_hir(crate_id, context).map_err(|(err, file_id)| (err.into(), file_id)) } - } const FUNCTION_TREE_HEIGHT: u32 = 5; @@ -1710,7 +1709,7 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> nonce: Field, storage_slot: Field, note_type_id: Field, - serialized_note: [Field; 12] + serialized_note: [Field; 20] ) -> pub [Field; 4] { [0, 0, 0, 0] }".to_string() @@ -1733,7 +1732,7 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> nonce: Field, storage_slot: Field, note_type_id: Field, - serialized_note: [Field; 12] + serialized_note: [Field; 20] ) -> pub [Field; 4] {{ let note_header = NoteHeader::new(contract_address, nonce, storage_slot); From 95f593e7457e7e8706cc8dd44a1926d1b3e2b88e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 16:21:35 +0000 Subject: [PATCH 08/17] Remove len imports --- boxes/blank/src/contracts/src/main.nr | 13 ------------- boxes/token/src/contracts/src/main.nr | 2 +- boxes/token/src/contracts/src/types/token_note.nr | 2 +- .../aztec-nr/value-note/src/balance_utils.nr | 2 +- .../contracts/benchmarking_contract/src/main.nr | 2 +- .../contracts/card_game_contract/src/cards.nr | 2 +- .../contracts/docs_example_contract/src/main.nr | 2 +- .../easy_private_token_contract/src/main.nr | 5 +---- .../contracts/ecdsa_account_contract/src/main.nr | 2 +- .../contracts/inclusion_proofs_contract/src/main.nr | 2 +- .../contracts/slow_tree_contract/src/main.nr | 2 +- .../contracts/test_contract/src/main.nr | 2 +- .../contracts/token_blacklist_contract/src/main.nr | 4 ++-- .../contracts/token_contract/src/main.nr | 2 +- 14 files changed, 14 insertions(+), 30 deletions(-) diff --git a/boxes/blank/src/contracts/src/main.nr b/boxes/blank/src/contracts/src/main.nr index d544c909a97..89c80306529 100644 --- a/boxes/blank/src/contracts/src/main.nr +++ b/boxes/blank/src/contracts/src/main.nr @@ -15,17 +15,4 @@ contract Blank { [pub_key.x, pub_key.y] } - - // A function which needs to be implemented by every contract working with storage. Replace it's content with your - // own logic once you start working with private storage. - // TODO: Remove this placeholder once https://github.com/AztecProtocol/aztec-packages/issues/2918 is implemented. - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 0] - ) -> pub [Field; 4] { - [0, 0, 0, 0] - } } diff --git a/boxes/token/src/contracts/src/main.nr b/boxes/token/src/contracts/src/main.nr index 5a5177de3f6..3c056a28ec0 100644 --- a/boxes/token/src/contracts/src/main.nr +++ b/boxes/token/src/contracts/src/main.nr @@ -41,7 +41,7 @@ contract Token { use crate::types::{ transparent_note::TransparentNote, - token_note::{TokenNote, TOKEN_NOTE_LEN}, + token_note::TokenNote, balances_map::BalancesMap }; // docs:end::imports diff --git a/boxes/token/src/contracts/src/types/token_note.nr b/boxes/token/src/contracts/src/types/token_note.nr index 7dfe681f395..95ccb9dc6ba 100644 --- a/boxes/token/src/contracts/src/types/token_note.nr +++ b/boxes/token/src/contracts/src/types/token_note.nr @@ -113,7 +113,7 @@ impl NoteInterface for TokenNote { fn get_note_type_id() -> Field { // TODO(#4519): autogenerate // python -c "print(int(''.join(str(ord(c)) for c in 'TokenNote')))" - 8411110710111078111116101 + F } } diff --git a/noir-projects/aztec-nr/value-note/src/balance_utils.nr b/noir-projects/aztec-nr/value-note/src/balance_utils.nr index 570f0cca729..6372d718902 100644 --- a/noir-projects/aztec-nr/value-note/src/balance_utils.nr +++ b/noir-projects/aztec-nr/value-note/src/balance_utils.nr @@ -1,6 +1,6 @@ use dep::aztec::note::{note_getter::view_notes, note_viewer_options::NoteViewerOptions}; use dep::aztec::state_vars::set::Set; -use crate::value_note::{VALUE_NOTE_LEN, ValueNote}; +use crate::value_note::ValueNote; unconstrained pub fn get_balance(set: Set) -> Field { get_balance_with_offset(set, 0) diff --git a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr index fb102d14266..86215deb334 100644 --- a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr @@ -5,7 +5,7 @@ // arise from code changes. contract Benchmarking { - use dep::value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote}}; + use dep::value_note::{utils::{increment, decrement}, value_note::ValueNote}; use dep::aztec::{ protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}, diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr index 9569a41b774..6b3e694768b 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -19,7 +19,7 @@ use dep::std::{ option::Option, }; use dep::value_note::{ - value_note::{ValueNote, VALUE_NOTE_LEN}, + value_note::ValueNote, }; struct Card { diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr index 534e51bb3c1..7c555eea3b5 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -30,7 +30,7 @@ contract DocsExample { // how to import methods from other files/folders within your workspace use crate::options::create_account_card_getter_options; use crate::types::{ - card_note::{CardNote, CARD_NOTE_LEN}, + card_note::CardNote, leader::Leader, }; diff --git a/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr index db812da9538..336bae7e326 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr @@ -12,10 +12,7 @@ contract EasyPrivateToken { }; use dep::value_note::{ balance_utils, - value_note::{ - ValueNote, - VALUE_NOTE_LEN, - }, + value_note::ValueNote, }; use dep::easy_private_state::easy_private_state::EasyPrivateUint; diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr index 22fb70e0475..d53117493fb 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr @@ -16,7 +16,7 @@ contract EcdsaAccount { auth_witness::get_auth_witness }; - use crate::ecdsa_public_key_note::{EcdsaPublicKeyNote, ECDSA_PUBLIC_KEY_NOTE_LEN}; + use crate::ecdsa_public_key_note::EcdsaPublicKeyNote; struct Storage { public_key: ImmutableSingleton, diff --git a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index db765d6d28b..eaaf052f99d 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -28,7 +28,7 @@ contract InclusionProofs { }; // docs:end:imports // docs:start:value_note_imports - use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; + use dep::value_note::value_note::ValueNote; // docs:end:value_note_imports struct Storage { private_values: Map>, diff --git a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr index 268f2a433ce..7950c230be8 100644 --- a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr @@ -8,7 +8,7 @@ mod types; contract SlowTree { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; use dep::std::option::Option; - use dep::value_note::{balance_utils, utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote}}; + use dep::value_note::{balance_utils, utils::{increment, decrement}, value_note::ValueNote}; use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, note::{note_header::NoteHeader, utils as note_utils}, diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index f20fa454926..ed935bf94fd 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -23,7 +23,7 @@ contract Test { }; use dep::token_portal_content_hash_lib::{get_mint_private_content_hash, get_mint_public_content_hash}; use dep::field_note::field_note::FieldNote; - use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; + use dep::value_note::value_note::ValueNote; #[event] struct ExampleEvent { diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index 39530b29f0f..92cb8dbab85 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -32,7 +32,7 @@ contract TokenBlacklist { state_vars::{map::Map, public_state::PublicState, set::Set, immutable_singleton::ImmutableSingleton}, }; - use dep::field_note::field_note::{FieldNote, FIELD_NOTE_LEN}; + use dep::field_note::field_note::FieldNote; use dep::authwit::{ auth::{ @@ -43,7 +43,7 @@ contract TokenBlacklist { use crate::types::{ transparent_note::TransparentNote, - token_note::{TokenNote, TOKEN_NOTE_LEN}, + token_note::TokenNote, balances_map::{BalancesMap}, roles::UserFlags, }; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index 5a5177de3f6..3c056a28ec0 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -41,7 +41,7 @@ contract Token { use crate::types::{ transparent_note::TransparentNote, - token_note::{TokenNote, TOKEN_NOTE_LEN}, + token_note::TokenNote, balances_map::BalancesMap }; // docs:end::imports From c908fdac1f8cb744d47c6c11016a7bea05917e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 16:45:02 +0000 Subject: [PATCH 09/17] Remove docs --- .../contracts/references/storage/main.md | 19 ------------------- .../resources/common_patterns/main.md | 11 ----------- .../writing_contracts/events/emit_event.md | 10 +--------- .../storage/define_storage.md | 8 -------- .../developers/debugging/aztecnr-errors.md | 10 ---------- .../aztecnr-getting-started.md | 10 ++-------- .../token_portal/withdrawing_to_l1.md | 7 ------- .../writing_private_voting_contract.md | 10 ---------- .../tutorials/writing_token_contract.md | 19 ------------------- docs/docs/misc/migration_notes.md | 8 ++++++++ .../nargo_fmt/tests/expected/contract.nr | 11 ----------- .../tooling/nargo_fmt/tests/input/contract.nr | 11 ----------- 12 files changed, 11 insertions(+), 123 deletions(-) diff --git a/docs/docs/developers/contracts/references/storage/main.md b/docs/docs/developers/contracts/references/storage/main.md index 6bc1f653915..f8260d0313f 100644 --- a/docs/docs/developers/contracts/references/storage/main.md +++ b/docs/docs/developers/contracts/references/storage/main.md @@ -129,8 +129,6 @@ contract Token { unconstrained fn balance_of_private(owner: AztecAddress) -> Field {} unconstrained fn balance_of_public(owner: AztecAddress) -> Field {} - - unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, serialized_note: [Field; VALUE_NOTE_LEN]) -> [Field; 4] {} } ``` @@ -193,8 +191,6 @@ Aztec transactions can pass data to Ethereum contracts through the rollup via th Unconstrained functions can be thought of as view functions from Solidity--they only return information from the contract storage or compute and return data without modifying contract storage. -The `compute_note_hash_and_nullifier` function allows contract devs to specify how to compute notes and nullifiers. This must be included in every contract because it depends on the storage slots, which are defined when we set up storage. - ## Contract dependencies Before we can implement the functions, we need set up the contract storage, and before we do that we need to import the appropriate dependencies. @@ -435,21 +431,6 @@ A getter function for checking the public balance of the provided Aztec account. #include_code balance_of_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -#### `compute_note_hash_and_nullifier` - -A getter function to compute the note hash and nullifier for notes in the contract's storage. - -This must be included in every contract because it depends on the storage slots, which are defined when we set up storage. - -#include_code compute_note_hash_and_nullifier /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - -:::danger -If your contract works with storage (has Storage struct defined), you **MUST** include a `compute_note_hash_and_nullifier` function. -If you don't yet have any private state variables defined put there a placeholder function: - -#include_code compute_note_hash_and_nullifier_placeholder /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust -::: - ## Compiling Now that the contract is complete, you can compile it with `aztec-nargo`. See the [Sandbox reference page](../../../sandbox/references/sandbox-reference.md) for instructions on setting it up. diff --git a/docs/docs/developers/contracts/resources/common_patterns/main.md b/docs/docs/developers/contracts/resources/common_patterns/main.md index 10af032bbef..51b733e2ef0 100644 --- a/docs/docs/developers/contracts/resources/common_patterns/main.md +++ b/docs/docs/developers/contracts/resources/common_patterns/main.md @@ -121,17 +121,6 @@ Hence, it's necessary to add a "randomness" field to your note to prevent such a #include_code address_note_def noir-projects/aztec-nr/address-note/src/address_note.nr rust -### Working with `compute_note_hash_and_nullifier()` - -Currently, if you have storage defined, the compiler will error if you don't have a `compute_note_hash_and_nullifier()` defined. Without this, the PXE can't process encrypted events and discover your notes. - -If your contract doesn't have anything to do with notes (e.g. operates solely in the public domain), you can do the following: -#include_code compute_note_hash_and_nullifier_placeholder /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust - -Otherwise, you need this method to help the PXE with processing your notes. In our [demo token contract](../../../tutorials/writing_token_contract.md#compute_note_hash_and_nullifier), we work with 2 kinds of notes: `ValueNote` and `TransparentNote`. Hence this method must define how to work with both: - -#include_code compute_note_hash_and_nullifier /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - ### L1 -- L2 interactions Refer to [Token Portal tutorial on bridging tokens between L1 and L2](../../../tutorials/token_portal/main.md) and/or [Uniswap tutorial that shows how to swap on L1 using funds on L2](../../../tutorials/uniswap/main.md). Both examples show how to: diff --git a/docs/docs/developers/contracts/writing_contracts/events/emit_event.md b/docs/docs/developers/contracts/writing_contracts/events/emit_event.md index 002f01284b4..0c4204b3d67 100644 --- a/docs/docs/developers/contracts/writing_contracts/events/emit_event.md +++ b/docs/docs/developers/contracts/writing_contracts/events/emit_event.md @@ -83,15 +83,7 @@ If the decryption is successful, the PXE will store the decrypted note inside a If the decryption fails, the specific log will be discarded. For the PXE to successfully process the decrypted note we need to compute the note's 'note hash' and 'nullifier'. -Aztec.nr enables smart contract developers to design custom notes, meaning developers can also customize how a note's note hash and nullifier should be computed. Because of this customizability, and because there will be a potentially-unlimited number of smart contracts deployed to Aztec, an PXE needs to be 'taught' how to compute the custom note hashes and nullifiers for a particular contract. Therefore, developers will need to implement a `compute_note_hash_and_nullifier` function inside their contracts. - -:::danger -If your contract works with storage (has Storage struct defined), you **MUST** include a `compute_note_hash_and_nullifier` function to allow PXE to process encrypted events. -::: - -Every time a new note is successfully decrypted, the PXE will expect the existence of a `compute_note_hash_and_nullifier` function, which must teach it how to correctly process the new note. - -#include_code compute_note_hash_and_nullifier /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +Aztec.nr enables smart contract developers to design custom notes, meaning developers can also customize how a note's note hash and nullifier should be computed. Because of this customizability, and because there will be a potentially-unlimited number of smart contracts deployed to Aztec, an PXE needs to be 'taught' how to compute the custom note hashes and nullifiers for a particular contract. This is done by a function called `compute_note_hash_and_nullifier`, which is automatically injected into every contract when compiled. ## Unencrypted Events diff --git a/docs/docs/developers/contracts/writing_contracts/storage/define_storage.md b/docs/docs/developers/contracts/writing_contracts/storage/define_storage.md index 74e555622a4..fabb2a27d8a 100644 --- a/docs/docs/developers/contracts/writing_contracts/storage/define_storage.md +++ b/docs/docs/developers/contracts/writing_contracts/storage/define_storage.md @@ -19,14 +19,6 @@ struct Storage { } ``` -:::danger -If your contract uses storage (has Storage struct defined), you **MUST** include a `compute_note_hash_and_nullifier` function to allow PXE to process encrypted events. See [encrypted events](../events/emit_event.md#successfully-process-the-encrypted-event) for more. - -If you don't yet have any private state variables defined you can use this placeholder function: - -#include_code compute_note_hash_and_nullifier_placeholder /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust -::: - Since Aztec.nr is written in Noir, which is state-less, we need to specify how the storage struct should be initialized to read and write data correctly. This is done by specifying an `init` function that is run in functions that rely on reading or altering the state variables. This `init` function must declare the Storage struct with an instantiation defining how variables are accessed and manipulated. The function MUST be called `init` for the Aztec.nr library to properly handle it (this will be relaxed in the future). ```rust diff --git a/docs/docs/developers/debugging/aztecnr-errors.md b/docs/docs/developers/debugging/aztecnr-errors.md index 5045e564c24..47ee1974597 100644 --- a/docs/docs/developers/debugging/aztecnr-errors.md +++ b/docs/docs/developers/debugging/aztecnr-errors.md @@ -14,16 +14,6 @@ aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_ You can learn more about dependencies and their paths [here](../contracts/resources/dependencies.md). -#### `compute_note_hash_and_nullifier function not found. Define it in your contract` - -Any smart contract that works with storage must include a [`compute_note_hash_and_nullifier`](https://github.com/AztecProtocol/aztec-packages/blob/6c20b45993ee9cbd319ab8351e2722e0c912f427/noir-projects/aztec-nr/aztec/src/note/utils.nr#L69) function to allow the PXE to process encrypted events. - -This is an example of this function in the token contract: - -#include_code compute_note_hash_and_nullifier noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - -This error may also show if the `compute_note_hash_and_nullifier` function is not correct or sits outside of the contract. - #### `backend has encountered an error` This is likely due to a version mismatch or bad install of barretenberg. Try [reinstalling nargo](../updating.md) or uninstalling barretenberg: diff --git a/docs/docs/developers/getting_started/aztecnr-getting-started.md b/docs/docs/developers/getting_started/aztecnr-getting-started.md index 90bc58654cf..474dfa3ba8c 100644 --- a/docs/docs/developers/getting_started/aztecnr-getting-started.md +++ b/docs/docs/developers/getting_started/aztecnr-getting-started.md @@ -120,13 +120,7 @@ The `increment` function works very similarly to the `constructor`, but instead ## Prevent double spending -Because our counters are private, the network can't directly verify if a note was spent or not, which could lead to double-spending. To solve this, we use a nullifier - a unique identifier generated from each spent note and its owner. Although this isn't really an issue in this simple smart contract, Aztec requires a contract that has any private functions to include this function. - -Add a new function into your contract as shown below: - -#include_code nullifier /noir-projects/noir-contracts/contracts/counter_contract/src/main.nr rust - -Here, we're computing both the note hash and the nullifier. The nullifier computation uses Aztec’s `compute_note_hash_and_nullifier` function, which takes details about the note's attributes eg contract address, nonce, storage slot, type id, and preimage. +Because our counters are private, the network can't directly verify if a note was spent or not, which could lead to double-spending. To solve this, we use a nullifier - a unique identifier generated from each spent note and its owner. Although this isn't really an issue in this simple smart contract, Aztec injects a special function called `compute_note_hash_and_nullifier` to determine these values for any given note produced by this contract. ## Getting a counter @@ -172,7 +166,7 @@ This will return something like this: ```bash ➜ counter aztec-cli get-accounts -Accounts found: +Accounts found: Address: 0x2fd4503a9b855a852272945df53d7173297c1469cceda31048b85118364b09a3 Public Key: 0x27c20118733174347b8082f578a7d8fb84b3ad38be293715eee8119ee5cd8a6d0d6b7d8124b37359663e75bcd2756f544a93b821a06f8e33fba68cc8029794d9 diff --git a/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md b/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md index cacc357bfe0..1af146666ce 100644 --- a/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md +++ b/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md @@ -60,13 +60,6 @@ We need a function that lets us read the token value. Paste this into `main.nr`: #include_code read_token /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust -And the `compute_note_hash_and_nullifier` required on every contract: - -```rust -#include_code compute_note_hash_and_nullifier_placeholder /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr raw -} -``` - ## Compile code Congratulations, you have written all the contracts we need for this tutorial! Now let's compile them. diff --git a/docs/docs/developers/tutorials/writing_private_voting_contract.md b/docs/docs/developers/tutorials/writing_private_voting_contract.md index 22d0b99406f..46766c3da23 100644 --- a/docs/docs/developers/tutorials/writing_private_voting_contract.md +++ b/docs/docs/developers/tutorials/writing_private_voting_contract.md @@ -163,16 +163,6 @@ Paste this function in your contract: Here, we are asserting that the `msg_sender()` is equal to the admin stored in public state. We have to create an `AztecAddress` type from the `msg_sender()` in order to do a direct comparison. -## compute_note_hash_and_nullifier - -Every Aztec contract that has storage must have a `compute_note_hash_and_nullifier()` function. If you try to compile without this function, you will get an error. This is explained in more detail [here](../contracts/resources/common_patterns/main.md#working-with-compute_note_hash_and_nullifier). - -At the end of the contract, paste this: - -#include_code compute_note_hash_and_nullifier noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr rust - -We can simply return `[0,0,0,0]` because we are not creating any notes in our contract. - ## Compiling and deploying The easiest way to compile the contract is with `aztec-nargo`. Run the following command in the directory with your Nargo.toml file: diff --git a/docs/docs/developers/tutorials/writing_token_contract.md b/docs/docs/developers/tutorials/writing_token_contract.md index 7a25ad513f5..7a0960f0f2d 100644 --- a/docs/docs/developers/tutorials/writing_token_contract.md +++ b/docs/docs/developers/tutorials/writing_token_contract.md @@ -129,8 +129,6 @@ contract Token { unconstrained fn balance_of_private(owner: AztecAddress) -> Field {} unconstrained fn balance_of_public(owner: AztecAddress) -> Field {} - - unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, note_type_id: Field, serialized_note: [Field; VALUE_NOTE_LEN]) -> [Field; 4] {} } ``` @@ -193,8 +191,6 @@ Aztec transactions can pass data to Ethereum contracts through the rollup via th Unconstrained functions can be thought of as view functions from Solidity--they only return information from the contract storage or compute and return data without modifying contract storage. -The `compute_note_hash_and_nullifier` function allows contract devs to specify how to compute notes and nullifiers. This must be included in every contract because it depends on the storage slots, which are defined when we set up storage. - ## Contract dependencies Before we can implement the functions, we need set up the contract storage, and before we do that we need to import the appropriate dependencies. @@ -435,21 +431,6 @@ A getter function for checking the public balance of the provided Aztec account. #include_code balance_of_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -#### `compute_note_hash_and_nullifier` - -A getter function to compute the note hash and nullifier for notes in the contract's storage. - -This must be included in every contract because it depends on the storage slots, which are defined when we set up storage. - -#include_code compute_note_hash_and_nullifier /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - -:::danger -If your contract works with storage (has Storage struct defined), you **MUST** include a `compute_note_hash_and_nullifier` function. -If you don't yet have any private state variables defined put there a placeholder function: - -#include_code compute_note_hash_and_nullifier_placeholder /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust -::: - ## Compiling Now that the contract is complete, you can compile it with `aztec-nargo`. See the [Sandbox reference page](../sandbox/references/sandbox-reference.md) for instructions on setting it up. diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index 326beddd8bb..6009c4d2809 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -6,6 +6,14 @@ keywords: [sandbox, cli, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. +## TBD + +### Autogenerate `compute_note_hash_and_nullifier` + +Historically developers have been required to include a `compute_note_hash_and_nullifier` function in each of their contracts. This function is now automatically generated, and all instances of it in contract code can be safely removed. + +It is possible to provide a user-defined implementation, in which case auto-generation will be skipped (though there are no known use cases for this). + ## 0.24.0 ### Introduce Note Type IDs diff --git a/noir/tooling/nargo_fmt/tests/expected/contract.nr b/noir/tooling/nargo_fmt/tests/expected/contract.nr index b80efeeb692..226667619f5 100644 --- a/noir/tooling/nargo_fmt/tests/expected/contract.nr +++ b/noir/tooling/nargo_fmt/tests/expected/contract.nr @@ -74,17 +74,6 @@ contract Benchmarking { fn broadcast(owner: Field) { emit_unencrypted_log(&mut context, storage.balances.at(owner).read()); } - - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - preimage: [Field; VALUE_NOTE_LEN] - ) -> [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) - } } // Uses the token bridge contract, which tells which input token we need to talk to and handles the exit funds to L1 diff --git a/noir/tooling/nargo_fmt/tests/input/contract.nr b/noir/tooling/nargo_fmt/tests/input/contract.nr index d10bfb745b6..f863a9dc955 100644 --- a/noir/tooling/nargo_fmt/tests/input/contract.nr +++ b/noir/tooling/nargo_fmt/tests/input/contract.nr @@ -70,17 +70,6 @@ contract Benchmarking { fn broadcast(owner: Field) { emit_unencrypted_log(&mut context, storage.balances.at(owner).read()); } - - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - preimage: [Field; VALUE_NOTE_LEN] - ) -> [Field; 4] { - let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) - } } // Uses the token bridge contract, which tells which input token we need to talk to and handles the exit funds to L1 From f4c70559ad4ac66bb816b26d9bae1b6ffbb1dc88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 16:54:45 +0000 Subject: [PATCH 10/17] Add some clarifying comments --- noir/aztec_macros/src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index b3e612ea626..cda52a0f2ec 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -1702,7 +1702,12 @@ fn generate_compute_note_hash_and_nullifier(note_types: &Vec) -> NoirFun } fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> String { + // TODO(#4649): The serialized_note parameter is a fixed-size array, but we don't know what length it should have. + // For now we hardcode it to 20, which is the same as MAX_NOTE_FIELDS_LENGTH. + if note_types.len() == 0 { + // TODO(#4520): Even if the contract does not include any notes, other parts of the stack expect for this + // function to exist, so we include a dummy version. We likely should error out here instead. " unconstrained fn compute_note_hash_and_nullifier( contract_address: AztecAddress, @@ -1714,6 +1719,9 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> [0, 0, 0, 0] }".to_string() } else { + // For contracts that include notes we do a simple if-else chain comparing note_type_id with the different + // get_note_type_id of each of the note types. + let if_statements: Vec = note_types.iter().map(|note_type| format!( "if (note_type_id == {0}::get_note_type_id()) {{ note_utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note) From 202d961f1a8ebbbd2da0b081b794070a8c2ee23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 16:55:48 +0000 Subject: [PATCH 11/17] Fix typo --- .../src/contracts/src/types/token_note.nr | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/boxes/token/src/contracts/src/types/token_note.nr b/boxes/token/src/contracts/src/types/token_note.nr index 95ccb9dc6ba..2be2ecb3e00 100644 --- a/boxes/token/src/contracts/src/types/token_note.nr +++ b/boxes/token/src/contracts/src/types/token_note.nr @@ -1,23 +1,9 @@ use dep::aztec::{ - protocol_types::{ - address::AztecAddress, - constants::MAX_READ_REQUESTS_PER_CALL - }, - note::{ - note_header::NoteHeader, - note_interface::NoteInterface, - utils::compute_note_hash_for_consumption, - }, - context::PrivateContext, - state_vars::set::Set, - log::emit_encrypted_log, - hash::pedersen_hash, -}; -use dep::aztec::oracle::{ - rand::rand, - nullifier_key::get_nullifier_secret_key, - get_public_key::get_public_key, + protocol_types::{address::AztecAddress, constants::MAX_READ_REQUESTS_PER_CALL}, + note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, + context::PrivateContext, state_vars::set::Set, log::emit_encrypted_log, hash::pedersen_hash }; +use dep::aztec::oracle::{rand::rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}; use dep::safe_math::SafeU120; use dep::std::option::Option; @@ -113,7 +99,7 @@ impl NoteInterface for TokenNote { fn get_note_type_id() -> Field { // TODO(#4519): autogenerate // python -c "print(int(''.join(str(ord(c)) for c in 'TokenNote')))" - F + 8411110710111078111116101 } } From 8282ab9d57a06ae3c54b76a9e8281d11cd692b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 17:02:30 +0000 Subject: [PATCH 12/17] Added comments about generalization --- noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs | 1 + noir/compiler/noirc_frontend/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 95f9a71a9b6..b10ca0f0769 100644 --- a/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -256,6 +256,7 @@ impl DefCollector { // Add the current crate to the collection of DefMaps context.def_maps.insert(crate_id, def_collector.def_map); + // TODO(#4653): generalize this function for macro_processor in ¯o_processors { macro_processor.process_unresolved_traits_impls(&crate_id, context, &def_collector.collected_traits_impls, &mut def_collector.collected_functions).unwrap_or_else( |(macro_err, file_id)| { diff --git a/noir/compiler/noirc_frontend/src/lib.rs b/noir/compiler/noirc_frontend/src/lib.rs index c92801439a0..55f5fb1ca40 100644 --- a/noir/compiler/noirc_frontend/src/lib.rs +++ b/noir/compiler/noirc_frontend/src/lib.rs @@ -76,6 +76,7 @@ pub mod macros_api { context: &HirContext, ) -> Result; + // TODO(#4653): generalize this function fn process_unresolved_traits_impls( &self, _crate_id: &CrateId, From 983fddcaecd3d50e76d43b3de7e484e94596139f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 18:06:43 +0000 Subject: [PATCH 13/17] Improve error handling --- noir/aztec_macros/src/lib.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index cda52a0f2ec..1b1f01233d0 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -1609,7 +1609,8 @@ fn inject_compute_note_hash_and_nullifier( collected_functions: &mut Vec, ) -> Result<(), (MacroError, FileId)> { // We first fetch modules in this crate which correspond to contracts, along with their file id. - let mut contract_module_file_ids: Vec<(LocalModuleId, FileId)> = context.def_map(crate_id).unwrap().modules().iter() + let contract_module_file_ids: Vec<(LocalModuleId, FileId)> = context.def_map(crate_id).expect("ICE: Missing crate in def_map") + .modules().iter() .filter(|(_, module)| module.is_contract) .map(|(idx, module)| (LocalModuleId(idx), module.location.file)) .collect(); @@ -1621,10 +1622,11 @@ fn inject_compute_note_hash_and_nullifier( panic!("Found multiple contracts in the same crate"); } - let (module_id, file_id) = contract_module_file_ids.pop().unwrap(); + let (module_id, file_id) = contract_module_file_ids[0]; // If compute_note_hash_and_nullifier is already defined by the user, we skip autogeneration in order to provide an // escape hatch for this mechanism. + // TODO(#4647): improve this diagnosis and error messaging. if collected_functions.iter().any(|coll_funcs_data| check_for_compute_note_hash_and_nullifier_definition(&coll_funcs_data.functions, module_id)) { return Ok(()); } @@ -1652,7 +1654,8 @@ fn inject_compute_note_hash_and_nullifier( // This crate's traits and impls have not yet been resolved, so we look for impls in unresolved_trait_impls. note_types.extend(unresolved_traits_impls.iter() - .filter(|trait_impl| trait_impl.trait_path.segments.last().unwrap().0.contents == "NoteInterface") + .filter(|trait_impl| + trait_impl.trait_path.segments.last().expect("ICE: empty trait_impl path").0.contents == "NoteInterface") .filter_map(|trait_impl| match &trait_impl.object_type.typ { UnresolvedTypeData::Named(path, _, _) => Some(path.segments.last().unwrap().0.contents.clone()), _ => None, @@ -1663,8 +1666,8 @@ fn inject_compute_note_hash_and_nullifier( // And inject the newly created function into the contract. - // We don't have a reasonable location for the source code of this autogenerated function, so we simply pass an - // empty span. This function should not produce errors anyway so this should not matter. + // TODO(#4373): We don't have a reasonable location for the source code of this autogenerated function, so we simply + // pass an empty span. This function should not produce errors anyway so this should not matter. let location = Location::new(Span::empty(0), file_id); // These are the same things the ModCollector does when collecting functions: we push the function to the @@ -1674,16 +1677,17 @@ fn inject_compute_note_hash_and_nullifier( let func_id = context.def_interner.push_empty_fn(); context.def_interner.push_function(func_id, &func.def, ModuleId { krate: *crate_id, local_id: module_id }, location); - let Ok(_) = context.def_map_mut(crate_id).unwrap() + context.def_map_mut(crate_id).unwrap() .modules_mut()[module_id.0] .declare_function( func.name_ident().clone(), func_id - ) - else { - panic!("Failed to declare the autogenerated compute_note_hash_and_nullifier function, likely due to a duplicate definition. This should not happen"); - }; + ).expect( + "Failed to declare the autogenerated compute_note_hash_and_nullifier function, likely due to a duplicate definition. See https://github.com/AztecProtocol/aztec-packages/issues/4647." + ); - collected_functions.iter_mut().find(|fns| fns.file_id == file_id).unwrap().push_fn(module_id, func_id, func.clone()); + collected_functions.iter_mut() + .find(|fns| fns.file_id == file_id).expect("ICE: no functions found in contract file") + .push_fn(module_id, func_id, func.clone()); Ok(()) } From 50fb8e4443dc7b3b3e7ad84771235822071d4d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 18:17:19 +0000 Subject: [PATCH 14/17] add fetch_struct_trait_impls --- noir/aztec_macros/src/lib.rs | 64 +++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index 1b1f01233d0..3587e590ab2 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -1624,7 +1624,7 @@ fn inject_compute_note_hash_and_nullifier( let (module_id, file_id) = contract_module_file_ids[0]; - // If compute_note_hash_and_nullifier is already defined by the user, we skip autogeneration in order to provide an + // If compute_note_hash_and_nullifier is already defined by the user, we skip auto-generation in order to provide an // escape hatch for this mechanism. // TODO(#4647): improve this diagnosis and error messaging. if collected_functions.iter().any(|coll_funcs_data| check_for_compute_note_hash_and_nullifier_definition(&coll_funcs_data.functions, module_id)) { @@ -1634,32 +1634,7 @@ fn inject_compute_note_hash_and_nullifier( // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the // contract might use. These are the types that implement the NoteInterface trait, which provides the // get_note_type_id function. - - let mut note_types: Vec = Vec::new(); - - // These note types can be declared in either external crates, or the contract's own crate. External crates have - // already been processed and resolved, but are available here via the NodeInterner. This is because the contract's - // crate is the last crate to be processed, after all of its dependencies. - for trait_impl_id in 0..(&context.def_interner.next_trait_impl_id()).0 { - let trait_impl = &context.def_interner.get_trait_implementation(TraitImplId(trait_impl_id)); - - if trait_impl.borrow().ident.0.contents == "NoteInterface" { - if let Type::Struct(s, _) = &trait_impl.borrow().typ { - note_types.push(s.borrow().name.0.contents.clone()); - } else { - panic!("Found impl for NoteInterface on non-Struct"); - } - } - } - - // This crate's traits and impls have not yet been resolved, so we look for impls in unresolved_trait_impls. - note_types.extend(unresolved_traits_impls.iter() - .filter(|trait_impl| - trait_impl.trait_path.segments.last().expect("ICE: empty trait_impl path").0.contents == "NoteInterface") - .filter_map(|trait_impl| match &trait_impl.object_type.typ { - UnresolvedTypeData::Named(path, _, _) => Some(path.segments.last().unwrap().0.contents.clone()), - _ => None, - })); + let note_types = fetch_struct_trait_impls(context, unresolved_traits_impls, "NoteInterface"); // We can now generate a version of compute_note_hash_and_nullifier tailored for the contract in this crate. let func = generate_compute_note_hash_and_nullifier(¬e_types); @@ -1692,6 +1667,41 @@ fn inject_compute_note_hash_and_nullifier( Ok(()) } +// Fetches the name of all structs that implement trait_name, both in the current crate and all of its dependencies. +fn fetch_struct_trait_impls( + context: &mut HirContext, + unresolved_traits_impls: &Vec, + trait_name: &str +) -> Vec { + let mut struct_typenames: Vec = Vec::new(); + + // These structs can be declared in either external crates or the current one. External crates that contain + // dependencies have already been processed and resolved, but are available here via the NodeInterner. Note that + // crates on which the current crate does not depend on may not have been processed, and will be ignored. + for trait_impl_id in 0..(&context.def_interner.next_trait_impl_id()).0 { + let trait_impl = &context.def_interner.get_trait_implementation(TraitImplId(trait_impl_id)); + + if trait_impl.borrow().ident.0.contents == *trait_name { + if let Type::Struct(s, _) = &trait_impl.borrow().typ { + struct_typenames.push(s.borrow().name.0.contents.clone()); + } else { + panic!("Found impl for {} on non-Struct", trait_name); + } + } + } + + // This crate's traits and impls have not yet been resolved, so we look for impls in unresolved_trait_impls. + struct_typenames.extend(unresolved_traits_impls.iter() + .filter(|trait_impl| + trait_impl.trait_path.segments.last().expect("ICE: empty trait_impl path").0.contents == *trait_name) + .filter_map(|trait_impl| match &trait_impl.object_type.typ { + UnresolvedTypeData::Named(path, _, _) => Some(path.segments.last().unwrap().0.contents.clone()), + _ => None, + })); + + struct_typenames +} + fn generate_compute_note_hash_and_nullifier(note_types: &Vec) -> NoirFunction { let function_source = generate_compute_note_hash_and_nullifier_source(note_types); From 0bc1d5b33842958ed52e076789ecc0f9bca3b056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 18:24:20 +0000 Subject: [PATCH 15/17] Add aztec dep check --- noir/aztec_macros/src/lib.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/noir/aztec_macros/src/lib.rs b/noir/aztec_macros/src/lib.rs index 3587e590ab2..a0a63d8a9a8 100644 --- a/noir/aztec_macros/src/lib.rs +++ b/noir/aztec_macros/src/lib.rs @@ -41,7 +41,11 @@ impl MacroProcessor for AztecMacro { unresolved_traits_impls: &Vec, collected_functions: &mut Vec, ) -> Result<(), (MacroError, FileId)> { - inject_compute_note_hash_and_nullifier(crate_id, context, unresolved_traits_impls, collected_functions) + if has_aztec_dependency(crate_id, context) { + inject_compute_note_hash_and_nullifier(crate_id, context, unresolved_traits_impls, collected_functions) + } else { + Ok(()) + } } fn process_typed_ast( @@ -320,15 +324,17 @@ fn check_for_aztec_dependency( crate_id: &CrateId, context: &HirContext, ) -> Result<(), (MacroError, FileId)> { - let crate_graph = &context.crate_graph[crate_id]; - let has_aztec_dependency = crate_graph.dependencies.iter().any(|dep| dep.as_name() == "aztec"); - if has_aztec_dependency { + if has_aztec_dependency(crate_id, context) { Ok(()) } else { - Err((AztecMacroError::AztecDepNotFound.into(), crate_graph.root_file_id)) + Err((AztecMacroError::AztecDepNotFound.into(), context.crate_graph[crate_id].root_file_id)) } } +fn has_aztec_dependency(crate_id: &CrateId, context: &HirContext) -> bool { + context.crate_graph[crate_id].dependencies.iter().any(|dep| dep.as_name() == "aztec") +} + // Check to see if the user has defined a storage struct fn check_for_storage_definition(module: &SortedModule) -> bool { module.types.iter().any(|r#struct| r#struct.name.0.contents == "Storage") From 52fcc5a234529d0f593811ac03e8544aeb68c06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 18:36:02 +0000 Subject: [PATCH 16/17] Add missing imports --- .../contracts/child_contract/src/main.nr | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr index 11a9dfa0414..9174b035484 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -3,22 +3,10 @@ contract Child { use dep::std::option::Option; use dep::aztec::{ - context::{PrivateContext, PublicContext, Context}, - log::emit_unencrypted_log, - state_vars::{ - public_state::PublicState, - set::Set - }, - protocol_types::{ - abis::{ - function_selector::FunctionSelector, - call_context::CallContext - }, - address::AztecAddress, - }, - note::{ - note_getter_options::NoteGetterOptions, - } + context::{PrivateContext, PublicContext, Context}, log::emit_unencrypted_log, + state_vars::{public_state::PublicState, set::Set}, + protocol_types::{abis::{function_selector::FunctionSelector, call_context::CallContext}, address::AztecAddress}, + note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader, utils as note_utils} }; use dep::value_note::value_note::ValueNote; From e56cf17daf2fd5f0a91d28f96510325f53379f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Fri, 16 Feb 2024 19:54:51 +0000 Subject: [PATCH 17/17] Fix proto circuit tests (again) --- .../__snapshots__/index.test.ts.snap | 300 ++++++++--------- .../src/class-registerer/index.ts | 2 +- .../__snapshots__/index.test.ts.snap | 308 +++++++++--------- .../src/instance-deployer/index.ts | 2 +- 4 files changed, 306 insertions(+), 306 deletions(-) diff --git a/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap index 779c773780e..763c59c36e7 100644 --- a/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap @@ -3,122 +3,122 @@ exports[`ClassRegisterer returns canonical protocol contract 1`] = ` { "address": AztecAddress { - "asBigInt": 18879165348792956523849879261898633134630135415990944739426750248408667290840n, + "asBigInt": 12165572618278205561135319266893715614363974000709547171863995507972204751528n, "asBuffer": { "data": [ - 41, - 189, - 58, - 154, - 80, - 221, - 75, + 26, + 229, + 120, + 87, + 210, + 210, + 52, + 118, + 43, + 74, + 102, + 9, + 134, + 217, + 77, + 250, + 54, + 27, + 6, + 163, + 9, + 77, + 124, + 119, 221, + 13, 19, - 197, - 63, - 198, - 221, - 136, - 25, - 100, - 190, - 50, - 192, - 64, - 34, - 232, - 215, - 204, - 105, - 110, - 25, - 72, - 184, - 50, - 124, - 216, + 48, + 120, + 81, + 106, + 168, ], "type": "Buffer", }, }, "contractClass": { "artifactHash": Fr { - "asBigInt": 10026203357347043763857861630754166863011605093072915309439432122921172595525n, + "asBigInt": 1364372310007692800585626333523730889923819928339145276751574119320046781646n, "asBuffer": { "data": [ - 22, - 42, - 161, - 71, - 156, - 116, + 3, 4, - 138, - 117, - 195, - 180, - 196, - 124, - 146, - 98, - 97, - 12, + 53, + 21, + 164, + 29, + 233, + 4, + 193, 147, - 67, - 131, - 237, - 163, - 102, - 130, - 82, - 161, - 229, + 128, + 246, + 235, + 216, + 242, + 66, + 55, + 97, + 55, + 80, + 84, + 212, + 24, + 60, + 24, + 13, + 127, + 108, + 77, + 239, + 196, 206, - 150, - 103, - 243, - 69, ], "type": "Buffer", }, }, "id": Fr { - "asBigInt": 15988644104676201200192077242461419082767909218193816497369696704044361007906n, + "asBigInt": 15823458103336768291861774407076060748007261259174556009564711604871953507490n, "asBuffer": { "data": [ - 35, + 34, + 251, + 194, + 137, + 56, + 109, + 23, 89, - 64, - 122, - 138, - 203, - 191, - 140, - 115, - 72, - 106, - 210, - 158, + 23, + 38, + 147, 215, - 154, - 180, - 169, - 216, - 155, - 63, - 82, - 29, 101, - 244, - 7, - 217, - 56, - 5, + 203, + 138, + 228, + 237, + 145, + 243, + 61, + 16, + 54, + 71, + 253, + 142, + 222, + 138, + 190, + 21, 41, - 123, - 67, - 34, + 228, + 162, ], "type": "Buffer", }, @@ -403,81 +403,81 @@ exports[`ClassRegisterer returns canonical protocol contract 1`] = ` }, "instance": { "address": AztecAddress { - "asBigInt": 18879165348792956523849879261898633134630135415990944739426750248408667290840n, + "asBigInt": 12165572618278205561135319266893715614363974000709547171863995507972204751528n, "asBuffer": { "data": [ - 41, - 189, - 58, - 154, - 80, - 221, - 75, + 26, + 229, + 120, + 87, + 210, + 210, + 52, + 118, + 43, + 74, + 102, + 9, + 134, + 217, + 77, + 250, + 54, + 27, + 6, + 163, + 9, + 77, + 124, + 119, 221, + 13, 19, - 197, - 63, - 198, - 221, - 136, - 25, - 100, - 190, - 50, - 192, - 64, - 34, - 232, - 215, - 204, - 105, - 110, - 25, - 72, - 184, - 50, - 124, - 216, + 48, + 120, + 81, + 106, + 168, ], "type": "Buffer", }, }, "contractClassId": Fr { - "asBigInt": 15988644104676201200192077242461419082767909218193816497369696704044361007906n, + "asBigInt": 15823458103336768291861774407076060748007261259174556009564711604871953507490n, "asBuffer": { "data": [ - 35, + 34, + 251, + 194, + 137, + 56, + 109, + 23, 89, - 64, - 122, - 138, - 203, - 191, - 140, - 115, - 72, - 106, - 210, - 158, + 23, + 38, + 147, 215, - 154, - 180, - 169, - 216, - 155, - 63, - 82, - 29, 101, - 244, - 7, - 217, - 56, - 5, + 203, + 138, + 228, + 237, + 145, + 243, + 61, + 16, + 54, + 71, + 253, + 142, + 222, + 138, + 190, + 21, 41, - 123, - 67, - 34, + 228, + 162, ], "type": "Buffer", }, diff --git a/yarn-project/protocol-contracts/src/class-registerer/index.ts b/yarn-project/protocol-contracts/src/class-registerer/index.ts index 217b158aff4..09d3cda26fc 100644 --- a/yarn-project/protocol-contracts/src/class-registerer/index.ts +++ b/yarn-project/protocol-contracts/src/class-registerer/index.ts @@ -13,5 +13,5 @@ export function getCanonicalClassRegisterer(): ProtocolContract { * @remarks This should not change often, hence we hardcode it to save from having to recompute it every time. */ export const ClassRegistererAddress = AztecAddress.fromString( - '0x29bd3a9a50dd4bdd13c53fc6dd881964be32c04022e8d7cc696e1948b8327cd8', + '0x1ae57857d2d234762b4a660986d94dfa361b06a3094d7c77dd0d133078516aa8', ); diff --git a/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap index 7de5c7e63f2..a30fc6c0ba0 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap @@ -3,122 +3,122 @@ exports[`InstanceDeployer returns canonical protocol contract 1`] = ` { "address": AztecAddress { - "asBigInt": 6114335376419651312789291039592727379508607669159505474839878685584297937951n, + "asBigInt": 3292754564016949916718877297115777598905061669834342030471417311460989046852n, "asBuffer": { "data": [ - 13, - 132, - 151, - 87, - 219, - 22, + 7, + 71, + 162, + 14, + 208, + 200, + 96, + 53, + 228, + 78, + 165, + 96, + 111, + 48, + 222, + 69, + 159, + 64, + 181, + 92, + 94, + 130, + 1, + 38, + 64, 170, - 125, - 24, - 214, - 26, - 196, - 234, - 97, - 72, - 134, - 120, - 220, - 253, 85, - 191, - 9, - 183, - 18, - 108, - 92, - 238, - 191, - 231, - 81, - 204, - 31, + 69, + 70, + 175, + 144, + 68, ], "type": "Buffer", }, }, "contractClass": { "artifactHash": Fr { - "asBigInt": 19070479700791057827478396638125001777177091043307328607370134174275317261568n, + "asBigInt": 14004623793815794786663172306952806542169300491436089583084017080489106515164n, "asBuffer": { "data": [ - 42, - 41, - 130, - 78, - 6, - 255, - 160, - 186, - 166, - 49, - 54, + 30, + 246, + 86, + 15, + 36, + 14, + 183, + 120, + 232, + 198, + 163, 244, - 6, - 126, - 146, - 222, - 76, - 236, - 179, - 56, - 209, - 21, - 19, - 124, - 178, - 51, - 251, - 148, - 238, - 47, - 229, - 0, + 175, + 96, + 159, + 150, + 221, + 22, + 123, + 72, + 71, + 20, + 2, + 134, + 20, + 176, + 2, + 23, + 9, + 248, + 164, + 220, ], "type": "Buffer", }, }, "id": Fr { - "asBigInt": 19003838234876564894705716440306205769025681419911568720344156830131976536513n, + "asBigInt": 18800681354736902372207149850261995699819228885238981092036778984892317144615n, "asBuffer": { "data": [ - 42, - 3, - 202, + 41, 144, - 172, - 187, - 17, - 134, - 95, - 60, - 85, - 167, 206, - 105, - 217, - 58, - 252, - 171, - 186, - 10, - 178, - 43, - 98, + 253, + 46, + 88, + 237, + 15, + 191, + 185, + 124, + 36, + 46, + 254, + 144, 100, - 166, - 105, - 57, - 35, - 50, - 234, - 1, - 193, + 66, + 216, + 236, + 181, + 113, + 20, + 163, + 159, + 75, + 11, + 21, + 162, + 80, + 133, + 150, + 39, ], "type": "Buffer", }, @@ -311,81 +311,81 @@ exports[`InstanceDeployer returns canonical protocol contract 1`] = ` }, "instance": { "address": AztecAddress { - "asBigInt": 6114335376419651312789291039592727379508607669159505474839878685584297937951n, + "asBigInt": 3292754564016949916718877297115777598905061669834342030471417311460989046852n, "asBuffer": { "data": [ - 13, - 132, - 151, - 87, - 219, - 22, + 7, + 71, + 162, + 14, + 208, + 200, + 96, + 53, + 228, + 78, + 165, + 96, + 111, + 48, + 222, + 69, + 159, + 64, + 181, + 92, + 94, + 130, + 1, + 38, + 64, 170, - 125, - 24, - 214, - 26, - 196, - 234, - 97, - 72, - 134, - 120, - 220, - 253, 85, - 191, - 9, - 183, - 18, - 108, - 92, - 238, - 191, - 231, - 81, - 204, - 31, + 69, + 70, + 175, + 144, + 68, ], "type": "Buffer", }, }, "contractClassId": Fr { - "asBigInt": 19003838234876564894705716440306205769025681419911568720344156830131976536513n, + "asBigInt": 18800681354736902372207149850261995699819228885238981092036778984892317144615n, "asBuffer": { "data": [ - 42, - 3, - 202, + 41, 144, - 172, - 187, - 17, - 134, - 95, - 60, - 85, - 167, 206, - 105, - 217, - 58, - 252, - 171, - 186, - 10, - 178, - 43, - 98, + 253, + 46, + 88, + 237, + 15, + 191, + 185, + 124, + 36, + 46, + 254, + 144, 100, - 166, - 105, - 57, - 35, - 50, - 234, - 1, - 193, + 66, + 216, + 236, + 181, + 113, + 20, + 163, + 159, + 75, + 11, + 21, + 162, + 80, + 133, + 150, + 39, ], "type": "Buffer", }, diff --git a/yarn-project/protocol-contracts/src/instance-deployer/index.ts b/yarn-project/protocol-contracts/src/instance-deployer/index.ts index b6f5aa9e3cc..5b4d71f37d6 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/index.ts +++ b/yarn-project/protocol-contracts/src/instance-deployer/index.ts @@ -9,5 +9,5 @@ export function getCanonicalInstanceDeployer(): ProtocolContract { } export const InstanceDeployerAddress = AztecAddress.fromString( - '0x0d849757db16aa7d18d61ac4ea61488678dcfd55bf09b7126c5ceebfe751cc1f', + '0x0747a20ed0c86035e44ea5606f30de459f40b55c5e82012640aa554546af9044', );