From e4d2df6b0b5592fe847e3c47020455ac8003d84d Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 10 Apr 2024 16:34:59 +0100 Subject: [PATCH] feat: separate nullfier_inclusion checks for private/public/avm (#5657) * Public stops using/accepting a Header or blockNumber. * I'm repurposing a `checkNullifierExists` oracle that was already defined in private/public. --- noir-projects/aztec-nr/aztec/src/context/avm_context.nr | 7 ++++--- noir-projects/aztec-nr/aztec/src/context/interface.nr | 1 + .../aztec-nr/aztec/src/context/public_context.nr | 7 +++++++ .../aztec-nr/aztec/src/history/nullifier_inclusion.nr | 8 ++------ noir-projects/aztec-nr/aztec/src/initializer.nr | 4 ++-- noir-projects/aztec-nr/aztec/src/oracle/notes.nr | 2 ++ .../contracts/avm_test_contract/src/main.nr | 2 +- .../contracts/inclusion_proofs_contract/src/main.nr | 2 +- .../simulator/src/public/public_execution_context.ts | 5 +++++ 9 files changed, 25 insertions(+), 13 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr index 8f7a0193349..7bb2872e6c0 100644 --- a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr @@ -52,9 +52,6 @@ impl AvmContext { pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool { l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1 } - pub fn nullifier_exists(self, nullifier: Field) -> bool { - nullifier_exists(nullifier) == 1 - } fn call_public_function_raw( self: &mut Self, @@ -106,6 +103,10 @@ impl PublicContextInterface for AvmContext { AztecAddress::zero() } + fn nullifier_exists(self, nullifier: Field) -> bool { + nullifier_exists(nullifier) == 1 + } + fn push_nullifier_read_request(&mut self, nullifier: Field) { assert(false, "'push_nullifier_read_request' not implemented!"); } diff --git a/noir-projects/aztec-nr/aztec/src/context/interface.nr b/noir-projects/aztec-nr/aztec/src/context/interface.nr index b6973e9e244..1a54cddf4ef 100644 --- a/noir-projects/aztec-nr/aztec/src/context/interface.nr +++ b/noir-projects/aztec-nr/aztec/src/context/interface.nr @@ -52,4 +52,5 @@ trait PublicContextInterface { function_selector: FunctionSelector, args: [Field; ARGS_COUNT] ) -> [Field; RETURN_VALUES_LENGTH]; + fn nullifier_exists(self, nullifier: Field) -> bool; } diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 46fbdc13ef9..c41d38986b3 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -220,6 +220,10 @@ impl PublicContextInterface for PublicContext { self.inputs.public_global_variables.fee_recipient } + fn nullifier_exists(self, nullifier: Field) -> bool { + nullifier_exists_oracle(nullifier) == 1 + } + fn push_nullifier_read_request(&mut self, nullifier: Field) { let request = ReadRequest { value: nullifier, counter: self.side_effect_counter }; self.nullifier_read_requests.push(request); @@ -302,3 +306,6 @@ impl PublicContextInterface for PublicContext { self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true) } } + +#[oracle(checkNullifierExists)] +fn nullifier_exists_oracle(nullifier: Field) -> Field {} diff --git a/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr index b047870a218..09d27840c88 100644 --- a/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr @@ -2,8 +2,7 @@ use dep::std::merkle::compute_merkle_root; use dep::protocol_types::header::Header; use crate::{ - context::{PrivateContext, ContextInterface}, - oracle::get_nullifier_membership_witness::get_nullifier_membership_witness, + context::PrivateContext, oracle::get_nullifier_membership_witness::get_nullifier_membership_witness, note::{utils::compute_siloed_nullifier, note_interface::NoteInterface} }; @@ -26,10 +25,7 @@ fn _nullifier_inclusion(nullifier: Field, header: Header) { // was included in the nullifier tree. } -pub fn prove_nullifier_inclusion( - nullifier: Field, - context: TContext -) where TContext: ContextInterface { +pub fn prove_nullifier_inclusion(nullifier: Field, context: PrivateContext) { _nullifier_inclusion(nullifier, context.get_header()); } diff --git a/noir-projects/aztec-nr/aztec/src/initializer.nr b/noir-projects/aztec-nr/aztec/src/initializer.nr index 023b37106e1..f0990a2a4f7 100644 --- a/noir-projects/aztec-nr/aztec/src/initializer.nr +++ b/noir-projects/aztec-nr/aztec/src/initializer.nr @@ -29,14 +29,14 @@ fn mark_as_initialized(context: &mut TContext) where TContext: Context pub fn assert_is_initialized_public(context: &mut PublicContext) { let init_nullifier = compute_contract_initialization_nullifier(context.this_address()); - prove_nullifier_inclusion(init_nullifier, *context); + assert(context.nullifier_exists(init_nullifier), "Not initialized"); } pub fn assert_is_initialized_avm(context: &mut AvmContext) { // WARNING: the AVM always expects UNSILOED nullifiers! // TODO(fcarreiro@): Change current private/public to take unsiloed nullifiers and an address. let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address()); - assert(context.nullifier_exists(init_nullifier)); + assert(context.nullifier_exists(init_nullifier), "Not initialized"); } pub fn assert_is_initialized_private(context: &mut PrivateContext) { diff --git a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr index d4c5d75eec6..18c3508e4d5 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr @@ -141,9 +141,11 @@ unconstrained pub fn get_notes( placeholder_opt_notes } +// Only ever use this in private! #[oracle(checkNullifierExists)] fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {} +// Only ever use this in private! unconstrained pub fn check_nullifier_exists(inner_nullifier: Field) -> bool { check_nullifier_exists_oracle(inner_nullifier) == 1 } 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 33a7d095cb7..1645be3c553 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 @@ -199,7 +199,7 @@ contract AvmTest { fn assert_unsiloed_nullifier_acvm(nullifier: Field) { // ACVM requires siloed nullifier. let siloed_nullifier = silo_nullifier(context.this_address(), nullifier); - prove_nullifier_inclusion(siloed_nullifier, context); + assert(context.nullifier_exists(siloed_nullifier)); } #[aztec(public-vm)] 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 6f3df9cf742..da02fa82a60 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 @@ -201,7 +201,7 @@ contract InclusionProofs { // Proves nullifier existed at latest block #[aztec(public)] fn test_nullifier_inclusion_from_public(nullifier: Field) { - prove_nullifier_inclusion(nullifier, context); + assert(context.nullifier_exists(nullifier)); } #[aztec(private)] diff --git a/yarn-project/simulator/src/public/public_execution_context.ts b/yarn-project/simulator/src/public/public_execution_context.ts index 08c07475c8d..0c395ef5afc 100644 --- a/yarn-project/simulator/src/public/public_execution_context.ts +++ b/yarn-project/simulator/src/public/public_execution_context.ts @@ -250,6 +250,11 @@ export class PublicExecutionContext extends TypedOracle { return await this.commitmentsDb.getNullifierMembershipWitnessAtLatestBlock(nullifier); } + public async checkNullifierExists(nullifier: Fr): Promise { + const witness = await this.commitmentsDb.getNullifierMembershipWitnessAtLatestBlock(nullifier); + return !!witness; + } + public async getContractInstance(address: AztecAddress): Promise { // Note to AVM implementor: The wrapper of the oracle call get_contract_instance in aztec-nr // automatically checks that the returned instance is correct, by hashing it together back