From 3acc686698853c8add5af6602411bed798922783 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 22 Apr 2024 17:11:28 +0000 Subject: [PATCH 001/125] Initial --- noir-projects/aztec-nr/aztec/src/keys.nr | 3 + .../src/keys/assert_public_key_freshness.nr | 90 +++++++++++++++++++ noir-projects/aztec-nr/aztec/src/lib.nr | 1 + noir-projects/aztec-nr/aztec/src/oracle.nr | 1 + .../aztec-nr/aztec/src/oracle/keys.nr | 24 +++++ .../contracts/test_contract/src/main.nr | 2 +- .../pxe/src/simulator_oracle/index.ts | 10 +++ .../simulator/src/acvm/oracle/oracle.ts | 9 ++ .../simulator/src/acvm/oracle/typed_oracle.ts | 8 +- .../simulator/src/client/db_oracle.ts | 4 +- .../simulator/src/client/view_data_oracle.ts | 6 ++ 11 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 noir-projects/aztec-nr/aztec/src/keys.nr create mode 100644 noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr create mode 100644 noir-projects/aztec-nr/aztec/src/oracle/keys.nr diff --git a/noir-projects/aztec-nr/aztec/src/keys.nr b/noir-projects/aztec-nr/aztec/src/keys.nr new file mode 100644 index 00000000000..ae78c653dd0 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/keys.nr @@ -0,0 +1,3 @@ +mod assert_public_key_freshness; + +use crate::keys::assert_public_key_freshness::Map; diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr new file mode 100644 index 00000000000..f94806c935d --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr @@ -0,0 +1,90 @@ +use dep::protocol_types::{constants::{GENERATOR_INDEX__PUBLIC_KEYS_HASH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, address::AztecAddress}; +use crate::context::PrivateContext; +use crate::note::{ + constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH}, + note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder, Comparator, NoteStatus, PropertySelector}, + note_interface::NoteInterface, note_viewer_options::NoteViewerOptions, + utils::compute_note_hash_for_consumption, +}; +use crate::state_vars::shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter; +use crate::hash::pedersen_hash; +use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; +use crate::oracle; + + +fn assert_nullifier_public_key_fresh( + context: &mut PrivateContext, + address: AztecAddress, + nullifier_public_key_to_test: Field +) { + // Canonical Key Registry + let contract_address_to_read = AztecAddress::from_field(123); + let storage_slot_of_nullifier_public_key = 1; + // We have to derive this slot to get the location of the shared mutable inside the Map + let derived_slot = pedersen_hash( + [storage_slot_of_nullifier_public_key, address.to_field()], + 0 + ); + + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, contract_address_to_read, derived_slot); + let nullifier_public_key = registry_private_getter.get_current_value_in_private(); + + if (nullifier_public_key == 0) { + check_key(address, 1, nullifier_public_key_to_test); + } else { + assert(nullifier_public_key == nullifier_public_key_to_test); + } +} + +fn check_key(address: AztecAddress, key_type: Field, key: Field) { + let mut keys = check_key_internal(address); + + keys[key_type] = key; + + _check_key_constrain_check_key_internal( + address, + keys[0], + keys[1], + keys[2], + keys[3], + keys[4], + ); +} + +unconstrained fn check_key_internal(address: AztecAddress) -> [Field; 5] { + let keys = oracle::keys::get_public_keys_for_address(address); + + keys +} + +fn _check_key_constrain_check_key_internal( + address: AztecAddress, + partial_address: Field, + nullifier_public_key: Field, + incoming_public_key: Field, + outgoing_public_key: Field, + tagging_public_key: Field + ) { + let public_keys_hash = poseidon2_hash([ + nullifier_public_key, + incoming_public_key, + outgoing_public_key, + tagging_public_key, + GENERATOR_INDEX__PUBLIC_KEYS_HASH, + ], + 5 + ); + + let computed_address = AztecAddress::from_field( + poseidon2_hash([ + partial_address.to_field(), + public_keys_hash.to_field(), + GENERATOR_INDEX__CONTRACT_ADDRESS_V1 as Field, + ], + 3 + ) + ); + + assert(computed_address.eq(address), "Computed address does not match supplied address"); +} diff --git a/noir-projects/aztec-nr/aztec/src/lib.nr b/noir-projects/aztec-nr/aztec/src/lib.nr index 81390fb52eb..67a3c8c55b4 100644 --- a/noir-projects/aztec-nr/aztec/src/lib.nr +++ b/noir-projects/aztec-nr/aztec/src/lib.nr @@ -3,6 +3,7 @@ mod deploy; mod hash; mod history; mod initializer; +mod keys; mod log; mod messaging; mod note; diff --git a/noir-projects/aztec-nr/aztec/src/oracle.nr b/noir-projects/aztec-nr/aztec/src/oracle.nr index 57415dc9575..41c6e37adfb 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle.nr @@ -10,6 +10,7 @@ mod get_nullifier_membership_witness; mod get_public_data_witness; mod get_membership_witness; mod get_public_key; +mod keys; mod nullifier_key; mod get_sibling_path; mod unsafe_rand; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr new file mode 100644 index 00000000000..6894ccab3b0 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -0,0 +1,24 @@ +use dep::protocol_types::address::AztecAddress; + +#[oracle(getPublicKeysForAddress)] +fn get_public_keys_for_address_oracle( + address: AztecAddress, +) -> [Field; 4] {} + +unconstrained fn get_public_keys_for_address_oracle_wrapper( + address: AztecAddress +) -> [Field; 4] { + get_public_keys_for_address_oracle( + address, + ) +} + +unconstrained pub fn get_public_keys_for_address( + address: AztecAddress, +) -> [Field; 4] { + let public_keys = get_public_keys_for_address_oracle_wrapper( + address, + ); + + public_keys +} 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 43a0d80c528..d03ef87095d 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -389,7 +389,7 @@ contract Test { 0 ); // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, derived_slot); + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, derived_slot); let nullifier_public_key = registry_private_getter.get_current_value_in_private(); context.emit_unencrypted_log(nullifier_public_key); diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index da0891190f6..ea9b08a033e 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -9,6 +9,7 @@ import { type SiblingPath, } from '@aztec/circuit-types'; import { + Point, type AztecAddress, type CompleteAddress, type EthAddress, @@ -78,6 +79,15 @@ export class SimulatorOracle implements DBOracle { return capsule; } + async getPublicKeysForAddress(address: AztecAddress): Promise { + const nullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(address); + const incomingViewingPublicKey = await this.keyStore.getMasterIncomingViewingPublicKey(address); + const outgoingViewingPublicKey = await this.keyStore.getMasterOutgoingViewingPublicKey(address); + const taggingPublicKey = await this.keyStore.getMasterTaggingPublicKey(address); + + return [nullifierPublicKey, incomingViewingPublicKey, outgoingViewingPublicKey, taggingPublicKey] + } + async getNotes(contractAddress: AztecAddress, storageSlot: Fr, status: NoteStatus) { const noteDaos = await this.db.getNotes({ contractAddress, diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index f1271b791dd..fa0dbc6a149 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -172,6 +172,15 @@ export class Oracle { return capsule.map(toACVMField); } + async getPublicKeysForAddress( + [address]: ACVMField[], + ): Promise { + const keys = await this.typedOracle.getPublicKeysForAddress(AztecAddress.fromField(fromACVMField(address))); + const acvmKeys = keys?.flatMap(key => key.toFields().map(f => toACVMField(f))) ?? Array(8).fill(toACVMField(0)); + + return acvmKeys; + } + async getNotes( [storageSlot]: ACVMField[], [numSelects]: ACVMField[], diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 70f57233af1..28ed6f9d4a1 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -17,7 +17,7 @@ import { } from '@aztec/circuits.js'; import { type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr } from '@aztec/foundation/fields'; +import { Fr, Point } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; /** Nullifier keys which both correspond to the same master nullifier secret key. */ @@ -140,6 +140,12 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('popCapsule'); } + getPublicKeysForAddress( + _address: AztecAddress, + ): Promise { + throw new OracleMethodNotAvailableError('getPublicKeysForAddress'); + } + getNotes( _storageSlot: Fr, _numSelects: number, diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 3c3d5126814..3e193b56472 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -9,7 +9,7 @@ import { type CompleteAddress, type Header } from '@aztec/circuits.js'; import { type FunctionArtifactWithDebugMetadata, type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { type EthAddress } from '@aztec/foundation/eth-address'; -import { type Fr } from '@aztec/foundation/fields'; +import { Point, type Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; import { type NoteData, type NullifierKeys } from '../acvm/index.js'; @@ -65,6 +65,8 @@ export interface DBOracle extends CommitmentsDB { */ popCapsule(): Promise; + getPublicKeysForAddress(address: AztecAddress): Promise; + /** * Retrieve nullifier keys associated with a specific account and app/contract address. * diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index b4c02039175..00bb685e8c8 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -166,6 +166,12 @@ export class ViewDataOracle extends TypedOracle { return this.db.popCapsule(); } + public override getPublicKeysForAddress( + address: AztecAddress, + ) { + return this.db.getPublicKeysForAddress(address); + } + /** * Gets some notes for a contract address and storage slot. * Returns a flattened array containing filtered notes. From 177445f1b16b6e9d1a0c31c30c9d588b9c1ad62a Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 22 Apr 2024 19:09:35 +0000 Subject: [PATCH 002/125] fix --- .../src/keys/assert_public_key_freshness.nr | 43 +++++++++++-------- .../aztec-nr/aztec/src/oracle/keys.nr | 31 +++++++++++-- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr index f94806c935d..a48175d30ce 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{constants::{GENERATOR_INDEX__PUBLIC_KEYS_HASH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, address::AztecAddress}; +use dep::protocol_types::{constants::{GENERATOR_INDEX__PUBLIC_KEYS_HASH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, address::AztecAddress, grumpkin_point::GrumpkinPoint}; use crate::context::PrivateContext; use crate::note::{ constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH}, @@ -15,7 +15,7 @@ use crate::oracle; fn assert_nullifier_public_key_fresh( context: &mut PrivateContext, address: AztecAddress, - nullifier_public_key_to_test: Field + nullifier_public_key_to_test: GrumpkinPoint, ) { // Canonical Key Registry let contract_address_to_read = AztecAddress::from_field(123); @@ -28,52 +28,57 @@ fn assert_nullifier_public_key_fresh( // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, contract_address_to_read, derived_slot); - let nullifier_public_key = registry_private_getter.get_current_value_in_private(); + let hashed_nullifier_public_key = registry_private_getter.get_current_value_in_private(); - if (nullifier_public_key == 0) { + if (hashed_nullifier_public_key == 0) { check_key(address, 1, nullifier_public_key_to_test); } else { - assert(nullifier_public_key == nullifier_public_key_to_test); + assert(hashed_nullifier_public_key == pedersen_hash(nullifier_public_key_to_test.serialize(), 0)); } } -fn check_key(address: AztecAddress, key_type: Field, key: Field) { - let mut keys = check_key_internal(address); +fn check_key(address: AztecAddress, key_type: Field, key: GrumpkinPoint) { + let mut (partial_address, keys) = check_key_internal(address); keys[key_type] = key; _check_key_constrain_check_key_internal( address, + partial_address, keys[0], keys[1], keys[2], keys[3], - keys[4], ); } -unconstrained fn check_key_internal(address: AztecAddress) -> [Field; 5] { +unconstrained fn check_key_internal(address: AztecAddress) -> (Field, [GrumpkinPoint; 4]) { let keys = oracle::keys::get_public_keys_for_address(address); + let partial_address = oracle::keys::get_address_metadata(address); - keys + (partial_address, keys) } fn _check_key_constrain_check_key_internal( address: AztecAddress, partial_address: Field, - nullifier_public_key: Field, - incoming_public_key: Field, - outgoing_public_key: Field, - tagging_public_key: Field + nullifier_public_key: GrumpkinPoint, + incoming_public_key: GrumpkinPoint, + outgoing_public_key: GrumpkinPoint, + tagging_public_key: GrumpkinPoint ) { let public_keys_hash = poseidon2_hash([ - nullifier_public_key, - incoming_public_key, - outgoing_public_key, - tagging_public_key, + nullifier_public_key.serialize()[0], + nullifier_public_key.serialize()[1], + incoming_public_key.serialize()[0], + incoming_public_key.serialize()[1], + outgoing_public_key.serialize()[0], + outgoing_public_key.serialize()[1], + tagging_public_key.serialize()[0], + tagging_public_key.serialize()[1], GENERATOR_INDEX__PUBLIC_KEYS_HASH, ], - 5 + 9 ); let computed_address = AztecAddress::from_field( diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 6894ccab3b0..44bb1cf5b96 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -1,13 +1,13 @@ -use dep::protocol_types::address::AztecAddress; +use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}; #[oracle(getPublicKeysForAddress)] fn get_public_keys_for_address_oracle( address: AztecAddress, -) -> [Field; 4] {} +) -> [GrumpkinPoint; 4] {} unconstrained fn get_public_keys_for_address_oracle_wrapper( address: AztecAddress -) -> [Field; 4] { +) -> [GrumpkinPoint; 4] { get_public_keys_for_address_oracle( address, ) @@ -15,10 +15,33 @@ unconstrained fn get_public_keys_for_address_oracle_wrapper( unconstrained pub fn get_public_keys_for_address( address: AztecAddress, -) -> [Field; 4] { +) -> [GrumpkinPoint; 4] { let public_keys = get_public_keys_for_address_oracle_wrapper( address, ); public_keys } + +#[oracle(getAddressMetadata)] +fn get_address_metadata_oracle( + address: AztecAddress, +) -> [Field; 1] {} + +unconstrained fn get_address_metadata_oracle_wrapper( + address: AztecAddress +) -> [Field; 1] { + get_address_metadata_oracle( + address, + ) +} + +unconstrained pub fn get_address_metadata( + address: AztecAddress, +) -> Field { + let partial_address = get_address_metadata_oracle_wrapper( + address, + ); + + partial_address[0] +} From fdbb60a11942d5c8472f73e5e596ef48a5657cc3 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 22 Apr 2024 20:55:26 +0000 Subject: [PATCH 003/125] good --- noir-projects/aztec-nr/aztec/src/keys.nr | 2 +- .../src/keys/assert_public_key_freshness.nr | 13 ++++--- .../aztec-nr/aztec/src/oracle/keys.nr | 36 +++++++++---------- yarn-project/circuit-types/src/keys/index.ts | 1 + yarn-project/key-store/src/address_book.ts | 25 +++++++++++++ yarn-project/key-store/src/index.ts | 1 + .../pxe/src/simulator_oracle/index.ts | 2 +- .../simulator/src/acvm/oracle/oracle.ts | 15 ++++---- .../simulator/src/acvm/oracle/typed_oracle.ts | 6 ++++ .../simulator/src/client/db_oracle.ts | 2 ++ 10 files changed, 70 insertions(+), 33 deletions(-) create mode 100644 yarn-project/key-store/src/address_book.ts diff --git a/noir-projects/aztec-nr/aztec/src/keys.nr b/noir-projects/aztec-nr/aztec/src/keys.nr index ae78c653dd0..7e83884a099 100644 --- a/noir-projects/aztec-nr/aztec/src/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/keys.nr @@ -1,3 +1,3 @@ mod assert_public_key_freshness; -use crate::keys::assert_public_key_freshness::Map; +use crate::keys::assert_public_key_freshness::assert_nullifier_public_key_fresh; diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr index a48175d30ce..80f218ce3bd 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{constants::{GENERATOR_INDEX__PUBLIC_KEYS_HASH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, address::AztecAddress, grumpkin_point::GrumpkinPoint}; +use dep::protocol_types::{constants::{GENERATOR_INDEX__PUBLIC_KEYS_HASH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint}; use crate::context::PrivateContext; use crate::note::{ constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH}, @@ -40,7 +40,7 @@ fn assert_nullifier_public_key_fresh( fn check_key(address: AztecAddress, key_type: Field, key: GrumpkinPoint) { let mut (partial_address, keys) = check_key_internal(address); - keys[key_type] = key; + assert(keys[key_type].eq(key)); _check_key_constrain_check_key_internal( address, @@ -52,16 +52,15 @@ fn check_key(address: AztecAddress, key_type: Field, key: GrumpkinPoint) { ); } -unconstrained fn check_key_internal(address: AztecAddress) -> (Field, [GrumpkinPoint; 4]) { - let keys = oracle::keys::get_public_keys_for_address(address); - let partial_address = oracle::keys::get_address_metadata(address); +unconstrained fn check_key_internal(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { + let (partial_address, public_keys) = oracle::keys::get_public_keys_and_partial_address(address); - (partial_address, keys) + (partial_address, public_keys) } fn _check_key_constrain_check_key_internal( address: AztecAddress, - partial_address: Field, + partial_address: PartialAddress, nullifier_public_key: GrumpkinPoint, incoming_public_key: GrumpkinPoint, outgoing_public_key: GrumpkinPoint, diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 44bb1cf5b96..4ff757be4d4 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}; +use dep::protocol_types::{address::{AztecAddress, PartialAddress, PublicKeysHash}, grumpkin_point::GrumpkinPoint}; #[oracle(getPublicKeysForAddress)] fn get_public_keys_for_address_oracle( @@ -23,25 +23,25 @@ unconstrained pub fn get_public_keys_for_address( public_keys } -#[oracle(getAddressMetadata)] -fn get_address_metadata_oracle( - address: AztecAddress, -) -> [Field; 1] {} -unconstrained fn get_address_metadata_oracle_wrapper( - address: AztecAddress -) -> [Field; 1] { - get_address_metadata_oracle( - address, - ) +#[oracle(getPublicKeysAndPartialAddress)] +fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 9] {} + +unconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: AztecAddress) -> [Field; 9] { + get_public_keys_and_partial_address_oracle(address) } -unconstrained pub fn get_address_metadata( - address: AztecAddress, -) -> Field { - let partial_address = get_address_metadata_oracle_wrapper( - address, - ); +pub fn get_public_keys_and_partial_address(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { + let result = get_public_keys_and_partial_address_oracle_wrapper(address); + let partial_address = PartialAddress::from_field(result[0]); + let nullifier_pub_key = GrumpkinPoint::new(result[1], result[2]); + let incoming_pub_key = GrumpkinPoint::new(result[3], result[4]); + let outgoing_pub_key = GrumpkinPoint::new(result[5], result[6]); + let tagging_pub_key = GrumpkinPoint::new(result[7], result[8]); + + // TODO(#5830): disabling the following constraint until we update the oracle according to the new key scheme + // let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address); + // assert(calculated_address.eq(address)); - partial_address[0] + (partial_address, [nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key]) } diff --git a/yarn-project/circuit-types/src/keys/index.ts b/yarn-project/circuit-types/src/keys/index.ts index f137b0d567a..02ea81b3bcc 100644 --- a/yarn-project/circuit-types/src/keys/index.ts +++ b/yarn-project/circuit-types/src/keys/index.ts @@ -1,2 +1,3 @@ export * from './key_pair.js'; export * from './key_store.js'; +export * from './address_book.js'; diff --git a/yarn-project/key-store/src/address_book.ts b/yarn-project/key-store/src/address_book.ts new file mode 100644 index 00000000000..8264007f396 --- /dev/null +++ b/yarn-project/key-store/src/address_book.ts @@ -0,0 +1,25 @@ +import { + Fr, + type AztecAddress, + type PartialAddress, +} from '@aztec/circuits.js'; +import { type AddressBook } from '@aztec/circuit-types'; +import { AztecKVStore, AztecMap } from '@aztec/kv-store'; + + +export class KVAddressBook implements AddressBook { + #addressMetadata: AztecMap; + + constructor(database: AztecKVStore) { + this.#addressMetadata = database.openMap('address_book'); + } + + public async addPartialAddress(partialAddress: PartialAddress, address: AztecAddress) { + await this.#addressMetadata.set(address.toString(), partialAddress.toBuffer()); + } + + getPartialAddress(address: AztecAddress): PartialAddress | undefined { + const partialBuf = this.#addressMetadata.get(address.toString()); + return partialBuf === undefined ? undefined : Fr.fromBuffer(partialBuf); + }; +} \ No newline at end of file diff --git a/yarn-project/key-store/src/index.ts b/yarn-project/key-store/src/index.ts index e4ae5ce271c..4f06a44db34 100644 --- a/yarn-project/key-store/src/index.ts +++ b/yarn-project/key-store/src/index.ts @@ -1 +1,2 @@ export * from './test_key_store.js'; +export * from './address_book.js'; diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index ea9b08a033e..56c53a2d806 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -9,11 +9,11 @@ import { type SiblingPath, } from '@aztec/circuit-types'; import { + Fr, Point, type AztecAddress, type CompleteAddress, type EthAddress, - type Fr, type FunctionSelector, type Header, type L1_TO_L2_MSG_TREE_HEIGHT, diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index fa0dbc6a149..02f820666fd 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -53,6 +53,7 @@ export class Oracle { ]; } + // TODO (ek): Nuke this async getPublicKeyAndPartialAddress([address]: ACVMField[]) { const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddress( AztecAddress.fromField(fromACVMField(address)), @@ -172,13 +173,15 @@ export class Oracle { return capsule.map(toACVMField); } - async getPublicKeysForAddress( - [address]: ACVMField[], - ): Promise { - const keys = await this.typedOracle.getPublicKeysForAddress(AztecAddress.fromField(fromACVMField(address))); - const acvmKeys = keys?.flatMap(key => key.toFields().map(f => toACVMField(f))) ?? Array(8).fill(toACVMField(0)); + async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { + const { partialAddress } = await this.typedOracle.getCompleteAddress( + AztecAddress.fromField(fromACVMField(address)), + ); + + const publicKeys = await this.typedOracle.getPublicKeysForAddress(AztecAddress.fromField(fromACVMField(address))); + const acvmKeys = publicKeys?.flatMap(key => key.toFields()) ?? Array(8).fill(toACVMField(0)); - return acvmKeys; + return [partialAddress, ...acvmKeys].map(toACVMField); } async getNotes( diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 28ed6f9d4a1..86b3d5d6439 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -146,6 +146,12 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getPublicKeysForAddress'); } + async getAddressMetadata( + _address: AztecAddress, + ): Promise { + throw new OracleMethodNotAvailableError('getAddressMetadata'); + } + getNotes( _storageSlot: Fr, _numSelects: number, diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 3e193b56472..b8d56098703 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -67,6 +67,8 @@ export interface DBOracle extends CommitmentsDB { getPublicKeysForAddress(address: AztecAddress): Promise; + getAddressMetadata(address: AztecAddress): Promise; + /** * Retrieve nullifier keys associated with a specific account and app/contract address. * From 2d3a95f66de8c88538480f8f1bb1a75223490f90 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 22 Apr 2024 20:58:38 +0000 Subject: [PATCH 004/125] asdf --- yarn-project/circuit-types/src/keys/index.ts | 1 - yarn-project/key-store/src/address_book.ts | 25 -------------------- yarn-project/key-store/src/index.ts | 1 - 3 files changed, 27 deletions(-) delete mode 100644 yarn-project/key-store/src/address_book.ts diff --git a/yarn-project/circuit-types/src/keys/index.ts b/yarn-project/circuit-types/src/keys/index.ts index 02ea81b3bcc..f137b0d567a 100644 --- a/yarn-project/circuit-types/src/keys/index.ts +++ b/yarn-project/circuit-types/src/keys/index.ts @@ -1,3 +1,2 @@ export * from './key_pair.js'; export * from './key_store.js'; -export * from './address_book.js'; diff --git a/yarn-project/key-store/src/address_book.ts b/yarn-project/key-store/src/address_book.ts deleted file mode 100644 index 8264007f396..00000000000 --- a/yarn-project/key-store/src/address_book.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { - Fr, - type AztecAddress, - type PartialAddress, -} from '@aztec/circuits.js'; -import { type AddressBook } from '@aztec/circuit-types'; -import { AztecKVStore, AztecMap } from '@aztec/kv-store'; - - -export class KVAddressBook implements AddressBook { - #addressMetadata: AztecMap; - - constructor(database: AztecKVStore) { - this.#addressMetadata = database.openMap('address_book'); - } - - public async addPartialAddress(partialAddress: PartialAddress, address: AztecAddress) { - await this.#addressMetadata.set(address.toString(), partialAddress.toBuffer()); - } - - getPartialAddress(address: AztecAddress): PartialAddress | undefined { - const partialBuf = this.#addressMetadata.get(address.toString()); - return partialBuf === undefined ? undefined : Fr.fromBuffer(partialBuf); - }; -} \ No newline at end of file diff --git a/yarn-project/key-store/src/index.ts b/yarn-project/key-store/src/index.ts index 4f06a44db34..e4ae5ce271c 100644 --- a/yarn-project/key-store/src/index.ts +++ b/yarn-project/key-store/src/index.ts @@ -1,2 +1 @@ export * from './test_key_store.js'; -export * from './address_book.js'; From 58f9650f88539f852a1c5e029743e958b42fdd3e Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 23 Apr 2024 15:13:24 +0000 Subject: [PATCH 005/125] working tests --- .../src/keys/assert_public_key_freshness.nr | 54 ++- .../key_registry_contract/src/main.nr | 46 +- .../contracts/test_contract/src/main.nr | 13 +- .../types/src/address/partial_address.nr | 4 + .../circuit-types/src/interfaces/pxe.ts | 5 +- .../circuit-types/src/keys/key_store.ts | 12 + .../end-to-end/src/e2e_key_registry.test.ts | 417 +++++++++++------- yarn-project/key-store/src/test_key_store.ts | 13 + .../pxe/src/pxe_service/pxe_service.ts | 9 +- .../simulator/src/acvm/oracle/oracle.ts | 26 +- .../simulator/src/acvm/oracle/typed_oracle.ts | 8 +- .../simulator/src/client/db_oracle.ts | 2 - 12 files changed, 382 insertions(+), 227 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr index 80f218ce3bd..5390a2b7848 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr @@ -1,4 +1,7 @@ -use dep::protocol_types::{constants::{GENERATOR_INDEX__PUBLIC_KEYS_HASH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint}; +use dep::protocol_types::{ + constants::{ + GENERATOR_INDEX__PUBLIC_KEYS_HASH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, + address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint}; use crate::context::PrivateContext; use crate::note::{ constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH}, @@ -7,18 +10,28 @@ use crate::note::{ utils::compute_note_hash_for_consumption, }; use crate::state_vars::shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter; -use crate::hash::pedersen_hash; -use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; +use crate::hash::{pedersen_hash, poseidon2_hash}; use crate::oracle; +struct PublicKeyTypeEnum { + NULLIFIER: u8, + INCOMING: u8, +} + +global PublicKeyType = PublicKeyTypeEnum { + NULLIFIER: 0, + INCOMING: 1, +}; -fn assert_nullifier_public_key_fresh( +pub fn assert_nullifier_public_key_fresh( context: &mut PrivateContext, address: AztecAddress, nullifier_public_key_to_test: GrumpkinPoint, + // remove after + registry_contract_address: AztecAddress, ) { // Canonical Key Registry - let contract_address_to_read = AztecAddress::from_field(123); + let contract_address_to_read = registry_contract_address; let storage_slot_of_nullifier_public_key = 1; // We have to derive this slot to get the location of the shared mutable inside the Map let derived_slot = pedersen_hash( @@ -31,15 +44,22 @@ fn assert_nullifier_public_key_fresh( let hashed_nullifier_public_key = registry_private_getter.get_current_value_in_private(); if (hashed_nullifier_public_key == 0) { - check_key(address, 1, nullifier_public_key_to_test); + check_key(address, PublicKeyType.NULLIFIER, nullifier_public_key_to_test); } else { - assert(hashed_nullifier_public_key == pedersen_hash(nullifier_public_key_to_test.serialize(), 0)); + assert(hashed_nullifier_public_key == poseidon2_hash(nullifier_public_key_to_test.serialize())); } } -fn check_key(address: AztecAddress, key_type: Field, key: GrumpkinPoint) { +fn check_key(address: AztecAddress, key_type: u8, key: GrumpkinPoint) { let mut (partial_address, keys) = check_key_internal(address); + crate::oracle::debug_log::debug_log_array_with_prefix("partial", [partial_address]); + crate::oracle::debug_log::debug_log_array_with_prefix("ACTUAL NULLIFIER", key.serialize()); + crate::oracle::debug_log::debug_log_array_with_prefix("nullifier", keys[0].serialize()); + crate::oracle::debug_log::debug_log_array_with_prefix("incoming", keys[1].serialize()); + crate::oracle::debug_log::debug_log_array_with_prefix("outgoing", keys[2].serialize()); + crate::oracle::debug_log::debug_log_array_with_prefix("tagging", keys[3].serialize()); + assert(keys[key_type].eq(key)); _check_key_constrain_check_key_internal( @@ -49,7 +69,7 @@ fn check_key(address: AztecAddress, key_type: Field, key: GrumpkinPoint) { keys[1], keys[2], keys[3], - ); + ) } unconstrained fn check_key_internal(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { @@ -76,19 +96,15 @@ fn _check_key_constrain_check_key_internal( tagging_public_key.serialize()[0], tagging_public_key.serialize()[1], GENERATOR_INDEX__PUBLIC_KEYS_HASH, - ], - 9 - ); + ]); let computed_address = AztecAddress::from_field( poseidon2_hash([ - partial_address.to_field(), - public_keys_hash.to_field(), - GENERATOR_INDEX__CONTRACT_ADDRESS_V1 as Field, - ], - 3 - ) + partial_address.to_field(), + public_keys_hash.to_field(), + GENERATOR_INDEX__CONTRACT_ADDRESS_V1, + ]) ); - assert(computed_address.eq(address), "Computed address does not match supplied address"); + assert(computed_address.eq(address)); } diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index d4ed6addd03..c0e2ff7e8af 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -10,6 +10,7 @@ contract KeyRegistry { protocol_types::{ abis::function_selector::FunctionSelector, contract_class_id::ContractClassId, + grumpkin_point::GrumpkinPoint, address::{ AztecAddress, EthAddress, @@ -34,19 +35,19 @@ contract KeyRegistry { struct Storage { // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. // Uncomment lines below to enable that functionality - nullifier_public_key_registry: Map>, + nullifier_public_key_hash_registry: Map>, // incoming_public_key_registry: Map>, // outgoing_public_key_registry: Map>, // tagging_public_key_registry: Map>, } #[aztec(public)] - fn rotate_nullifier_public_key( + fn rotate_nullifier_public_key_hash( address: AztecAddress, - new_nullifier_public_key: Field, + new_nullifier_public_key_hash: Field, ) { assert( - new_nullifier_public_key != 0, + new_nullifier_public_key_hash != 0, "New nullifier public key must be non-zero" ); @@ -54,25 +55,26 @@ contract KeyRegistry { assert_current_call_valid_authwit_public(&mut context, address); } - let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); + let nullifier_key_registry = storage.nullifier_public_key_hash_registry.at(address); - nullifier_key_registry.schedule_value_change(new_nullifier_public_key); + nullifier_key_registry.schedule_value_change(new_nullifier_public_key_hash); } #[aztec(public)] fn register( address: AztecAddress, partial_address: PartialAddress, - nullifier_public_key: Field, - incoming_public_key: Field, - outgoing_public_key: Field, - tagging_public_key: Field, + nullifier_public_key: GrumpkinPoint, + incoming_public_key: GrumpkinPoint, + outgoing_public_key: GrumpkinPoint, + tagging_public_key: GrumpkinPoint, ) { assert( - (nullifier_public_key != 0) & - (incoming_public_key != 0) & - (outgoing_public_key != 0) & - (tagging_public_key != 0), + !partial_address.is_zero() & + !nullifier_public_key.is_zero() & + !incoming_public_key.is_zero() & + !outgoing_public_key.is_zero() & + !tagging_public_key.is_zero(), "All public keys must be non-zero" ); @@ -81,10 +83,14 @@ contract KeyRegistry { // let address = AztecAddress::compute(public_keys_hash, partial_address); // We could also pass in original_public_keys_hash instead of computing it here, if all we need the original one is for being able to prove ownership of address let public_keys_hash = poseidon2_hash([ - nullifier_public_key, - incoming_public_key, - outgoing_public_key, - tagging_public_key, + nullifier_public_key.serialize()[0], + nullifier_public_key.serialize()[1], + incoming_public_key.serialize()[0], + incoming_public_key.serialize()[1], + outgoing_public_key.serialize()[0], + outgoing_public_key.serialize()[1], + tagging_public_key.serialize()[0], + tagging_public_key.serialize()[1], GENERATOR_INDEX__PUBLIC_KEYS_HASH, ] ); @@ -100,14 +106,14 @@ contract KeyRegistry { assert(computed_address.eq(address), "Computed address does not match supplied address"); - let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); + let nullifier_key_hash_registry = storage.nullifier_public_key_hash_registry.at(address); // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. // Uncomment lines below to enable that functionality // let incoming_key_registry = storage.incoming_public_key_registry.at(address); // let outgoing_key_registry = storage.outgoing_public_key_registry.at(address); // let tagging_key_registry = storage.taggin_public_key_registry.at(address); - nullifier_key_registry.schedule_value_change(nullifier_public_key); + nullifier_key_hash_registry.schedule_value_change(poseidon2_hash(nullifier_public_key.serialize())); // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. // Uncomment lines below to enable that functionality // incoming_key_registry.schedule_value_change(new_incoming_public_key); // outgoing_key_registry.schedule_value_change(new_outgoing_public_key); 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 d03ef87095d..982a6b36e79 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -7,7 +7,8 @@ contract Test { use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, - constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, traits::Serialize + constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, traits::Serialize, + grumpkin_point::GrumpkinPoint }; use dep::aztec::note::constants::MAX_NOTES_PER_PAGE; @@ -15,6 +16,7 @@ contract Test { use dep::aztec::state_vars::shared_mutable::SharedMutablePrivateGetter; use dep::aztec::{ + keys::assert_public_key_freshness::assert_nullifier_public_key_fresh, context::{Context, inputs::private_context_inputs::PrivateContextInputs}, hash::{pedersen_hash, compute_secret_hash, ArgsHasher}, note::{ @@ -411,6 +413,15 @@ contract Test { context.emit_unencrypted_log(authorized); } + #[aztec(private)] + fn test_nullifier_key_freshness( + address: AztecAddress, + public_nullifying_key: GrumpkinPoint, + key_registry_contract: AztecAddress, + ) { + assert_nullifier_public_key_fresh(&mut context, address, public_nullifying_key, key_registry_contract); + } + #[aztec(public)] fn delay() { // We use this as a util function to "mine a block" diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr index 359fae794ba..b7b6b7caec1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr @@ -69,6 +69,10 @@ impl PartialAddress { self.inner } + pub fn is_zero(self) -> bool { + self.to_field() == 0 + } + pub fn assert_is_zero(self) { assert(self.to_field() == 0); } diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 0eba3e00512..b1f0fb0327c 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -1,4 +1,4 @@ -import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; +import { Point, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -73,7 +73,8 @@ export interface PXE { * the recipient's notes. We can send notes to this account because we can encrypt them with the recipient's * public key. */ - registerRecipient(recipient: CompleteAddress): Promise; + // TODO: FIX THIS AFTER THE COMPLETE ADDRESS REFACTOR + registerRecipient(recipient: CompleteAddress, publicKeys?: Point[]): Promise; /** * Retrieves the user accounts registered on this PXE Service. diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 55c69f0facb..f670683d905 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -1,4 +1,5 @@ import { + Point, type AztecAddress, type Fr, type GrumpkinPrivateKey, @@ -116,4 +117,15 @@ export interface KeyStore { * @returns A Promise that resolves to the public keys hash. */ getPublicKeysHash(account: AztecAddress): Promise; + + /** + * + */ + addPublicKeysForAccount( + accountAddress: AztecAddress, + masterNullifierPublicKey: Point, + masterIncomingViewingPublicKey: Point, + masterOutgoingViewingPublicKey: Point, + masterTaggingPublicKey: Point, + ): Promise; } diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 37f6ac8cea5..6418d9924e1 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -1,5 +1,5 @@ import { type AccountWallet, AztecAddress, Fr, type PXE } from '@aztec/aztec.js'; -import { GeneratorIndex } from '@aztec/circuits.js'; +import { CompleteAddress, GeneratorIndex, PartialAddress, Point } from '@aztec/circuits.js'; import { poseidon2Hash } from '@aztec/foundation/crypto'; import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; @@ -35,102 +35,245 @@ describe('SharedMutablePrivateGetter', () => { afterAll(() => teardown()); - describe('failure cases', () => { - let accountAddedToRegistry: AztecAddress; - - describe('should fail registering with bad input', () => { - const partialAddress = new Fr(69); - - const masterNullifierPublicKey = new Fr(12); - const masterIncomingViewingPublicKey = new Fr(34); - const masterOutgoingViewingPublicKey = new Fr(56); - const masterTaggingPublicKey = new Fr(78); - - // TODO(#5726): use computePublicKeysHash function - const publicKeysHash = poseidon2Hash([ - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - GeneratorIndex.PUBLIC_KEYS_HASH, - ]); - - // We hash the partial address and the public keys hash to get the account address - // TODO(#5726): Move the following line to AztecAddress class? - accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); - - it('should fail registering with mismatched address', async () => { - const mismatchedAddress = Fr.random(); - - await expect( - keyRegistry - .withWallet(wallets[0]) - .methods.register( - AztecAddress.fromField(mismatchedAddress), - partialAddress, - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - ) - .send() - .wait(), - ).rejects.toThrow('Computed address does not match supplied address'); - }); - - it('should fail registering with mismatched nullifier public key', async () => { - const mismatchedMasterNullifierPublicKey = Fr.random(); - - await expect( - keyRegistry - .withWallet(wallets[0]) - .methods.register( - AztecAddress.fromField(accountAddedToRegistry), - partialAddress, - mismatchedMasterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - ) - .send() - .wait(), - ).rejects.toThrow('Computed address does not match supplied address'); - }); - }); - - describe('should fail when rotating keys with bad input', () => { - it('should fail when trying to rotate setting a 0 key', async () => { - await expect( - keyRegistry - .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)) - .send() - .wait(), - ).rejects.toThrow('New nullifier public key must be non-zero'); - }); - - it('should fail when trying to rotate for another address without authwit', async () => { - await expect( - keyRegistry - .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)) - .send() - .wait(), - ).rejects.toThrow('Assertion failed: Message not authorized by account'); - }); - }); - }); + // describe('failure cases', () => { + // let accountAddedToRegistry: AztecAddress; + + // describe('should fail registering with bad input', () => { + // const partialAddress = new Fr(69); + + // const masterNullifierPublicKey = new Fr(12); + // const masterIncomingViewingPublicKey = new Fr(34); + // const masterOutgoingViewingPublicKey = new Fr(56); + // const masterTaggingPublicKey = new Fr(78); + + // // TODO(#5726): use computePublicKeysHash function + // const publicKeysHash = poseidon2Hash([ + // masterNullifierPublicKey, + // masterIncomingViewingPublicKey, + // masterOutgoingViewingPublicKey, + // masterTaggingPublicKey, + // GeneratorIndex.PUBLIC_KEYS_HASH, + // ]); + + // // We hash the partial address and the public keys hash to get the account address + // // TODO(#5726): Move the following line to AztecAddress class? + // accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + // it('should fail registering with mismatched address', async () => { + // const mismatchedAddress = Fr.random(); + + // await expect( + // keyRegistry + // .withWallet(wallets[0]) + // .methods.register( + // AztecAddress.fromField(mismatchedAddress), + // partialAddress, + // masterNullifierPublicKey, + // masterIncomingViewingPublicKey, + // masterOutgoingViewingPublicKey, + // masterTaggingPublicKey, + // ) + // .send() + // .wait(), + // ).rejects.toThrow('Computed address does not match supplied address'); + // }); + + // it('should fail registering with mismatched nullifier public key', async () => { + // const mismatchedMasterNullifierPublicKey = Fr.random(); + + // await expect( + // keyRegistry + // .withWallet(wallets[0]) + // .methods.register( + // AztecAddress.fromField(accountAddedToRegistry), + // partialAddress, + // mismatchedMasterNullifierPublicKey, + // masterIncomingViewingPublicKey, + // masterOutgoingViewingPublicKey, + // masterTaggingPublicKey, + // ) + // .send() + // .wait(), + // ).rejects.toThrow('Computed address does not match supplied address'); + // }); + // }); + + // describe('should fail when rotating keys with bad input', () => { + // it('should fail when trying to rotate setting a 0 key', async () => { + // await expect( + // keyRegistry + // .withWallet(wallets[0]) + // .methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)) + // .send() + // .wait(), + // ).rejects.toThrow('New nullifier public key must be non-zero'); + // }); + + // it('should fail when trying to rotate for another address without authwit', async () => { + // await expect( + // keyRegistry + // .withWallet(wallets[0]) + // .methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)) + // .send() + // .wait(), + // ).rejects.toThrow('Assertion failed: Message not authorized by account'); + // }); + // }); + // }); + + // describe('key registration flow', () => { + // let accountAddedToRegistry: AztecAddress; + + // it('should generate and register with original keys', async () => { + // const partialAddress = new Fr(69); + + // const masterNullifierPublicKey = new Fr(12); + // const masterIncomingViewingPublicKey = new Fr(34); + // const masterOutgoingViewingPublicKey = new Fr(56); + // const masterTaggingPublicKey = new Fr(78); + + // const publicKeysHash = poseidon2Hash([ + // masterNullifierPublicKey, + // masterIncomingViewingPublicKey, + // masterOutgoingViewingPublicKey, + // masterTaggingPublicKey, + // GeneratorIndex.PUBLIC_KEYS_HASH, + // ]); + + // // We hash the partial address and the public keys hash to get the account address + // // TODO(#5726): Move the following line to AztecAddress class? + // accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + // await keyRegistry + // .withWallet(wallets[0]) + // .methods.register( + // AztecAddress.fromField(accountAddedToRegistry), + // partialAddress, + // masterNullifierPublicKey, + // masterIncomingViewingPublicKey, + // masterOutgoingViewingPublicKey, + // masterTaggingPublicKey, + // ) + // .send() + // .wait(); + // }); + + // it('checks our registry contract from test contract and fails because the address has not been registered yet', async () => { + // const { txHash } = await testContract.methods + // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + // .send() + // .wait(); + + // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); + // }); + + // it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { + // await delay(5); + + // const { txHash } = await testContract.methods + // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + // .send() + // .wait(); + + // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); + // }); + // }); + + // describe('key rotation flow', () => { + // it('we rotate the nullifier key', async () => { + // // This changes + // const newMasterNullifierPublicKey = new Fr(910); + + // await keyRegistry + // .withWallet(wallets[0]) + // .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) + // .send() + // .wait(); + // }); + + // it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + // const { txHash } = await testContract.methods + // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + // .send() + // .wait(); + + // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); + // }); + + // it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + // await delay(5); + + // const { txHash } = await testContract.methods + // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + // .send() + // .wait(); + + // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + // }); + // }); + + // describe('key rotation flow with authwit', () => { + // it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { + // // This changes + // const newMasterNullifierPublicKey = new Fr(420); + + // const action = keyRegistry + // .withWallet(wallets[1]) + // .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey); + + // await wallets[0] + // .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) + // .send() + // .wait(); + + // await action.send().wait(); + // }); + + // it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + // const { txHash } = await testContract.methods + // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + // .send() + // .wait(); + + // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + // }); + + // it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + // await delay(5); + + // const { txHash } = await testContract.methods + // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + // .send() + // .wait(); + + // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(420)); + // }); + // }); describe('key registration flow', () => { let accountAddedToRegistry: AztecAddress; + let masterNullifierPublicKey: Point; + let masterIncomingViewingPublicKey: Point; + let masterOutgoingViewingPublicKey: Point; + let masterTaggingPublicKey: Point; + let partialAddress: PartialAddress; it('should generate and register with original keys', async () => { - const partialAddress = new Fr(69); + partialAddress = new Fr(69); - const masterNullifierPublicKey = new Fr(12); - const masterIncomingViewingPublicKey = new Fr(34); - const masterOutgoingViewingPublicKey = new Fr(56); - const masterTaggingPublicKey = new Fr(78); + masterNullifierPublicKey = new Point(new Fr(1), new Fr(2)); + masterIncomingViewingPublicKey = new Point(new Fr(3), new Fr(4)); + masterOutgoingViewingPublicKey = new Point(new Fr(5), new Fr(6)); + masterTaggingPublicKey = new Point(new Fr(7), new Fr(8)); const publicKeysHash = poseidon2Hash([ masterNullifierPublicKey, @@ -166,96 +309,34 @@ describe('SharedMutablePrivateGetter', () => { const rawLogs = await pxe.getUnencryptedLogs({ txHash }); expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); - }); - - it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { - await delay(5); - - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) - .send() - .wait(); - - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); - }); - }); - - describe('key rotation flow', () => { - it('we rotate the nullifier key', async () => { - // This changes - const newMasterNullifierPublicKey = new Fr(910); - - await keyRegistry - .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) - .send() - .wait(); + // Checks freshness of newly added keys, but the change hasn't been affected yet + await expect(testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey, keyRegistry.address).send().wait()).rejects.toThrow(); }); - it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); - - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); - }); + it('', async () => { + // FIX THIS + await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), [ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey]); + await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey, keyRegistry.address).send().wait(); + }) - it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { await delay(5); const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); - - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); - }); - }); - - describe('key rotation flow with authwit', () => { - it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { - // This changes - const newMasterNullifierPublicKey = new Fr(420); - - const action = keyRegistry - .withWallet(wallets[1]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey); - - await wallets[0] - .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) - .send() - .wait(); - - await action.send().wait(); - }); - - it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) .send() .wait(); const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); - }); - it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { - await delay(5); - - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); - - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(masterNullifierPublicKey.toFields())); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(420)); + await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey, keyRegistry.address).send().wait(); }); }); }); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index c2755aecf0e..288ffc9430d 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -292,4 +292,17 @@ export class TestKeyStore implements KeyStore { } return Promise.resolve(Fr.fromBuffer(publicKeysHashBuffer)); } + + public async addPublicKeysForAccount( + accountAddress: AztecAddress, + masterNullifierPublicKey: Point, + masterIncomingViewingPublicKey: Point, + masterOutgoingViewingPublicKey: Point, + masterTaggingPublicKey: Point, + ): Promise { + await this.#keys.set(`${accountAddress.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); + } } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 5f90b66be33..3e75a1fe655 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -42,7 +42,7 @@ import { import { computeCommitmentNonce, siloNullifier } from '@aztec/circuits.js/hash'; import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection'; -import { Fr } from '@aztec/foundation/fields'; +import { Fr, Point } from '@aztec/foundation/fields'; import { SerialQueue } from '@aztec/foundation/fifo'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; @@ -216,8 +216,13 @@ export class PXEService implements PXE { return this.keyStore.getPublicKeysHash(address); } - public async registerRecipient(recipient: CompleteAddress): Promise { + public async registerRecipient(recipient: CompleteAddress, publicKeys: Point[] = []): Promise { const wasAdded = await this.db.addCompleteAddress(recipient); + + if (publicKeys.length !== 0) { + await this.keyStore.addPublicKeysForAccount(recipient.address, publicKeys[0], publicKeys[1], publicKeys[2], publicKeys[3]); + } + if (wasAdded) { this.log.info(`Added recipient:\n ${recipient.toReadableString()}`); } else { diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 02f820666fd..26a4a677c59 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -1,5 +1,5 @@ import { MerkleTreeId, UnencryptedL2Log } from '@aztec/circuit-types'; -import { acvmFieldMessageToString, oracleDebugCallToFormattedStr } from '@aztec/circuits.js'; +import { type PartialAddress, acvmFieldMessageToString, oracleDebugCallToFormattedStr } from '@aztec/circuits.js'; import { EventSelector, FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, Point } from '@aztec/foundation/fields'; @@ -174,12 +174,26 @@ export class Oracle { } async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { - const { partialAddress } = await this.typedOracle.getCompleteAddress( - AztecAddress.fromField(fromACVMField(address)), - ); + let partialAddress: PartialAddress; + let publicKeys: Point[] | undefined; + try { + ({ partialAddress } = await this.typedOracle.getCompleteAddress( + AztecAddress.fromField(fromACVMField(address)), + )); + } catch (err) { + partialAddress = Fr.ZERO; + } + + try { + publicKeys = await this.typedOracle.getPublicKeysForAddress(AztecAddress.fromField(fromACVMField(address))); + } catch(err) { + publicKeys = Array(4).fill(Point.ZERO); + } + + console.log('partial address', partialAddress); + console.log('public keys', publicKeys); - const publicKeys = await this.typedOracle.getPublicKeysForAddress(AztecAddress.fromField(fromACVMField(address))); - const acvmKeys = publicKeys?.flatMap(key => key.toFields()) ?? Array(8).fill(toACVMField(0)); + const acvmKeys = publicKeys.flatMap(key => key.toFields()); return [partialAddress, ...acvmKeys].map(toACVMField); } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 86b3d5d6439..103214d3c98 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -142,16 +142,10 @@ export abstract class TypedOracle { getPublicKeysForAddress( _address: AztecAddress, - ): Promise { + ): Promise { throw new OracleMethodNotAvailableError('getPublicKeysForAddress'); } - async getAddressMetadata( - _address: AztecAddress, - ): Promise { - throw new OracleMethodNotAvailableError('getAddressMetadata'); - } - getNotes( _storageSlot: Fr, _numSelects: number, diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index b8d56098703..3e193b56472 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -67,8 +67,6 @@ export interface DBOracle extends CommitmentsDB { getPublicKeysForAddress(address: AztecAddress): Promise; - getAddressMetadata(address: AztecAddress): Promise; - /** * Retrieve nullifier keys associated with a specific account and app/contract address. * From 1b13804151dc797e3b376900dc40eeb56b243907 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 15:22:54 +0000 Subject: [PATCH 006/125] cleanup --- .../src/keys/assert_public_key_freshness.nr | 55 +- .../key_registry_contract/src/main.nr | 8 +- .../contracts/test_contract/src/main.nr | 3 +- .../end-to-end/src/e2e_key_registry.test.ts | 549 ++++++++++-------- 4 files changed, 339 insertions(+), 276 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr index 5390a2b7848..d1961792feb 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr @@ -1,68 +1,65 @@ use dep::protocol_types::{ + address::{ + AztecAddress, + PartialAddress + }, constants::{ - GENERATOR_INDEX__PUBLIC_KEYS_HASH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, - address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint}; + GENERATOR_INDEX__PUBLIC_KEYS_HASH, + GENERATOR_INDEX__CONTRACT_ADDRESS_V1, + CANONICAL_KEY_REGISTRY_ADDRESS + }, + grumpkin_point::GrumpkinPoint, +}; + use crate::context::PrivateContext; -use crate::note::{ - constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH}, - note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder, Comparator, NoteStatus, PropertySelector}, - note_interface::NoteInterface, note_viewer_options::NoteViewerOptions, - utils::compute_note_hash_for_consumption, +use crate::hash::{ + pedersen_hash, + poseidon2_hash, }; -use crate::state_vars::shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter; -use crate::hash::{pedersen_hash, poseidon2_hash}; use crate::oracle; +use crate::state_vars::shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter; struct PublicKeyTypeEnum { NULLIFIER: u8, - INCOMING: u8, } global PublicKeyType = PublicKeyTypeEnum { NULLIFIER: 0, - INCOMING: 1, }; pub fn assert_nullifier_public_key_fresh( context: &mut PrivateContext, address: AztecAddress, nullifier_public_key_to_test: GrumpkinPoint, - // remove after - registry_contract_address: AztecAddress, ) { - // Canonical Key Registry - let contract_address_to_read = registry_contract_address; + // This is the storage slot of the nullifier_public_key inside the key registry contract let storage_slot_of_nullifier_public_key = 1; // We have to derive this slot to get the location of the shared mutable inside the Map + // This should mimic how maps derive their slots let derived_slot = pedersen_hash( [storage_slot_of_nullifier_public_key, address.to_field()], 0 ); // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, contract_address_to_read, derived_slot); + // We read from the canonical Key Registry + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS), derived_slot); let hashed_nullifier_public_key = registry_private_getter.get_current_value_in_private(); + // In the case that the value is not found in the registry we need to manually pass in the address preimage if (hashed_nullifier_public_key == 0) { - check_key(address, PublicKeyType.NULLIFIER, nullifier_public_key_to_test); + check_public_key_validity(address, PublicKeyType.NULLIFIER, nullifier_public_key_to_test); } else { assert(hashed_nullifier_public_key == poseidon2_hash(nullifier_public_key_to_test.serialize())); } } -fn check_key(address: AztecAddress, key_type: u8, key: GrumpkinPoint) { - let mut (partial_address, keys) = check_key_internal(address); - - crate::oracle::debug_log::debug_log_array_with_prefix("partial", [partial_address]); - crate::oracle::debug_log::debug_log_array_with_prefix("ACTUAL NULLIFIER", key.serialize()); - crate::oracle::debug_log::debug_log_array_with_prefix("nullifier", keys[0].serialize()); - crate::oracle::debug_log::debug_log_array_with_prefix("incoming", keys[1].serialize()); - crate::oracle::debug_log::debug_log_array_with_prefix("outgoing", keys[2].serialize()); - crate::oracle::debug_log::debug_log_array_with_prefix("tagging", keys[3].serialize()); +fn check_public_key_validity(address: AztecAddress, key_type: u8, key: GrumpkinPoint) { + let (partial_address, keys) = get_public_keys_and_partial_address_internal(address); assert(keys[key_type].eq(key)); - _check_key_constrain_check_key_internal( + _check_public_key_validity_constrain_internal( address, partial_address, keys[0], @@ -72,13 +69,13 @@ fn check_key(address: AztecAddress, key_type: u8, key: GrumpkinPoint) { ) } -unconstrained fn check_key_internal(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { +unconstrained fn get_public_keys_and_partial_address_internal(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { let (partial_address, public_keys) = oracle::keys::get_public_keys_and_partial_address(address); (partial_address, public_keys) } -fn _check_key_constrain_check_key_internal( +fn _check_public_key_validity_constrain_internal( address: AztecAddress, partial_address: PartialAddress, nullifier_public_key: GrumpkinPoint, diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index ea5b1dd551a..6124253c417 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -34,12 +34,12 @@ contract KeyRegistry { } #[aztec(public)] - fn rotate_nullifier_public_key_hash( + fn rotate_nullifier_public_key( address: AztecAddress, - new_nullifier_public_key_hash: Field, + new_nullifier_public_key: GrumpkinPoint, ) { assert( - new_nullifier_public_key_hash != 0, + !new_nullifier_public_key.is_zero(), "New nullifier public key must be non-zero" ); @@ -49,7 +49,7 @@ contract KeyRegistry { let nullifier_key_registry = storage.nullifier_public_key_hash_registry.at(address); - nullifier_key_registry.schedule_value_change(new_nullifier_public_key_hash); + nullifier_key_registry.schedule_value_change(poseidon2_hash(new_nullifier_public_key.serialize())); } #[aztec(public)] 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 d5f5142fd03..68311b75f4f 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -414,9 +414,8 @@ contract Test { fn test_nullifier_key_freshness( address: AztecAddress, public_nullifying_key: GrumpkinPoint, - key_registry_contract: AztecAddress, ) { - assert_nullifier_public_key_fresh(&mut context, address, public_nullifying_key, key_registry_contract); + assert_nullifier_public_key_fresh(&mut context, address, public_nullifying_key); } #[aztec(public)] diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 967d9c1ee4a..a16f3e56ad9 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -10,11 +10,11 @@ import { publicDeployAccounts, setup } from './fixtures/utils.js'; const TIMEOUT = 100_000; -describe('SharedMutablePrivateGetter', () => { +describe('Key Registry', () => { let keyRegistry: KeyRegistryContract; + let pxe: PXE; let testContract: TestContract; - let pxe: PXE; jest.setTimeout(TIMEOUT); let wallets: AccountWallet[]; @@ -38,245 +38,102 @@ describe('SharedMutablePrivateGetter', () => { afterAll(() => teardown()); - // describe('failure cases', () => { - // let accountAddedToRegistry: AztecAddress; - - // describe('should fail registering with bad input', () => { - // const partialAddress = new Fr(69); - - // const masterNullifierPublicKey = new Fr(12); - // const masterIncomingViewingPublicKey = new Fr(34); - // const masterOutgoingViewingPublicKey = new Fr(56); - // const masterTaggingPublicKey = new Fr(78); - - // // TODO(#5726): use computePublicKeysHash function - // const publicKeysHash = poseidon2Hash([ - // masterNullifierPublicKey, - // masterIncomingViewingPublicKey, - // masterOutgoingViewingPublicKey, - // masterTaggingPublicKey, - // GeneratorIndex.PUBLIC_KEYS_HASH, - // ]); - - // // We hash the partial address and the public keys hash to get the account address - // // TODO(#5726): Move the following line to AztecAddress class? - // accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); - - // it('should fail registering with mismatched address', async () => { - // const mismatchedAddress = Fr.random(); - - // await expect( - // keyRegistry - // .withWallet(wallets[0]) - // .methods.register( - // AztecAddress.fromField(mismatchedAddress), - // partialAddress, - // masterNullifierPublicKey, - // masterIncomingViewingPublicKey, - // masterOutgoingViewingPublicKey, - // masterTaggingPublicKey, - // ) - // .send() - // .wait(), - // ).rejects.toThrow('Computed address does not match supplied address'); - // }); - - // it('should fail registering with mismatched nullifier public key', async () => { - // const mismatchedMasterNullifierPublicKey = Fr.random(); - - // await expect( - // keyRegistry - // .withWallet(wallets[0]) - // .methods.register( - // AztecAddress.fromField(accountAddedToRegistry), - // partialAddress, - // mismatchedMasterNullifierPublicKey, - // masterIncomingViewingPublicKey, - // masterOutgoingViewingPublicKey, - // masterTaggingPublicKey, - // ) - // .send() - // .wait(), - // ).rejects.toThrow('Computed address does not match supplied address'); - // }); - // }); - - // describe('should fail when rotating keys with bad input', () => { - // it('should fail when trying to rotate setting a 0 key', async () => { - // await expect( - // keyRegistry - // .withWallet(wallets[0]) - // .methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)) - // .send() - // .wait(), - // ).rejects.toThrow('New nullifier public key must be non-zero'); - // }); - - // it('should fail when trying to rotate for another address without authwit', async () => { - // await expect( - // keyRegistry - // .withWallet(wallets[0]) - // .methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)) - // .send() - // .wait(), - // ).rejects.toThrow('Assertion failed: Message not authorized by account'); - // }); - // }); - // }); - - // describe('key registration flow', () => { - // let accountAddedToRegistry: AztecAddress; - - // it('should generate and register with original keys', async () => { - // const partialAddress = new Fr(69); - - // const masterNullifierPublicKey = new Fr(12); - // const masterIncomingViewingPublicKey = new Fr(34); - // const masterOutgoingViewingPublicKey = new Fr(56); - // const masterTaggingPublicKey = new Fr(78); - - // const publicKeysHash = poseidon2Hash([ - // masterNullifierPublicKey, - // masterIncomingViewingPublicKey, - // masterOutgoingViewingPublicKey, - // masterTaggingPublicKey, - // GeneratorIndex.PUBLIC_KEYS_HASH, - // ]); - - // // We hash the partial address and the public keys hash to get the account address - // // TODO(#5726): Move the following line to AztecAddress class? - // accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); - - // await keyRegistry - // .withWallet(wallets[0]) - // .methods.register( - // AztecAddress.fromField(accountAddedToRegistry), - // partialAddress, - // masterNullifierPublicKey, - // masterIncomingViewingPublicKey, - // masterOutgoingViewingPublicKey, - // masterTaggingPublicKey, - // ) - // .send() - // .wait(); - // }); - - // it('checks our registry contract from test contract and fails because the address has not been registered yet', async () => { - // const { txHash } = await testContract.methods - // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) - // .send() - // .wait(); - - // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); - // }); - - // it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { - // await delay(5); - - // const { txHash } = await testContract.methods - // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) - // .send() - // .wait(); - - // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); - // }); - // }); - - // describe('key rotation flow', () => { - // it('we rotate the nullifier key', async () => { - // // This changes - // const newMasterNullifierPublicKey = new Fr(910); - - // await keyRegistry - // .withWallet(wallets[0]) - // .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) - // .send() - // .wait(); - // }); - - // it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - // const { txHash } = await testContract.methods - // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - // .send() - // .wait(); - - // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); - // }); - - // it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { - // await delay(5); - - // const { txHash } = await testContract.methods - // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - // .send() - // .wait(); - - // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); - // }); - // }); - - // describe('key rotation flow with authwit', () => { - // it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { - // // This changes - // const newMasterNullifierPublicKey = new Fr(420); - - // const action = keyRegistry - // .withWallet(wallets[1]) - // .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey); - - // await wallets[0] - // .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) - // .send() - // .wait(); - - // await action.send().wait(); - // }); - - // it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - // const { txHash } = await testContract.methods - // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - // .send() - // .wait(); - - // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); - // }); - - // it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { - // await delay(5); - - // const { txHash } = await testContract.methods - // .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - // .send() - // .wait(); - - // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(420)); - // }); - // }); + describe('failure cases', () => { + let accountAddedToRegistry: AztecAddress; + + describe('should fail registering with bad input', () => { + const partialAddress = new Fr(69); + + const masterNullifierPublicKey = new Fr(12); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); + + // TODO(#5726): use computePublicKeysHash function + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Move the following line to AztecAddress class? + accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + it('should fail registering with mismatched address', async () => { + const mismatchedAddress = Fr.random(); + + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(mismatchedAddress), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(), + ).rejects.toThrow('Computed address does not match supplied address'); + }); + + it('should fail registering with mismatched nullifier public key', async () => { + const mismatchedMasterNullifierPublicKey = Fr.random(); + + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + mismatchedMasterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(), + ).rejects.toThrow('Computed address does not match supplied address'); + }); + }); + + describe('should fail when rotating keys with bad input', () => { + it('should fail when trying to rotate setting a 0 key', async () => { + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)) + .send() + .wait(), + ).rejects.toThrow('New nullifier public key must be non-zero'); + }); + + it('should fail when trying to rotate for another address without authwit', async () => { + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)) + .send() + .wait(), + ).rejects.toThrow('Assertion failed: Message not authorized by account'); + }); + }); + }); describe('key registration flow', () => { let accountAddedToRegistry: AztecAddress; - let masterNullifierPublicKey: Point; - let masterIncomingViewingPublicKey: Point; - let masterOutgoingViewingPublicKey: Point; - let masterTaggingPublicKey: Point; - let partialAddress: PartialAddress; it('should generate and register with original keys', async () => { - partialAddress = new Fr(69); + const partialAddress = new Fr(69); - masterNullifierPublicKey = new Point(new Fr(1), new Fr(2)); - masterIncomingViewingPublicKey = new Point(new Fr(3), new Fr(4)); - masterOutgoingViewingPublicKey = new Point(new Fr(5), new Fr(6)); - masterTaggingPublicKey = new Point(new Fr(7), new Fr(8)); + const masterNullifierPublicKey = new Fr(12); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); const publicKeysHash = poseidon2Hash([ masterNullifierPublicKey, @@ -312,22 +169,210 @@ describe('SharedMutablePrivateGetter', () => { const rawLogs = await pxe.getUnencryptedLogs({ txHash }); expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); + }); + + it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); + }); + }); + + describe('key rotation flow', () => { + it('we rotate the nullifier key', async () => { + // This changes + const newMasterNullifierPublicKey = new Fr(910); + + await keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) + .send() + .wait(); + }); + + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); + }); + + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + }); + }); + + describe('key rotation flow with authwit', () => { + it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { + // This changes + const newMasterNullifierPublicKey = new Fr(420); + + const action = keyRegistry + .withWallet(wallets[1]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey); + + await wallets[0] + .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) + .send() + .wait(); + + await action.send().wait(); + }); + + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + }); - // Checks freshness of newly added keys, but the change hasn't been affected yet - await expect(testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey, keyRegistry.address).send().wait()).rejects.toThrow(); + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(420)); }); + }); - it('', async () => { + describe('key registration flow no PXE', () => { + const masterNullifierPublicKey: Point = new Point(new Fr(9), new Fr(10)); + const masterIncomingViewingPublicKey: Point = new Point(new Fr(11), new Fr(12)); + const masterOutgoingViewingPublicKey: Point = new Point(new Fr(13), new Fr(14)); + const masterTaggingPublicKey: Point = new Point(new Fr(15), new Fr(16)); + const partialAddress: PartialAddress = new Fr(420); + + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Move the following line to AztecAddress class? + const accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { + await expect(testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait()).rejects.toThrow(); + }); + + it('Now we add it to registry', async () => { + await keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(); + }); + + it('checks key freshness and fails because the address change has not been applied yet due to lack of delay', async () => { + await expect(testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait()).rejects.toThrow(); + }); + + it('checks key freshness after a delay, and is successful', async () => { + await delay(5); + + await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait(); + }); + }); + + describe('key registration flow via PXE', () => { + const masterNullifierPublicKey: Point = new Point(new Fr(1), new Fr(2)); + const masterIncomingViewingPublicKey: Point = new Point(new Fr(3), new Fr(4)); + const masterOutgoingViewingPublicKey: Point = new Point(new Fr(5), new Fr(6)); + const masterTaggingPublicKey: Point = new Point(new Fr(7), new Fr(8)); + const partialAddress: PartialAddress = new Fr(69);; + + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Move the following line to AztecAddress class? + const accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { + await expect(testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait()).rejects.toThrow(); + }) + + it('should succeed because we register our recipient manually and the lib checks our pxe', async () => { // FIX THIS await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), [ masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey]); - await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey, keyRegistry.address).send().wait(); + await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait(); }) - it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { + it('Now we add it to registry', async () => { + await keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(); + }) + + it('we start the change in the registry, it has not been applied yet, but we still see we have a fresh key due to it being added in the pxe', async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); + + // Checks freshness of newly added keys, but the change hasn't been affected yet, but we have manually added it to our pxe so it should pass + await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait(); + }); + + it('in the case where the key exists both in the pxe and our registry, we know it works', async () => { await delay(5); const { txHash } = await testContract.methods @@ -339,7 +384,29 @@ describe('SharedMutablePrivateGetter', () => { expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(masterNullifierPublicKey.toFields())); - await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey, keyRegistry.address).send().wait(); + await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait(); + }); + }); + + describe('key rotation flow; assert keys are fresh', () => { + const newMasterNullifierPublicKey = new Point(new Fr(910), new Fr(1112)); + + it('we rotate the nullifier key', async () => { + await keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) + .send() + .wait(); + }); + + it("checks our registry contract from test contract and fails because the change hasn't been applied yet", async () => { + await expect(testContract.methods.test_nullifier_key_freshness(wallets[0].getAddress(), newMasterNullifierPublicKey).send().wait()).rejects.toThrow(); + }); + + it('checks our registry contract from test contract and succeeds because the change has been applied', async () => { + await delay(5); + + await testContract.methods.test_nullifier_key_freshness(wallets[0].getAddress(), newMasterNullifierPublicKey).send().wait(); }); }); }); From 211a060db0040faad1e34c0219a816021f4bd5db Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 15:26:02 +0000 Subject: [PATCH 007/125] yarn format --- .../circuit-types/src/interfaces/pxe.ts | 2 +- .../circuit-types/src/keys/key_store.ts | 4 +- .../end-to-end/jest.integration.config.json | 2 +- .../end-to-end/src/e2e_key_registry.test.ts | 68 ++++++++++++++----- yarn-project/package.common.json | 2 +- .../pxe/src/pxe_service/pxe_service.ts | 12 +++- .../pxe/src/simulator_oracle/index.ts | 7 +- .../simulator/src/acvm/oracle/oracle.ts | 9 +-- .../simulator/src/acvm/oracle/typed_oracle.ts | 6 +- .../simulator/src/client/db_oracle.ts | 3 +- .../simulator/src/client/view_data_oracle.ts | 4 +- 11 files changed, 75 insertions(+), 44 deletions(-) diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 0fc42af9308..f36958df987 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -1,4 +1,4 @@ -import { Point, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; +import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress, type Point } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index f670683d905..e5cefbd7bc4 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -1,9 +1,9 @@ import { - Point, type AztecAddress, type Fr, type GrumpkinPrivateKey, type PartialAddress, + type Point, type PublicKey, } from '@aztec/circuits.js'; @@ -119,7 +119,7 @@ export interface KeyStore { getPublicKeysHash(account: AztecAddress): Promise; /** - * + * */ addPublicKeysForAccount( accountAddress: AztecAddress, diff --git a/yarn-project/end-to-end/jest.integration.config.json b/yarn-project/end-to-end/jest.integration.config.json index 84d61df320c..721267ff552 100644 --- a/yarn-project/end-to-end/jest.integration.config.json +++ b/yarn-project/end-to-end/jest.integration.config.json @@ -6,7 +6,7 @@ "moduleNameMapper": { "^(\\.{1,2}/.*)\\.js$": "$1" }, - "reporters": [["default", {"summaryThreshold": 9999}]], + "reporters": [["default", { "summaryThreshold": 9999 }]], "testRegex": "./src/.*\\.test\\.ts$", "rootDir": "./src" } diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index a16f3e56ad9..2b686e27288 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -1,5 +1,5 @@ import { type AccountWallet, AztecAddress, Fr, type PXE } from '@aztec/aztec.js'; -import { CompleteAddress, GeneratorIndex, PartialAddress, Point } from '@aztec/circuits.js'; +import { CompleteAddress, GeneratorIndex, type PartialAddress, Point } from '@aztec/circuits.js'; import { poseidon2Hash } from '@aztec/foundation/crypto'; import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; @@ -13,7 +13,7 @@ const TIMEOUT = 100_000; describe('Key Registry', () => { let keyRegistry: KeyRegistryContract; - let pxe: PXE; + let pxe: PXE; let testContract: TestContract; jest.setTimeout(TIMEOUT); @@ -282,7 +282,12 @@ describe('Key Registry', () => { const accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { - await expect(testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait()).rejects.toThrow(); + await expect( + testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) + .send() + .wait(), + ).rejects.toThrow(); }); it('Now we add it to registry', async () => { @@ -301,13 +306,21 @@ describe('Key Registry', () => { }); it('checks key freshness and fails because the address change has not been applied yet due to lack of delay', async () => { - await expect(testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait()).rejects.toThrow(); + await expect( + testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) + .send() + .wait(), + ).rejects.toThrow(); }); it('checks key freshness after a delay, and is successful', async () => { await delay(5); - await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait(); + await testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) + .send() + .wait(); }); }); @@ -316,7 +329,7 @@ describe('Key Registry', () => { const masterIncomingViewingPublicKey: Point = new Point(new Fr(3), new Fr(4)); const masterOutgoingViewingPublicKey: Point = new Point(new Fr(5), new Fr(6)); const masterTaggingPublicKey: Point = new Point(new Fr(7), new Fr(8)); - const partialAddress: PartialAddress = new Fr(69);; + const partialAddress: PartialAddress = new Fr(69); const publicKeysHash = poseidon2Hash([ masterNullifierPublicKey, @@ -331,8 +344,13 @@ describe('Key Registry', () => { const accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { - await expect(testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait()).rejects.toThrow(); - }) + await expect( + testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) + .send() + .wait(), + ).rejects.toThrow(); + }); it('should succeed because we register our recipient manually and the lib checks our pxe', async () => { // FIX THIS @@ -340,9 +358,13 @@ describe('Key Registry', () => { masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, - masterTaggingPublicKey]); - await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait(); - }) + masterTaggingPublicKey, + ]); + await testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) + .send() + .wait(); + }); it('Now we add it to registry', async () => { await keyRegistry @@ -357,7 +379,7 @@ describe('Key Registry', () => { ) .send() .wait(); - }) + }); it('we start the change in the registry, it has not been applied yet, but we still see we have a fresh key due to it being added in the pxe', async () => { const { txHash } = await testContract.methods @@ -369,7 +391,10 @@ describe('Key Registry', () => { expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); // Checks freshness of newly added keys, but the change hasn't been affected yet, but we have manually added it to our pxe so it should pass - await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait(); + await testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) + .send() + .wait(); }); it('in the case where the key exists both in the pxe and our registry, we know it works', async () => { @@ -384,7 +409,10 @@ describe('Key Registry', () => { expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(masterNullifierPublicKey.toFields())); - await testContract.methods.test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey).send().wait(); + await testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) + .send() + .wait(); }); }); @@ -400,13 +428,21 @@ describe('Key Registry', () => { }); it("checks our registry contract from test contract and fails because the change hasn't been applied yet", async () => { - await expect(testContract.methods.test_nullifier_key_freshness(wallets[0].getAddress(), newMasterNullifierPublicKey).send().wait()).rejects.toThrow(); + await expect( + testContract.methods + .test_nullifier_key_freshness(wallets[0].getAddress(), newMasterNullifierPublicKey) + .send() + .wait(), + ).rejects.toThrow(); }); it('checks our registry contract from test contract and succeeds because the change has been applied', async () => { await delay(5); - await testContract.methods.test_nullifier_key_freshness(wallets[0].getAddress(), newMasterNullifierPublicKey).send().wait(); + await testContract.methods + .test_nullifier_key_freshness(wallets[0].getAddress(), newMasterNullifierPublicKey) + .send() + .wait(); }); }); }); diff --git a/yarn-project/package.common.json b/yarn-project/package.common.json index 80b56a8d697..6fcf1a28315 100644 --- a/yarn-project/package.common.json +++ b/yarn-project/package.common.json @@ -24,7 +24,7 @@ "moduleNameMapper": { "^(\\.{1,2}/.*)\\.[cm]?js$": "$1" }, - "reporters": [["default", {"summaryThreshold": 9999}]], + "reporters": [["default", { "summaryThreshold": 9999 }]], "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$", "rootDir": "./src" } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 607f4679940..b9ef265e408 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -42,7 +42,7 @@ import { import { computeCommitmentNonce, siloNullifier } from '@aztec/circuits.js/hash'; import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection'; -import { Fr, Point } from '@aztec/foundation/fields'; +import { Fr, type Point } from '@aztec/foundation/fields'; import { SerialQueue } from '@aztec/foundation/fifo'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; @@ -218,9 +218,15 @@ export class PXEService implements PXE { public async registerRecipient(recipient: CompleteAddress, publicKeys: Point[] = []): Promise { const wasAdded = await this.db.addCompleteAddress(recipient); - + if (publicKeys.length !== 0) { - await this.keyStore.addPublicKeysForAccount(recipient.address, publicKeys[0], publicKeys[1], publicKeys[2], publicKeys[3]); + await this.keyStore.addPublicKeysForAccount( + recipient.address, + publicKeys[0], + publicKeys[1], + publicKeys[2], + publicKeys[3], + ); } if (wasAdded) { diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 80b51a611b8..867ca8d0824 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -9,14 +9,13 @@ import { type SiblingPath, } from '@aztec/circuit-types'; import { - Fr, - Point, type AztecAddress, type CompleteAddress, - type EthAddress, + type Fr, type FunctionSelector, type Header, type L1_TO_L2_MSG_TREE_HEIGHT, + type Point, } from '@aztec/circuits.js'; import { computeL1ToL2MessageNullifier } from '@aztec/circuits.js/hash'; import { type FunctionArtifactWithDebugMetadata, getFunctionArtifactWithDebugMetadata } from '@aztec/foundation/abi'; @@ -85,7 +84,7 @@ export class SimulatorOracle implements DBOracle { const outgoingViewingPublicKey = await this.keyStore.getMasterOutgoingViewingPublicKey(address); const taggingPublicKey = await this.keyStore.getMasterTaggingPublicKey(address); - return [nullifierPublicKey, incomingViewingPublicKey, outgoingViewingPublicKey, taggingPublicKey] + return [nullifierPublicKey, incomingViewingPublicKey, outgoingViewingPublicKey, taggingPublicKey]; } async getNotes(contractAddress: AztecAddress, storageSlot: Fr, status: NoteStatus) { diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 4aca6d5f5e7..8226f58a1bc 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -176,22 +176,17 @@ export class Oracle { let partialAddress: PartialAddress; let publicKeys: Point[] | undefined; try { - ({ partialAddress } = await this.typedOracle.getCompleteAddress( - AztecAddress.fromField(fromACVMField(address)), - )); + ({ partialAddress } = await this.typedOracle.getCompleteAddress(AztecAddress.fromField(fromACVMField(address)))); } catch (err) { partialAddress = Fr.ZERO; } try { publicKeys = await this.typedOracle.getPublicKeysForAddress(AztecAddress.fromField(fromACVMField(address))); - } catch(err) { + } catch (err) { publicKeys = Array(4).fill(Point.ZERO); } - console.log('partial address', partialAddress); - console.log('public keys', publicKeys); - const acvmKeys = publicKeys.flatMap(key => key.toFields()); return [partialAddress, ...acvmKeys].map(toACVMField); diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 568b6c38f6d..de60e6e55e1 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -17,7 +17,7 @@ import { } from '@aztec/circuits.js'; import { type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr, Point } from '@aztec/foundation/fields'; +import { Fr, type Point } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; /** Nullifier keys which both correspond to the same master nullifier secret key. */ @@ -140,9 +140,7 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('popCapsule'); } - getPublicKeysForAddress( - _address: AztecAddress, - ): Promise { + getPublicKeysForAddress(_address: AztecAddress): Promise { throw new OracleMethodNotAvailableError('getPublicKeysForAddress'); } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 8433ca44d88..9287249f1cf 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -8,8 +8,7 @@ import { import { type CompleteAddress, type Header } from '@aztec/circuits.js'; import { type FunctionArtifactWithDebugMetadata, type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { type EthAddress } from '@aztec/foundation/eth-address'; -import { Point, type Fr } from '@aztec/foundation/fields'; +import { type Fr, type Point } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; import { type NoteData, type NullifierKeys } from '../acvm/index.js'; diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 00bb685e8c8..d2a85c4a242 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -166,9 +166,7 @@ export class ViewDataOracle extends TypedOracle { return this.db.popCapsule(); } - public override getPublicKeysForAddress( - address: AztecAddress, - ) { + public override getPublicKeysForAddress(address: AztecAddress) { return this.db.getPublicKeysForAddress(address); } From 29bfb809d0e84fdeaa90d6ea2da160a884585d10 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 15:28:47 +0000 Subject: [PATCH 008/125] fix --- noir-projects/aztec-nr/aztec/src/keys.nr | 2 +- .../aztec-nr/aztec/src/keys/assert_public_key_freshness.nr | 2 +- .../noir-contracts/contracts/test_contract/src/main.nr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys.nr b/noir-projects/aztec-nr/aztec/src/keys.nr index 7e83884a099..427d30ba671 100644 --- a/noir-projects/aztec-nr/aztec/src/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/keys.nr @@ -1,3 +1,3 @@ mod assert_public_key_freshness; -use crate::keys::assert_public_key_freshness::assert_nullifier_public_key_fresh; +use crate::keys::assert_public_key_freshness::assert_nullifier_public_key_is_fresh; diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr index d1961792feb..a1fffce3ef4 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr @@ -27,7 +27,7 @@ global PublicKeyType = PublicKeyTypeEnum { NULLIFIER: 0, }; -pub fn assert_nullifier_public_key_fresh( +pub fn assert_nullifier_public_key_is_fresh( context: &mut PrivateContext, address: AztecAddress, nullifier_public_key_to_test: GrumpkinPoint, 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 68311b75f4f..5d8fecf96da 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -19,7 +19,7 @@ contract Test { use dep::aztec::state_vars::shared_mutable::SharedMutablePrivateGetter; use dep::aztec::{ - keys::assert_public_key_freshness::assert_nullifier_public_key_fresh, + keys::assert_public_key_freshness::assert_nullifier_public_key_is_fresh, context::{Context, inputs::private_context_inputs::PrivateContextInputs}, hash::{pedersen_hash, compute_secret_hash, ArgsHasher}, note::{ @@ -415,7 +415,7 @@ contract Test { address: AztecAddress, public_nullifying_key: GrumpkinPoint, ) { - assert_nullifier_public_key_fresh(&mut context, address, public_nullifying_key); + assert_nullifier_public_key_is_fresh(&mut context, address, public_nullifying_key); } #[aztec(public)] From 7d1620d6ca9b6c9bdc147b0fcc878edc5f14c8e1 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 16:47:18 +0000 Subject: [PATCH 009/125] change some stuff --- .../src/keys/assert_public_key_freshness.nr | 48 +---- .../aztec-nr/aztec/src/oracle/keys.nr | 97 +++++---- .../end-to-end/src/e2e_key_registry.test.ts | 192 +++++++++--------- .../pxe/src/simulator_oracle/index.ts | 2 + .../simulator/src/acvm/oracle/oracle.ts | 1 + .../simulator/src/client/db_oracle.ts | 6 + .../simulator/src/client/view_data_oracle.ts | 7 + 7 files changed, 180 insertions(+), 173 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr index a1fffce3ef4..46a9122dc19 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr @@ -55,53 +55,13 @@ pub fn assert_nullifier_public_key_is_fresh( } fn check_public_key_validity(address: AztecAddress, key_type: u8, key: GrumpkinPoint) { - let (partial_address, keys) = get_public_keys_and_partial_address_internal(address); + let keys = get_public_keys_internal(address); assert(keys[key_type].eq(key)); - - _check_public_key_validity_constrain_internal( - address, - partial_address, - keys[0], - keys[1], - keys[2], - keys[3], - ) -} - -unconstrained fn get_public_keys_and_partial_address_internal(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { - let (partial_address, public_keys) = oracle::keys::get_public_keys_and_partial_address(address); - - (partial_address, public_keys) } -fn _check_public_key_validity_constrain_internal( - address: AztecAddress, - partial_address: PartialAddress, - nullifier_public_key: GrumpkinPoint, - incoming_public_key: GrumpkinPoint, - outgoing_public_key: GrumpkinPoint, - tagging_public_key: GrumpkinPoint - ) { - let public_keys_hash = poseidon2_hash([ - nullifier_public_key.serialize()[0], - nullifier_public_key.serialize()[1], - incoming_public_key.serialize()[0], - incoming_public_key.serialize()[1], - outgoing_public_key.serialize()[0], - outgoing_public_key.serialize()[1], - tagging_public_key.serialize()[0], - tagging_public_key.serialize()[1], - GENERATOR_INDEX__PUBLIC_KEYS_HASH, - ]); - - let computed_address = AztecAddress::from_field( - poseidon2_hash([ - partial_address.to_field(), - public_keys_hash.to_field(), - GENERATOR_INDEX__CONTRACT_ADDRESS_V1, - ]) - ); +fn get_public_keys_internal(address: AztecAddress) -> [GrumpkinPoint; 4] { + let (_, public_keys) = oracle::keys::get_public_keys_and_partial_address(address); - assert(computed_address.eq(address)); + public_keys } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 4ff757be4d4..ca67986d093 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -1,47 +1,76 @@ -use dep::protocol_types::{address::{AztecAddress, PartialAddress, PublicKeysHash}, grumpkin_point::GrumpkinPoint}; +use dep::protocol_types::{ + address::{ + AztecAddress, + PartialAddress, + PublicKeysHash, + }, + constants::{ + GENERATOR_INDEX__PUBLIC_KEYS_HASH, + GENERATOR_INDEX__CONTRACT_ADDRESS_V1, + }, + grumpkin_point::GrumpkinPoint, +}; -#[oracle(getPublicKeysForAddress)] -fn get_public_keys_for_address_oracle( - address: AztecAddress, -) -> [GrumpkinPoint; 4] {} +use crate::hash::poseidon2_hash; -unconstrained fn get_public_keys_for_address_oracle_wrapper( - address: AztecAddress -) -> [GrumpkinPoint; 4] { - get_public_keys_for_address_oracle( - address, - ) +#[oracle(getPublicKeysAndPartialAddress)] +fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 9] {} + +unconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: AztecAddress) -> [Field; 9] { + get_public_keys_and_partial_address_oracle(address) } -unconstrained pub fn get_public_keys_for_address( - address: AztecAddress, -) -> [GrumpkinPoint; 4] { - let public_keys = get_public_keys_for_address_oracle_wrapper( +pub fn get_public_keys_and_partial_address(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { + let result = get_public_keys_and_partial_address_oracle_wrapper(address); + + let partial_address = PartialAddress::from_field(result[0]); + let nullifier_pub_key = GrumpkinPoint::new(result[1], result[2]); + let incoming_pub_key = GrumpkinPoint::new(result[3], result[4]); + let outgoing_pub_key = GrumpkinPoint::new(result[5], result[6]); + let tagging_pub_key = GrumpkinPoint::new(result[7], result[8]); + + _check_public_key_validity_constrain_oracle( address, + partial_address, + nullifier_pub_key, + incoming_pub_key, + outgoing_pub_key, + tagging_pub_key, ); - public_keys + (partial_address, [nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key]) } +fn _check_public_key_validity_constrain_oracle( + address: AztecAddress, + partial_address: PartialAddress, + nullifier_public_key: GrumpkinPoint, + incoming_public_key: GrumpkinPoint, + outgoing_public_key: GrumpkinPoint, + tagging_public_key: GrumpkinPoint + ) { + let public_keys_hash = poseidon2_hash([ + nullifier_public_key.serialize()[0], + nullifier_public_key.serialize()[1], + incoming_public_key.serialize()[0], + incoming_public_key.serialize()[1], + outgoing_public_key.serialize()[0], + outgoing_public_key.serialize()[1], + tagging_public_key.serialize()[0], + tagging_public_key.serialize()[1], + GENERATOR_INDEX__PUBLIC_KEYS_HASH, + ]); -#[oracle(getPublicKeysAndPartialAddress)] -fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 9] {} +// TODO: #5830: we can compute this like below once refactored +// let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address); -unconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: AztecAddress) -> [Field; 9] { - get_public_keys_and_partial_address_oracle(address) -} + let computed_address = AztecAddress::from_field( + poseidon2_hash([ + partial_address.to_field(), + public_keys_hash.to_field(), + GENERATOR_INDEX__CONTRACT_ADDRESS_V1, + ]) + ); -pub fn get_public_keys_and_partial_address(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { - let result = get_public_keys_and_partial_address_oracle_wrapper(address); - let partial_address = PartialAddress::from_field(result[0]); - let nullifier_pub_key = GrumpkinPoint::new(result[1], result[2]); - let incoming_pub_key = GrumpkinPoint::new(result[3], result[4]); - let outgoing_pub_key = GrumpkinPoint::new(result[5], result[6]); - let tagging_pub_key = GrumpkinPoint::new(result[7], result[8]); - - // TODO(#5830): disabling the following constraint until we update the oracle according to the new key scheme - // let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address); - // assert(calculated_address.eq(address)); - - (partial_address, [nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key]) + assert(computed_address.eq(address)); } diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 2b686e27288..e11585002cb 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -22,7 +22,7 @@ describe('Key Registry', () => { let teardown: () => Promise; beforeAll(async () => { - ({ teardown, pxe, wallets } = await setup(2)); + ({ teardown, pxe, wallets } = await setup(3)); keyRegistry = await KeyRegistryContract.at(getCanonicalKeyRegistryAddress(), wallets[0]); testContract = await TestContract.deploy(wallets[0]).send().deployed(); @@ -42,12 +42,11 @@ describe('Key Registry', () => { let accountAddedToRegistry: AztecAddress; describe('should fail registering with bad input', () => { - const partialAddress = new Fr(69); - - const masterNullifierPublicKey = new Fr(12); - const masterIncomingViewingPublicKey = new Fr(34); - const masterOutgoingViewingPublicKey = new Fr(56); - const masterTaggingPublicKey = new Fr(78); + const masterNullifierPublicKey: Point = new Point(new Fr(1), new Fr(2)); + const masterIncomingViewingPublicKey: Point = new Point(new Fr(3), new Fr(4)); + const masterOutgoingViewingPublicKey: Point = new Point(new Fr(5), new Fr(6)); + const masterTaggingPublicKey: Point = new Point(new Fr(7), new Fr(8)); + const partialAddress: PartialAddress = new Fr(69); // TODO(#5726): use computePublicKeysHash function const publicKeysHash = poseidon2Hash([ @@ -82,7 +81,7 @@ describe('Key Registry', () => { }); it('should fail registering with mismatched nullifier public key', async () => { - const mismatchedMasterNullifierPublicKey = Fr.random(); + const mismatchedMasterNullifierPublicKey = Point.random(); await expect( keyRegistry @@ -106,7 +105,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), Point.ZERO) .send() .wait(), ).rejects.toThrow('New nullifier public key must be non-zero'); @@ -116,7 +115,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)) + .methods.rotate_nullifier_public_key(wallets[1].getAddress(), Point.random()) .send() .wait(), ).rejects.toThrow('Assertion failed: Message not authorized by account'); @@ -126,14 +125,13 @@ describe('Key Registry', () => { describe('key registration flow', () => { let accountAddedToRegistry: AztecAddress; + const masterNullifierPublicKey: Point = new Point(new Fr(1), new Fr(2)); it('should generate and register with original keys', async () => { - const partialAddress = new Fr(69); - - const masterNullifierPublicKey = new Fr(12); - const masterIncomingViewingPublicKey = new Fr(34); - const masterOutgoingViewingPublicKey = new Fr(56); - const masterTaggingPublicKey = new Fr(78); + const masterIncomingViewingPublicKey: Point = new Point(new Fr(3), new Fr(4)); + const masterOutgoingViewingPublicKey: Point = new Point(new Fr(5), new Fr(6)); + const masterTaggingPublicKey: Point = new Point(new Fr(7), new Fr(8)); + const partialAddress: PartialAddress = new Fr(69); const publicKeysHash = poseidon2Hash([ masterNullifierPublicKey, @@ -181,86 +179,89 @@ describe('Key Registry', () => { const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(masterNullifierPublicKey.toFields())); }); }); - describe('key rotation flow', () => { - it('we rotate the nullifier key', async () => { - // This changes - const newMasterNullifierPublicKey = new Fr(910); - - await keyRegistry - .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) - .send() - .wait(); - }); - - it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); - - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); - }); - - it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { - await delay(5); - - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); + describe('key rotation flows', () => { + const firstNewMasterNullifierPublicKey = Point.random(); - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); - }); - }); - - describe('key rotation flow with authwit', () => { - it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { + describe('normal key rotation flow', () => { // This changes - const newMasterNullifierPublicKey = new Fr(420); - - const action = keyRegistry - .withWallet(wallets[1]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey); - - await wallets[0] - .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) - .send() - .wait(); - - await action.send().wait(); - }); - - it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); - - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + + it('we rotate the nullifier key', async () => { + await keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), firstNewMasterNullifierPublicKey) + .send() + .wait(); + }); + + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); + }); + + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); + }); }); - - it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { - await delay(5); - - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); - - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(420)); + + describe('key rotation flow with authwit', () => { + // This changes + const secondNewMasterNullifierPublicKey = Point.random(); + + it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { + const action = keyRegistry + .withWallet(wallets[1]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), secondNewMasterNullifierPublicKey); + + await wallets[0] + .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) + .send() + .wait(); + + await action.send().wait(); + }); + + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); + }); + + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(secondNewMasterNullifierPublicKey.toFields())); + }); }); - }); + }) describe('key registration flow no PXE', () => { const masterNullifierPublicKey: Point = new Point(new Fr(9), new Fr(10)); @@ -325,11 +326,12 @@ describe('Key Registry', () => { }); describe('key registration flow via PXE', () => { - const masterNullifierPublicKey: Point = new Point(new Fr(1), new Fr(2)); - const masterIncomingViewingPublicKey: Point = new Point(new Fr(3), new Fr(4)); - const masterOutgoingViewingPublicKey: Point = new Point(new Fr(5), new Fr(6)); - const masterTaggingPublicKey: Point = new Point(new Fr(7), new Fr(8)); - const partialAddress: PartialAddress = new Fr(69); + const masterNullifierPublicKey: Point = new Point(new Fr(17), new Fr(18)); + const masterIncomingViewingPublicKey: Point = new Point(new Fr(19), new Fr(20)); + const masterOutgoingViewingPublicKey: Point = new Point(new Fr(21), new Fr(22)); + const masterTaggingPublicKey: Point = new Point(new Fr(23), new Fr(24)); + + const partialAddress: PartialAddress = new Fr(69420); const publicKeysHash = poseidon2Hash([ masterNullifierPublicKey, @@ -397,7 +399,7 @@ describe('Key Registry', () => { .wait(); }); - it('in the case where the key exists both in the pxe and our registry, we know it works', async () => { + it('in the case where the key exists both in the pxe and our registry, we know nothing weird will happen', async () => { await delay(5); const { txHash } = await testContract.methods diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 867ca8d0824..0a81cc5b1d6 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -44,6 +44,7 @@ export class SimulatorOracle implements DBOracle { return { masterNullifierPublicKey, appNullifierSecretKey }; } + // TODO: #5834 async getCompleteAddress(address: AztecAddress): Promise { const completeAddress = await this.db.getCompleteAddress(address); if (!completeAddress) { @@ -78,6 +79,7 @@ export class SimulatorOracle implements DBOracle { return capsule; } + // TODO: #5834 async getPublicKeysForAddress(address: AztecAddress): Promise { const nullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(address); const incomingViewingPublicKey = await this.keyStore.getMasterIncomingViewingPublicKey(address); diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 8226f58a1bc..3eaf7f9411f 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -175,6 +175,7 @@ export class Oracle { async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { let partialAddress: PartialAddress; let publicKeys: Point[] | undefined; + // TODO #5834: This should be reworked to return the public keys as well try { ({ partialAddress } = await this.typedOracle.getCompleteAddress(AztecAddress.fromField(fromACVMField(address)))); } catch (err) { diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 9287249f1cf..2646898a612 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -64,6 +64,12 @@ export interface DBOracle extends CommitmentsDB { */ popCapsule(): Promise; + /** + * Gets public keys for an address, getCompleteAddress should be modified to include this + * @param The address to look up + * @returns The public keys for a specific address + * TODO: #5834 + */ getPublicKeysForAddress(address: AztecAddress): Promise; /** diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index d2a85c4a242..48c4adc873f 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -166,6 +166,13 @@ export class ViewDataOracle extends TypedOracle { return this.db.popCapsule(); } + + /** + * Gets public keys for an address, getCompleteAddress should be modified to include this + * @param The address to look up + * @returns The public keys for a specific address + * TODO: #5834 + */ public override getPublicKeysForAddress(address: AztecAddress) { return this.db.getPublicKeysForAddress(address); } From f0ece6935a48d79059db942134574bfb483d8345 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 16:49:51 +0000 Subject: [PATCH 010/125] fix --- yarn-project/simulator/src/acvm/oracle/oracle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 3eaf7f9411f..900a99558f9 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -53,7 +53,7 @@ export class Oracle { ]; } - // TODO (ek): Nuke this + // TODO: #5830 Nuke this async getPublicKeyAndPartialAddress([address]: ACVMField[]) { const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddress( AztecAddress.fromField(fromACVMField(address)), From 046100659ec34f09dd36ba7a180485c1ca75e339 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 16:50:55 +0000 Subject: [PATCH 011/125] fix --- yarn-project/simulator/src/acvm/oracle/oracle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 900a99558f9..0aaca5464f9 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -53,7 +53,7 @@ export class Oracle { ]; } - // TODO: #5830 Nuke this + // TODO: #5834 Nuke this async getPublicKeyAndPartialAddress([address]: ACVMField[]) { const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddress( AztecAddress.fromField(fromACVMField(address)), From e4f6d15b5c4d0ca3d209f2e77fbbc0aefc47d871 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 16:52:15 +0000 Subject: [PATCH 012/125] asdf --- yarn-project/pxe/src/pxe_service/pxe_service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index b9ef265e408..b302acf598d 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -219,6 +219,7 @@ export class PXEService implements PXE { public async registerRecipient(recipient: CompleteAddress, publicKeys: Point[] = []): Promise { const wasAdded = await this.db.addCompleteAddress(recipient); + // #5834 if (publicKeys.length !== 0) { await this.keyStore.addPublicKeysForAccount( recipient.address, From f9a844b701c4fd7410343171728917fba335e535 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 16:58:13 +0000 Subject: [PATCH 013/125] fix --- yarn-project/circuit-types/src/interfaces/pxe.ts | 2 +- yarn-project/circuit-types/src/keys/key_store.ts | 7 ++++++- yarn-project/pxe/src/pxe_service/pxe_service.ts | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index f36958df987..eab85b46980 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -73,7 +73,7 @@ export interface PXE { * the recipient's notes. We can send notes to this account because we can encrypt them with the recipient's * public key. */ - // TODO: FIX THIS AFTER THE COMPLETE ADDRESS REFACTOR + // TODO: #5834: FIX THIS AFTER THE COMPLETE ADDRESS REFACTOR registerRecipient(recipient: CompleteAddress, publicKeys?: Point[]): Promise; /** diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index e5cefbd7bc4..dd77bde64ed 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -119,7 +119,12 @@ export interface KeyStore { getPublicKeysHash(account: AztecAddress): Promise; /** - * + * This is used to register a recipient / for storing public keys of an address + * @param accountAddress - The account address to store keys for. + * @param masterNullifierPublicKey - The stored master nullifier public key + * @param masterIncomingViewingPublicKey - The stored incoming viewing public key + * @param masterOutgoingViewingPublicKey - The stored outgoing viewing public key + * @param masterTaggingPublicKey - The stored master tagging public key */ addPublicKeysForAccount( accountAddress: AztecAddress, diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index b302acf598d..c1747a2d6c4 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -219,7 +219,7 @@ export class PXEService implements PXE { public async registerRecipient(recipient: CompleteAddress, publicKeys: Point[] = []): Promise { const wasAdded = await this.db.addCompleteAddress(recipient); - // #5834 + // TODO #5834: This should be refactored to be okay with only adding complete address if (publicKeys.length !== 0) { await this.keyStore.addPublicKeysForAccount( recipient.address, From 0e0b63e3fe7c8c4907c0bfa7c1fce615b818b4c4 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 18:51:05 +0000 Subject: [PATCH 014/125] fix --- .../src/keys/assert_public_key_freshness.nr | 6 +- .../aztec-nr/aztec/src/oracle/keys.nr | 6 +- .../end-to-end/src/e2e_key_registry.test.ts | 90 +++++++++++++------ 3 files changed, 69 insertions(+), 33 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr index 46a9122dc19..dc0915b92e4 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr @@ -44,13 +44,13 @@ pub fn assert_nullifier_public_key_is_fresh( // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly // We read from the canonical Key Registry let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS), derived_slot); - let hashed_nullifier_public_key = registry_private_getter.get_current_value_in_private(); + let hashed_nullifier_public_key_in_registry = registry_private_getter.get_current_value_in_private(); // In the case that the value is not found in the registry we need to manually pass in the address preimage - if (hashed_nullifier_public_key == 0) { + if (hashed_nullifier_public_key_in_registry == 0) { check_public_key_validity(address, PublicKeyType.NULLIFIER, nullifier_public_key_to_test); } else { - assert(hashed_nullifier_public_key == poseidon2_hash(nullifier_public_key_to_test.serialize())); + assert(hashed_nullifier_public_key_in_registry == poseidon2_hash(nullifier_public_key_to_test.serialize())); } } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index ca67986d093..2a7fd4a41ee 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -66,9 +66,9 @@ fn _check_public_key_validity_constrain_oracle( let computed_address = AztecAddress::from_field( poseidon2_hash([ - partial_address.to_field(), - public_keys_hash.to_field(), - GENERATOR_INDEX__CONTRACT_ADDRESS_V1, + partial_address.to_field(), + public_keys_hash.to_field(), + GENERATOR_INDEX__CONTRACT_ADDRESS_V1, ]) ); diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index e11585002cb..6ca01a15d1e 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -42,11 +42,11 @@ describe('Key Registry', () => { let accountAddedToRegistry: AztecAddress; describe('should fail registering with bad input', () => { - const masterNullifierPublicKey: Point = new Point(new Fr(1), new Fr(2)); - const masterIncomingViewingPublicKey: Point = new Point(new Fr(3), new Fr(4)); - const masterOutgoingViewingPublicKey: Point = new Point(new Fr(5), new Fr(6)); - const masterTaggingPublicKey: Point = new Point(new Fr(7), new Fr(8)); - const partialAddress: PartialAddress = new Fr(69); + const masterNullifierPublicKey = Point.random(); + const masterIncomingViewingPublicKey = Point.random(); + const masterOutgoingViewingPublicKey = Point.random(); + const masterTaggingPublicKey = Point.random(); + const partialAddress: PartialAddress = Fr.random(); // TODO(#5726): use computePublicKeysHash function const publicKeysHash = poseidon2Hash([ @@ -59,16 +59,16 @@ describe('Key Registry', () => { // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? - accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + accountAddedToRegistry = AztecAddress.fromField(poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1])); it('should fail registering with mismatched address', async () => { - const mismatchedAddress = Fr.random(); + const mismatchedAddress = AztecAddress.random(); await expect( keyRegistry .withWallet(wallets[0]) .methods.register( - AztecAddress.fromField(mismatchedAddress), + mismatchedAddress, partialAddress, masterNullifierPublicKey, masterIncomingViewingPublicKey, @@ -143,7 +143,7 @@ describe('Key Registry', () => { // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? - accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + accountAddedToRegistry = AztecAddress.fromField(poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1])); await keyRegistry .withWallet(wallets[0]) @@ -186,9 +186,7 @@ describe('Key Registry', () => { describe('key rotation flows', () => { const firstNewMasterNullifierPublicKey = Point.random(); - describe('normal key rotation flow', () => { - // This changes - + describe('normal key rotation flow', () => { it('we rotate the nullifier key', async () => { await keyRegistry .withWallet(wallets[0]) @@ -222,7 +220,7 @@ describe('Key Registry', () => { }); describe('key rotation flow with authwit', () => { - // This changes + // This is the new value const secondNewMasterNullifierPublicKey = Point.random(); it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { @@ -263,11 +261,11 @@ describe('Key Registry', () => { }); }) - describe('key registration flow no PXE', () => { - const masterNullifierPublicKey: Point = new Point(new Fr(9), new Fr(10)); - const masterIncomingViewingPublicKey: Point = new Point(new Fr(11), new Fr(12)); - const masterOutgoingViewingPublicKey: Point = new Point(new Fr(13), new Fr(14)); - const masterTaggingPublicKey: Point = new Point(new Fr(15), new Fr(16)); + describe('test keys are fresh: key registration flow, no PXE', () => { + const masterNullifierPublicKey = Point.random(); + const masterIncomingViewingPublicKey = Point.random(); + const masterOutgoingViewingPublicKey = Point.random(); + const masterTaggingPublicKey = Point.random(); const partialAddress: PartialAddress = new Fr(420); const publicKeysHash = poseidon2Hash([ @@ -280,7 +278,7 @@ describe('Key Registry', () => { // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? - const accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + const accountAddedToRegistry = AztecAddress.fromField(poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1])); it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { await expect( @@ -288,7 +286,7 @@ describe('Key Registry', () => { .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) .send() .wait(), - ).rejects.toThrow(); + ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); }); it('Now we add it to registry', async () => { @@ -312,7 +310,7 @@ describe('Key Registry', () => { .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) .send() .wait(), - ).rejects.toThrow(); + ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); }); it('checks key freshness after a delay, and is successful', async () => { @@ -323,9 +321,24 @@ describe('Key Registry', () => { .send() .wait(); }); + + it('should succeed even if our pxe gives conflicting information', async () => { + // FIX THIS (#5834) + await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), [ + new Point(Fr.random(), Fr.random()), + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ]); + + await testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) + .send() + .wait(); + }); }); - describe('key registration flow via PXE', () => { + describe('test keys are fresh: key registration flow, with PXE', () => { const masterNullifierPublicKey: Point = new Point(new Fr(17), new Fr(18)); const masterIncomingViewingPublicKey: Point = new Point(new Fr(19), new Fr(20)); const masterOutgoingViewingPublicKey: Point = new Point(new Fr(21), new Fr(22)); @@ -343,7 +356,7 @@ describe('Key Registry', () => { // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? - const accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + const accountAddedToRegistry = AztecAddress.fromField(poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1])); it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { await expect( @@ -351,11 +364,27 @@ describe('Key Registry', () => { .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) .send() .wait(), - ).rejects.toThrow(); + ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); + }); + + it('should fail when we register bad keys and the lib checks our pxe', async () => { + const randAddress = AztecAddress.random(); + // FIX THIS (#5834) + await pxe.registerRecipient(CompleteAddress.create(randAddress, Point.ZERO, partialAddress), [ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ]); + + await expect(testContract.methods + .test_nullifier_key_freshness(randAddress, masterNullifierPublicKey) + .send() + .wait()).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); }); it('should succeed because we register our recipient manually and the lib checks our pxe', async () => { - // FIX THIS + // FIX THIS (#5834) await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), [ masterNullifierPublicKey, masterIncomingViewingPublicKey, @@ -368,6 +397,13 @@ describe('Key Registry', () => { .wait(); }); + it('should fail when we put in a different key', async () => { + await expect(testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterIncomingViewingPublicKey) + .send() + .wait()).rejects.toThrow(`Cannot satisfy constraint 'keys[key_type].eq(key)'`); + }); + it('Now we add it to registry', async () => { await keyRegistry .withWallet(wallets[0]) @@ -419,7 +455,7 @@ describe('Key Registry', () => { }); describe('key rotation flow; assert keys are fresh', () => { - const newMasterNullifierPublicKey = new Point(new Fr(910), new Fr(1112)); + const newMasterNullifierPublicKey = Point.random(); it('we rotate the nullifier key', async () => { await keyRegistry @@ -435,7 +471,7 @@ describe('Key Registry', () => { .test_nullifier_key_freshness(wallets[0].getAddress(), newMasterNullifierPublicKey) .send() .wait(), - ).rejects.toThrow(); + ).rejects.toThrow(`Cannot satisfy constraint 'hashed_nullifier_public_key == poseidon2_hash(nullifier_public_key_to_test.serialize())`); }); it('checks our registry contract from test contract and succeeds because the change has been applied', async () => { From 9051c8ebaa0410a8a3a07e7c03e0ac2727db617f Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 19:23:58 +0000 Subject: [PATCH 015/125] format --- .../end-to-end/src/e2e_key_registry.test.ts | 89 +++++++++++-------- .../simulator/src/client/view_data_oracle.ts | 1 - 2 files changed, 53 insertions(+), 37 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 6ca01a15d1e..c719e0a0f5c 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -59,7 +59,9 @@ describe('Key Registry', () => { // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? - accountAddedToRegistry = AztecAddress.fromField(poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1])); + accountAddedToRegistry = AztecAddress.fromField( + poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]), + ); it('should fail registering with mismatched address', async () => { const mismatchedAddress = AztecAddress.random(); @@ -143,7 +145,9 @@ describe('Key Registry', () => { // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? - accountAddedToRegistry = AztecAddress.fromField(poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1])); + accountAddedToRegistry = AztecAddress.fromField( + poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]), + ); await keyRegistry .withWallet(wallets[0]) @@ -186,7 +190,7 @@ describe('Key Registry', () => { describe('key rotation flows', () => { const firstNewMasterNullifierPublicKey = Point.random(); - describe('normal key rotation flow', () => { + describe('normal key rotation flow', () => { it('we rotate the nullifier key', async () => { await keyRegistry .withWallet(wallets[0]) @@ -194,72 +198,78 @@ describe('Key Registry', () => { .send() .wait(); }); - + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); - + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); }); - + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { await delay(5); - + const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); - + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual( + poseidon2Hash(firstNewMasterNullifierPublicKey.toFields()), + ); }); }); - + describe('key rotation flow with authwit', () => { // This is the new value const secondNewMasterNullifierPublicKey = Point.random(); - + it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { const action = keyRegistry .withWallet(wallets[1]) .methods.rotate_nullifier_public_key(wallets[0].getAddress(), secondNewMasterNullifierPublicKey); - + await wallets[0] .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) .send() .wait(); - + await action.send().wait(); }); - + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); - + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual( + poseidon2Hash(firstNewMasterNullifierPublicKey.toFields()), + ); }); - + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { await delay(5); - + const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); - + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(secondNewMasterNullifierPublicKey.toFields())); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual( + poseidon2Hash(secondNewMasterNullifierPublicKey.toFields()), + ); }); }); - }) + }); describe('test keys are fresh: key registration flow, no PXE', () => { const masterNullifierPublicKey = Point.random(); @@ -278,7 +288,9 @@ describe('Key Registry', () => { // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? - const accountAddedToRegistry = AztecAddress.fromField(poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1])); + const accountAddedToRegistry = AztecAddress.fromField( + poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]), + ); it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { await expect( @@ -323,7 +335,7 @@ describe('Key Registry', () => { }); it('should succeed even if our pxe gives conflicting information', async () => { - // FIX THIS (#5834) + // FIX THIS (#5834) await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), [ new Point(Fr.random(), Fr.random()), masterIncomingViewingPublicKey, @@ -356,7 +368,9 @@ describe('Key Registry', () => { // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? - const accountAddedToRegistry = AztecAddress.fromField(poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1])); + const accountAddedToRegistry = AztecAddress.fromField( + poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]), + ); it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { await expect( @@ -369,7 +383,7 @@ describe('Key Registry', () => { it('should fail when we register bad keys and the lib checks our pxe', async () => { const randAddress = AztecAddress.random(); - // FIX THIS (#5834) + // FIX THIS (#5834) await pxe.registerRecipient(CompleteAddress.create(randAddress, Point.ZERO, partialAddress), [ masterNullifierPublicKey, masterIncomingViewingPublicKey, @@ -377,10 +391,9 @@ describe('Key Registry', () => { masterTaggingPublicKey, ]); - await expect(testContract.methods - .test_nullifier_key_freshness(randAddress, masterNullifierPublicKey) - .send() - .wait()).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); + await expect( + testContract.methods.test_nullifier_key_freshness(randAddress, masterNullifierPublicKey).send().wait(), + ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); }); it('should succeed because we register our recipient manually and the lib checks our pxe', async () => { @@ -398,10 +411,12 @@ describe('Key Registry', () => { }); it('should fail when we put in a different key', async () => { - await expect(testContract.methods - .test_nullifier_key_freshness(accountAddedToRegistry, masterIncomingViewingPublicKey) - .send() - .wait()).rejects.toThrow(`Cannot satisfy constraint 'keys[key_type].eq(key)'`); + await expect( + testContract.methods + .test_nullifier_key_freshness(accountAddedToRegistry, masterIncomingViewingPublicKey) + .send() + .wait(), + ).rejects.toThrow(`Cannot satisfy constraint 'keys[key_type].eq(key)'`); }); it('Now we add it to registry', async () => { @@ -471,7 +486,9 @@ describe('Key Registry', () => { .test_nullifier_key_freshness(wallets[0].getAddress(), newMasterNullifierPublicKey) .send() .wait(), - ).rejects.toThrow(`Cannot satisfy constraint 'hashed_nullifier_public_key == poseidon2_hash(nullifier_public_key_to_test.serialize())`); + ).rejects.toThrow( + `Cannot satisfy constraint 'hashed_nullifier_public_key == poseidon2_hash(nullifier_public_key_to_test.serialize())`, + ); }); it('checks our registry contract from test contract and succeeds because the change has been applied', async () => { diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 48c4adc873f..2bc1fbfc937 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -166,7 +166,6 @@ export class ViewDataOracle extends TypedOracle { return this.db.popCapsule(); } - /** * Gets public keys for an address, getCompleteAddress should be modified to include this * @param The address to look up From 6e3509acbb06f7644ef839df8ebb545a0b1f61e9 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 26 Apr 2024 19:48:50 +0000 Subject: [PATCH 016/125] test --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index c719e0a0f5c..ce62bc216ff 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -487,7 +487,7 @@ describe('Key Registry', () => { .send() .wait(), ).rejects.toThrow( - `Cannot satisfy constraint 'hashed_nullifier_public_key == poseidon2_hash(nullifier_public_key_to_test.serialize())`, + `Cannot satisfy constraint 'hashed_nullifier_public_key_in_registry == poseidon2_hash(nullifier_public_key_to_test.serialize())'`, ); }); From afdd9df08a08b100a395f7820b9ff9251e8029cc Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 29 Apr 2024 20:16:10 +0000 Subject: [PATCH 017/125] initial --- .../src/keys/assert_public_key_freshness.nr | 38 ++++++++++++++++--- .../aztec-nr/aztec/src/oracle/keys.nr | 21 +++++----- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr index dc0915b92e4..54c82e76cd3 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr @@ -48,20 +48,48 @@ pub fn assert_nullifier_public_key_is_fresh( // In the case that the value is not found in the registry we need to manually pass in the address preimage if (hashed_nullifier_public_key_in_registry == 0) { - check_public_key_validity(address, PublicKeyType.NULLIFIER, nullifier_public_key_to_test); + check_public_key_validity(address, PublicKeyType.NULLIFIER, nullifier_public_key_to_test, true); } else { assert(hashed_nullifier_public_key_in_registry == poseidon2_hash(nullifier_public_key_to_test.serialize())); } } -fn check_public_key_validity(address: AztecAddress, key_type: u8, key: GrumpkinPoint) { - let keys = get_public_keys_internal(address); +pub fn get_fresh_nullifier_public_key_hash( + context: &mut PrivateContext, + address: AztecAddress, +) -> Field { + // This is the storage slot of the nullifier_public_key inside the key registry contract + let storage_slot_of_nullifier_public_key = 1; + // We have to derive this slot to get the location of the shared mutable inside the Map + // This should mimic how maps derive their slots + let derived_slot = pedersen_hash( + [storage_slot_of_nullifier_public_key, address.to_field()], + 0 + ); + + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + // We read from the canonical Key Registry + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS), derived_slot); + let hashed_nullifier_public_key_in_registry = registry_private_getter.get_current_value_in_private(); + + let nullifier_public_key_hash = if hashed_nullifier_public_key_in_registry == 0 { + let keys = get_public_keys_internal(address, false); + poseidon2_hash(keys[PublicKeyType.NULLIFIER].serialize()) + } else { + hashed_nullifier_public_key_in_registry + }; + + nullifier_public_key_hash +} + +fn check_public_key_validity(address: AztecAddress, key_type: u8, key: GrumpkinPoint, check_validity: bool) { + let keys = get_public_keys_internal(address, check_validity); assert(keys[key_type].eq(key)); } -fn get_public_keys_internal(address: AztecAddress) -> [GrumpkinPoint; 4] { - let (_, public_keys) = oracle::keys::get_public_keys_and_partial_address(address); +fn get_public_keys_internal(address: AztecAddress, check_validity: bool) -> [GrumpkinPoint; 4] { + let (_, public_keys) = oracle::keys::get_public_keys_and_partial_address(address, check_validity); public_keys } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 2a7fd4a41ee..36389f4f418 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -20,7 +20,7 @@ unconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: Azt get_public_keys_and_partial_address_oracle(address) } -pub fn get_public_keys_and_partial_address(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { +pub fn get_public_keys_and_partial_address(address: AztecAddress, check_validity: bool) -> (PartialAddress, [GrumpkinPoint; 4]) { let result = get_public_keys_and_partial_address_oracle_wrapper(address); let partial_address = PartialAddress::from_field(result[0]); @@ -29,14 +29,17 @@ pub fn get_public_keys_and_partial_address(address: AztecAddress) -> (PartialAdd let outgoing_pub_key = GrumpkinPoint::new(result[5], result[6]); let tagging_pub_key = GrumpkinPoint::new(result[7], result[8]); - _check_public_key_validity_constrain_oracle( - address, - partial_address, - nullifier_pub_key, - incoming_pub_key, - outgoing_pub_key, - tagging_pub_key, - ); + // check_validity is only used if the address does not exist in the registry, which means that there has been no key rotation + if (check_validity) { + _check_public_key_validity_constrain_oracle( + address, + partial_address, + nullifier_pub_key, + incoming_pub_key, + outgoing_pub_key, + tagging_pub_key, + ); + } (partial_address, [nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key]) } From 48b0626c45e8ebff9f5016803a43becc950307e0 Mon Sep 17 00:00:00 2001 From: Esau Date: Mon, 29 Apr 2024 22:17:24 +0200 Subject: [PATCH 018/125] initial --- .../aztec/src/context/private_context.nr | 6 +-- .../aztec/src/oracle/nullifier_key.nr | 18 ++++---- .../aztec-nr/value-note/src/value_note.nr | 34 ++++++++------- .../src/subscription_note.nr | 32 +++++++------- .../src/types/token_note.nr | 39 ++++++++--------- .../token_contract/src/types/balances_map.nr | 4 +- .../token_contract/src/types/token_note.nr | 39 ++++++++--------- .../circuit-types/src/keys/key_store.ts | 17 ++++++++ yarn-project/key-store/src/test_key_store.ts | 42 ++++++++++++++++++- .../pxe/src/simulator_oracle/index.ts | 6 +-- .../simulator/src/acvm/oracle/oracle.ts | 4 +- .../simulator/src/client/db_oracle.ts | 4 +- .../simulator/src/client/view_data_oracle.ts | 6 +-- 13 files changed, 160 insertions(+), 91 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 40fe7613575..1614df4670e 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -212,9 +212,9 @@ impl PrivateContext { self.side_effect_counter = self.side_effect_counter + 1; } - pub fn request_app_nullifier_secret_key(&mut self, account: AztecAddress) -> Field { + pub fn request_app_nullifier_secret_key(&mut self, master_public_nullifying_key_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { - let keys = get_nullifier_keys(account); + let keys = get_nullifier_keys(master_public_nullifying_key_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, app_nullifier_secret_key: keys.app_nullifier_secret_key @@ -226,7 +226,7 @@ impl PrivateContext { let keys = self.nullifier_key.unwrap_unchecked(); // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); - assert(keys.account == account, "Cannot query nullifier key for more than one account per call"); + assert(keys.master_nullifier_public_key_hash == master_public_nullifying_key_hash, "Cannot query nullifier key for more than one master_nullifying_public_key_hash per call"); keys }; keys.app_nullifier_secret_key diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 0926fca65e6..69cc8d00f4c 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -2,27 +2,27 @@ use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, // Nullifier keys pertaining to a specific account struct NullifierKeys { - account: AztecAddress, + master_nullifier_public_key_hash: Field, master_nullifier_public_key: GrumpkinPoint, app_nullifier_secret_key: Field, } #[oracle(getNullifierKeys)] -fn get_nullifier_keys_oracle(_account: AztecAddress) -> [Field; 3] {} +fn get_nullifier_keys_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} -unconstrained fn get_nullifier_keys_internal(account: AztecAddress) -> NullifierKeys { - let result = get_nullifier_keys_oracle(account); +unconstrained fn get_nullifier_keys_internal(master_nullifier_public_key_hash: Field) -> NullifierKeys { + let result = get_nullifier_keys_oracle(master_nullifier_public_key_hash); NullifierKeys { - account, + master_nullifier_public_key_hash, master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, app_nullifier_secret_key: result[2], } } -pub fn get_nullifier_keys(account: AztecAddress) -> NullifierKeys { - get_nullifier_keys_internal(account) +pub fn get_nullifier_keys(master_nullifier_public_key_hash: Field) -> NullifierKeys { + get_nullifier_keys_internal(master_nullifier_public_key_hash) } -pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { - get_nullifier_keys_internal(account).app_nullifier_secret_key +pub fn get_app_nullifier_secret_key(master_nullifier_public_key_hash: Field) -> Field { + get_nullifier_keys_internal(master_nullifier_public_key_hash).app_nullifier_secret_key } diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index b67cd8a98dc..3190baa13a1 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -14,7 +14,10 @@ global VALUE_NOTE_LEN: Field = 3; // 3 plus a header. #[aztec(note)] struct ValueNote { value: Field, - owner: AztecAddress, + // the nullifying public key of the person who owns the note. The owner (recipient) to ensure that the note + // can be privately spent. When nullifier secret and encryption private key is same + // we can simply use the owner for this one. + owner_nullifying_public_key_hash: Field, randomness: Field, } // docs:end:value-note-def @@ -24,7 +27,7 @@ impl NoteInterface for ValueNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -36,7 +39,7 @@ impl NoteInterface for ValueNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -46,23 +49,24 @@ impl NoteInterface for ValueNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field) { - let encryption_pub_key = get_public_key(self.owner); - emit_encrypted_log( - context, - (*context).this_address(), - slot, - Self::get_note_type_id(), - encryption_pub_key, - self.serialize_content(), - ); + // TODO (ek): Disabled this until we fix the emit log types + // let encryption_pub_key = get_public_key(self.owner_nullifying_public_key_hash); + // emit_encrypted_log( + // context, + // (*context).this_address(), + // slot, + // Self::get_note_type_id(), + // encryption_pub_key, + // self.serialize_content(), + // ); } } impl ValueNote { - pub fn new(value: Field, owner: AztecAddress) -> Self { + pub fn new(value: Field, owner_nullifying_public_key_hash: Field) -> Self { let randomness = unsafe_rand(); let header = NoteHeader::empty(); - ValueNote { value, owner, randomness, header } + ValueNote { value, randomness, owner_nullifying_public_key_hash, header } } } @@ -70,6 +74,6 @@ impl Serialize<7> for ValueNote { fn serialize(self) -> [Field; 7] { let header = self.header.serialize(); - [self.value, self.owner.to_field(), self.randomness, header[0], header[1], header[2], header[3]] + [self.value, self.owner_nullifying_public_key_hash, self.randomness, header[0], header[1], header[2], header[3]] } } diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index 435f61191b3..8e3afe180bd 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -11,15 +11,18 @@ global SUBSCRIPTION_NOTE_LEN: Field = 3; // TODO: Do we need to include a nonce, in case we want to read/nullify/recreate with the same pubkey value? #[aztec(note)] struct SubscriptionNote { - owner: AztecAddress, expiry_block_number: Field, remaining_txs: Field, + // the nullifying public key of the person who owns the note. The owner (recipient) to ensure that the note + // can be privately spent. When nullifier secret and encryption private key is same + // we can simply use the owner for this one. + owner_nullifying_public_key_hash: Field, } impl NoteInterface for SubscriptionNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -29,7 +32,7 @@ impl NoteInterface for SubscriptionNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -39,20 +42,21 @@ impl NoteInterface for SubscriptionNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field) { - let encryption_pub_key = get_public_key(self.owner); - emit_encrypted_log( - context, - (*context).this_address(), - slot, - Self::get_note_type_id(), - encryption_pub_key, - self.serialize_content(), - ); + // TODO (ek): Disabled this until we fix the emit log types + // let encryption_pub_key = get_public_key(self.owner_nullifying_public_key_hash); + // emit_encrypted_log( + // context, + // (*context).this_address(), + // slot, + // Self::get_note_type_id(), + // encryption_pub_key, + // self.serialize_content(), + // ); } } impl SubscriptionNote { - pub fn new(owner: AztecAddress, expiry_block_number: Field, remaining_txs: Field) -> Self { - SubscriptionNote { owner, expiry_block_number, remaining_txs, header: NoteHeader::empty() } + pub fn new(expiry_block_number: Field, remaining_txs: Field, owner_nullifying_public_key_hash: Field) -> Self { + SubscriptionNote { expiry_block_number, remaining_txs, owner_nullifying_public_key_hash, header: NoteHeader::empty() } } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index 5f6edf94d5f..f37b35c7c83 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -6,9 +6,9 @@ use dep::aztec::{ }; trait OwnedNote { - fn new(amount: U128, owner: AztecAddress) -> Self; + fn new(amount: U128, owner_nullifying_public_key_hash: Field) -> Self; fn get_amount(self) -> U128; - fn get_owner(self) -> AztecAddress; + fn get_owner_nullifying_public_key_hash(self) -> Field; } global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. @@ -17,10 +17,10 @@ global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. struct TokenNote { // the amount of tokens in the note amount: U128, - // the provider of secrets for the nullifier. The owner (recipient) to ensure that the note + // the nullifying public key of the person who owns the note. The owner (recipient) to ensure that the note // can be privately spent. When nullifier secret and encryption private key is same // we can simply use the owner for this one. - owner: AztecAddress, + owner_nullifying_public_key_hash: Field, // randomness of the note to hide contents. randomness: Field, } @@ -29,7 +29,7 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -40,7 +40,7 @@ impl NoteInterface for TokenNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -52,24 +52,25 @@ impl NoteInterface for TokenNote { fn broadcast(self, context: &mut PrivateContext, slot: Field) { // We only bother inserting the note if non-empty to save funds on gas. if !(self.amount == U128::from_integer(0)) { - let encryption_pub_key = get_public_key(self.owner); - emit_encrypted_log( - context, - (*context).this_address(), - slot, - Self::get_note_type_id(), - encryption_pub_key, - self.serialize_content(), - ); + // TODO (ek): Disabled this until we fix the emit log types + // let encryption_pub_key = get_public_key(self.owner_nullifying_public_key_hash); + // emit_encrypted_log( + // context, + // (*context).this_address(), + // slot, + // Self::get_note_type_id(), + // encryption_pub_key, + // self.serialize_content(), + // ); } } } impl OwnedNote for TokenNote { - fn new(amount: U128, owner: AztecAddress) -> Self { + fn new(amount: U128, owner_nullifying_public_key_hash: Field) -> Self { Self { amount, - owner, + owner_nullifying_public_key_hash, randomness: unsafe_rand(), header: NoteHeader::empty(), } @@ -79,7 +80,7 @@ impl OwnedNote for TokenNote { self.amount } - fn get_owner(self) -> AztecAddress { - self.owner + fn get_owner_nullifying_public_key_hash(self) -> Field { + self.owner_nullifying_public_key_hash } } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 0a71bd9891e..605d5a5a647 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -60,7 +60,9 @@ impl BalancesMap { owner: AztecAddress, addend: U128 ) where T: NoteInterface + OwnedNote { - let mut addend_note = T::new(addend, owner); + // Lookup in registry + let nullifier_public_key_hash = 0; + let mut addend_note = T::new(addend, nullifier_public_key_hash); // docs:start:insert self.map.at(owner).insert(&mut addend_note, true); diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 5f6edf94d5f..f37b35c7c83 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -6,9 +6,9 @@ use dep::aztec::{ }; trait OwnedNote { - fn new(amount: U128, owner: AztecAddress) -> Self; + fn new(amount: U128, owner_nullifying_public_key_hash: Field) -> Self; fn get_amount(self) -> U128; - fn get_owner(self) -> AztecAddress; + fn get_owner_nullifying_public_key_hash(self) -> Field; } global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. @@ -17,10 +17,10 @@ global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. struct TokenNote { // the amount of tokens in the note amount: U128, - // the provider of secrets for the nullifier. The owner (recipient) to ensure that the note + // the nullifying public key of the person who owns the note. The owner (recipient) to ensure that the note // can be privately spent. When nullifier secret and encryption private key is same // we can simply use the owner for this one. - owner: AztecAddress, + owner_nullifying_public_key_hash: Field, // randomness of the note to hide contents. randomness: Field, } @@ -29,7 +29,7 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -40,7 +40,7 @@ impl NoteInterface for TokenNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -52,24 +52,25 @@ impl NoteInterface for TokenNote { fn broadcast(self, context: &mut PrivateContext, slot: Field) { // We only bother inserting the note if non-empty to save funds on gas. if !(self.amount == U128::from_integer(0)) { - let encryption_pub_key = get_public_key(self.owner); - emit_encrypted_log( - context, - (*context).this_address(), - slot, - Self::get_note_type_id(), - encryption_pub_key, - self.serialize_content(), - ); + // TODO (ek): Disabled this until we fix the emit log types + // let encryption_pub_key = get_public_key(self.owner_nullifying_public_key_hash); + // emit_encrypted_log( + // context, + // (*context).this_address(), + // slot, + // Self::get_note_type_id(), + // encryption_pub_key, + // self.serialize_content(), + // ); } } } impl OwnedNote for TokenNote { - fn new(amount: U128, owner: AztecAddress) -> Self { + fn new(amount: U128, owner_nullifying_public_key_hash: Field) -> Self { Self { amount, - owner, + owner_nullifying_public_key_hash, randomness: unsafe_rand(), header: NoteHeader::empty(), } @@ -79,7 +80,7 @@ impl OwnedNote for TokenNote { self.amount } - fn get_owner(self) -> AztecAddress { - self.owner + fn get_owner_nullifying_public_key_hash(self) -> Field { + self.owner_nullifying_public_key_hash } } diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index dd77bde64ed..2ce244d91ab 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -31,6 +31,14 @@ export interface KeyStore { */ getAccounts(): Promise; + /** + * Gets the master nullifier public key for a given master nullifier public key hash. + * @throws If the master nullifier public key hash does not exist in the key store. + * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the master nullifier public key. + * @returns The master nullifier public key for the account. + */ + getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise; + /** * Gets the master nullifier public key for a given account. * @throws If the account does not exist in the key store. @@ -72,6 +80,15 @@ export interface KeyStore { */ getAppNullifierSecretKey(account: AztecAddress, app: AztecAddress): Promise; + /** + * Retrieves application nullifier secret key. + * @throws If the masterNullifierPublicKeyHash does not exist in the key store. + * @param masterNullifierPublicKeyHash - The account to retrieve the application nullifier secret key for. + * @param app - The application address to retrieve the nullifier secret key for. + * @returns A Promise that resolves to the application nullifier secret key. + */ + getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr, app: AztecAddress): Promise; + /** * Retrieves application incoming viewing secret key. * @throws If the account does not exist in the key store. diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 288ffc9430d..708dcae15a0 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -58,7 +58,7 @@ export class TestKeyStore implements KeyStore { const accountAddressFr = poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]); const accountAddress = AztecAddress.fromField(accountAddressFr); - // We save the keys to db + // We save the keys to db associated with the account address await this.#keys.set(`${accountAddress.toString()}-public_keys_hash`, publicKeysHash.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); @@ -71,6 +71,11 @@ export class TestKeyStore implements KeyStore { await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); + const masterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + // We save nullifier keys to db under the master nullifier key hash + await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); + await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); + // At last, we return the newly derived account address return Promise.resolve(accountAddress); } @@ -102,6 +107,22 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); } + /** + * Gets the master nullifier public key for a given master nullifier public key hash. + * @throws If the master nullifier public key hash does not exist in the key store. + * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the master nullifier public key. + * @returns The master nullifier public key for the account. + */ + getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise { + const masterNullifierPublicKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-npk_m`); + if (!masterNullifierPublicKeyBuffer) { + throw new Error( + `Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`, + ); + } + return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); + } + /** * Gets the master incoming viewing public key for a given account. * @throws If the account does not exist in the key store. @@ -169,6 +190,25 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(appNullifierSecretKey); } +/** + * Retrieves application nullifier secret key. + * @throws If the masterNullifierPublicKeyHash does not exist in the key store. + * @param masterNullifierPublicKeyHash - The account to retrieve the application nullifier secret key for. + * @param app - The application address to retrieve the nullifier secret key for. + * @returns A Promise that resolves to the application nullifier secret key. + */ + getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr, app: AztecAddress): Promise { + const masterNullifierSecretKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-nsk_m`); + if (!masterNullifierSecretKeyBuffer) { + throw new Error( + `Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`, + ); + } + const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); + const appNullifierSecretKey = computeAppNullifierSecretKey(masterNullifierSecretKey, app); + return Promise.resolve(appNullifierSecretKey); + } + /** * Retrieves application incoming viewing secret key. * @throws If the account does not exist in the key store. diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 0a81cc5b1d6..ec3f317fddf 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -38,9 +38,9 @@ export class SimulatorOracle implements DBOracle { private log = createDebugLogger('aztec:pxe:simulator_oracle'), ) {} - async getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise { - const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(accountAddress); - const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(accountAddress, contractAddress); + async getNullifierKeys(masterNullifierPublicKeyHash: AztecAddress, contractAddress: AztecAddress): Promise { + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash); + const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash, contractAddress); return { masterNullifierPublicKey, appNullifierSecretKey }; } diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 625830ba973..ee3bb211e04 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -42,9 +42,9 @@ export class Oracle { return unpacked.map(toACVMField); } - async getNullifierKeys([accountAddress]: ACVMField[]): Promise { + async getNullifierKeys([masterNullifierPublicKeyHash]: ACVMField[]): Promise { const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( - fromACVMField(accountAddress), + fromACVMField(masterNullifierPublicKeyHash), ); return [ toACVMField(masterNullifierPublicKey.x), diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 2646898a612..c8ec5a6d02a 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -75,12 +75,12 @@ export interface DBOracle extends CommitmentsDB { /** * Retrieve nullifier keys associated with a specific account and app/contract address. * - * @param accountAddress - The account address. + * @param masterNullifierPublicKeyHash - The master nullifer public key hash. * @param contractAddress - The contract address. * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise; + getNullifierKeys(masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 2bc1fbfc937..4222e794dd9 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -37,12 +37,12 @@ export class ViewDataOracle extends TypedOracle { /** * Retrieve nullifier keys associated with a specific account and app/contract address. * - * @param accountAddress - The account address. + * @param masterNullifierPublicKeyHash - The master nullifer public key hash. * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - public override getNullifierKeys(account: AztecAddress): Promise { - return this.db.getNullifierKeys(account, this.contractAddress); + public override getNullifierKeys(masterNullifierPublicKeyHash: Fr): Promise { + return this.db.getNullifierKeys(masterNullifierPublicKeyHash, this.contractAddress); } /** From 0ca8578b0713e104555103eccb87cb9aa3276b91 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 1 May 2024 12:00:42 +0000 Subject: [PATCH 019/125] Addressing comments --- noir-projects/aztec-nr/aztec/src/keys.nr | 4 +- .../src/keys/assert_public_key_freshness.nr | 67 ------ .../aztec-nr/aztec/src/keys/getters.nr | 55 +++++ .../aztec-nr/aztec/src/oracle/keys.nr | 53 +---- .../aztec-nr/aztec/src/state_vars/map.nr | 6 +- .../key_registry_contract/src/main.nr | 34 +-- .../contracts/test_contract/src/main.nr | 28 ++- .../crates/types/src/address/aztec_address.nr | 19 ++ .../types/src/address/public_keys_hash.nr | 27 ++- .../circuit-types/src/keys/key_store.ts | 1 + .../end-to-end/jest.integration.config.json | 2 +- .../end-to-end/src/e2e_key_registry.test.ts | 221 +++++++----------- .../end-to-end/src/e2e_state_vars.test.ts | 18 +- yarn-project/key-store/src/test_key_store.ts | 1 + yarn-project/package.common.json | 2 +- .../simulator/src/acvm/oracle/oracle.ts | 7 +- 16 files changed, 237 insertions(+), 308 deletions(-) delete mode 100644 noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr create mode 100644 noir-projects/aztec-nr/aztec/src/keys/getters.nr diff --git a/noir-projects/aztec-nr/aztec/src/keys.nr b/noir-projects/aztec-nr/aztec/src/keys.nr index 427d30ba671..25249687e3c 100644 --- a/noir-projects/aztec-nr/aztec/src/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/keys.nr @@ -1,3 +1,3 @@ -mod assert_public_key_freshness; +mod getters; -use crate::keys::assert_public_key_freshness::assert_nullifier_public_key_is_fresh; +use crate::keys::getters::get_fresh_nullifier_public_key_hash; diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr deleted file mode 100644 index dc0915b92e4..00000000000 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ /dev/null @@ -1,67 +0,0 @@ -use dep::protocol_types::{ - address::{ - AztecAddress, - PartialAddress - }, - constants::{ - GENERATOR_INDEX__PUBLIC_KEYS_HASH, - GENERATOR_INDEX__CONTRACT_ADDRESS_V1, - CANONICAL_KEY_REGISTRY_ADDRESS - }, - grumpkin_point::GrumpkinPoint, -}; - -use crate::context::PrivateContext; -use crate::hash::{ - pedersen_hash, - poseidon2_hash, -}; -use crate::oracle; -use crate::state_vars::shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter; - -struct PublicKeyTypeEnum { - NULLIFIER: u8, -} - -global PublicKeyType = PublicKeyTypeEnum { - NULLIFIER: 0, -}; - -pub fn assert_nullifier_public_key_is_fresh( - context: &mut PrivateContext, - address: AztecAddress, - nullifier_public_key_to_test: GrumpkinPoint, -) { - // This is the storage slot of the nullifier_public_key inside the key registry contract - let storage_slot_of_nullifier_public_key = 1; - // We have to derive this slot to get the location of the shared mutable inside the Map - // This should mimic how maps derive their slots - let derived_slot = pedersen_hash( - [storage_slot_of_nullifier_public_key, address.to_field()], - 0 - ); - - // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - // We read from the canonical Key Registry - let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS), derived_slot); - let hashed_nullifier_public_key_in_registry = registry_private_getter.get_current_value_in_private(); - - // In the case that the value is not found in the registry we need to manually pass in the address preimage - if (hashed_nullifier_public_key_in_registry == 0) { - check_public_key_validity(address, PublicKeyType.NULLIFIER, nullifier_public_key_to_test); - } else { - assert(hashed_nullifier_public_key_in_registry == poseidon2_hash(nullifier_public_key_to_test.serialize())); - } -} - -fn check_public_key_validity(address: AztecAddress, key_type: u8, key: GrumpkinPoint) { - let keys = get_public_keys_internal(address); - - assert(keys[key_type].eq(key)); -} - -fn get_public_keys_internal(address: AztecAddress) -> [GrumpkinPoint; 4] { - let (_, public_keys) = oracle::keys::get_public_keys_and_partial_address(address); - - public_keys -} diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr new file mode 100644 index 00000000000..321441e7a7e --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -0,0 +1,55 @@ +use dep::protocol_types::{ + address::{ + AztecAddress, + PartialAddress + }, + constants::{ + GENERATOR_INDEX__PUBLIC_KEYS_HASH, + GENERATOR_INDEX__CONTRACT_ADDRESS_V1, + CANONICAL_KEY_REGISTRY_ADDRESS + }, + grumpkin_point::GrumpkinPoint, +}; + +use crate::context::PrivateContext; +use crate::hash::{ + pedersen_hash, + poseidon2_hash, +}; +use crate::oracle; +use crate::state_vars::{ + map::derive_storage_slot_in_map, + shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter, +}; + +struct PublicKeyTypeEnum { + NULLIFIER: u8, +} + +global PublicKeyType = PublicKeyTypeEnum { + NULLIFIER: 0, +}; + +pub fn get_fresh_nullifier_public_key_hash( + context: &mut PrivateContext, + address: AztecAddress, +) -> Field { + // This is the storage slot of the nullifier_public_key inside the key registry contract + let storage_slot_of_nullifier_public_key = 1; + + let derived_slot = derive_storage_slot_in_map(storage_slot_of_nullifier_public_key, address); + + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + // We read from the canonical Key Registry + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS), derived_slot); + let nullifier_public_key_hash_in_registry = registry_private_getter.get_current_value_in_private(); + + let nullifier_public_key_hash = if nullifier_public_key_hash_in_registry == 0 { + let keys = oracle::keys::get_public_keys(address); + poseidon2_hash(keys[PublicKeyType.NULLIFIER].serialize()) + } else { + nullifier_public_key_hash_in_registry + }; + + nullifier_public_key_hash +} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 2a7fd4a41ee..98ea76ed617 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -20,57 +20,24 @@ unconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: Azt get_public_keys_and_partial_address_oracle(address) } -pub fn get_public_keys_and_partial_address(address: AztecAddress) -> (PartialAddress, [GrumpkinPoint; 4]) { +pub fn get_public_keys(address: AztecAddress) -> [GrumpkinPoint; 4] { let result = get_public_keys_and_partial_address_oracle_wrapper(address); - let partial_address = PartialAddress::from_field(result[0]); - let nullifier_pub_key = GrumpkinPoint::new(result[1], result[2]); - let incoming_pub_key = GrumpkinPoint::new(result[3], result[4]); - let outgoing_pub_key = GrumpkinPoint::new(result[5], result[6]); - let tagging_pub_key = GrumpkinPoint::new(result[7], result[8]); + let nullifier_pub_key = GrumpkinPoint::new(result[0], result[1]); + let incoming_pub_key = GrumpkinPoint::new(result[2], result[3]); + let outgoing_pub_key = GrumpkinPoint::new(result[4], result[5]); + let tagging_pub_key = GrumpkinPoint::new(result[6], result[7]); + let partial_address = PartialAddress::from_field(result[8]); - _check_public_key_validity_constrain_oracle( - address, - partial_address, + let computed_address = AztecAddress::compute_from_public_keys_and_partial_address( nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key, - ); - - (partial_address, [nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key]) -} - -fn _check_public_key_validity_constrain_oracle( - address: AztecAddress, - partial_address: PartialAddress, - nullifier_public_key: GrumpkinPoint, - incoming_public_key: GrumpkinPoint, - outgoing_public_key: GrumpkinPoint, - tagging_public_key: GrumpkinPoint - ) { - let public_keys_hash = poseidon2_hash([ - nullifier_public_key.serialize()[0], - nullifier_public_key.serialize()[1], - incoming_public_key.serialize()[0], - incoming_public_key.serialize()[1], - outgoing_public_key.serialize()[0], - outgoing_public_key.serialize()[1], - tagging_public_key.serialize()[0], - tagging_public_key.serialize()[1], - GENERATOR_INDEX__PUBLIC_KEYS_HASH, - ]); - -// TODO: #5830: we can compute this like below once refactored -// let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address); - - let computed_address = AztecAddress::from_field( - poseidon2_hash([ - partial_address.to_field(), - public_keys_hash.to_field(), - GENERATOR_INDEX__CONTRACT_ADDRESS_V1, - ]) + partial_address, ); assert(computed_address.eq(address)); + + [nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key] } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/map.nr b/noir-projects/aztec-nr/aztec/src/state_vars/map.nr index a138a8deb9c..c075578db3f 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/map.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/map.nr @@ -27,10 +27,14 @@ impl Map { // docs:start:at pub fn at(self, key: K) -> V where K: ToField { // TODO(#1204): use a generator index for the storage slot - let derived_storage_slot = pedersen_hash([self.storage_slot, key.to_field()], 0); + let derived_storage_slot = derive_storage_slot_in_map(self.storage_slot, key); let state_var_constructor = self.state_var_constructor; state_var_constructor(self.context, derived_storage_slot) } // docs:end:at } + +pub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField { + pedersen_hash([storage_slot, key.to_field()], 0) +} diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 6124253c417..9d25af0055e 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -25,9 +25,12 @@ contract KeyRegistry { #[aztec(storage)] struct Storage { + //! This should stay at storage slot 1. If you change this, make sure you change the hardcoded value in keys/assert_public_key_freshness. + //! We use this hardcoded storage slot with derive_storage_slot_in_map and the SharedMutablePrivateGetter to directly read the value at an address in this contract. + nullifier_public_key_hash_registry: Map>, + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. // Uncomment lines below to enable that functionality - nullifier_public_key_hash_registry: Map>, // incoming_public_key_registry: Map>, // outgoing_public_key_registry: Map>, // tagging_public_key_registry: Map>, @@ -70,30 +73,13 @@ contract KeyRegistry { "All public keys must be non-zero" ); - // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns - // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); - // let address = AztecAddress::compute(public_keys_hash, partial_address); // We could also pass in original_public_keys_hash instead of computing it here, if all we need the original one is for being able to prove ownership of address - let public_keys_hash = poseidon2_hash([ - nullifier_public_key.serialize()[0], - nullifier_public_key.serialize()[1], - incoming_public_key.serialize()[0], - incoming_public_key.serialize()[1], - outgoing_public_key.serialize()[0], - outgoing_public_key.serialize()[1], - tagging_public_key.serialize()[0], - tagging_public_key.serialize()[1], - GENERATOR_INDEX__PUBLIC_KEYS_HASH, - ] - ); - - let computed_address = AztecAddress::from_field( - poseidon2_hash([ - partial_address.to_field(), - public_keys_hash.to_field(), - GENERATOR_INDEX__CONTRACT_ADDRESS_V1 as Field, - ] - ) + let computed_address = AztecAddress::compute_from_public_keys_and_partial_address( + nullifier_public_key, + incoming_public_key, + outgoing_public_key, + tagging_public_key, + partial_address, ); assert(computed_address.eq(address), "Computed address does not match supplied address"); 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 e84e4b4e596..7349bb9c2c5 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -10,18 +10,18 @@ contract Test { use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, - constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, traits::Serialize, + constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, CANONICAL_KEY_REGISTRY_ADDRESS}, traits::Serialize, grumpkin_point::GrumpkinPoint }; use dep::aztec::note::constants::MAX_NOTES_PER_PAGE; - use dep::aztec::state_vars::shared_mutable::SharedMutablePrivateGetter; + use dep::aztec::state_vars::{shared_mutable::SharedMutablePrivateGetter, map::derive_storage_slot_in_map}; use dep::aztec::{ - keys::assert_public_key_freshness::assert_nullifier_public_key_is_fresh, + keys::getters::get_fresh_nullifier_public_key_hash, context::{Context, inputs::private_context_inputs::PrivateContextInputs}, - hash::{pedersen_hash, compute_secret_hash, ArgsHasher}, + hash::{pedersen_hash, poseidon2_hash, compute_secret_hash, ArgsHasher}, note::{ lifecycle::{create_note, destroy_note}, note_getter::{get_notes, view_notes}, note_getter_options::NoteStatus @@ -379,36 +379,34 @@ contract Test { #[aztec(private)] fn test_shared_mutable_private_getter_for_registry_contract( - contract_address_to_read: AztecAddress, storage_slot_of_shared_mutable: Field, address_to_get_in_registry: AztecAddress - ) { + ) -> Field { // We have to derive this slot to get the location of the shared mutable inside the Map - let derived_slot = dep::aztec::hash::pedersen_hash( - [storage_slot_of_shared_mutable, address_to_get_in_registry.to_field()], - 0 - ); + let derived_slot = derive_storage_slot_in_map(storage_slot_of_shared_mutable, address_to_get_in_registry); + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, derived_slot); + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS), derived_slot); let nullifier_public_key = registry_private_getter.get_current_value_in_private(); - context.emit_unencrypted_log(nullifier_public_key); + nullifier_public_key } #[aztec(private)] fn test_shared_mutable_private_getter( contract_address_to_read: AztecAddress, storage_slot_of_shared_mutable: Field - ) { + ) -> AztecAddress { // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new( context, contract_address_to_read, storage_slot_of_shared_mutable ); + let authorized = test.get_current_value_in_private(); - context.emit_unencrypted_log(authorized); + authorized } #[aztec(private)] @@ -416,7 +414,7 @@ contract Test { address: AztecAddress, public_nullifying_key: GrumpkinPoint, ) { - assert_nullifier_public_key_is_fresh(&mut context, address, public_nullifying_key); + assert_eq(get_fresh_nullifier_public_key_hash(&mut context, address), poseidon2_hash(public_nullifying_key.serialize())); } #[aztec(public)] diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr index fcbae4871d9..06463ce268c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr @@ -61,6 +61,25 @@ impl AztecAddress { ) } + pub fn compute_from_public_keys_and_partial_address( + nullifier_public_key: GrumpkinPoint, + incoming_public_key: GrumpkinPoint, + outgoing_public_key: GrumpkinPoint, + tagging_public_key: GrumpkinPoint, + partial_address: PartialAddress, + ) -> AztecAddress { + let public_keys_hash = PublicKeysHash::compute_new( + nullifier_public_key, + incoming_public_key, + outgoing_public_key, + tagging_public_key, + ); + + let computed_address = AztecAddress::compute(public_keys_hash, partial_address); + + computed_address + } + pub fn is_zero(self) -> bool { self.inner == 0 } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr index dfe3023abb2..9ea508fc140 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr @@ -1,6 +1,7 @@ use crate::{ - constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, grumpkin_point::GrumpkinPoint, - traits::{ToField, Serialize, Deserialize} + constants::{GENERATOR_INDEX__PARTIAL_ADDRESS, GENERATOR_INDEX__PUBLIC_KEYS_HASH}, hash::pedersen_hash, grumpkin_point::GrumpkinPoint, + traits::{ToField, Serialize, Deserialize}, + hash::poseidon2_hash, }; // Public keys hash. Used in the computation of an address. @@ -50,6 +51,28 @@ impl PublicKeysHash { ) } + // TODO(#5830): Use this as the new one + pub fn compute_new( + nullifier_public_key: GrumpkinPoint, + incoming_public_key: GrumpkinPoint, + outgoing_public_key: GrumpkinPoint, + tagging_public_key: GrumpkinPoint + ) -> Self { + PublicKeysHash::from_field( + poseidon2_hash([ + nullifier_public_key.x, + nullifier_public_key.y, + incoming_public_key.x, + incoming_public_key.y, + outgoing_public_key.x, + outgoing_public_key.y, + tagging_public_key.x, + tagging_public_key.y, + GENERATOR_INDEX__PUBLIC_KEYS_HASH, + ]) + ) + } + pub fn to_field(self) -> Field { self.inner } diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index dd77bde64ed..168ec8d5f04 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -126,6 +126,7 @@ export interface KeyStore { * @param masterOutgoingViewingPublicKey - The stored outgoing viewing public key * @param masterTaggingPublicKey - The stored master tagging public key */ + // TODO(#5834): Move this function out of here. Key store should only be used for accounts, not recipients addPublicKeysForAccount( accountAddress: AztecAddress, masterNullifierPublicKey: Point, diff --git a/yarn-project/end-to-end/jest.integration.config.json b/yarn-project/end-to-end/jest.integration.config.json index 721267ff552..84d61df320c 100644 --- a/yarn-project/end-to-end/jest.integration.config.json +++ b/yarn-project/end-to-end/jest.integration.config.json @@ -6,7 +6,7 @@ "moduleNameMapper": { "^(\\.{1,2}/.*)\\.js$": "$1" }, - "reporters": [["default", { "summaryThreshold": 9999 }]], + "reporters": [["default", {"summaryThreshold": 9999}]], "testRegex": "./src/.*\\.test\\.ts$", "rootDir": "./src" } diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index ce62bc216ff..a02e952fecc 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -41,7 +41,7 @@ describe('Key Registry', () => { describe('failure cases', () => { let accountAddedToRegistry: AztecAddress; - describe('should fail registering with bad input', () => { + describe('should fail when registering with different types of invalid input', () => { const masterNullifierPublicKey = Point.random(); const masterIncomingViewingPublicKey = Point.random(); const masterOutgoingViewingPublicKey = Point.random(); @@ -57,13 +57,13 @@ describe('Key Registry', () => { GeneratorIndex.PUBLIC_KEYS_HASH, ]); - // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Move the following line to AztecAddress class? accountAddedToRegistry = AztecAddress.fromField( - poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]), + poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]), ); - it('should fail registering with mismatched address', async () => { + it('should fail when we register with a mismatched address', async () => { const mismatchedAddress = AztecAddress.random(); await expect( @@ -82,7 +82,7 @@ describe('Key Registry', () => { ).rejects.toThrow('Computed address does not match supplied address'); }); - it('should fail registering with mismatched nullifier public key', async () => { + it('should fail when we register with mismatched nullifier public key', async () => { const mismatchedMasterNullifierPublicKey = Point.random(); await expect( @@ -102,8 +102,8 @@ describe('Key Registry', () => { }); }); - describe('should fail when rotating keys with bad input', () => { - it('should fail when trying to rotate setting a 0 key', async () => { + describe('should fail when rotating keys with different types of bad input', () => { + it('should fail when we try to rotate keys, while setting a 0 key', async () => { await expect( keyRegistry .withWallet(wallets[0]) @@ -113,7 +113,7 @@ describe('Key Registry', () => { ).rejects.toThrow('New nullifier public key must be non-zero'); }); - it('should fail when trying to rotate for another address without authwit', async () => { + it('should fail when we try to rotate keys for another address without authwit', async () => { await expect( keyRegistry .withWallet(wallets[0]) @@ -127,13 +127,13 @@ describe('Key Registry', () => { describe('key registration flow', () => { let accountAddedToRegistry: AztecAddress; - const masterNullifierPublicKey: Point = new Point(new Fr(1), new Fr(2)); + const masterNullifierPublicKey = Point.random(); - it('should generate and register with original keys', async () => { - const masterIncomingViewingPublicKey: Point = new Point(new Fr(3), new Fr(4)); - const masterOutgoingViewingPublicKey: Point = new Point(new Fr(5), new Fr(6)); - const masterTaggingPublicKey: Point = new Point(new Fr(7), new Fr(8)); - const partialAddress: PartialAddress = new Fr(69); + it('should generate master public keys, a partial address, and register with the key registry', async () => { + const masterIncomingViewingPublicKey = Point.random(); + const masterOutgoingViewingPublicKey = Point.random(); + const masterTaggingPublicKey = Point.random(); + const partialAddress: PartialAddress = new Fr(420); const publicKeysHash = poseidon2Hash([ masterNullifierPublicKey, @@ -143,10 +143,9 @@ describe('Key Registry', () => { GeneratorIndex.PUBLIC_KEYS_HASH, ]); - // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? accountAddedToRegistry = AztecAddress.fromField( - poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]), + poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]), ); await keyRegistry @@ -161,75 +160,60 @@ describe('Key Registry', () => { ) .send() .wait(); - }); - it('checks our registry contract from test contract and fails because the address has not been registered yet', async () => { - const { txHash } = await testContract.methods + // We check if our registered nullifier key is equal to the key obtained from the getter by + // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet + const emptyNullifierPublicKey = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) - .send() - .wait(); + .simulate(); - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); - }); + expect(new Fr(emptyNullifierPublicKey)).toEqual(Fr.ZERO); - it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { + // We check it again after a delay and expect that the change has been applied and consequently the assert is true await delay(5); - const { txHash } = await testContract.methods + const nullifierPublicKey = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) - .send() - .wait(); + .simulate(); - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(masterNullifierPublicKey.toFields())); + expect(new Fr(nullifierPublicKey)).toEqual(poseidon2Hash(masterNullifierPublicKey.toFields())); }); }); describe('key rotation flows', () => { const firstNewMasterNullifierPublicKey = Point.random(); - describe('normal key rotation flow', () => { - it('we rotate the nullifier key', async () => { + describe('key rotation flow without authwit', () => { + it('we call the key registry to rotate our nullifier key', async () => { await keyRegistry .withWallet(wallets[0]) .methods.rotate_nullifier_public_key(wallets[0].getAddress(), firstNewMasterNullifierPublicKey) .send() .wait(); - }); - - it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); - }); + // We check if our rotated nullifier key is equal to the key obtained from the getter by + // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet + const emptyNullifierPublicKey = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .simulate(); - it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { - await delay(5); + expect(new Fr(emptyNullifierPublicKey)).toEqual(Fr.ZERO); - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); + // We check it again after a delay and expect that the change has been applied and consequently the assert is true + await delay(5); - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + const nullifierPublicKey = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .simulate(); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual( - poseidon2Hash(firstNewMasterNullifierPublicKey.toFields()), - ); + expect(new Fr(nullifierPublicKey)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); }); }); describe('key rotation flow with authwit', () => { - // This is the new value const secondNewMasterNullifierPublicKey = Point.random(); - it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { + it(`wallet 1 rotates wallet 0's nullifying public key with an authwit`, async () => { const action = keyRegistry .withWallet(wallets[1]) .methods.rotate_nullifier_public_key(wallets[0].getAddress(), secondNewMasterNullifierPublicKey); @@ -240,38 +224,28 @@ describe('Key Registry', () => { .wait(); await action.send().wait(); - }); - it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - const { txHash } = await testContract.methods + // We check if our rotated nullifier key is equal to the key obtained from the getter by + // reading our registry contract from the test contract. We expect this value to be the old one, because the new one hasn't been applied + const oldNullifierPublicKey = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); + .simulate(); - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual( - poseidon2Hash(firstNewMasterNullifierPublicKey.toFields()), - ); - }); + expect(new Fr(oldNullifierPublicKey)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); - it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + // We check it again after a delay and expect that the change has been applied and consequently the assert is true await delay(5); - const { txHash } = await testContract.methods + const newNullifierPublicKey = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) - .send() - .wait(); - - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + .simulate(); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual( - poseidon2Hash(secondNewMasterNullifierPublicKey.toFields()), - ); + expect(new Fr(newNullifierPublicKey)).toEqual(poseidon2Hash(secondNewMasterNullifierPublicKey.toFields())); }); }); }); - describe('test keys are fresh: key registration flow, no PXE', () => { + describe('testing get_fresh_nullifier_public_key_hash: key registration flow, no PXE', () => { const masterNullifierPublicKey = Point.random(); const masterIncomingViewingPublicKey = Point.random(); const masterOutgoingViewingPublicKey = Point.random(); @@ -286,10 +260,9 @@ describe('Key Registry', () => { GeneratorIndex.PUBLIC_KEYS_HASH, ]); - // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? const accountAddedToRegistry = AztecAddress.fromField( - poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]), + poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]), ); it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { @@ -301,7 +274,7 @@ describe('Key Registry', () => { ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); }); - it('Now we add it to registry', async () => { + it('adds an entry to the key registry, and checks the key freshness without and with conflicting information from our pxe', async () => { await keyRegistry .withWallet(wallets[0]) .methods.register( @@ -314,28 +287,25 @@ describe('Key Registry', () => { ) .send() .wait(); - }); - it('checks key freshness and fails because the address change has not been applied yet due to lack of delay', async () => { + // We check if our registered nullifier key is equal to the key obtained from the getter by + // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet await expect( testContract.methods .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) .send() .wait(), ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); - }); - it('checks key freshness after a delay, and is successful', async () => { + // We check it again after a delay and expect that the change has been applied and consequently the assert is true await delay(5); await testContract.methods .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) .send() .wait(); - }); - it('should succeed even if our pxe gives conflicting information', async () => { - // FIX THIS (#5834) + // TODO: (#5834) Refactor complete address to move the public keys await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), [ new Point(Fr.random(), Fr.random()), masterIncomingViewingPublicKey, @@ -343,6 +313,7 @@ describe('Key Registry', () => { masterTaggingPublicKey, ]); + // Our check should still succeed even if our pxe gives conflicting information, taking the registry as the source of truth. await testContract.methods .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) .send() @@ -350,12 +321,11 @@ describe('Key Registry', () => { }); }); - describe('test keys are fresh: key registration flow, with PXE', () => { - const masterNullifierPublicKey: Point = new Point(new Fr(17), new Fr(18)); - const masterIncomingViewingPublicKey: Point = new Point(new Fr(19), new Fr(20)); - const masterOutgoingViewingPublicKey: Point = new Point(new Fr(21), new Fr(22)); - const masterTaggingPublicKey: Point = new Point(new Fr(23), new Fr(24)); - + describe('testing assert_nullifier_key_is_fresh: key registration flow, with PXE', () => { + const masterNullifierPublicKey = Point.random(); + const masterIncomingViewingPublicKey = Point.random(); + const masterOutgoingViewingPublicKey = Point.random(); + const masterTaggingPublicKey = Point.random(); const partialAddress: PartialAddress = new Fr(69420); const publicKeysHash = poseidon2Hash([ @@ -366,10 +336,9 @@ describe('Key Registry', () => { GeneratorIndex.PUBLIC_KEYS_HASH, ]); - // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Move the following line to AztecAddress class? const accountAddedToRegistry = AztecAddress.fromField( - poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]), + poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]), ); it('should fail as we have not registered anything to the registry nor have we registered a recipient', async () => { @@ -381,9 +350,9 @@ describe('Key Registry', () => { ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); }); - it('should fail when we register bad keys and the lib checks our pxe', async () => { + it('should fail when we try to check the public keys for a invalid address', async () => { const randAddress = AztecAddress.random(); - // FIX THIS (#5834) + // TODO: (#5834) Refactor complete address to move the public keys await pxe.registerRecipient(CompleteAddress.create(randAddress, Point.ZERO, partialAddress), [ masterNullifierPublicKey, masterIncomingViewingPublicKey, @@ -394,32 +363,24 @@ describe('Key Registry', () => { await expect( testContract.methods.test_nullifier_key_freshness(randAddress, masterNullifierPublicKey).send().wait(), ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); - }); + }) - it('should succeed because we register our recipient manually and the lib checks our pxe', async () => { - // FIX THIS (#5834) + it('adds a recipient to our pxe, and checks the key freshness with and without adding an entry to our key registry', async () => { + // TODO: (#5834) Refactor complete address to move the public keys await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), [ masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, ]); + + // The check should succeed because we register our recipient manually and the lib checks our pxe await testContract.methods .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) .send() .wait(); - }); - - it('should fail when we put in a different key', async () => { - await expect( - testContract.methods - .test_nullifier_key_freshness(accountAddedToRegistry, masterIncomingViewingPublicKey) - .send() - .wait(), - ).rejects.toThrow(`Cannot satisfy constraint 'keys[key_type].eq(key)'`); - }); - it('Now we add it to registry', async () => { + // Now we add the keys to registry await keyRegistry .withWallet(wallets[0]) .methods.register( @@ -432,36 +393,23 @@ describe('Key Registry', () => { ) .send() .wait(); - }); - it('we start the change in the registry, it has not been applied yet, but we still see we have a fresh key due to it being added in the pxe', async () => { - const { txHash } = await testContract.methods + // We check if our rotated nullifier key is equal to the key obtained from the getter by + // reading our registry contract from the test contract. We expect this to be 0 because the change has not been applied yet + const emptyNullifierPublicKey = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) - .send() - .wait(); + .simulate(); - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); + expect(new Fr(emptyNullifierPublicKey)).toEqual(Fr.ZERO); - // Checks freshness of newly added keys, but the change hasn't been affected yet, but we have manually added it to our pxe so it should pass + // We check if our rotated nullifier key is equal to the key obtained from the getter. We expect this to succeed because even though the change + // has not been applied yet to the registry, we have manually the keys to our pxe await testContract.methods .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) .send() .wait(); - }); - - it('in the case where the key exists both in the pxe and our registry, we know nothing weird will happen', async () => { - await delay(5); - - const { txHash } = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) - .send() - .wait(); - - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(poseidon2Hash(masterNullifierPublicKey.toFields())); + // In the case where the key exists both in the pxe and our registry, we know that our assert will still remain true await testContract.methods .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) .send() @@ -469,29 +417,28 @@ describe('Key Registry', () => { }); }); - describe('key rotation flow; assert keys are fresh', () => { + describe('testing assert_nullifier_key_is_fresh: key rotation flow', () => { const newMasterNullifierPublicKey = Point.random(); - it('we rotate the nullifier key', async () => { + it('we rotate the nullifier key and check that the key is fresh', async () => { await keyRegistry .withWallet(wallets[0]) .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) .send() .wait(); - }); - it("checks our registry contract from test contract and fails because the change hasn't been applied yet", async () => { + // We check if our rotated nullifier key is equal to the key obtained from the getter by + // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet await expect( testContract.methods .test_nullifier_key_freshness(wallets[0].getAddress(), newMasterNullifierPublicKey) .send() .wait(), ).rejects.toThrow( - `Cannot satisfy constraint 'hashed_nullifier_public_key_in_registry == poseidon2_hash(nullifier_public_key_to_test.serialize())'`, + `Cannot satisfy constraint 'assert_eq(get_fresh_nullifier_public_key_hash(&mut context, address), poseidon2_hash(public_nullifying_key.serialize()))'`, ); - }); - it('checks our registry contract from test contract and succeeds because the change has been applied', async () => { + // We check it again after a delay and expect that the change has been applied and consequently the assert is true await delay(5); await testContract.methods diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index 8a6ed6dc23e..c9e8609a9c1 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -249,27 +249,21 @@ describe('e2e_state_vars', () => { }, 30_000); it("checks authorized in auth contract from test contract and finds the old value because the change hasn't been applied yet", async () => { - const { txHash } = await testContract.methods + const authorized = await testContract.methods .test_shared_mutable_private_getter(authContract.address, 2) - .send() - .wait(); + .simulate(); - // The function above emits an unencrypted log as a means of returning the data - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); + expect(AztecAddress.fromBigInt(authorized)).toEqual(AztecAddress.ZERO); }); it('checks authorized in auth contract from test contract and finds the correctly set value', async () => { await delay(5); - const { txHash } = await testContract.methods + const authorized = await testContract.methods .test_shared_mutable_private_getter(authContract.address, 2) - .send() - .wait(); + .simulate(); - // The function above emits an unencrypted log as a means of returning the data - const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(6969696969)); + expect(AztecAddress.fromBigInt(authorized)).toEqual(AztecAddress.fromBigInt(6969696969n)); }); }); }); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 288ffc9430d..a3c0d4b239b 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -293,6 +293,7 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(Fr.fromBuffer(publicKeysHashBuffer)); } + // TODO(#5834): Re-add separation between recipients and accounts in keystore. public async addPublicKeysForAccount( accountAddress: AztecAddress, masterNullifierPublicKey: Point, diff --git a/yarn-project/package.common.json b/yarn-project/package.common.json index 6fcf1a28315..80b56a8d697 100644 --- a/yarn-project/package.common.json +++ b/yarn-project/package.common.json @@ -24,7 +24,7 @@ "moduleNameMapper": { "^(\\.{1,2}/.*)\\.[cm]?js$": "$1" }, - "reporters": [["default", { "summaryThreshold": 9999 }]], + "reporters": [["default", {"summaryThreshold": 9999}]], "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$", "rootDir": "./src" } diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 625830ba973..f46990d5ca9 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -173,8 +173,9 @@ export class Oracle { } async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { - let partialAddress: PartialAddress; let publicKeys: Point[] | undefined; + let partialAddress: PartialAddress; + // TODO #5834: This should be reworked to return the public keys as well try { ({ partialAddress } = await this.typedOracle.getCompleteAddress(AztecAddress.fromField(fromACVMField(address)))); @@ -188,9 +189,9 @@ export class Oracle { publicKeys = Array(4).fill(Point.ZERO); } - const acvmKeys = publicKeys.flatMap(key => key.toFields()); + const acvmPublicKeys = publicKeys.flatMap(key => key.toFields()); - return [partialAddress, ...acvmKeys].map(toACVMField); + return [...acvmPublicKeys, partialAddress].map(toACVMField); } async getNotes( From c852740f1700ff71979479e795d7c4c89b877438 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Wed, 1 May 2024 07:09:34 -0500 Subject: [PATCH 020/125] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- yarn-project/circuit-types/src/interfaces/pxe.ts | 2 +- yarn-project/simulator/src/client/db_oracle.ts | 4 ++-- yarn-project/simulator/src/client/view_data_oracle.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index eab85b46980..0e95d024727 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -73,7 +73,7 @@ export interface PXE { * the recipient's notes. We can send notes to this account because we can encrypt them with the recipient's * public key. */ - // TODO: #5834: FIX THIS AFTER THE COMPLETE ADDRESS REFACTOR + // TODO: #5834: Nuke publicKeys optional parameter after `CompleteAddress` refactor. registerRecipient(recipient: CompleteAddress, publicKeys?: Point[]): Promise; /** diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 2646898a612..eb545df6e11 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -65,10 +65,10 @@ export interface DBOracle extends CommitmentsDB { popCapsule(): Promise; /** - * Gets public keys for an address, getCompleteAddress should be modified to include this + * Gets public keys for an address. * @param The address to look up * @returns The public keys for a specific address - * TODO: #5834 + * TODO(#5834): Replace with `getCompleteAddress`. */ getPublicKeysForAddress(address: AztecAddress): Promise; diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 2bc1fbfc937..50dc2552c25 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -167,10 +167,10 @@ export class ViewDataOracle extends TypedOracle { } /** - * Gets public keys for an address, getCompleteAddress should be modified to include this + * Gets public keys for an address. * @param The address to look up * @returns The public keys for a specific address - * TODO: #5834 + * TODO(#5834): Replace with `getCompleteAddress`. */ public override getPublicKeysForAddress(address: AztecAddress) { return this.db.getPublicKeysForAddress(address); From b76ab1a613164f4d8c73133e102f854594380c92 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 1 May 2024 12:56:20 +0000 Subject: [PATCH 021/125] fix --- .../end-to-end/src/e2e_key_registry.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 501e2734cc3..4fb21eb4a99 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -164,7 +164,7 @@ describe('Key Registry', () => { // We check if our registered nullifier key is equal to the key obtained from the getter by // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet const emptyNullifierPublicKey = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .test_shared_mutable_private_getter_for_registry_contract(1, accountAddedToRegistry) .simulate(); expect(new Fr(emptyNullifierPublicKey)).toEqual(Fr.ZERO); @@ -173,7 +173,7 @@ describe('Key Registry', () => { await delay(5); const nullifierPublicKey = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .test_shared_mutable_private_getter_for_registry_contract(1, accountAddedToRegistry) .simulate(); expect(new Fr(nullifierPublicKey)).toEqual(poseidon2Hash(masterNullifierPublicKey.toFields())); @@ -194,7 +194,7 @@ describe('Key Registry', () => { // We check if our rotated nullifier key is equal to the key obtained from the getter by // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet const emptyNullifierPublicKey = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .test_shared_mutable_private_getter_for_registry_contract(1, wallets[0].getAddress()) .simulate(); expect(new Fr(emptyNullifierPublicKey)).toEqual(Fr.ZERO); @@ -203,7 +203,7 @@ describe('Key Registry', () => { await delay(5); const nullifierPublicKey = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .test_shared_mutable_private_getter_for_registry_contract(1, wallets[0].getAddress()) .simulate(); expect(new Fr(nullifierPublicKey)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); @@ -228,7 +228,7 @@ describe('Key Registry', () => { // We check if our rotated nullifier key is equal to the key obtained from the getter by // reading our registry contract from the test contract. We expect this value to be the old one, because the new one hasn't been applied const oldNullifierPublicKey = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .test_shared_mutable_private_getter_for_registry_contract(1, wallets[0].getAddress()) .simulate(); expect(new Fr(oldNullifierPublicKey)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); @@ -237,7 +237,7 @@ describe('Key Registry', () => { await delay(5); const newNullifierPublicKey = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .test_shared_mutable_private_getter_for_registry_contract(1, wallets[0].getAddress()) .simulate(); expect(new Fr(newNullifierPublicKey)).toEqual(poseidon2Hash(secondNewMasterNullifierPublicKey.toFields())); @@ -397,7 +397,7 @@ describe('Key Registry', () => { // We check if our rotated nullifier key is equal to the key obtained from the getter by // reading our registry contract from the test contract. We expect this to be 0 because the change has not been applied yet const emptyNullifierPublicKey = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .test_shared_mutable_private_getter_for_registry_contract(1, accountAddedToRegistry) .simulate(); expect(new Fr(emptyNullifierPublicKey)).toEqual(Fr.ZERO); From 59a4c1894063620d2810b91c3f42cf82bf940477 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 1 May 2024 16:22:05 +0000 Subject: [PATCH 022/125] format --- .../end-to-end/src/e2e_key_registry.test.ts | 43 +++++++++---------- .../end-to-end/src/e2e_state_vars.test.ts | 5 +-- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 4fb21eb4a99..092ee32682d 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -57,7 +57,6 @@ describe('Key Registry', () => { GeneratorIndex.PUBLIC_KEYS_HASH, ]); - // TODO(#5726): Move the following line to AztecAddress class? accountAddedToRegistry = AztecAddress.fromField( poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]), @@ -161,7 +160,7 @@ describe('Key Registry', () => { .send() .wait(); - // We check if our registered nullifier key is equal to the key obtained from the getter by + // We check if our registered nullifier key is equal to the key obtained from the getter by // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet const emptyNullifierPublicKey = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(1, accountAddedToRegistry) @@ -191,22 +190,22 @@ describe('Key Registry', () => { .send() .wait(); - // We check if our rotated nullifier key is equal to the key obtained from the getter by - // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet - const emptyNullifierPublicKey = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(1, wallets[0].getAddress()) - .simulate(); + // We check if our rotated nullifier key is equal to the key obtained from the getter by + // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet + const emptyNullifierPublicKey = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(1, wallets[0].getAddress()) + .simulate(); - expect(new Fr(emptyNullifierPublicKey)).toEqual(Fr.ZERO); + expect(new Fr(emptyNullifierPublicKey)).toEqual(Fr.ZERO); - // We check it again after a delay and expect that the change has been applied and consequently the assert is true - await delay(5); + // We check it again after a delay and expect that the change has been applied and consequently the assert is true + await delay(5); - const nullifierPublicKey = await testContract.methods - .test_shared_mutable_private_getter_for_registry_contract(1, wallets[0].getAddress()) - .simulate(); + const nullifierPublicKey = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(1, wallets[0].getAddress()) + .simulate(); - expect(new Fr(nullifierPublicKey)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); + expect(new Fr(nullifierPublicKey)).toEqual(poseidon2Hash(firstNewMasterNullifierPublicKey.toFields())); }); }); @@ -225,9 +224,9 @@ describe('Key Registry', () => { await action.send().wait(); - // We check if our rotated nullifier key is equal to the key obtained from the getter by - // reading our registry contract from the test contract. We expect this value to be the old one, because the new one hasn't been applied - const oldNullifierPublicKey = await testContract.methods + // We check if our rotated nullifier key is equal to the key obtained from the getter by + // reading our registry contract from the test contract. We expect this value to be the old one, because the new one hasn't been applied + const oldNullifierPublicKey = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(1, wallets[0].getAddress()) .simulate(); @@ -288,7 +287,7 @@ describe('Key Registry', () => { .send() .wait(); - // We check if our registered nullifier key is equal to the key obtained from the getter by + // We check if our registered nullifier key is equal to the key obtained from the getter by // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet await expect( testContract.methods @@ -363,7 +362,7 @@ describe('Key Registry', () => { await expect( testContract.methods.test_nullifier_key_freshness(randAddress, masterNullifierPublicKey).send().wait(), ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); - }) + }); it('adds a recipient to our pxe, and checks the key freshness with and without adding an entry to our key registry', async () => { // TODO: (#5834) Refactor complete address to move the public keys @@ -394,7 +393,7 @@ describe('Key Registry', () => { .send() .wait(); - // We check if our rotated nullifier key is equal to the key obtained from the getter by + // We check if our rotated nullifier key is equal to the key obtained from the getter by // reading our registry contract from the test contract. We expect this to be 0 because the change has not been applied yet const emptyNullifierPublicKey = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(1, accountAddedToRegistry) @@ -402,7 +401,7 @@ describe('Key Registry', () => { expect(new Fr(emptyNullifierPublicKey)).toEqual(Fr.ZERO); - // We check if our rotated nullifier key is equal to the key obtained from the getter. We expect this to succeed because even though the change + // We check if our rotated nullifier key is equal to the key obtained from the getter. We expect this to succeed because even though the change // has not been applied yet to the registry, we have manually the keys to our pxe await testContract.methods .test_nullifier_key_freshness(accountAddedToRegistry, masterNullifierPublicKey) @@ -427,7 +426,7 @@ describe('Key Registry', () => { .send() .wait(); - // We check if our rotated nullifier key is equal to the key obtained from the getter by + // We check if our rotated nullifier key is equal to the key obtained from the getter by // reading our registry contract from the test contract. We expect this to fail because the change has not been applied yet await expect( testContract.methods diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index 426072cf8fc..dcdbdfd9454 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr, type PXE, type Wallet } from '@aztec/aztec.js'; +import { AztecAddress, Fr, type Wallet } from '@aztec/aztec.js'; import { AuthContract, DocsExampleContract, TestContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -8,7 +8,6 @@ import { setup } from './fixtures/utils.js'; const TIMEOUT = 100_000; describe('e2e_state_vars', () => { - let pxe: PXE; jest.setTimeout(TIMEOUT); let wallet: Wallet; @@ -20,7 +19,7 @@ describe('e2e_state_vars', () => { const RANDOMNESS = 2n; beforeAll(async () => { - ({ teardown, wallet, pxe } = await setup(2)); + ({ teardown, wallet } = await setup(2)); contract = await DocsExampleContract.deploy(wallet).send().deployed(); }); From dd9ae574bd05213ee5df72cb3a3e5035610bb04c Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 1 May 2024 18:43:32 +0200 Subject: [PATCH 023/125] test --- .../aztec-nr/value-note/src/value_note.nr | 34 ++++++++----------- .../src/subscription_note.nr | 32 ++++++++--------- 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 3190baa13a1..b67cd8a98dc 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -14,10 +14,7 @@ global VALUE_NOTE_LEN: Field = 3; // 3 plus a header. #[aztec(note)] struct ValueNote { value: Field, - // the nullifying public key of the person who owns the note. The owner (recipient) to ensure that the note - // can be privately spent. When nullifier secret and encryption private key is same - // we can simply use the owner for this one. - owner_nullifying_public_key_hash: Field, + owner: AztecAddress, randomness: Field, } // docs:end:value-note-def @@ -27,7 +24,7 @@ impl NoteInterface for ValueNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); + let secret = context.request_app_nullifier_secret_key(self.owner); poseidon2_hash([ note_hash_for_nullify, secret, @@ -39,7 +36,7 @@ impl NoteInterface for ValueNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); + let secret = get_app_nullifier_secret_key(self.owner); poseidon2_hash([ note_hash_for_nullify, secret, @@ -49,24 +46,23 @@ impl NoteInterface for ValueNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field) { - // TODO (ek): Disabled this until we fix the emit log types - // let encryption_pub_key = get_public_key(self.owner_nullifying_public_key_hash); - // emit_encrypted_log( - // context, - // (*context).this_address(), - // slot, - // Self::get_note_type_id(), - // encryption_pub_key, - // self.serialize_content(), - // ); + let encryption_pub_key = get_public_key(self.owner); + emit_encrypted_log( + context, + (*context).this_address(), + slot, + Self::get_note_type_id(), + encryption_pub_key, + self.serialize_content(), + ); } } impl ValueNote { - pub fn new(value: Field, owner_nullifying_public_key_hash: Field) -> Self { + pub fn new(value: Field, owner: AztecAddress) -> Self { let randomness = unsafe_rand(); let header = NoteHeader::empty(); - ValueNote { value, randomness, owner_nullifying_public_key_hash, header } + ValueNote { value, owner, randomness, header } } } @@ -74,6 +70,6 @@ impl Serialize<7> for ValueNote { fn serialize(self) -> [Field; 7] { let header = self.header.serialize(); - [self.value, self.owner_nullifying_public_key_hash, self.randomness, header[0], header[1], header[2], header[3]] + [self.value, self.owner.to_field(), self.randomness, header[0], header[1], header[2], header[3]] } } diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index 8e3afe180bd..435f61191b3 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -11,18 +11,15 @@ global SUBSCRIPTION_NOTE_LEN: Field = 3; // TODO: Do we need to include a nonce, in case we want to read/nullify/recreate with the same pubkey value? #[aztec(note)] struct SubscriptionNote { + owner: AztecAddress, expiry_block_number: Field, remaining_txs: Field, - // the nullifying public key of the person who owns the note. The owner (recipient) to ensure that the note - // can be privately spent. When nullifier secret and encryption private key is same - // we can simply use the owner for this one. - owner_nullifying_public_key_hash: Field, } impl NoteInterface for SubscriptionNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); + let secret = context.request_app_nullifier_secret_key(self.owner); poseidon2_hash([ note_hash_for_nullify, secret, @@ -32,7 +29,7 @@ impl NoteInterface for SubscriptionNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); + let secret = get_app_nullifier_secret_key(self.owner); poseidon2_hash([ note_hash_for_nullify, secret, @@ -42,21 +39,20 @@ impl NoteInterface for SubscriptionNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field) { - // TODO (ek): Disabled this until we fix the emit log types - // let encryption_pub_key = get_public_key(self.owner_nullifying_public_key_hash); - // emit_encrypted_log( - // context, - // (*context).this_address(), - // slot, - // Self::get_note_type_id(), - // encryption_pub_key, - // self.serialize_content(), - // ); + let encryption_pub_key = get_public_key(self.owner); + emit_encrypted_log( + context, + (*context).this_address(), + slot, + Self::get_note_type_id(), + encryption_pub_key, + self.serialize_content(), + ); } } impl SubscriptionNote { - pub fn new(expiry_block_number: Field, remaining_txs: Field, owner_nullifying_public_key_hash: Field) -> Self { - SubscriptionNote { expiry_block_number, remaining_txs, owner_nullifying_public_key_hash, header: NoteHeader::empty() } + pub fn new(owner: AztecAddress, expiry_block_number: Field, remaining_txs: Field) -> Self { + SubscriptionNote { owner, expiry_block_number, remaining_txs, header: NoteHeader::empty() } } } From 32598c9997b66516858ed3d58674dee501bf7ffd Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 1 May 2024 16:43:39 +0000 Subject: [PATCH 024/125] remove --- .../src/keys/assert_public_key_freshness.nr | 95 ------------------- 1 file changed, 95 deletions(-) delete mode 100644 noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr diff --git a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr b/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr deleted file mode 100644 index 54c82e76cd3..00000000000 --- a/noir-projects/aztec-nr/aztec/src/keys/assert_public_key_freshness.nr +++ /dev/null @@ -1,95 +0,0 @@ -use dep::protocol_types::{ - address::{ - AztecAddress, - PartialAddress - }, - constants::{ - GENERATOR_INDEX__PUBLIC_KEYS_HASH, - GENERATOR_INDEX__CONTRACT_ADDRESS_V1, - CANONICAL_KEY_REGISTRY_ADDRESS - }, - grumpkin_point::GrumpkinPoint, -}; - -use crate::context::PrivateContext; -use crate::hash::{ - pedersen_hash, - poseidon2_hash, -}; -use crate::oracle; -use crate::state_vars::shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter; - -struct PublicKeyTypeEnum { - NULLIFIER: u8, -} - -global PublicKeyType = PublicKeyTypeEnum { - NULLIFIER: 0, -}; - -pub fn assert_nullifier_public_key_is_fresh( - context: &mut PrivateContext, - address: AztecAddress, - nullifier_public_key_to_test: GrumpkinPoint, -) { - // This is the storage slot of the nullifier_public_key inside the key registry contract - let storage_slot_of_nullifier_public_key = 1; - // We have to derive this slot to get the location of the shared mutable inside the Map - // This should mimic how maps derive their slots - let derived_slot = pedersen_hash( - [storage_slot_of_nullifier_public_key, address.to_field()], - 0 - ); - - // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - // We read from the canonical Key Registry - let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS), derived_slot); - let hashed_nullifier_public_key_in_registry = registry_private_getter.get_current_value_in_private(); - - // In the case that the value is not found in the registry we need to manually pass in the address preimage - if (hashed_nullifier_public_key_in_registry == 0) { - check_public_key_validity(address, PublicKeyType.NULLIFIER, nullifier_public_key_to_test, true); - } else { - assert(hashed_nullifier_public_key_in_registry == poseidon2_hash(nullifier_public_key_to_test.serialize())); - } -} - -pub fn get_fresh_nullifier_public_key_hash( - context: &mut PrivateContext, - address: AztecAddress, -) -> Field { - // This is the storage slot of the nullifier_public_key inside the key registry contract - let storage_slot_of_nullifier_public_key = 1; - // We have to derive this slot to get the location of the shared mutable inside the Map - // This should mimic how maps derive their slots - let derived_slot = pedersen_hash( - [storage_slot_of_nullifier_public_key, address.to_field()], - 0 - ); - - // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - // We read from the canonical Key Registry - let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS), derived_slot); - let hashed_nullifier_public_key_in_registry = registry_private_getter.get_current_value_in_private(); - - let nullifier_public_key_hash = if hashed_nullifier_public_key_in_registry == 0 { - let keys = get_public_keys_internal(address, false); - poseidon2_hash(keys[PublicKeyType.NULLIFIER].serialize()) - } else { - hashed_nullifier_public_key_in_registry - }; - - nullifier_public_key_hash -} - -fn check_public_key_validity(address: AztecAddress, key_type: u8, key: GrumpkinPoint, check_validity: bool) { - let keys = get_public_keys_internal(address, check_validity); - - assert(keys[key_type].eq(key)); -} - -fn get_public_keys_internal(address: AztecAddress, check_validity: bool) -> [GrumpkinPoint; 4] { - let (_, public_keys) = oracle::keys::get_public_keys_and_partial_address(address, check_validity); - - public_keys -} From 0f0df8160ef9621b3fc329b9da27d96d73ceb9ca Mon Sep 17 00:00:00 2001 From: Esau Date: Wed, 1 May 2024 18:47:53 +0200 Subject: [PATCH 025/125] another --- .../src/types/token_note.nr | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index f37b35c7c83..5f6edf94d5f 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -6,9 +6,9 @@ use dep::aztec::{ }; trait OwnedNote { - fn new(amount: U128, owner_nullifying_public_key_hash: Field) -> Self; + fn new(amount: U128, owner: AztecAddress) -> Self; fn get_amount(self) -> U128; - fn get_owner_nullifying_public_key_hash(self) -> Field; + fn get_owner(self) -> AztecAddress; } global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. @@ -17,10 +17,10 @@ global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. struct TokenNote { // the amount of tokens in the note amount: U128, - // the nullifying public key of the person who owns the note. The owner (recipient) to ensure that the note + // the provider of secrets for the nullifier. The owner (recipient) to ensure that the note // can be privately spent. When nullifier secret and encryption private key is same // we can simply use the owner for this one. - owner_nullifying_public_key_hash: Field, + owner: AztecAddress, // randomness of the note to hide contents. randomness: Field, } @@ -29,7 +29,7 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); + let secret = context.request_app_nullifier_secret_key(self.owner); poseidon2_hash([ note_hash_for_nullify, secret, @@ -40,7 +40,7 @@ impl NoteInterface for TokenNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); + let secret = get_app_nullifier_secret_key(self.owner); poseidon2_hash([ note_hash_for_nullify, secret, @@ -52,25 +52,24 @@ impl NoteInterface for TokenNote { fn broadcast(self, context: &mut PrivateContext, slot: Field) { // We only bother inserting the note if non-empty to save funds on gas. if !(self.amount == U128::from_integer(0)) { - // TODO (ek): Disabled this until we fix the emit log types - // let encryption_pub_key = get_public_key(self.owner_nullifying_public_key_hash); - // emit_encrypted_log( - // context, - // (*context).this_address(), - // slot, - // Self::get_note_type_id(), - // encryption_pub_key, - // self.serialize_content(), - // ); + let encryption_pub_key = get_public_key(self.owner); + emit_encrypted_log( + context, + (*context).this_address(), + slot, + Self::get_note_type_id(), + encryption_pub_key, + self.serialize_content(), + ); } } } impl OwnedNote for TokenNote { - fn new(amount: U128, owner_nullifying_public_key_hash: Field) -> Self { + fn new(amount: U128, owner: AztecAddress) -> Self { Self { amount, - owner_nullifying_public_key_hash, + owner, randomness: unsafe_rand(), header: NoteHeader::empty(), } @@ -80,7 +79,7 @@ impl OwnedNote for TokenNote { self.amount } - fn get_owner_nullifying_public_key_hash(self) -> Field { - self.owner_nullifying_public_key_hash + fn get_owner(self) -> AztecAddress { + self.owner } } From cf27fc9ee147acb790a887dc7e6354a97d8d6e84 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 1 May 2024 17:21:47 +0000 Subject: [PATCH 026/125] Add support for both --- .../aztec/src/context/private_context.nr | 30 ++++++++++++-- .../aztec/src/oracle/nullifier_key.nr | 40 ++++++++++++++----- .../pxe/src/simulator_oracle/index.ts | 8 +++- .../simulator/src/acvm/oracle/oracle.ts | 13 +++++- .../simulator/src/acvm/oracle/typed_oracle.ts | 4 ++ .../simulator/src/client/db_oracle.ts | 12 +++++- .../simulator/src/client/view_data_oracle.ts | 13 +++++- 7 files changed, 103 insertions(+), 17 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 1614df4670e..47b0a7709b5 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -4,7 +4,7 @@ use crate::{ oracle::{ arguments, returns, call_private_function::call_private_function_internal, enqueue_public_function_call::enqueue_public_function_call_internal, header::get_header_at, - nullifier_key::{get_nullifier_keys, NullifierKeys} + nullifier_key::{get_nullifier_keys, get_nullifier_keys_with_master_nullifier_public_key_hash, NullifierKeys} } }; use dep::protocol_types::{ @@ -212,9 +212,9 @@ impl PrivateContext { self.side_effect_counter = self.side_effect_counter + 1; } - pub fn request_app_nullifier_secret_key(&mut self, master_public_nullifying_key_hash: Field) -> Field { + pub fn request_app_nullifier_secret_key(&mut self, account: AztecAddress) -> Field { let keys = if self.nullifier_key.is_none() { - let keys = get_nullifier_keys(master_public_nullifying_key_hash); + let keys = get_nullifier_keys(account); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, app_nullifier_secret_key: keys.app_nullifier_secret_key @@ -226,7 +226,29 @@ impl PrivateContext { let keys = self.nullifier_key.unwrap_unchecked(); // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); - assert(keys.master_nullifier_public_key_hash == master_public_nullifying_key_hash, "Cannot query nullifier key for more than one master_nullifying_public_key_hash per call"); + assert(keys.account == account, "Cannot query nullifier key for more than one account per call"); + keys + }; + keys.app_nullifier_secret_key + } + + // TODO(ek): Replace above with this + pub fn request_app_nullifier_secret_key_with_master_public_nullifying_key_hash(&mut self, master_public_nullifying_key_hash: Field) -> Field { + let keys = if self.nullifier_key.is_none() { + let keys = get_nullifier_keys_with_master_nullifier_public_key_hash(master_public_nullifying_key_hash); + let request = NullifierKeyValidationRequest { + master_nullifier_public_key: keys.master_nullifier_public_key, + app_nullifier_secret_key: keys.app_nullifier_secret_key + }; + self.nullifier_key_validation_requests.push(request); + self.nullifier_key = Option::some(keys); + keys + } else { + let keys = self.nullifier_key.unwrap_unchecked(); + // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. + assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); + // TODO: (ek) Enable this after we nuke all the accounts + // assert(keys.master_nullifier_public_key_hash == master_public_nullifying_key_hash, "Cannot query nullifier key for more than one master_nullifying_public_key_hash per call"); keys }; keys.app_nullifier_secret_key diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 69cc8d00f4c..13b9fee6469 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -2,27 +2,49 @@ use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, // Nullifier keys pertaining to a specific account struct NullifierKeys { - master_nullifier_public_key_hash: Field, + // TODO: (ek) Replace this with master_nullifier_public_key_hash + account: AztecAddress, master_nullifier_public_key: GrumpkinPoint, app_nullifier_secret_key: Field, } #[oracle(getNullifierKeys)] -fn get_nullifier_keys_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} +fn get_nullifier_keys_oracle(_account: AztecAddress) -> [Field; 3] {} -unconstrained fn get_nullifier_keys_internal(master_nullifier_public_key_hash: Field) -> NullifierKeys { - let result = get_nullifier_keys_oracle(master_nullifier_public_key_hash); +unconstrained fn get_nullifier_keys_internal(account: AztecAddress) -> NullifierKeys { + let result = get_nullifier_keys_oracle(account); NullifierKeys { - master_nullifier_public_key_hash, + account, master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, app_nullifier_secret_key: result[2], } } -pub fn get_nullifier_keys(master_nullifier_public_key_hash: Field) -> NullifierKeys { - get_nullifier_keys_internal(master_nullifier_public_key_hash) +pub fn get_nullifier_keys(account: AztecAddress) -> NullifierKeys { + get_nullifier_keys_internal(account) } -pub fn get_app_nullifier_secret_key(master_nullifier_public_key_hash: Field) -> Field { - get_nullifier_keys_internal(master_nullifier_public_key_hash).app_nullifier_secret_key +pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { + get_nullifier_keys_internal(account).app_nullifier_secret_key +} + +// TODO(ek): Replace the one above with this +#[oracle(getNullifierKeysWithMasterNullifierPublicKeyHash)] +fn get_nullifier_keys_with_master_nullifier_public_key_hash_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} + +unconstrained fn get_nullifier_keys_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash: Field) -> NullifierKeys { + let result = get_nullifier_keys_with_master_nullifier_public_key_hash_oracle(master_nullifier_public_key_hash); + NullifierKeys { + account: AztecAddress::zero(), + master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, + app_nullifier_secret_key: result[2], + } +} + +pub fn get_nullifier_keys_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> NullifierKeys { + get_nullifier_keys_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash) +} + +pub fn get_app_nullifier_secret_key_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> Field { + get_nullifier_keys_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash).app_nullifier_secret_key } diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index ec3f317fddf..ab2978172c3 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -38,7 +38,13 @@ export class SimulatorOracle implements DBOracle { private log = createDebugLogger('aztec:pxe:simulator_oracle'), ) {} - async getNullifierKeys(masterNullifierPublicKeyHash: AztecAddress, contractAddress: AztecAddress): Promise { + async getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise { + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(accountAddress); + const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(accountAddress, contractAddress); + return { masterNullifierPublicKey, appNullifierSecretKey }; + } + + async getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: AztecAddress, contractAddress: AztecAddress): Promise { const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash); const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash, contractAddress); return { masterNullifierPublicKey, appNullifierSecretKey }; diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index d3d37b2efed..bc2aa3bc282 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -42,7 +42,18 @@ export class Oracle { return unpacked.map(toACVMField); } - async getNullifierKeys([masterNullifierPublicKeyHash]: ACVMField[]): Promise { + async getNullifierKeys([accountAddress]: ACVMField[]): Promise { + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( + fromACVMField(accountAddress), + ); + return [ + toACVMField(masterNullifierPublicKey.x), + toACVMField(masterNullifierPublicKey.y), + toACVMField(appNullifierSecretKey), + ]; + } + + async getNullifierKeysWithMasterNullifierPublicKeyHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise { const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( fromACVMField(masterNullifierPublicKeyHash), ); diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index af2be1de22c..738c9e6066d 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -93,6 +93,10 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getNullifierKeys'); } + getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise { + throw new OracleMethodNotAvailableError('getNullifierKeys'); + } + getPublicKeyAndPartialAddress(_address: AztecAddress): Promise { throw new OracleMethodNotAvailableError('getPublicKeyAndPartialAddress'); } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 4e10b61a3ec..eb949e3797c 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -72,6 +72,16 @@ export interface DBOracle extends CommitmentsDB { */ getPublicKeysForAddress(address: AztecAddress): Promise; + /** + * Retrieve nullifier keys associated with a specific account and app/contract address. + * + * @param accountAddress - The account address. + * @param contractAddress - The contract address. + * @returns A Promise that resolves to nullifier keys of a requested account and contract. + * @throws An error if the account is not registered in the database. + */ + getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise; + /** * Retrieve nullifier keys associated with a specific account and app/contract address. * @@ -80,7 +90,7 @@ export interface DBOracle extends CommitmentsDB { * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - getNullifierKeys(masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress): Promise; + getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 4ebf20fadbf..09236481ba4 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -34,6 +34,17 @@ export class ViewDataOracle extends TypedOracle { super(); } +/** + * Retrieve nullifier keys associated with a specific account and app/contract address. + * + * @param accountAddress - The account address. + * @returns A Promise that resolves to nullifier keys of a requested account and contract. + * @throws An error if the account is not registered in the database. + */ + public override getNullifierKeys(account: AztecAddress): Promise { + return this.db.getNullifierKeys(account, this.contractAddress); + } + /** * Retrieve nullifier keys associated with a specific account and app/contract address. * @@ -41,7 +52,7 @@ export class ViewDataOracle extends TypedOracle { * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - public override getNullifierKeys(masterNullifierPublicKeyHash: Fr): Promise { + public override getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise { return this.db.getNullifierKeys(masterNullifierPublicKeyHash, this.contractAddress); } From 194df19b36aef093b785d5113a4a5e33891540c5 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 1 May 2024 18:20:42 +0000 Subject: [PATCH 027/125] Address comments --- .../aztec-nr/aztec/src/keys/getters.nr | 30 ++++++++++++-- .../aztec-nr/aztec/src/oracle/keys.nr | 21 ++-------- .../key_registry_contract/src/main.nr | 4 ++ .../contracts/test_contract/src/main.nr | 39 ++++++++++--------- .../types/src/address/public_keys_hash.nr | 4 +- .../end-to-end/src/e2e_key_registry.test.ts | 10 ++--- 6 files changed, 62 insertions(+), 46 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index 321441e7a7e..bbc0eb2dda8 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -16,7 +16,7 @@ use crate::hash::{ pedersen_hash, poseidon2_hash, }; -use crate::oracle; +use crate::oracle::keys::get_public_keys_and_partial_address; use crate::state_vars::{ map::derive_storage_slot_in_map, shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter, @@ -35,17 +35,19 @@ pub fn get_fresh_nullifier_public_key_hash( address: AztecAddress, ) -> Field { // This is the storage slot of the nullifier_public_key inside the key registry contract + // TODO: (#6133) We should have this be directly imported from the other contract if possible, or at least this should not be this brittle let storage_slot_of_nullifier_public_key = 1; let derived_slot = derive_storage_slot_in_map(storage_slot_of_nullifier_public_key, address); - // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly // We read from the canonical Key Registry + // TODO: (#6134) It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly. + // We should allow for this usecase without needing to hard code it here. let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(*context, AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS), derived_slot); let nullifier_public_key_hash_in_registry = registry_private_getter.get_current_value_in_private(); let nullifier_public_key_hash = if nullifier_public_key_hash_in_registry == 0 { - let keys = oracle::keys::get_public_keys(address); + let keys = get_original_public_keys_internal(address); poseidon2_hash(keys[PublicKeyType.NULLIFIER].serialize()) } else { nullifier_public_key_hash_in_registry @@ -53,3 +55,25 @@ pub fn get_fresh_nullifier_public_key_hash( nullifier_public_key_hash } + +// This constraint only works on keys that have not been rotated, otherwise this call will fail as the public keys are not constrained +fn get_original_public_keys_internal(address: AztecAddress) -> [GrumpkinPoint; 4] { + let (public_keys, partial_address) = get_public_keys_and_partial_address(address); + + let nullifier_pub_key = public_keys[0]; + let incoming_pub_key = public_keys[1]; + let outgoing_pub_key = public_keys[2]; + let tagging_pub_key = public_keys[3]; + + let computed_address = AztecAddress::compute_from_public_keys_and_partial_address( + nullifier_pub_key, + incoming_pub_key, + outgoing_pub_key, + tagging_pub_key, + partial_address, + ); + + assert(computed_address.eq(address)); + + [nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key] +} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 98ea76ed617..d8737a0dd06 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -2,12 +2,7 @@ use dep::protocol_types::{ address::{ AztecAddress, PartialAddress, - PublicKeysHash, }, - constants::{ - GENERATOR_INDEX__PUBLIC_KEYS_HASH, - GENERATOR_INDEX__CONTRACT_ADDRESS_V1, - }, grumpkin_point::GrumpkinPoint, }; @@ -20,7 +15,7 @@ unconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: Azt get_public_keys_and_partial_address_oracle(address) } -pub fn get_public_keys(address: AztecAddress) -> [GrumpkinPoint; 4] { +fn get_public_keys_and_partial_address(address: AztecAddress) -> ([GrumpkinPoint; 4], PartialAddress) { let result = get_public_keys_and_partial_address_oracle_wrapper(address); let nullifier_pub_key = GrumpkinPoint::new(result[0], result[1]); @@ -29,15 +24,5 @@ pub fn get_public_keys(address: AztecAddress) -> [GrumpkinPoint; 4] { let tagging_pub_key = GrumpkinPoint::new(result[6], result[7]); let partial_address = PartialAddress::from_field(result[8]); - let computed_address = AztecAddress::compute_from_public_keys_and_partial_address( - nullifier_pub_key, - incoming_pub_key, - outgoing_pub_key, - tagging_pub_key, - partial_address, - ); - - assert(computed_address.eq(address)); - - [nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key] -} + ([nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key], partial_address) +} \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 9d25af0055e..2d2111d07dd 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -40,14 +40,18 @@ contract KeyRegistry { fn rotate_nullifier_public_key( address: AztecAddress, new_nullifier_public_key: GrumpkinPoint, + nonce: Field, ) { assert( !new_nullifier_public_key.is_zero(), "New nullifier public key must be non-zero" ); + // TODO: (#6137) if (!address.eq(context.msg_sender())) { assert_current_call_valid_authwit_public(&mut context, address); + } else { + assert(nonce == 0, "invalid nonce"); } let nullifier_key_registry = storage.nullifier_public_key_hash_registry.at(address); 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 7349bb9c2c5..29c71837291 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -10,7 +10,7 @@ contract Test { use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, - constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, CANONICAL_KEY_REGISTRY_ADDRESS}, traits::Serialize, + constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, CANONICAL_KEY_REGISTRY_ADDRESS}, traits::{Serialize, ToField, FromField}, grumpkin_point::GrumpkinPoint }; @@ -377,6 +377,26 @@ contract Test { constant.value } + // This function is used in the e2e_state_vars to test the SharedMutablePrivateGetter in isolation + #[aztec(private)] + fn test_shared_mutable_private_getter( + contract_address_to_read: AztecAddress, + storage_slot_of_shared_mutable: Field + ) where T: FromField, T: ToField { + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new( + context, + contract_address_to_read, + storage_slot_of_shared_mutable + ); + + let ret = test.get_current_value_in_private(); + + ret.to_field() + } + + // This function is used for testing the registry contract and fresh public key getters. If nothing exists in the registry, but we have added public + // keys to the pxe, this function will return nothing, but the public key getters will return the correct value #[aztec(private)] fn test_shared_mutable_private_getter_for_registry_contract( storage_slot_of_shared_mutable: Field, @@ -392,23 +412,6 @@ contract Test { nullifier_public_key } - #[aztec(private)] - fn test_shared_mutable_private_getter( - contract_address_to_read: AztecAddress, - storage_slot_of_shared_mutable: Field - ) -> AztecAddress { - // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new( - context, - contract_address_to_read, - storage_slot_of_shared_mutable - ); - - let authorized = test.get_current_value_in_private(); - - authorized - } - #[aztec(private)] fn test_nullifier_key_freshness( address: AztecAddress, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr index 9ea508fc140..bff82cc1644 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr @@ -38,7 +38,7 @@ impl PublicKeysHash { Self { inner: field } } - // TODO(#5830): update this + // TODO(#5830): When we do this refactor, rename compute_new -> compute pub fn compute(public_key: GrumpkinPoint) -> Self { PublicKeysHash::from_field( pedersen_hash( @@ -51,7 +51,7 @@ impl PublicKeysHash { ) } - // TODO(#5830): Use this as the new one + // TODO(#5830): When we do this refactor, rename compute_new -> compute pub fn compute_new( nullifier_public_key: GrumpkinPoint, incoming_public_key: GrumpkinPoint, diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 092ee32682d..ebfc6a07fa1 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -106,7 +106,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), Point.ZERO) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), Point.ZERO, new Fr(1)) .send() .wait(), ).rejects.toThrow('New nullifier public key must be non-zero'); @@ -116,7 +116,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[1].getAddress(), Point.random()) + .methods.rotate_nullifier_public_key(wallets[1].getAddress(), Point.random(), new Fr(1)) .send() .wait(), ).rejects.toThrow('Assertion failed: Message not authorized by account'); @@ -186,7 +186,7 @@ describe('Key Registry', () => { it('we call the key registry to rotate our nullifier key', async () => { await keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), firstNewMasterNullifierPublicKey) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), firstNewMasterNullifierPublicKey, new Fr(1)) .send() .wait(); @@ -215,7 +215,7 @@ describe('Key Registry', () => { it(`wallet 1 rotates wallet 0's nullifying public key with an authwit`, async () => { const action = keyRegistry .withWallet(wallets[1]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), secondNewMasterNullifierPublicKey); + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), secondNewMasterNullifierPublicKey, new Fr(1)); await wallets[0] .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) @@ -422,7 +422,7 @@ describe('Key Registry', () => { it('we rotate the nullifier key and check that the key is fresh', async () => { await keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey, new Fr(1)) .send() .wait(); From a85f5131a497450ce04838369381a613e167f833 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 1 May 2024 19:45:14 +0000 Subject: [PATCH 028/125] fix --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index ebfc6a07fa1..b801beed9e4 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -106,7 +106,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), Point.ZERO, new Fr(1)) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), Point.ZERO, Fr.ZERO) .send() .wait(), ).rejects.toThrow('New nullifier public key must be non-zero'); @@ -116,7 +116,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[1].getAddress(), Point.random(), new Fr(1)) + .methods.rotate_nullifier_public_key(wallets[1].getAddress(), Point.random(), Fr.ZERO) .send() .wait(), ).rejects.toThrow('Assertion failed: Message not authorized by account'); @@ -186,7 +186,7 @@ describe('Key Registry', () => { it('we call the key registry to rotate our nullifier key', async () => { await keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), firstNewMasterNullifierPublicKey, new Fr(1)) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), firstNewMasterNullifierPublicKey, Fr.ZERO) .send() .wait(); @@ -215,7 +215,7 @@ describe('Key Registry', () => { it(`wallet 1 rotates wallet 0's nullifying public key with an authwit`, async () => { const action = keyRegistry .withWallet(wallets[1]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), secondNewMasterNullifierPublicKey, new Fr(1)); + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), secondNewMasterNullifierPublicKey, Fr.ZERO); await wallets[0] .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) @@ -422,7 +422,7 @@ describe('Key Registry', () => { it('we rotate the nullifier key and check that the key is fresh', async () => { await keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey, new Fr(1)) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey, Fr.ZERO) .send() .wait(); From 94db9f592074157afc8c7af2bed61f25f58bc603 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 1 May 2024 20:01:05 +0000 Subject: [PATCH 029/125] Okay --- .../noir-contracts/contracts/test_contract/src/main.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 29c71837291..74f0e049512 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -382,7 +382,7 @@ contract Test { fn test_shared_mutable_private_getter( contract_address_to_read: AztecAddress, storage_slot_of_shared_mutable: Field - ) where T: FromField, T: ToField { + ) -> Field where T: FromField, T: ToField { // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new( context, From 6f0d45777d7930a8e4c5d23a4b0c2b22bdd83423 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 12:39:35 +0000 Subject: [PATCH 030/125] fix good ? --- .../aztec/src/oracle/get_public_key.nr | 19 ++++++++++++++ .../token_contract/src/types/balances_map.nr | 10 +++++--- .../token_contract/src/types/token_note.nr | 25 +++++++++---------- .../circuit-types/src/keys/key_store.ts | 2 ++ yarn-project/key-store/src/test_key_store.ts | 16 +++++++++++- .../pxe/src/simulator_oracle/index.ts | 8 +++++- .../simulator/src/acvm/oracle/oracle.ts | 6 +++++ .../simulator/src/acvm/oracle/typed_oracle.ts | 4 +++ .../simulator/src/client/db_oracle.ts | 2 ++ .../simulator/src/client/view_data_oracle.ts | 4 +++ 10 files changed, 78 insertions(+), 18 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr index a509e8c1b54..f09ba005bbb 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr @@ -18,3 +18,22 @@ pub fn get_public_key(address: AztecAddress) -> GrumpkinPoint { pub_key } + +#[oracle(getPublicKeyAndPartialAddressWithMasterNullifierPublicKeyHash)] +fn get_public_key_and_partial_address_with_master_nullifier_public_key_hash_oracle(master_nullifier_public_key_hash: Field) -> [Field; 3] {} + +unconstrained fn get_public_key_and_partial_address_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash: Field) -> [Field; 3] { + get_public_key_and_partial_address_with_master_nullifier_public_key_hash_oracle(master_nullifier_public_key_hash) +} + +pub fn get_public_key_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> GrumpkinPoint { + let result = get_public_key_and_partial_address_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash); + let pub_key = GrumpkinPoint::new(result[0], result[1]); + let partial_address = PartialAddress::from_field(result[2]); + + // TODO(#5830): disabling the following constraint until we update the oracle according to the new key scheme + // let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address); + // assert(calculated_address.eq(address)); + + pub_key +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 605d5a5a647..e61a07c5c12 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -5,7 +5,8 @@ use dep::aztec::prelude::{ use dep::aztec::{ context::{PublicContext, Context}, hash::pedersen_hash, protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - note::{note_getter::view_notes, note_getter_options::SortOrder} + note::{note_getter::view_notes, note_getter_options::SortOrder}, + keys::getters::get_fresh_nullifier_public_key_hash, }; use crate::types::token_note::{TokenNote, OwnedNote}; @@ -60,8 +61,11 @@ impl BalancesMap { owner: AztecAddress, addend: U128 ) where T: NoteInterface + OwnedNote { - // Lookup in registry - let nullifier_public_key_hash = 0; + // We fetch the nullifier public key hash in the registry / from our PXE + let nullifier_public_key_hash = get_fresh_nullifier_public_key_hash(self.map.context.private.unwrap(), owner); + + dep::aztec::oracle::debug_log::debug_log_array_with_prefix("Nullifier Pub Key Hash", [nullifier_public_key_hash]); + let mut addend_note = T::new(addend, nullifier_public_key_hash); // docs:start:insert diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index f37b35c7c83..a790a9238ac 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -2,7 +2,7 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext, emit_encrypted_log}, protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key, get_public_key::get_public_key} + oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key_with_master_nullifier_public_key_hash, get_public_key::get_public_key_with_master_nullifier_public_key_hash} }; trait OwnedNote { @@ -29,7 +29,7 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); + let secret = context.request_app_nullifier_secret_key_with_master_public_nullifying_key_hash(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -40,7 +40,7 @@ impl NoteInterface for TokenNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner_nullifying_public_key_hash); + let secret = get_app_nullifier_secret_key_with_master_nullifier_public_key_hash(self.owner_nullifying_public_key_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -52,16 +52,15 @@ impl NoteInterface for TokenNote { fn broadcast(self, context: &mut PrivateContext, slot: Field) { // We only bother inserting the note if non-empty to save funds on gas. if !(self.amount == U128::from_integer(0)) { - // TODO (ek): Disabled this until we fix the emit log types - // let encryption_pub_key = get_public_key(self.owner_nullifying_public_key_hash); - // emit_encrypted_log( - // context, - // (*context).this_address(), - // slot, - // Self::get_note_type_id(), - // encryption_pub_key, - // self.serialize_content(), - // ); + let encryption_pub_key = get_public_key_with_master_nullifier_public_key_hash(self.owner_nullifying_public_key_hash); + emit_encrypted_log( + context, + (*context).this_address(), + slot, + Self::get_note_type_id(), + encryption_pub_key, + self.serialize_content(), + ); } } } diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 7fc0a5988cb..c833f40301d 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -135,6 +135,8 @@ export interface KeyStore { */ getPublicKeysHash(account: AztecAddress): Promise; + getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): AztecAddress; + /** * This is used to register a recipient / for storing public keys of an address * @param accountAddress - The account address to store keys for. diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 752660e8953..3454963971d 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -72,9 +72,11 @@ export class TestKeyStore implements KeyStore { await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); const masterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); - // We save nullifier keys to db under the master nullifier key hash + + // We save nullifier keys and account address to db under the master nullifier key hash await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-accountAddress`, accountAddress.toBuffer()); // At last, we return the newly derived account address return Promise.resolve(accountAddress); @@ -333,6 +335,18 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(Fr.fromBuffer(publicKeysHashBuffer)); } + public getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): AztecAddress { + const accountAddressBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-accountAddress`); + + if (!accountAddressBuffer) { + throw new Error( + `Master nullifier public key hash ${masterNullifierPublicKeyHash.toString()} does not exist.`, + ); + } + + return AztecAddress.fromBuffer(accountAddressBuffer); + } + // TODO(#5834): Re-add separation between recipients and accounts in keystore. public async addPublicKeysForAccount( accountAddress: AztecAddress, diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index ab2978172c3..7e4ee2fdd36 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -9,7 +9,7 @@ import { type SiblingPath, } from '@aztec/circuit-types'; import { - type AztecAddress, + AztecAddress, type CompleteAddress, type Fr, type FunctionSelector, @@ -61,6 +61,12 @@ export class SimulatorOracle implements DBOracle { return completeAddress; } + // TODO: #5834 + getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKey: Fr): Promise { + const address = this.keyStore.getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKey); + return this.getCompleteAddress(address); + } + async getContractInstance(address: AztecAddress): Promise { const instance = await this.db.getContractInstance(address); if (!instance) { diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index bc2aa3bc282..d24387315a3 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -72,6 +72,12 @@ export class Oracle { return [publicKey.x, publicKey.y, partialAddress].map(toACVMField); } + // TODO: #5834 Nuke this + async getPublicKeyAndPartialAddressWithMasterNullifierPublicKeyHash([masterNullifierPublicKeyHash]: ACVMField[]) { + const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddressWithMasterNullifierPublicKey(fromACVMField(masterNullifierPublicKeyHash)); + return [publicKey.x, publicKey.y, partialAddress].map(toACVMField); + } + async getContractInstance([address]: ACVMField[]) { const instance = await this.typedOracle.getContractInstance(AztecAddress.fromField(fromACVMField(address))); diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 738c9e6066d..92481d7898c 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -136,6 +136,10 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getCompleteAddress'); } + getCompleteAddressWithMasterNullifierPublicKey(_masterNullifierPublicKeyHash: Fr): Promise { + throw new OracleMethodNotAvailableError('getCompleteAddressWithMasterNullifierPublicKey'); + } + getAuthWitness(_messageHash: Fr): Promise { throw new OracleMethodNotAvailableError('getAuthWitness'); } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index eb949e3797c..58689cd2b89 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -50,6 +50,8 @@ export interface DBOracle extends CommitmentsDB { */ getCompleteAddress(address: AztecAddress): Promise; + getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKey: Fr): Promise; + /** * Retrieve the auth witness for a given message hash. * @param messageHash - The message hash. diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 09236481ba4..4360e7f8c18 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -147,6 +147,10 @@ export class ViewDataOracle extends TypedOracle { return this.db.getCompleteAddress(address); } + public override getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKeyHash: Fr): Promise { + return this.db.getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKeyHash); + } + /** * Returns a contract instance associated with an address or throws if not found. * @param address - Address. From 2f19996a9455198548229411e6dcb1efc4ba41a0 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 13:48:32 +0000 Subject: [PATCH 031/125] fix --- yarn-project/key-store/src/test_key_store.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 3454963971d..1dd1b51c288 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -61,7 +61,7 @@ export class TestKeyStore implements KeyStore { // We save the keys to db associated with the account address await this.#keys.set(`${accountAddress.toString()}-public_keys_hash`, publicKeysHash.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-nsk_m-account`, masterNullifierSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer()); @@ -74,7 +74,7 @@ export class TestKeyStore implements KeyStore { const masterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); // We save nullifier keys and account address to db under the master nullifier key hash - await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); + await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-nsk_m-mnpk`, masterNullifierSecretKey.toBuffer()); await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-accountAddress`, accountAddress.toBuffer()); @@ -88,8 +88,8 @@ export class TestKeyStore implements KeyStore { */ public getAccounts(): Promise { const allMapKeys = Array.from(this.#keys.keys()); - // We return account addresses based on the map keys that end with '-nsk_m' - const accounts = allMapKeys.filter(key => key.endsWith('-nsk_m')).map(key => key.split('-')[0]); + // We return account addresses based on the map keys that end with '-nsk_m-account' + const accounts = allMapKeys.filter(key => key.endsWith('-nsk_m-account')).map(key => key.split('-')[0]); return Promise.resolve(accounts.map(account => AztecAddress.fromString(account))); } @@ -181,7 +181,7 @@ export class TestKeyStore implements KeyStore { * @returns A Promise that resolves to the application nullifier secret key. */ public async getAppNullifierSecretKey(account: AztecAddress, app: AztecAddress): Promise { - const masterNullifierSecretKeyBuffer = this.#keys.get(`${account.toString()}-nsk_m`); + const masterNullifierSecretKeyBuffer = this.#keys.get(`${account.toString()}-nsk_m-account`); if (!masterNullifierSecretKeyBuffer) { throw new Error( `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, @@ -200,7 +200,7 @@ export class TestKeyStore implements KeyStore { * @returns A Promise that resolves to the application nullifier secret key. */ getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr, app: AztecAddress): Promise { - const masterNullifierSecretKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-nsk_m`); + const masterNullifierSecretKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-nsk_m-mnpk`); if (!masterNullifierSecretKeyBuffer) { throw new Error( `Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`, @@ -278,7 +278,7 @@ export class TestKeyStore implements KeyStore { // We extract the account address from the map key const accountAddress = key.split('-')[0]; // We fetch the secret key and return it - const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountAddress.toString()}-nsk_m`); + const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountAddress.toString()}-nsk_m-account`); if (!masterNullifierSecretKeyBuffer) { throw new Error(`Could not find master nullifier secret key for account ${accountAddress.toString()}`); } From fffee53bc4a14aee49b63bf2a131adfeda4028f5 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 13:50:24 +0000 Subject: [PATCH 032/125] fmt --- .../circuit-types/src/keys/key_store.ts | 5 ++- yarn-project/key-store/src/test_key_store.ts | 33 +++++++++---------- .../pxe/src/simulator_oracle/index.ts | 16 ++++++--- .../simulator/src/acvm/oracle/oracle.ts | 8 +++-- .../simulator/src/acvm/oracle/typed_oracle.ts | 2 +- .../simulator/src/client/db_oracle.ts | 5 ++- .../simulator/src/client/view_data_oracle.ts | 22 ++++++++----- 7 files changed, 55 insertions(+), 36 deletions(-) diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index c833f40301d..3fb41d6c0e1 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -87,7 +87,10 @@ export interface KeyStore { * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ - getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr, app: AztecAddress): Promise; + getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash( + masterNullifierPublicKeyHash: Fr, + app: AztecAddress, + ): Promise; /** * Retrieves application incoming viewing secret key. diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 1dd1b51c288..6e811730470 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -109,7 +109,7 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); } - /** + /** * Gets the master nullifier public key for a given master nullifier public key hash. * @throws If the master nullifier public key hash does not exist in the key store. * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the master nullifier public key. @@ -118,9 +118,7 @@ export class TestKeyStore implements KeyStore { getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise { const masterNullifierPublicKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-npk_m`); if (!masterNullifierPublicKeyBuffer) { - throw new Error( - `Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`, - ); + throw new Error(`Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); } return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); } @@ -192,19 +190,20 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(appNullifierSecretKey); } -/** - * Retrieves application nullifier secret key. - * @throws If the masterNullifierPublicKeyHash does not exist in the key store. - * @param masterNullifierPublicKeyHash - The account to retrieve the application nullifier secret key for. - * @param app - The application address to retrieve the nullifier secret key for. - * @returns A Promise that resolves to the application nullifier secret key. - */ - getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr, app: AztecAddress): Promise { + /** + * Retrieves application nullifier secret key. + * @throws If the masterNullifierPublicKeyHash does not exist in the key store. + * @param masterNullifierPublicKeyHash - The account to retrieve the application nullifier secret key for. + * @param app - The application address to retrieve the nullifier secret key for. + * @returns A Promise that resolves to the application nullifier secret key. + */ + getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash( + masterNullifierPublicKeyHash: Fr, + app: AztecAddress, + ): Promise { const masterNullifierSecretKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-nsk_m-mnpk`); if (!masterNullifierSecretKeyBuffer) { - throw new Error( - `Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`, - ); + throw new Error(`Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); } const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); const appNullifierSecretKey = computeAppNullifierSecretKey(masterNullifierSecretKey, app); @@ -339,9 +338,7 @@ export class TestKeyStore implements KeyStore { const accountAddressBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-accountAddress`); if (!accountAddressBuffer) { - throw new Error( - `Master nullifier public key hash ${masterNullifierPublicKeyHash.toString()} does not exist.`, - ); + throw new Error(`Master nullifier public key hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); } return AztecAddress.fromBuffer(accountAddressBuffer); diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 7e4ee2fdd36..ff0dcd28648 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -9,7 +9,7 @@ import { type SiblingPath, } from '@aztec/circuit-types'; import { - AztecAddress, + type AztecAddress, type CompleteAddress, type Fr, type FunctionSelector, @@ -44,9 +44,17 @@ export class SimulatorOracle implements DBOracle { return { masterNullifierPublicKey, appNullifierSecretKey }; } - async getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: AztecAddress, contractAddress: AztecAddress): Promise { - const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash); - const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash, contractAddress); + async getNullifierKeysWithMasterNullifierPublicKeyHash( + masterNullifierPublicKeyHash: AztecAddress, + contractAddress: AztecAddress, + ): Promise { + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash( + masterNullifierPublicKeyHash, + ); + const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash( + masterNullifierPublicKeyHash, + contractAddress, + ); return { masterNullifierPublicKey, appNullifierSecretKey }; } diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index d24387315a3..099e794ec32 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -53,7 +53,9 @@ export class Oracle { ]; } - async getNullifierKeysWithMasterNullifierPublicKeyHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise { + async getNullifierKeysWithMasterNullifierPublicKeyHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise< + ACVMField[] + > { const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( fromACVMField(masterNullifierPublicKeyHash), ); @@ -74,7 +76,9 @@ export class Oracle { // TODO: #5834 Nuke this async getPublicKeyAndPartialAddressWithMasterNullifierPublicKeyHash([masterNullifierPublicKeyHash]: ACVMField[]) { - const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddressWithMasterNullifierPublicKey(fromACVMField(masterNullifierPublicKeyHash)); + const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddressWithMasterNullifierPublicKey( + fromACVMField(masterNullifierPublicKeyHash), + ); return [publicKey.x, publicKey.y, partialAddress].map(toACVMField); } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 92481d7898c..6e36bdd0f15 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -93,7 +93,7 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getNullifierKeys'); } - getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise { + getNullifierKeysWithMasterNullifierPublicKeyHash(_masterNullifierPublicKeyHash: Fr): Promise { throw new OracleMethodNotAvailableError('getNullifierKeys'); } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 58689cd2b89..b133861d6af 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -92,7 +92,10 @@ export interface DBOracle extends CommitmentsDB { * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress): Promise; + getNullifierKeysWithMasterNullifierPublicKeyHash( + masterNullifierPublicKeyHash: Fr, + contractAddress: AztecAddress, + ): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 4360e7f8c18..c8a34bb8e86 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -34,13 +34,13 @@ export class ViewDataOracle extends TypedOracle { super(); } -/** - * Retrieve nullifier keys associated with a specific account and app/contract address. - * - * @param accountAddress - The account address. - * @returns A Promise that resolves to nullifier keys of a requested account and contract. - * @throws An error if the account is not registered in the database. - */ + /** + * Retrieve nullifier keys associated with a specific account and app/contract address. + * + * @param accountAddress - The account address. + * @returns A Promise that resolves to nullifier keys of a requested account and contract. + * @throws An error if the account is not registered in the database. + */ public override getNullifierKeys(account: AztecAddress): Promise { return this.db.getNullifierKeys(account, this.contractAddress); } @@ -52,7 +52,9 @@ export class ViewDataOracle extends TypedOracle { * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - public override getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise { + public override getNullifierKeysWithMasterNullifierPublicKeyHash( + masterNullifierPublicKeyHash: Fr, + ): Promise { return this.db.getNullifierKeys(masterNullifierPublicKeyHash, this.contractAddress); } @@ -147,7 +149,9 @@ export class ViewDataOracle extends TypedOracle { return this.db.getCompleteAddress(address); } - public override getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKeyHash: Fr): Promise { + public override getCompleteAddressWithMasterNullifierPublicKey( + masterNullifierPublicKeyHash: Fr, + ): Promise { return this.db.getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKeyHash); } From 4416ccb9daa5e89e4f7174bab6a2e046a51d4c98 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 14:16:22 +0000 Subject: [PATCH 033/125] fix --- .../contracts/token_contract/src/types/token_note.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 601ecd982af..47c9e4db84a 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -52,7 +52,7 @@ impl NoteInterface for TokenNote { fn broadcast(self, context: &mut PrivateContext, slot: Field) { // We only bother inserting the note if non-empty to save funds on gas. if !(self.amount == U128::from_integer(0)) { - let encryption_pub_key = get_public_key_with_master_nullifier_public_key_hash(self.owner); + let encryption_pub_key = get_public_key_with_master_nullifier_public_key_hash(self.owner_nullifying_public_key_hash); context.emit_encrypted_log( (*context).this_address(), slot, From c4a745f219ca6d1224a7541c0c1b03406afc95c8 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 19:15:24 +0000 Subject: [PATCH 034/125] Fix --- .../aztec-nr/aztec/src/context/private_context.nr | 6 ++++-- .../aztec-nr/aztec/src/oracle/get_public_key.nr | 1 + noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr | 2 +- .../contracts/token_contract/src/types/balances_map.nr | 2 -- yarn-project/circuit-types/src/keys/key_store.ts | 6 ++++++ yarn-project/key-store/src/test_key_store.ts | 6 ++++++ yarn-project/simulator/src/client/db_oracle.ts | 5 +++++ yarn-project/simulator/src/client/view_data_oracle.ts | 9 ++++++--- 8 files changed, 29 insertions(+), 8 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index f37123a464d..64d7ce3ab8d 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -223,10 +223,12 @@ impl PrivateContext { keys.app_nullifier_secret_key } - // TODO(ek): Replace above with this + // TODO(ek): Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address pub fn request_app_nullifier_secret_key_with_master_public_nullifying_key_hash(&mut self, master_public_nullifying_key_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { let keys = get_nullifier_keys_with_master_nullifier_public_key_hash(master_public_nullifying_key_hash); + // Should we inside here constrain the below? + // assert(keys.master_nullifier_public_key_hash == master_public_nullifying_key_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, app_nullifier_secret_key: keys.app_nullifier_secret_key @@ -238,7 +240,7 @@ impl PrivateContext { let keys = self.nullifier_key.unwrap_unchecked(); // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); - // TODO: (ek) Enable this after we nuke all the accounts + // TODO: (ek) Enable this after we nuke the account in all notes and when NullifierKeys has a reference to master_nullifier_public_key_hash // assert(keys.master_nullifier_public_key_hash == master_public_nullifying_key_hash, "Cannot query nullifier key for more than one master_nullifying_public_key_hash per call"); keys }; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr index f09ba005bbb..08ef83bf0db 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr @@ -26,6 +26,7 @@ unconstrained fn get_public_key_and_partial_address_with_master_nullifier_public get_public_key_and_partial_address_with_master_nullifier_public_key_hash_oracle(master_nullifier_public_key_hash) } +// TODO: This is used when we emit encrypted logs and will be changed. pub fn get_public_key_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> GrumpkinPoint { let result = get_public_key_and_partial_address_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash); let pub_key = GrumpkinPoint::new(result[0], result[1]); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 13b9fee6469..cb17de88ba8 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -28,7 +28,7 @@ pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { get_nullifier_keys_internal(account).app_nullifier_secret_key } -// TODO(ek): Replace the one above with this +// TODO(ek): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address #[oracle(getNullifierKeysWithMasterNullifierPublicKeyHash)] fn get_nullifier_keys_with_master_nullifier_public_key_hash_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 687755f9880..249a5f5ed7c 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -64,8 +64,6 @@ impl BalancesMap { // We fetch the nullifier public key hash in the registry / from our PXE let nullifier_public_key_hash = get_fresh_nullifier_public_key_hash(self.map.context.private.unwrap(), owner); - dep::aztec::oracle::debug_log::debug_log_array_with_prefix("Nullifier Pub Key Hash", [nullifier_public_key_hash]); - let mut addend_note = T::new(addend, nullifier_public_key_hash); // docs:start:insert diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 3fb41d6c0e1..2a149cca2ad 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -138,6 +138,12 @@ export interface KeyStore { */ getPublicKeysHash(account: AztecAddress): Promise; + /** + * Gets the account address for a given master nullifier public key hash. + * @throws If the master nullifier public key hash does not exist in the key store. + * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the address. + * @returns The address for the account. + */ getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): AztecAddress; /** diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 6e811730470..4fc79e14fab 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -334,6 +334,12 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(Fr.fromBuffer(publicKeysHashBuffer)); } + /** + * Gets the account address for a given master nullifier public key hash. + * @throws If the master nullifier public key hash does not exist in the key store. + * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the address. + * @returns The address for the account. + */ public getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): AztecAddress { const accountAddressBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-accountAddress`); diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index b133861d6af..ed95fc80089 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -50,6 +50,11 @@ export interface DBOracle extends CommitmentsDB { */ getCompleteAddress(address: AztecAddress): Promise; + /** + * Retrieve the complete address associated to a given master nullifier public key hash. + * @param masterNullifierPublicKeyHash - Master nullifier public key hash to fetch the complete address for. + * @returns A complete address associated with the input master nullifier public key hash. + */ getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKey: Fr): Promise; /** diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index c8a34bb8e86..7dfd82125b2 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -36,7 +36,6 @@ export class ViewDataOracle extends TypedOracle { /** * Retrieve nullifier keys associated with a specific account and app/contract address. - * * @param accountAddress - The account address. * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. @@ -46,8 +45,7 @@ export class ViewDataOracle extends TypedOracle { } /** - * Retrieve nullifier keys associated with a specific account and app/contract address. - * + * Retrieve nullifier keys associated with a specific masterNullifierPublicKeyHash and app/contract address. * @param masterNullifierPublicKeyHash - The master nullifer public key hash. * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. @@ -149,6 +147,11 @@ export class ViewDataOracle extends TypedOracle { return this.db.getCompleteAddress(address); } + /** + * Retrieve the complete address associated to a given master nullifier public key hash. + * @param masterNullifierPublicKeyHash - Master nullifier public key hash to fetch the complete address for. + * @returns A complete address associated with the input master nullifier public key hash. + */ public override getCompleteAddressWithMasterNullifierPublicKey( masterNullifierPublicKeyHash: Fr, ): Promise { From d69e1129eae69afc949f645cd664e23c98e0c3b8 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 20:36:09 +0000 Subject: [PATCH 035/125] fix --- .../src/guides/writing_an_account_contract.test.ts | 6 +++--- yarn-project/simulator/src/acvm/oracle/oracle.ts | 2 +- yarn-project/simulator/src/acvm/oracle/typed_oracle.ts | 2 +- yarn-project/simulator/src/client/view_data_oracle.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts index 1d4b7fc7007..c5a56d197f2 100644 --- a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts +++ b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts @@ -64,7 +64,7 @@ describe('guides/writing_an_account_contract', () => { logger.info(`Deployed account contract at ${address}`); // docs:start:account-contract-works - const token = await TokenContract.deploy(wallet, { address }, 'TokenName', 'TokenSymbol', 18).send().deployed(); + const token = await TokenContract.deploy(wallet, address, 'TokenName', 'TokenSymbol', 18).send().deployed(); logger.info(`Deployed token contract at ${token.address}`); const secret = Fr.random(); @@ -84,9 +84,9 @@ describe('guides/writing_an_account_contract', () => { ); await pxe.addNote(extendedNote); - await token.methods.redeem_shield({ address }, mintAmount, secret).send().wait(); + await token.methods.redeem_shield(address, mintAmount, secret).send().wait(); - const balance = await token.methods.balance_of_private({ address }).simulate(); + const balance = await token.methods.balance_of_private(address).simulate(); logger.info(`Balance of wallet is now ${balance}`); // docs:end:account-contract-works expect(balance).toEqual(50n); diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 5c3f9dd42fd..19626b077b4 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -56,7 +56,7 @@ export class Oracle { async getNullifierKeysWithMasterNullifierPublicKeyHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise< ACVMField[] > { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeysWithMasterNullifierPublicKeyHash( fromACVMField(masterNullifierPublicKeyHash), ); return [ diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 751d7e9db04..314029a12e8 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -94,7 +94,7 @@ export abstract class TypedOracle { } getNullifierKeysWithMasterNullifierPublicKeyHash(_masterNullifierPublicKeyHash: Fr): Promise { - throw new OracleMethodNotAvailableError('getNullifierKeys'); + throw new OracleMethodNotAvailableError('getNullifierKeysWithMasterNullifierPublicKeyHash'); } getPublicKeyAndPartialAddress(_address: AztecAddress): Promise { diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 7dfd82125b2..7e0b27a1726 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -53,7 +53,7 @@ export class ViewDataOracle extends TypedOracle { public override getNullifierKeysWithMasterNullifierPublicKeyHash( masterNullifierPublicKeyHash: Fr, ): Promise { - return this.db.getNullifierKeys(masterNullifierPublicKeyHash, this.contractAddress); + return this.db.getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash, this.contractAddress); } /** From b954ecc5febc72bf6143c0682009228d0918daa3 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 20:53:13 +0000 Subject: [PATCH 036/125] format --- yarn-project/simulator/src/acvm/oracle/oracle.ts | 7 ++++--- yarn-project/simulator/src/client/db_oracle.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 19626b077b4..5122be53114 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -56,9 +56,10 @@ export class Oracle { async getNullifierKeysWithMasterNullifierPublicKeyHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise< ACVMField[] > { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeysWithMasterNullifierPublicKeyHash( - fromACVMField(masterNullifierPublicKeyHash), - ); + const { masterNullifierPublicKey, appNullifierSecretKey } = + await this.typedOracle.getNullifierKeysWithMasterNullifierPublicKeyHash( + fromACVMField(masterNullifierPublicKeyHash), + ); return [ toACVMField(masterNullifierPublicKey.x), toACVMField(masterNullifierPublicKey.y), diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index ed95fc80089..d74b707aa8d 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -90,7 +90,7 @@ export interface DBOracle extends CommitmentsDB { getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise; /** - * Retrieve nullifier keys associated with a specific account and app/contract address. + * Retrieve nullifier keys associated with a specific master nullifier public key hash and app/contract address. * * @param masterNullifierPublicKeyHash - The master nullifer public key hash. * @param contractAddress - The contract address. From 577b69cb451519d5787e22d8e60fafeb36854fe5 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 22:35:08 +0000 Subject: [PATCH 037/125] one --- yarn-project/simulator/src/client/simulator.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index ef9fd366291..e49599ea6f1 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -47,7 +47,7 @@ describe('Simulator', () => { oracle = mock(); node = mock(); - oracle.getNullifierKeys.mockResolvedValue({ + oracle.getNullifierKeysWithMasterNullifierPublicKeyHash.mockResolvedValue({ masterNullifierPublicKey: ownerMasterNullifierPublicKey, appNullifierSecretKey, }); From 11b484826fd48720abf7a1795c672d5705d24a16 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 22:46:24 +0000 Subject: [PATCH 038/125] fix --- yarn-project/key-store/src/test_key_store.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 4fc79e14fab..c6ab226bb5a 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -66,7 +66,7 @@ export class TestKeyStore implements KeyStore { await this.#keys.set(`${accountAddress.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-npk_m-account`, masterNullifierPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); @@ -74,8 +74,8 @@ export class TestKeyStore implements KeyStore { const masterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); // We save nullifier keys and account address to db under the master nullifier key hash - await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-nsk_m-mnpk`, masterNullifierSecretKey.toBuffer()); - await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-nsk_m-mnpkh`, masterNullifierSecretKey.toBuffer()); + await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-npk_m-mnpkh`, masterNullifierPublicKey.toBuffer()); await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-accountAddress`, accountAddress.toBuffer()); // At last, we return the newly derived account address @@ -100,7 +100,7 @@ export class TestKeyStore implements KeyStore { * @returns The master nullifier public key for the account. */ public async getMasterNullifierPublicKey(account: AztecAddress): Promise { - const masterNullifierPublicKeyBuffer = this.#keys.get(`${account.toString()}-npk_m`); + const masterNullifierPublicKeyBuffer = this.#keys.get(`${account.toString()}-npk_m-account`); if (!masterNullifierPublicKeyBuffer) { throw new Error( `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, @@ -116,7 +116,7 @@ export class TestKeyStore implements KeyStore { * @returns The master nullifier public key for the account. */ getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise { - const masterNullifierPublicKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-npk_m`); + const masterNullifierPublicKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-npk_m-mnpkh`); if (!masterNullifierPublicKeyBuffer) { throw new Error(`Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); } @@ -201,7 +201,7 @@ export class TestKeyStore implements KeyStore { masterNullifierPublicKeyHash: Fr, app: AztecAddress, ): Promise { - const masterNullifierSecretKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-nsk_m-mnpk`); + const masterNullifierSecretKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-nsk_m-mnpkh`); if (!masterNullifierSecretKeyBuffer) { throw new Error(`Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); } @@ -273,7 +273,7 @@ export class TestKeyStore implements KeyStore { public getMasterNullifierSecretKeyForPublicKey(masterNullifierPublicKey: PublicKey): Promise { // We iterate over the map keys to find the account address that corresponds to the provided public key for (const [key, value] of this.#keys.entries()) { - if (value.equals(masterNullifierPublicKey.toBuffer())) { + if (value.equals(masterNullifierPublicKey.toBuffer()) && key.endsWith('account')) { // We extract the account address from the map key const accountAddress = key.split('-')[0]; // We fetch the secret key and return it @@ -358,7 +358,7 @@ export class TestKeyStore implements KeyStore { masterOutgoingViewingPublicKey: Point, masterTaggingPublicKey: Point, ): Promise { - await this.#keys.set(`${accountAddress.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-npk_m-account`, masterNullifierPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); From a74311be730c3c0549bf68d05a98dd6bd93c84d3 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 2 May 2024 23:58:03 +0000 Subject: [PATCH 039/125] Fix --- .../aztec.js/src/wallet/base_wallet.ts | 5 +++- .../circuit-types/src/interfaces/pxe.ts | 10 +++++++ .../circuit-types/src/keys/key_store.ts | 1 + .../end-to-end/src/e2e_2_pxes.test.ts | 30 ++++++++++++++----- yarn-project/key-store/src/test_key_store.ts | 15 ++++++++++ .../pxe/src/pxe_service/pxe_service.ts | 13 ++++++++ 6 files changed, 66 insertions(+), 8 deletions(-) diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index eeacdb4f23a..a771ac515f3 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -15,7 +15,7 @@ import { type TxHash, type TxReceipt, } from '@aztec/circuit-types'; -import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; +import { Point, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -83,6 +83,9 @@ export abstract class BaseWallet implements Wallet { getRegisteredAccountPublicKeysHash(address: AztecAddress): Promise { return this.pxe.getRegisteredAccountPublicKeysHash(address); } + getRegisteredAccountPublicKeys(address: AztecAddress): Promise { + return this.pxe.getRegisteredAccountPublicKeys(address); + } getRecipients(): Promise { return this.pxe.getRecipients(); } diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 0e95d024727..65baf5d6bc1 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -100,6 +100,16 @@ export interface PXE { */ getRegisteredAccountPublicKeysHash(address: AztecAddress): Promise; + /** + * Retrieves the public keys of the account corresponding to the provided aztec address. + * + * @param address - The address of account. + * @returns The public keys of the requested account if found. + * TODO(#5834): refactor complete address and merge with getRegisteredAccount? + * TODO?: Refactor this ? This is used in e2e_2_pxes to share keys with another sender + */ + getRegisteredAccountPublicKeys(address: AztecAddress): Promise; + /** * Retrieves the recipients added to this PXE Service. * @returns An array of recipients registered on this PXE Service. diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 2a149cca2ad..f4d2e4b2e49 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -153,6 +153,7 @@ export interface KeyStore { * @param masterIncomingViewingPublicKey - The stored incoming viewing public key * @param masterOutgoingViewingPublicKey - The stored outgoing viewing public key * @param masterTaggingPublicKey - The stored master tagging public key + * @remarks This also adds the master nullifier public key hash to the store for the recipient */ // TODO(#5834): Move this function out of here. Key store should only be used for accounts, not recipients addPublicKeysForAccount( diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index 4f7f20cbe87..bf581215b97 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -119,10 +119,14 @@ describe('e2e_2_pxes', () => { const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); const tokenAddress = tokenInstance.address; + // Get public keys of both accounts + const walletAPublicKeys = await pxeA.getRegisteredAccountPublicKeys(walletA.getAddress()); + const walletBPublicKeys = await pxeB.getRegisteredAccountPublicKeys(walletB.getAddress()); + // Add account B to wallet A - await pxeA.registerRecipient(walletB.getCompleteAddress()); + await pxeA.registerRecipient(walletB.getCompleteAddress(), walletBPublicKeys); // Add account A to wallet B - await pxeB.registerRecipient(walletA.getCompleteAddress()); + await pxeB.registerRecipient(walletA.getCompleteAddress(), walletAPublicKeys); // Add token to PXE B (PXE A already has it because it was deployed through it) await pxeB.registerContract({ @@ -215,10 +219,14 @@ describe('e2e_2_pxes', () => { const tokenInstance = await deployTokenContract(userABalance, walletA.getAddress(), pxeA); const contractWithWalletA = await TokenContract.at(tokenInstance.address, walletA); + // Get public keys of both accounts + const walletAPublicKeys = await pxeA.getRegisteredAccountPublicKeys(walletA.getAddress()); + const walletBPublicKeys = await pxeB.getRegisteredAccountPublicKeys(walletB.getAddress()); + // Add account B to wallet A - await pxeA.registerRecipient(walletB.getCompleteAddress()); + await pxeA.registerRecipient(walletB.getCompleteAddress(), walletBPublicKeys); // Add account A to wallet B - await pxeB.registerRecipient(walletA.getCompleteAddress()); + await pxeB.registerRecipient(walletA.getCompleteAddress(), walletAPublicKeys); // Add token to PXE B (PXE A already has it because it was deployed through it) await pxeB.registerContract({ @@ -268,10 +276,14 @@ describe('e2e_2_pxes', () => { const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); const tokenAddress = tokenInstance.address; + // Get public keys of both accounts + const walletAPublicKeys = await pxeA.getRegisteredAccountPublicKeys(walletA.getAddress()); + const walletBPublicKeys = await pxeB.getRegisteredAccountPublicKeys(walletB.getAddress()); + // Add account B to wallet A - await pxeA.registerRecipient(walletB.getCompleteAddress()); + await pxeA.registerRecipient(walletB.getCompleteAddress(), walletBPublicKeys); // Add account A to wallet B - await pxeB.registerRecipient(walletA.getCompleteAddress()); + await pxeB.registerRecipient(walletA.getCompleteAddress(), walletAPublicKeys); // Check initial balances and logs are as expected await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); @@ -311,7 +323,11 @@ describe('e2e_2_pxes', () => { await sharedAccountOnB.register(); const sharedWalletOnB = await sharedAccountOnB.getWallet(); - await pxeA.registerRecipient(walletB.getCompleteAddress()); + // Get the public keys of wallet B + const walletBPublicKeys = await pxeB.getRegisteredAccountPublicKeys(walletB.getAddress()); + + // Register wallet B in the pxe of wallet A + await pxeA.registerRecipient(walletB.getCompleteAddress(), walletBPublicKeys); // deploy the contract on PXE A const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index c6ab226bb5a..12ef7ad58fe 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -350,6 +350,15 @@ export class TestKeyStore implements KeyStore { return AztecAddress.fromBuffer(accountAddressBuffer); } + /** + * This is used to register a recipient / for storing public keys of an address + * @param accountAddress - The account address to store keys for. + * @param masterNullifierPublicKey - The stored master nullifier public key + * @param masterIncomingViewingPublicKey - The stored incoming viewing public key + * @param masterOutgoingViewingPublicKey - The stored outgoing viewing public key + * @param masterTaggingPublicKey - The stored master tagging public key + * @remarks This also adds the master nullifier public key hash to the store for the recipient + */ // TODO(#5834): Re-add separation between recipients and accounts in keystore. public async addPublicKeysForAccount( accountAddress: AztecAddress, @@ -362,5 +371,11 @@ export class TestKeyStore implements KeyStore { await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); + + const masterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + + // We save nullifier keys and account address to db under the master nullifier key hash + await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-npk_m-mnpkh`, masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-accountAddress`, accountAddress.toBuffer()); } } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index dc75deb293b..721f84f875f 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -211,6 +211,19 @@ export class PXEService implements PXE { return this.keyStore.getPublicKeysHash(address); } + public async getRegisteredAccountPublicKeys(address: AztecAddress): Promise { + const accounts = await this.keyStore.getAccounts(); + if (!accounts.some(account => account.equals(address))) { + return undefined; + } + return Promise.all([ + this.keyStore.getMasterNullifierPublicKey(address), + this.keyStore.getMasterIncomingViewingPublicKey(address), + this.keyStore.getMasterOutgoingViewingPublicKey(address), + this.keyStore.getMasterTaggingPublicKey(address), + ]); + } + public async registerRecipient(recipient: CompleteAddress, publicKeys: Point[] = []): Promise { const wasAdded = await this.db.addCompleteAddress(recipient); From 1d9964a753d6c23cfa3c193ea5e76308090e4142 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 3 May 2024 00:02:13 +0000 Subject: [PATCH 040/125] comments --- yarn-project/key-store/src/test_key_store.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 12ef7ad58fe..0bbb07c2f21 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -372,6 +372,7 @@ export class TestKeyStore implements KeyStore { await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); + //! This is especially disgusting / hacky, and will be refactored. const masterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); // We save nullifier keys and account address to db under the master nullifier key hash From 5fa644dca7bb734c070df53cf1120d3e6de1eff1 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 3 May 2024 00:05:17 +0000 Subject: [PATCH 041/125] format --- yarn-project/aztec.js/src/wallet/base_wallet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index a771ac515f3..dac03cfbc0e 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -15,7 +15,7 @@ import { type TxHash, type TxReceipt, } from '@aztec/circuit-types'; -import { Point, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; +import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress, type Point } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; From 227378cc1347ceb7db03c0d1b572295f5f29cd21 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 3 May 2024 12:53:10 +0000 Subject: [PATCH 042/125] testkeystore Small refactor Fixes --- .../aztec/src/context/private_context.nr | 11 +- .../aztec/src/oracle/get_public_key.nr | 3 +- .../aztec/src/oracle/nullifier_key.nr | 4 +- .../token_contract/src/types/token_note.nr | 10 +- .../aztec.js/src/wallet/base_wallet.ts | 4 +- .../circuit-types/src/interfaces/pxe.ts | 9 +- .../circuit-types/src/keys/key_store.ts | 30 +---- .../circuits.js/src/types/public_key.ts | 7 ++ .../end-to-end/src/e2e_key_registry.test.ts | 14 +-- yarn-project/key-store/src/test_key_store.ts | 118 +++++++----------- .../pxe/src/pxe_service/pxe_service.ts | 28 +++-- .../pxe/src/simulator_oracle/index.ts | 4 +- 12 files changed, 105 insertions(+), 137 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index ee52270fbcf..3ff5011afbf 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -32,7 +32,8 @@ use dep::protocol_types::{ contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, - traits::{is_empty, Deserialize, Empty} + traits::{is_empty, Deserialize, Empty}, + hash::poseidon2_hash }; // When finished, one can call .finish() to convert back to the abi @@ -227,8 +228,7 @@ impl PrivateContext { pub fn request_app_nullifier_secret_key_with_master_public_nullifying_key_hash(&mut self, master_public_nullifying_key_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { let keys = get_nullifier_keys_with_master_nullifier_public_key_hash(master_public_nullifying_key_hash); - // Should we inside here constrain the below? - // assert(keys.master_nullifier_public_key_hash == master_public_nullifying_key_hash); + assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), master_public_nullifying_key_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, app_nullifier_secret_key: keys.app_nullifier_secret_key @@ -240,10 +240,11 @@ impl PrivateContext { let keys = self.nullifier_key.unwrap_unchecked(); // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); - // TODO: (ek) Enable this after we nuke the account in all notes and when NullifierKeys has a reference to master_nullifier_public_key_hash - // assert(keys.master_nullifier_public_key_hash == master_public_nullifying_key_hash, "Cannot query nullifier key for more than one master_nullifying_public_key_hash per call"); keys }; + + // TODO: (#6176) (ek) Enable this after we nuke the account in all notes and when NullifierKeys has a reference to master_nullifier_public_key_hash + // assert_eq(keys.master_nullifier_public_key_hash, master_public_nullifying_key_hash); keys.app_nullifier_secret_key } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr index 08ef83bf0db..13d3184e845 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr @@ -26,7 +26,8 @@ unconstrained fn get_public_key_and_partial_address_with_master_nullifier_public get_public_key_and_partial_address_with_master_nullifier_public_key_hash_oracle(master_nullifier_public_key_hash) } -// TODO: This is used when we emit encrypted logs and will be changed. +// TODO (#5901): This is used when we emit encrypted logs and will be changed. +// TODO (#6178): This function should not be contraining things here. pub fn get_public_key_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> GrumpkinPoint { let result = get_public_key_and_partial_address_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash); let pub_key = GrumpkinPoint::new(result[0], result[1]); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index cb17de88ba8..077672399ee 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -28,7 +28,7 @@ pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { get_nullifier_keys_internal(account).app_nullifier_secret_key } -// TODO(ek): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address +// TODO (#6176): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address #[oracle(getNullifierKeysWithMasterNullifierPublicKeyHash)] fn get_nullifier_keys_with_master_nullifier_public_key_hash_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} @@ -41,10 +41,12 @@ unconstrained fn get_nullifier_keys_with_master_nullifier_public_key_hash_intern } } +// We get the full struct Nullifier Keys here pub fn get_nullifier_keys_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> NullifierKeys { get_nullifier_keys_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash) } +// We are only getting the app_nullifier_secret_key here pub fn get_app_nullifier_secret_key_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> Field { get_nullifier_keys_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash).app_nullifier_secret_key } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 47c9e4db84a..e408237fd09 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -15,13 +15,12 @@ global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. #[aztec(note)] struct TokenNote { - // the amount of tokens in the note + // The amount of tokens in the note amount: U128, - // the nullifying public key of the person who owns the note. The owner (recipient) to ensure that the note - // can be privately spent. When nullifier secret and encryption private key is same - // we can simply use the owner for this one. + // The nullifying public key hash of the person who owns the note. + // This is used with the app_nullifier_secret_key to ensure that the note can be privately spent. owner_nullifying_public_key_hash: Field, - // randomness of the note to hide contents. + // Randomness of the note to hide its contents randomness: Field, } @@ -51,6 +50,7 @@ impl NoteInterface for TokenNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field) { // We only bother inserting the note if non-empty to save funds on gas. + // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format if !(self.amount == U128::from_integer(0)) { let encryption_pub_key = get_public_key_with_master_nullifier_public_key_hash(self.owner_nullifying_public_key_hash); context.emit_encrypted_log( diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index dac03cfbc0e..bf6c6aeaef5 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -15,7 +15,7 @@ import { type TxHash, type TxReceipt, } from '@aztec/circuit-types'; -import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress, type Point } from '@aztec/circuits.js'; +import { PublicKeys, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress, type Point } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -83,7 +83,7 @@ export abstract class BaseWallet implements Wallet { getRegisteredAccountPublicKeysHash(address: AztecAddress): Promise { return this.pxe.getRegisteredAccountPublicKeysHash(address); } - getRegisteredAccountPublicKeys(address: AztecAddress): Promise { + getRegisteredAccountPublicKeys(address: AztecAddress): Promise { return this.pxe.getRegisteredAccountPublicKeys(address); } getRecipients(): Promise { diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 65baf5d6bc1..db5cc4274f4 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -1,4 +1,4 @@ -import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress, type Point } from '@aztec/circuits.js'; +import { type PublicKeys, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -68,13 +68,14 @@ export interface PXE { * in order to be able to encrypt data for this recipient. * * @param recipient - The complete address of the recipient + * @param publicKeys - The public keys of the recipient (see #5834) * @remarks Called recipient because we can only send notes to this account and not receive them via this PXE Service. * This is because we don't have the associated private key and for this reason we can't decrypt * the recipient's notes. We can send notes to this account because we can encrypt them with the recipient's * public key. */ // TODO: #5834: Nuke publicKeys optional parameter after `CompleteAddress` refactor. - registerRecipient(recipient: CompleteAddress, publicKeys?: Point[]): Promise; + registerRecipient(recipient: CompleteAddress, publicKeys?: PublicKeys): Promise; /** * Retrieves the user accounts registered on this PXE Service. @@ -106,9 +107,9 @@ export interface PXE { * @param address - The address of account. * @returns The public keys of the requested account if found. * TODO(#5834): refactor complete address and merge with getRegisteredAccount? - * TODO?: Refactor this ? This is used in e2e_2_pxes to share keys with another sender + * This will change after the re enabling separation of keystore and pxe. We shouldn't need both this function and the above one */ - getRegisteredAccountPublicKeys(address: AztecAddress): Promise; + getRegisteredAccountPublicKeys(address: AztecAddress): Promise; /** * Retrieves the recipients added to this PXE Service. diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index f4d2e4b2e49..06a6e55042a 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -32,20 +32,12 @@ export interface KeyStore { getAccounts(): Promise; /** - * Gets the master nullifier public key for a given master nullifier public key hash. - * @throws If the master nullifier public key hash does not exist in the key store. - * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the master nullifier public key. - * @returns The master nullifier public key for the account. - */ - getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise; - - /** - * Gets the master nullifier public key for a given account. + * Gets the master nullifier public key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param account - The account address for which to retrieve the master nullifier public key. + * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the master nullifier public key. * @returns The master nullifier public key for the account. */ - getMasterNullifierPublicKey(account: AztecAddress): Promise; + getMasterNullifierPublicKey(accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr): Promise; /** * Gets the master incoming viewing public key for a given account. @@ -72,26 +64,14 @@ export interface KeyStore { getMasterTaggingPublicKey(account: AztecAddress): Promise; /** - * Retrieves application nullifier secret key. + * Derives and returns the application nullifier secret key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the application nullifier secret key for. + * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the application nullifier secret key. * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ getAppNullifierSecretKey(account: AztecAddress, app: AztecAddress): Promise; - /** - * Retrieves application nullifier secret key. - * @throws If the masterNullifierPublicKeyHash does not exist in the key store. - * @param masterNullifierPublicKeyHash - The account to retrieve the application nullifier secret key for. - * @param app - The application address to retrieve the nullifier secret key for. - * @returns A Promise that resolves to the application nullifier secret key. - */ - getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash( - masterNullifierPublicKeyHash: Fr, - app: AztecAddress, - ): Promise; - /** * Retrieves application incoming viewing secret key. * @throws If the account does not exist in the key store. diff --git a/yarn-project/circuits.js/src/types/public_key.ts b/yarn-project/circuits.js/src/types/public_key.ts index 0109de4c8ea..e4d135d88ee 100644 --- a/yarn-project/circuits.js/src/types/public_key.ts +++ b/yarn-project/circuits.js/src/types/public_key.ts @@ -2,3 +2,10 @@ import { type Point } from '@aztec/foundation/fields'; /** Represents a user public key. */ export type PublicKey = Point; + +export type PublicKeys = { + masterNullifierPublicKey: Point, + masterIncomingViewingPublicKey: Point, + masterOutgoingViewingPublicKey: Point, + masterTaggingPublicKey: Point, +} diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index b801beed9e4..007b1e7797e 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -305,12 +305,12 @@ describe('Key Registry', () => { .wait(); // TODO: (#5834) Refactor complete address to move the public keys - await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), [ - new Point(Fr.random(), Fr.random()), + await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), { + masterNullifierPublicKey: new Point(Fr.random(), Fr.random()), masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, - ]); + }); // Our check should still succeed even if our pxe gives conflicting information, taking the registry as the source of truth. await testContract.methods @@ -352,12 +352,12 @@ describe('Key Registry', () => { it('should fail when we try to check the public keys for a invalid address', async () => { const randAddress = AztecAddress.random(); // TODO: (#5834) Refactor complete address to move the public keys - await pxe.registerRecipient(CompleteAddress.create(randAddress, Point.ZERO, partialAddress), [ + await pxe.registerRecipient(CompleteAddress.create(randAddress, Point.ZERO, partialAddress), { masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, - ]); + }); await expect( testContract.methods.test_nullifier_key_freshness(randAddress, masterNullifierPublicKey).send().wait(), @@ -366,12 +366,12 @@ describe('Key Registry', () => { it('adds a recipient to our pxe, and checks the key freshness with and without adding an entry to our key registry', async () => { // TODO: (#5834) Refactor complete address to move the public keys - await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), [ + await pxe.registerRecipient(CompleteAddress.create(accountAddedToRegistry, Point.ZERO, partialAddress), { masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, - ]); + }); // The check should succeed because we register our recipient manually and the lib checks our pxe await testContract.methods diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 0bbb07c2f21..c086db4aaaa 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -61,23 +61,17 @@ export class TestKeyStore implements KeyStore { // We save the keys to db associated with the account address await this.#keys.set(`${accountAddress.toString()}-public_keys_hash`, publicKeysHash.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-nsk_m-account`, masterNullifierSecretKey.toBuffer()); + // Naming of keys is as follows ${from}-${to}_${any modifiers (m = master, h = hash)} + await this.#keys.set(`${accountAddress.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-npk_m-account`, masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); - const masterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); - - // We save nullifier keys and account address to db under the master nullifier key hash - await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-nsk_m-mnpkh`, masterNullifierSecretKey.toBuffer()); - await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-npk_m-mnpkh`, masterNullifierPublicKey.toBuffer()); - await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-accountAddress`, accountAddress.toBuffer()); - // At last, we return the newly derived account address return Promise.resolve(accountAddress); } @@ -88,37 +82,24 @@ export class TestKeyStore implements KeyStore { */ public getAccounts(): Promise { const allMapKeys = Array.from(this.#keys.keys()); - // We return account addresses based on the map keys that end with '-nsk_m-account' - const accounts = allMapKeys.filter(key => key.endsWith('-nsk_m-account')).map(key => key.split('-')[0]); + // We return account addresses based on the map keys that end with '-nsk_m' + const accounts = allMapKeys.filter(key => key.endsWith('-nsk_m')).map(key => key.split('-')[0]); return Promise.resolve(accounts.map(account => AztecAddress.fromString(account))); } /** - * Gets the master nullifier public key for a given account. + * Gets the master nullifier public key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param account - The account address for which to retrieve the master nullifier public key. - * @returns The master nullifier public key for the account. - */ - public async getMasterNullifierPublicKey(account: AztecAddress): Promise { - const masterNullifierPublicKeyBuffer = this.#keys.get(`${account.toString()}-npk_m-account`); - if (!masterNullifierPublicKeyBuffer) { - throw new Error( - `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, - ); - } - return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); - } - - /** - * Gets the master nullifier public key for a given master nullifier public key hash. - * @throws If the master nullifier public key hash does not exist in the key store. - * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the master nullifier public key. + * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the master nullifier public key. * @returns The master nullifier public key for the account. */ - getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): Promise { - const masterNullifierPublicKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-npk_m-mnpkh`); + public async getMasterNullifierPublicKey(accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr): Promise { + const masterNullifierPublicKeyBuffer = this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-npk_m`) ?? + this.#keys.get(`${this.getAccountAddressForMasterNullifierPublicKeyHashInternal(accountOrMasterNullifierPublicKeyHash)?.toString()}-npk_m`); if (!masterNullifierPublicKeyBuffer) { - throw new Error(`Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); + throw new Error( + `Account or master nullifier public key hash ${accountOrMasterNullifierPublicKeyHash.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); } return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); } @@ -172,38 +153,22 @@ export class TestKeyStore implements KeyStore { } /** - * Retrieves application nullifier secret key. + * Derives and returns the application nullifier secret key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param account - The account to retrieve the application nullifier secret key for. + * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the application nullifier secret key. * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ - public async getAppNullifierSecretKey(account: AztecAddress, app: AztecAddress): Promise { - const masterNullifierSecretKeyBuffer = this.#keys.get(`${account.toString()}-nsk_m-account`); - if (!masterNullifierSecretKeyBuffer) { - throw new Error( - `Account ${account.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, - ); - } - const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); - const appNullifierSecretKey = computeAppNullifierSecretKey(masterNullifierSecretKey, app); - return Promise.resolve(appNullifierSecretKey); - } - - /** - * Retrieves application nullifier secret key. - * @throws If the masterNullifierPublicKeyHash does not exist in the key store. - * @param masterNullifierPublicKeyHash - The account to retrieve the application nullifier secret key for. - * @param app - The application address to retrieve the nullifier secret key for. - * @returns A Promise that resolves to the application nullifier secret key. - */ - getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash( - masterNullifierPublicKeyHash: Fr, + public async getAppNullifierSecretKey( + accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr, app: AztecAddress, ): Promise { - const masterNullifierSecretKeyBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-nsk_m-mnpkh`); + const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-nsk_m`) ?? + this.#keys.get(`${this.getAccountAddressForMasterNullifierPublicKeyHashInternal(accountOrMasterNullifierPublicKeyHash)?.toString()}-nsk_m`); if (!masterNullifierSecretKeyBuffer) { - throw new Error(`Master nullifier public keys hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); + throw new Error( + `Account or master nullifier public key hash ${accountOrMasterNullifierPublicKeyHash.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); } const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); const appNullifierSecretKey = computeAppNullifierSecretKey(masterNullifierSecretKey, app); @@ -273,11 +238,11 @@ export class TestKeyStore implements KeyStore { public getMasterNullifierSecretKeyForPublicKey(masterNullifierPublicKey: PublicKey): Promise { // We iterate over the map keys to find the account address that corresponds to the provided public key for (const [key, value] of this.#keys.entries()) { - if (value.equals(masterNullifierPublicKey.toBuffer()) && key.endsWith('account')) { + if (value.equals(masterNullifierPublicKey.toBuffer()) && key.endsWith('-npk_m')) { // We extract the account address from the map key const accountAddress = key.split('-')[0]; // We fetch the secret key and return it - const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountAddress.toString()}-nsk_m-account`); + const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountAddress.toString()}-nsk_m`); if (!masterNullifierSecretKeyBuffer) { throw new Error(`Could not find master nullifier secret key for account ${accountAddress.toString()}`); } @@ -340,14 +305,15 @@ export class TestKeyStore implements KeyStore { * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the address. * @returns The address for the account. */ - public getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): AztecAddress { - const accountAddressBuffer = this.#keys.get(`${masterNullifierPublicKeyHash.toString()}-accountAddress`); - - if (!accountAddressBuffer) { - throw new Error(`Master nullifier public key hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); + // TODO(#5834): Re-add separation between recipients and accounts in keystore. Refactor this utilizing getAccounts. + public getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr) { + const account = this.getAccountAddressForMasterNullifierPublicKeyHashInternal(masterNullifierPublicKeyHash); + if (!account) { + throw new Error( + `Master nullifier public key hash ${masterNullifierPublicKeyHash.toString()} does not exist.`, + ); } - - return AztecAddress.fromBuffer(accountAddressBuffer); + return account; } /** @@ -367,16 +333,24 @@ export class TestKeyStore implements KeyStore { masterOutgoingViewingPublicKey: Point, masterTaggingPublicKey: Point, ): Promise { - await this.#keys.set(`${accountAddress.toString()}-npk_m-account`, masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-npk_m`, masterNullifierPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); + } - //! This is especially disgusting / hacky, and will be refactored. - const masterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + getAccountAddressForMasterNullifierPublicKeyHashInternal(masterNullifierPublicKeyHash: Fr): AztecAddress | undefined { + for (const [key, value] of this.#keys.entries()) { + if (key.endsWith('-npk_m')) { + const computedMasterNullifierPublicKeyHash = poseidon2Hash(Point.fromBuffer(value).toFields()); + if (computedMasterNullifierPublicKeyHash.equals(masterNullifierPublicKeyHash)) { + // We extract the account address from the map key + const accountAddress = key.split('-')[0]; + return AztecAddress.fromString(accountAddress); + } + } + } - // We save nullifier keys and account address to db under the master nullifier key hash - await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-npk_m-mnpkh`, masterNullifierPublicKey.toBuffer()); - await this.#keys.set(`${masterNullifierPublicKeyHash.toString()}-accountAddress`, accountAddress.toBuffer()); + return undefined; } } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 721f84f875f..48004ae8180 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -33,6 +33,7 @@ import { type PublicCallRequest, computeContractClassId, getContractClassFromArtifact, + PublicKeys, } from '@aztec/circuits.js'; import { computeCommitmentNonce, siloNullifier } from '@aztec/circuits.js/hash'; import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; @@ -211,30 +212,31 @@ export class PXEService implements PXE { return this.keyStore.getPublicKeysHash(address); } - public async getRegisteredAccountPublicKeys(address: AztecAddress): Promise { + public async getRegisteredAccountPublicKeys(address: AztecAddress): Promise { const accounts = await this.keyStore.getAccounts(); if (!accounts.some(account => account.equals(address))) { return undefined; } - return Promise.all([ - this.keyStore.getMasterNullifierPublicKey(address), - this.keyStore.getMasterIncomingViewingPublicKey(address), - this.keyStore.getMasterOutgoingViewingPublicKey(address), - this.keyStore.getMasterTaggingPublicKey(address), - ]); + + return { + masterNullifierPublicKey: await this.keyStore.getMasterNullifierPublicKey(address), + masterIncomingViewingPublicKey: await this.keyStore.getMasterIncomingViewingPublicKey(address), + masterOutgoingViewingPublicKey: await this.keyStore.getMasterOutgoingViewingPublicKey(address), + masterTaggingPublicKey: await this.keyStore.getMasterTaggingPublicKey(address), + } } - public async registerRecipient(recipient: CompleteAddress, publicKeys: Point[] = []): Promise { + public async registerRecipient(recipient: CompleteAddress, publicKeys?: PublicKeys): Promise { const wasAdded = await this.db.addCompleteAddress(recipient); // TODO #5834: This should be refactored to be okay with only adding complete address - if (publicKeys.length !== 0) { + if (publicKeys !== undefined) { await this.keyStore.addPublicKeysForAccount( recipient.address, - publicKeys[0], - publicKeys[1], - publicKeys[2], - publicKeys[3], + publicKeys.masterNullifierPublicKey, + publicKeys.masterIncomingViewingPublicKey, + publicKeys.masterOutgoingViewingPublicKey, + publicKeys.masterTaggingPublicKey, ); } diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index ff0dcd28648..99814643e93 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -48,10 +48,10 @@ export class SimulatorOracle implements DBOracle { masterNullifierPublicKeyHash: AztecAddress, contractAddress: AztecAddress, ): Promise { - const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKeyWithMasterNullifierPublicKeyHash( + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey( masterNullifierPublicKeyHash, ); - const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKeyWithMasterNullifierPublicKeyHash( + const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey( masterNullifierPublicKeyHash, contractAddress, ); From f5659f52eb96cf9b1e9685f0a02446be99545bec Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 3 May 2024 15:34:10 +0000 Subject: [PATCH 043/125] format --- .../aztec.js/src/wallet/base_wallet.ts | 8 ++++- .../circuit-types/src/interfaces/pxe.ts | 8 ++++- .../circuits.js/src/types/public_key.ts | 10 +++--- yarn-project/key-store/src/test_key_store.ts | 32 ++++++++++++------- .../pxe/src/pxe_service/pxe_service.ts | 6 ++-- .../pxe/src/simulator_oracle/index.ts | 4 +-- 6 files changed, 44 insertions(+), 24 deletions(-) diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index bf6c6aeaef5..bc48e904a7e 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -15,7 +15,13 @@ import { type TxHash, type TxReceipt, } from '@aztec/circuit-types'; -import { PublicKeys, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress, type Point } from '@aztec/circuits.js'; +import { + type AztecAddress, + type CompleteAddress, + type Fr, + type PartialAddress, + type PublicKeys, +} from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index db5cc4274f4..e15d1ae0334 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -1,4 +1,10 @@ -import { type PublicKeys, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; +import { + type AztecAddress, + type CompleteAddress, + type Fr, + type PartialAddress, + type PublicKeys, +} from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; diff --git a/yarn-project/circuits.js/src/types/public_key.ts b/yarn-project/circuits.js/src/types/public_key.ts index e4d135d88ee..817e08f1e51 100644 --- a/yarn-project/circuits.js/src/types/public_key.ts +++ b/yarn-project/circuits.js/src/types/public_key.ts @@ -4,8 +4,8 @@ import { type Point } from '@aztec/foundation/fields'; export type PublicKey = Point; export type PublicKeys = { - masterNullifierPublicKey: Point, - masterIncomingViewingPublicKey: Point, - masterOutgoingViewingPublicKey: Point, - masterTaggingPublicKey: Point, -} + masterNullifierPublicKey: Point; + masterIncomingViewingPublicKey: Point; + masterOutgoingViewingPublicKey: Point; + masterTaggingPublicKey: Point; +}; diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index c086db4aaaa..76284099f8e 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -93,13 +93,20 @@ export class TestKeyStore implements KeyStore { * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the master nullifier public key. * @returns The master nullifier public key for the account. */ - public async getMasterNullifierPublicKey(accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr): Promise { - const masterNullifierPublicKeyBuffer = this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-npk_m`) ?? - this.#keys.get(`${this.getAccountAddressForMasterNullifierPublicKeyHashInternal(accountOrMasterNullifierPublicKeyHash)?.toString()}-npk_m`); + public async getMasterNullifierPublicKey( + accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr, + ): Promise { + const masterNullifierPublicKeyBuffer = + this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-npk_m`) ?? + this.#keys.get( + `${this.getAccountAddressForMasterNullifierPublicKeyHashInternal( + accountOrMasterNullifierPublicKeyHash, + )?.toString()}-npk_m`, + ); if (!masterNullifierPublicKeyBuffer) { - throw new Error( - `Account or master nullifier public key hash ${accountOrMasterNullifierPublicKeyHash.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, - ); + throw new Error( + `Account or master nullifier public key hash ${accountOrMasterNullifierPublicKeyHash.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + ); } return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); } @@ -163,8 +170,13 @@ export class TestKeyStore implements KeyStore { accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr, app: AztecAddress, ): Promise { - const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-nsk_m`) ?? - this.#keys.get(`${this.getAccountAddressForMasterNullifierPublicKeyHashInternal(accountOrMasterNullifierPublicKeyHash)?.toString()}-nsk_m`); + const masterNullifierSecretKeyBuffer = + this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-nsk_m`) ?? + this.#keys.get( + `${this.getAccountAddressForMasterNullifierPublicKeyHashInternal( + accountOrMasterNullifierPublicKeyHash, + )?.toString()}-nsk_m`, + ); if (!masterNullifierSecretKeyBuffer) { throw new Error( `Account or master nullifier public key hash ${accountOrMasterNullifierPublicKeyHash.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, @@ -309,9 +321,7 @@ export class TestKeyStore implements KeyStore { public getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr) { const account = this.getAccountAddressForMasterNullifierPublicKeyHashInternal(masterNullifierPublicKeyHash); if (!account) { - throw new Error( - `Master nullifier public key hash ${masterNullifierPublicKeyHash.toString()} does not exist.`, - ); + throw new Error(`Master nullifier public key hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); } return account; } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 48004ae8180..f937fe5b3c5 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -31,14 +31,14 @@ import { type PartialAddress, type PrivateKernelTailCircuitPublicInputs, type PublicCallRequest, + type PublicKeys, computeContractClassId, getContractClassFromArtifact, - PublicKeys, } from '@aztec/circuits.js'; import { computeCommitmentNonce, siloNullifier } from '@aztec/circuits.js/hash'; import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection'; -import { Fr, type Point } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { SerialQueue } from '@aztec/foundation/fifo'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; @@ -223,7 +223,7 @@ export class PXEService implements PXE { masterIncomingViewingPublicKey: await this.keyStore.getMasterIncomingViewingPublicKey(address), masterOutgoingViewingPublicKey: await this.keyStore.getMasterOutgoingViewingPublicKey(address), masterTaggingPublicKey: await this.keyStore.getMasterTaggingPublicKey(address), - } + }; } public async registerRecipient(recipient: CompleteAddress, publicKeys?: PublicKeys): Promise { diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 99814643e93..427a5e796c7 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -48,9 +48,7 @@ export class SimulatorOracle implements DBOracle { masterNullifierPublicKeyHash: AztecAddress, contractAddress: AztecAddress, ): Promise { - const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey( - masterNullifierPublicKeyHash, - ); + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(masterNullifierPublicKeyHash); const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey( masterNullifierPublicKeyHash, contractAddress, From c8901ff60bd7cea6c6b382c257cee32e57d2c0f4 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 3 May 2024 15:55:49 +0000 Subject: [PATCH 044/125] Adding comments --- noir-projects/aztec-nr/aztec/src/context/private_context.nr | 2 +- noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 3ff5011afbf..48f6a9216f1 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -224,7 +224,7 @@ impl PrivateContext { keys.app_nullifier_secret_key } - // TODO(ek): Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address + // TODO: (#6176) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address pub fn request_app_nullifier_secret_key_with_master_public_nullifying_key_hash(&mut self, master_public_nullifying_key_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { let keys = get_nullifier_keys_with_master_nullifier_public_key_hash(master_public_nullifying_key_hash); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr index 13d3184e845..5b8c16ea49b 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr @@ -19,6 +19,7 @@ pub fn get_public_key(address: AztecAddress) -> GrumpkinPoint { pub_key } +// TODO(#5901 -> #5834): This should be refactored, would be most effective to do it after new encrypted log scheme, as well as key store pxe separation. #[oracle(getPublicKeyAndPartialAddressWithMasterNullifierPublicKeyHash)] fn get_public_key_and_partial_address_with_master_nullifier_public_key_hash_oracle(master_nullifier_public_key_hash: Field) -> [Field; 3] {} From ec75986141acfcaeaf705d8ae1fe34a87ef40773 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 3 May 2024 16:04:21 +0000 Subject: [PATCH 045/125] comments --- noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr | 2 +- yarn-project/circuit-types/src/keys/key_store.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 077672399ee..1af61f659a5 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -2,7 +2,7 @@ use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, // Nullifier keys pertaining to a specific account struct NullifierKeys { - // TODO: (ek) Replace this with master_nullifier_public_key_hash + // TODO (#6176): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address account: AztecAddress, master_nullifier_public_key: GrumpkinPoint, app_nullifier_secret_key: Field, diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 06a6e55042a..c804eb87006 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -70,7 +70,7 @@ export interface KeyStore { * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ - getAppNullifierSecretKey(account: AztecAddress, app: AztecAddress): Promise; + getAppNullifierSecretKey(accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr, app: AztecAddress): Promise; /** * Retrieves application incoming viewing secret key. From 4bfaefaafa6c8ff64f949a727636885f02bd43a1 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 3 May 2024 16:09:30 +0000 Subject: [PATCH 046/125] why --- barretenberg/ts/src/examples/simple.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/ts/src/examples/simple.test.ts b/barretenberg/ts/src/examples/simple.test.ts index 4af243a631d..0b2ad74c523 100644 --- a/barretenberg/ts/src/examples/simple.test.ts +++ b/barretenberg/ts/src/examples/simple.test.ts @@ -14,7 +14,7 @@ describe('simple', () => { const crs = await Crs.new(2 ** 19 + 1); await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data())); - }, 30000); + }, 60_000); afterAll(async () => { await api.destroy(); From d9704abe0fe6babdcb46e7b8a91d31c407730f26 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Sat, 4 May 2024 12:04:24 +0000 Subject: [PATCH 047/125] fix --- noir-projects/aztec-nr/aztec/src/context/private_context.nr | 2 +- yarn-project/pxe/src/pxe_service/pxe_service.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 2329abf3af5..7b0a92ba2b3 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -9,7 +9,7 @@ use crate::{ nullifier_key::{get_nullifier_keys, get_nullifier_keys_with_master_nullifier_public_key_hash, NullifierKeys}, enqueue_public_function_call::{ enqueue_public_function_call_internal, set_public_teardown_function_call_internal, - parse_public_call_stack_item_from_oracle + parse_public_call_stack_item_from_oracle}, }, }; use dep::protocol_types::{ diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index d46a75d57b8..3d7a3e682a8 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -30,7 +30,7 @@ import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, type PartialAddress, type PrivateKernelTailCircuitPublicInputs, - type PublicCallRequest, + PublicCallRequest, type PublicKeys, computeContractClassId, getContractClassFromArtifact, From b9733a0ab59ad738266de311163843882eeddc3b Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 6 May 2024 10:58:48 +0000 Subject: [PATCH 048/125] Fix --- noir-projects/aztec-nr/aztec/src/keys/getters.nr | 6 +++++- .../token_contract/src/types/balances_map.nr | 6 +++--- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 12 ++++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index b6fc2759fb7..f06f4b0ce5c 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint}; +use dep::protocol_types::{address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}; use crate::{ context::PrivateContext, oracle::keys::get_public_keys_and_partial_address, state_vars::{ @@ -22,6 +22,10 @@ pub fn get_npk_m(context: &mut PrivateContext, address: AztecAddress) -> Grumpki get_master_key(context, address, NULLIFIER_INDEX) } +pub fn get_npk_m_hash(context: &mut PrivateContext, address: AztecAddress) -> Field { + poseidon2_hash(get_master_key(context, address, NULLIFIER_INDEX).serialize()) +} + pub fn get_ivpk_m(context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint { get_master_key(context, address, INCOMING_INDEX) } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 249a5f5ed7c..9cbd4530aaa 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -4,9 +4,9 @@ use dep::aztec::prelude::{ }; use dep::aztec::{ context::{PublicContext, Context}, hash::pedersen_hash, - protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, hash::poseidon2_hash}, note::{note_getter::view_notes, note_getter_options::SortOrder}, - keys::getters::get_fresh_nullifier_public_key_hash, + keys::getters::get_npk_m_hash, }; use crate::types::token_note::{TokenNote, OwnedNote}; @@ -62,7 +62,7 @@ impl BalancesMap { addend: U128 ) where T: NoteInterface + OwnedNote { // We fetch the nullifier public key hash in the registry / from our PXE - let nullifier_public_key_hash = get_fresh_nullifier_public_key_hash(self.map.context.private.unwrap(), owner); + let nullifier_public_key_hash = get_npk_m_hash(self.map.context.private.unwrap(), owner); let mut addend_note = T::new(addend, nullifier_public_key_hash); diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 48fb1fa90ab..dbb3119e448 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -113,12 +113,12 @@ describe('Key Registry', () => { newAccountPartialAddress, ); - await pxe.registerRecipient(newAccountCompleteAddress, [ - newAccountKeys.masterNullifierPublicKey, - newAccountKeys.masterIncomingViewingPublicKey, - newAccountKeys.masterOutgoingViewingPublicKey, - newAccountKeys.masterTaggingPublicKey, - ]); + await pxe.registerRecipient(newAccountCompleteAddress, { + masterNullifierPublicKey: newAccountKeys.masterNullifierPublicKey, + masterIncomingViewingPublicKey: newAccountKeys.masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey: newAccountKeys.masterOutgoingViewingPublicKey, + masterTaggingPublicKey: newAccountKeys.masterTaggingPublicKey, + }); // Should succeed as the account is now registered as a recipient in PXE await testContract.methods From 9a3829cad35ee4c13220c25913ad6c4dd544af98 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 6 May 2024 11:05:13 +0000 Subject: [PATCH 049/125] fix --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index dbb3119e448..8ab96d0d1dc 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -118,7 +118,7 @@ describe('Key Registry', () => { masterIncomingViewingPublicKey: newAccountKeys.masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey: newAccountKeys.masterOutgoingViewingPublicKey, masterTaggingPublicKey: newAccountKeys.masterTaggingPublicKey, - }); + }); // Should succeed as the account is now registered as a recipient in PXE await testContract.methods From b432ad23c245ce191bb1d772986836e9ef41c516 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 10:02:04 +0000 Subject: [PATCH 050/125] Fix naming --- .../aztec/src/context/private_context.nr | 10 ++++----- .../aztec-nr/aztec/src/keys/getters.nr | 2 +- .../aztec/src/oracle/get_public_key.nr | 10 ++++----- .../aztec/src/oracle/nullifier_key.nr | 14 ++++++------ .../token_contract/src/types/balances_map.nr | 4 ++-- .../token_contract/src/types/token_note.nr | 22 +++++++++---------- 6 files changed, 30 insertions(+), 32 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 7b0a92ba2b3..b6ca4d8f84e 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -6,7 +6,7 @@ use crate::{ arguments, returns, call_private_function::call_private_function_internal, header::get_header_at, logs::emit_encrypted_log, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, - nullifier_key::{get_nullifier_keys, get_nullifier_keys_with_master_nullifier_public_key_hash, NullifierKeys}, + nullifier_key::{get_nullifier_keys, get_nk_with_npk_m_h, NullifierKeys}, enqueue_public_function_call::{ enqueue_public_function_call_internal, set_public_teardown_function_call_internal, parse_public_call_stack_item_from_oracle}, @@ -227,10 +227,9 @@ impl PrivateContext { } // TODO: (#6176) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address - pub fn request_app_nullifier_secret_key_with_master_public_nullifying_key_hash(&mut self, master_public_nullifying_key_hash: Field) -> Field { + pub fn request_nsk_app_with_npk_m_h(&mut self, master_public_nullifying_key_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { - let keys = get_nullifier_keys_with_master_nullifier_public_key_hash(master_public_nullifying_key_hash); - assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), master_public_nullifying_key_hash); + let keys = get_nk_with_npk_m_h(master_public_nullifying_key_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, app_nullifier_secret_key: keys.app_nullifier_secret_key @@ -245,8 +244,7 @@ impl PrivateContext { keys }; - // TODO: (#6176) (ek) Enable this after we nuke the account in all notes and when NullifierKeys has a reference to master_nullifier_public_key_hash - // assert_eq(keys.master_nullifier_public_key_hash, master_public_nullifying_key_hash); + assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), master_public_nullifying_key_hash); keys.app_nullifier_secret_key } diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index f06f4b0ce5c..5371272bada 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -22,7 +22,7 @@ pub fn get_npk_m(context: &mut PrivateContext, address: AztecAddress) -> Grumpki get_master_key(context, address, NULLIFIER_INDEX) } -pub fn get_npk_m_hash(context: &mut PrivateContext, address: AztecAddress) -> Field { +pub fn get_npk_m_h(context: &mut PrivateContext, address: AztecAddress) -> Field { poseidon2_hash(get_master_key(context, address, NULLIFIER_INDEX).serialize()) } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr index 5b8c16ea49b..3af70b10c91 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr @@ -21,16 +21,16 @@ pub fn get_public_key(address: AztecAddress) -> GrumpkinPoint { // TODO(#5901 -> #5834): This should be refactored, would be most effective to do it after new encrypted log scheme, as well as key store pxe separation. #[oracle(getPublicKeyAndPartialAddressWithMasterNullifierPublicKeyHash)] -fn get_public_key_and_partial_address_with_master_nullifier_public_key_hash_oracle(master_nullifier_public_key_hash: Field) -> [Field; 3] {} +fn get_public_key_and_partial_address_with_npk_m_h_oracle(master_nullifier_public_key_hash: Field) -> [Field; 3] {} -unconstrained fn get_public_key_and_partial_address_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash: Field) -> [Field; 3] { - get_public_key_and_partial_address_with_master_nullifier_public_key_hash_oracle(master_nullifier_public_key_hash) +unconstrained fn get_public_key_and_partial_address_with_npk_m_h_internal(master_nullifier_public_key_hash: Field) -> [Field; 3] { + get_public_key_and_partial_address_with_npk_m_h_oracle(master_nullifier_public_key_hash) } // TODO (#5901): This is used when we emit encrypted logs and will be changed. // TODO (#6178): This function should not be contraining things here. -pub fn get_public_key_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> GrumpkinPoint { - let result = get_public_key_and_partial_address_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash); +pub fn get_public_key_with_npk_m_h(master_nullifier_public_key_hash: Field) -> GrumpkinPoint { + let result = get_public_key_and_partial_address_with_npk_m_h_internal(master_nullifier_public_key_hash); let pub_key = GrumpkinPoint::new(result[0], result[1]); let partial_address = PartialAddress::from_field(result[2]); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 1af61f659a5..cf0117268f3 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -30,10 +30,10 @@ pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { // TODO (#6176): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address #[oracle(getNullifierKeysWithMasterNullifierPublicKeyHash)] -fn get_nullifier_keys_with_master_nullifier_public_key_hash_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} +fn get_nk_with_npk_m_h_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} -unconstrained fn get_nullifier_keys_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash: Field) -> NullifierKeys { - let result = get_nullifier_keys_with_master_nullifier_public_key_hash_oracle(master_nullifier_public_key_hash); +unconstrained fn get_nk_with_npk_m_h_internal(master_nullifier_public_key_hash: Field) -> NullifierKeys { + let result = get_nk_with_npk_m_h_oracle(master_nullifier_public_key_hash); NullifierKeys { account: AztecAddress::zero(), master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, @@ -42,11 +42,11 @@ unconstrained fn get_nullifier_keys_with_master_nullifier_public_key_hash_intern } // We get the full struct Nullifier Keys here -pub fn get_nullifier_keys_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> NullifierKeys { - get_nullifier_keys_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash) +pub fn get_nk_with_npk_m_h(master_nullifier_public_key_hash: Field) -> NullifierKeys { + get_nk_with_npk_m_h_internal(master_nullifier_public_key_hash) } // We are only getting the app_nullifier_secret_key here -pub fn get_app_nullifier_secret_key_with_master_nullifier_public_key_hash(master_nullifier_public_key_hash: Field) -> Field { - get_nullifier_keys_with_master_nullifier_public_key_hash_internal(master_nullifier_public_key_hash).app_nullifier_secret_key +pub fn get_nsk_app_with_npk_m_h(master_nullifier_public_key_hash: Field) -> Field { + get_nk_with_npk_m_h_internal(master_nullifier_public_key_hash).app_nullifier_secret_key } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 9cbd4530aaa..ad8f7ff0dca 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -6,7 +6,7 @@ use dep::aztec::{ context::{PublicContext, Context}, hash::pedersen_hash, protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, hash::poseidon2_hash}, note::{note_getter::view_notes, note_getter_options::SortOrder}, - keys::getters::get_npk_m_hash, + keys::getters::get_npk_m_h, }; use crate::types::token_note::{TokenNote, OwnedNote}; @@ -62,7 +62,7 @@ impl BalancesMap { addend: U128 ) where T: NoteInterface + OwnedNote { // We fetch the nullifier public key hash in the registry / from our PXE - let nullifier_public_key_hash = get_npk_m_hash(self.map.context.private.unwrap(), owner); + let nullifier_public_key_hash = get_npk_m_h(self.map.context.private.unwrap(), owner); let mut addend_note = T::new(addend, nullifier_public_key_hash); diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index e408237fd09..5e64fcfdac3 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -2,13 +2,13 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key_with_master_nullifier_public_key_hash, get_public_key::get_public_key_with_master_nullifier_public_key_hash} + oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nsk_app_with_npk_m_h, get_public_key::get_public_key_with_npk_m_h} }; trait OwnedNote { - fn new(amount: U128, owner_nullifying_public_key_hash: Field) -> Self; + fn new(amount: U128, owner_npk_m_h: Field) -> Self; fn get_amount(self) -> U128; - fn get_owner_nullifying_public_key_hash(self) -> Field; + fn get_owner_npk_m_h(self) -> Field; } global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. @@ -19,7 +19,7 @@ struct TokenNote { amount: U128, // The nullifying public key hash of the person who owns the note. // This is used with the app_nullifier_secret_key to ensure that the note can be privately spent. - owner_nullifying_public_key_hash: Field, + owner_npk_m_h: Field, // Randomness of the note to hide its contents randomness: Field, } @@ -28,7 +28,7 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key_with_master_public_nullifying_key_hash(self.owner_nullifying_public_key_hash); + let secret = context.request_nsk_app_with_npk_m_h(self.owner_npk_m_h); poseidon2_hash([ note_hash_for_nullify, secret, @@ -39,7 +39,7 @@ impl NoteInterface for TokenNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key_with_master_nullifier_public_key_hash(self.owner_nullifying_public_key_hash); + let secret = get_nsk_app_with_npk_m_h(self.owner_npk_m_h); poseidon2_hash([ note_hash_for_nullify, secret, @@ -52,7 +52,7 @@ impl NoteInterface for TokenNote { // We only bother inserting the note if non-empty to save funds on gas. // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format if !(self.amount == U128::from_integer(0)) { - let encryption_pub_key = get_public_key_with_master_nullifier_public_key_hash(self.owner_nullifying_public_key_hash); + let encryption_pub_key = get_public_key_with_npk_m_h(self.owner_npk_m_h); context.emit_encrypted_log( (*context).this_address(), slot, @@ -65,10 +65,10 @@ impl NoteInterface for TokenNote { } impl OwnedNote for TokenNote { - fn new(amount: U128, owner_nullifying_public_key_hash: Field) -> Self { + fn new(amount: U128, owner_npk_m_h: Field) -> Self { Self { amount, - owner_nullifying_public_key_hash, + owner_npk_m_h, randomness: unsafe_rand(), header: NoteHeader::empty(), } @@ -78,7 +78,7 @@ impl OwnedNote for TokenNote { self.amount } - fn get_owner_nullifying_public_key_hash(self) -> Field { - self.owner_nullifying_public_key_hash + fn get_owner_npk_m_h(self) -> Field { + self.owner_npk_m_h } } From f734d3fcd9ea61ade3f1cdba7e3bd6b534f833cf Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 10:16:42 +0000 Subject: [PATCH 051/125] address comments --- .../aztec-nr/aztec/src/oracle/get_public_key.nr | 2 +- .../aztec-nr/aztec/src/oracle/nullifier_key.nr | 2 +- yarn-project/pxe/src/simulator_oracle/index.ts | 6 +++--- yarn-project/simulator/src/acvm/oracle/oracle.ts | 15 ++++++--------- .../simulator/src/acvm/oracle/typed_oracle.ts | 8 ++++---- yarn-project/simulator/src/client/db_oracle.ts | 7 ++----- .../simulator/src/client/simulator.test.ts | 2 +- .../simulator/src/client/view_data_oracle.ts | 12 ++++-------- 8 files changed, 22 insertions(+), 32 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr index 3af70b10c91..08ff0f5a97a 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr @@ -20,7 +20,7 @@ pub fn get_public_key(address: AztecAddress) -> GrumpkinPoint { } // TODO(#5901 -> #5834): This should be refactored, would be most effective to do it after new encrypted log scheme, as well as key store pxe separation. -#[oracle(getPublicKeyAndPartialAddressWithMasterNullifierPublicKeyHash)] +#[oracle(getPublicKeyAndPartialAddressWithNpkMH)] fn get_public_key_and_partial_address_with_npk_m_h_oracle(master_nullifier_public_key_hash: Field) -> [Field; 3] {} unconstrained fn get_public_key_and_partial_address_with_npk_m_h_internal(master_nullifier_public_key_hash: Field) -> [Field; 3] { diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index cf0117268f3..fdee2cebcf0 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -29,7 +29,7 @@ pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { } // TODO (#6176): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address -#[oracle(getNullifierKeysWithMasterNullifierPublicKeyHash)] +#[oracle(getNullifierKeysWithNpkMH)] fn get_nk_with_npk_m_h_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} unconstrained fn get_nk_with_npk_m_h_internal(master_nullifier_public_key_hash: Field) -> NullifierKeys { diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 3b2f3a6a34c..328e40a835e 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -44,7 +44,7 @@ export class SimulatorOracle implements DBOracle { return { masterNullifierPublicKey, appNullifierSecretKey }; } - async getNullifierKeysWithMasterNullifierPublicKeyHash( + async getNullifierKeysWithNpkMH( masterNullifierPublicKeyHash: AztecAddress, contractAddress: AztecAddress, ): Promise { @@ -68,8 +68,8 @@ export class SimulatorOracle implements DBOracle { } // TODO: #5834 - getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKey: Fr): Promise { - const address = this.keyStore.getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKey); + getCompleteAddressWithNpkMH(masterNullifierPublicKeyHash: Fr): Promise { + const address = this.keyStore.getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash); return this.getCompleteAddress(address); } diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 955e2d06b9a..02f696f1b77 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -53,13 +53,10 @@ export class Oracle { ]; } - async getNullifierKeysWithMasterNullifierPublicKeyHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise< - ACVMField[] - > { - const { masterNullifierPublicKey, appNullifierSecretKey } = - await this.typedOracle.getNullifierKeysWithMasterNullifierPublicKeyHash( - fromACVMField(masterNullifierPublicKeyHash), - ); + async getNullifierKeysWithNpkMH([masterNullifierPublicKeyHash]: ACVMField[]): Promise { + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeysWithNpkMH( + fromACVMField(masterNullifierPublicKeyHash), + ); return [ toACVMField(masterNullifierPublicKey.x), toACVMField(masterNullifierPublicKey.y), @@ -76,8 +73,8 @@ export class Oracle { } // TODO: #5834 Nuke this - async getPublicKeyAndPartialAddressWithMasterNullifierPublicKeyHash([masterNullifierPublicKeyHash]: ACVMField[]) { - const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddressWithMasterNullifierPublicKey( + async getPublicKeyAndPartialAddressWithNpkMH([masterNullifierPublicKeyHash]: ACVMField[]) { + const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddressWithNpkMH( fromACVMField(masterNullifierPublicKeyHash), ); return [publicKey.x, publicKey.y, partialAddress].map(toACVMField); diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 314029a12e8..5ea9023698f 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -93,8 +93,8 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getNullifierKeys'); } - getNullifierKeysWithMasterNullifierPublicKeyHash(_masterNullifierPublicKeyHash: Fr): Promise { - throw new OracleMethodNotAvailableError('getNullifierKeysWithMasterNullifierPublicKeyHash'); + getNullifierKeysWithNpkMH(_masterNullifierPublicKeyHash: Fr): Promise { + throw new OracleMethodNotAvailableError('getNullifierKeysWithNpkMH'); } getPublicKeyAndPartialAddress(_address: AztecAddress): Promise { @@ -136,8 +136,8 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getCompleteAddress'); } - getCompleteAddressWithMasterNullifierPublicKey(_masterNullifierPublicKeyHash: Fr): Promise { - throw new OracleMethodNotAvailableError('getCompleteAddressWithMasterNullifierPublicKey'); + getCompleteAddressWithNpkMH(_masterNullifierPublicKeyHash: Fr): Promise { + throw new OracleMethodNotAvailableError('getCompleteAddressWithNpkMH'); } getAuthWitness(_messageHash: Fr): Promise { diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 028bae9a303..b517a53c9fe 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -55,7 +55,7 @@ export interface DBOracle extends CommitmentsDB { * @param masterNullifierPublicKeyHash - Master nullifier public key hash to fetch the complete address for. * @returns A complete address associated with the input master nullifier public key hash. */ - getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKey: Fr): Promise; + getCompleteAddressWithNpkMH(masterNullifierPublicKeyHash: Fr): Promise; /** * Retrieve the auth witness for a given message hash. @@ -97,10 +97,7 @@ export interface DBOracle extends CommitmentsDB { * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - getNullifierKeysWithMasterNullifierPublicKeyHash( - masterNullifierPublicKeyHash: Fr, - contractAddress: AztecAddress, - ): Promise; + getNullifierKeysWithNpkMH(masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index a4c6f419232..cb22aa7eed9 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -43,7 +43,7 @@ describe('Simulator', () => { oracle = mock(); node = mock(); - oracle.getNullifierKeysWithMasterNullifierPublicKeyHash.mockResolvedValue({ + oracle.getNullifierKeysWithNpkMH.mockResolvedValue({ masterNullifierPublicKey: ownerMasterNullifierPublicKey, appNullifierSecretKey, }); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 7e0b27a1726..3f4c63ae8e5 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -50,10 +50,8 @@ export class ViewDataOracle extends TypedOracle { * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - public override getNullifierKeysWithMasterNullifierPublicKeyHash( - masterNullifierPublicKeyHash: Fr, - ): Promise { - return this.db.getNullifierKeysWithMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash, this.contractAddress); + public override getNullifierKeysWithNpkMH(masterNullifierPublicKeyHash: Fr): Promise { + return this.db.getNullifierKeysWithNpkMH(masterNullifierPublicKeyHash, this.contractAddress); } /** @@ -152,10 +150,8 @@ export class ViewDataOracle extends TypedOracle { * @param masterNullifierPublicKeyHash - Master nullifier public key hash to fetch the complete address for. * @returns A complete address associated with the input master nullifier public key hash. */ - public override getCompleteAddressWithMasterNullifierPublicKey( - masterNullifierPublicKeyHash: Fr, - ): Promise { - return this.db.getCompleteAddressWithMasterNullifierPublicKey(masterNullifierPublicKeyHash); + public override getCompleteAddressWithNpkMH(masterNullifierPublicKeyHash: Fr): Promise { + return this.db.getCompleteAddressWithNpkMH(masterNullifierPublicKeyHash); } /** From 04f058f8be3d6f79adde20883070d839014786d7 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 10:56:49 +0000 Subject: [PATCH 052/125] fix --- noir-projects/aztec-nr/aztec/src/context/private_context.nr | 1 + 1 file changed, 1 insertion(+) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index b6ca4d8f84e..f8053bff359 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -244,6 +244,7 @@ impl PrivateContext { keys }; + // We have to check if the key that was requested or cached corresponds to the one we request for assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), master_public_nullifying_key_hash); keys.app_nullifier_secret_key } From 76850bdcd52782263438cd63d426d84e85d1e36c Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 11:07:49 +0000 Subject: [PATCH 053/125] fix --- .../aztec-nr/aztec/src/context/private_context.nr | 4 ++-- .../aztec-nr/aztec/src/oracle/nullifier_key.nr | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index f8053bff359..49ea7ed44ac 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -6,7 +6,7 @@ use crate::{ arguments, returns, call_private_function::call_private_function_internal, header::get_header_at, logs::emit_encrypted_log, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, - nullifier_key::{get_nullifier_keys, get_nk_with_npk_m_h, NullifierKeys}, + nullifier_key::{get_nullifier_keys, get_nullifier_keys_with_npk_m_h, NullifierKeys}, enqueue_public_function_call::{ enqueue_public_function_call_internal, set_public_teardown_function_call_internal, parse_public_call_stack_item_from_oracle}, @@ -229,7 +229,7 @@ impl PrivateContext { // TODO: (#6176) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address pub fn request_nsk_app_with_npk_m_h(&mut self, master_public_nullifying_key_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { - let keys = get_nk_with_npk_m_h(master_public_nullifying_key_hash); + let keys = get_nullifier_keys_with_npk_m_h(master_public_nullifying_key_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, app_nullifier_secret_key: keys.app_nullifier_secret_key diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index fdee2cebcf0..4040633ca34 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -30,10 +30,10 @@ pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { // TODO (#6176): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address #[oracle(getNullifierKeysWithNpkMH)] -fn get_nk_with_npk_m_h_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} +fn get_nullifier_keys_with_npk_m_h_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} -unconstrained fn get_nk_with_npk_m_h_internal(master_nullifier_public_key_hash: Field) -> NullifierKeys { - let result = get_nk_with_npk_m_h_oracle(master_nullifier_public_key_hash); +unconstrained fn get_nullifier_keys_with_npk_m_h_internal(master_nullifier_public_key_hash: Field) -> NullifierKeys { + let result = get_nullifier_keys_with_npk_m_h_oracle(master_nullifier_public_key_hash); NullifierKeys { account: AztecAddress::zero(), master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, @@ -42,11 +42,11 @@ unconstrained fn get_nk_with_npk_m_h_internal(master_nullifier_public_key_hash: } // We get the full struct Nullifier Keys here -pub fn get_nk_with_npk_m_h(master_nullifier_public_key_hash: Field) -> NullifierKeys { - get_nk_with_npk_m_h_internal(master_nullifier_public_key_hash) +pub fn get_nullifier_keys_with_npk_m_h(master_nullifier_public_key_hash: Field) -> NullifierKeys { + get_nullifier_keys_with_npk_m_h_internal(master_nullifier_public_key_hash) } // We are only getting the app_nullifier_secret_key here pub fn get_nsk_app_with_npk_m_h(master_nullifier_public_key_hash: Field) -> Field { - get_nk_with_npk_m_h_internal(master_nullifier_public_key_hash).app_nullifier_secret_key + get_nullifier_keys_with_npk_m_h_internal(master_nullifier_public_key_hash).app_nullifier_secret_key } From 4f86276fb194ac407119a602c33df2945a0346b2 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 11:11:05 +0000 Subject: [PATCH 054/125] fix --- .../contracts/token_contract/src/types/balances_map.nr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index ad8f7ff0dca..82a76f4b792 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -62,9 +62,9 @@ impl BalancesMap { addend: U128 ) where T: NoteInterface + OwnedNote { // We fetch the nullifier public key hash in the registry / from our PXE - let nullifier_public_key_hash = get_npk_m_h(self.map.context.private.unwrap(), owner); + let owner_npk_m_h = get_npk_m_h(self.map.context.private.unwrap(), owner); - let mut addend_note = T::new(addend, nullifier_public_key_hash); + let mut addend_note = T::new(addend, owner_npk_m_h); // docs:start:insert self.map.at(owner).insert(&mut addend_note, true); From b85388dc5cda86013f17d0a08746f3a357c9dd6e Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 19:14:38 +0000 Subject: [PATCH 055/125] fix formatting --- .../contracts/token_contract/src/types/balances_map.nr | 3 +-- .../contracts/token_contract/src/types/token_note.nr | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 82a76f4b792..ffe373fc501 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -5,8 +5,7 @@ use dep::aztec::prelude::{ use dep::aztec::{ context::{PublicContext, Context}, hash::pedersen_hash, protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, hash::poseidon2_hash}, - note::{note_getter::view_notes, note_getter_options::SortOrder}, - keys::getters::get_npk_m_h, + note::{note_getter::view_notes, note_getter_options::SortOrder}, keys::getters::get_npk_m_h }; use crate::types::token_note::{TokenNote, OwnedNote}; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 5e64fcfdac3..917d98136f0 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -2,7 +2,10 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nsk_app_with_npk_m_h, get_public_key::get_public_key_with_npk_m_h} + oracle::{ + unsafe_rand::unsafe_rand, nullifier_key::get_nsk_app_with_npk_m_h, + get_public_key::get_public_key_with_npk_m_h +} }; trait OwnedNote { From 29f422572a7ca55cbdf5e1b1107bd82603d14419 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 19:26:54 +0000 Subject: [PATCH 056/125] nargo fmt --- .../aztec-nr/aztec/src/context/private_context.nr | 15 ++++++++------- noir-projects/aztec-nr/aztec/src/keys/getters.nr | 5 ++++- .../aztec-nr/aztec/src/oracle/nullifier_key.nr | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 167786cb70b..7f31e14f856 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -3,14 +3,14 @@ use crate::{ messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher, compute_encrypted_log_hash, compute_unencrypted_log_hash}, oracle::{ - arguments, returns, call_private_function::call_private_function_internal, - header::get_header_at, + arguments, returns, call_private_function::call_private_function_internal, header::get_header_at, logs::emit_encrypted_log, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, nullifier_key::{get_nullifier_keys, get_nullifier_keys_with_npk_m_h, NullifierKeys}, enqueue_public_function_call::{ enqueue_public_function_call_internal, set_public_teardown_function_call_internal, - parse_public_call_stack_item_from_oracle}, - }, + parse_public_call_stack_item_from_oracle +} +} }; use dep::protocol_types::{ abis::{ @@ -31,8 +31,7 @@ use dep::protocol_types::{ contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, - traits::{is_empty, Deserialize, Empty}, - hash::poseidon2_hash + traits::{is_empty, Deserialize, Empty}, hash::poseidon2_hash }; // When finished, one can call .finish() to convert back to the abi @@ -241,7 +240,9 @@ impl PrivateContext { }; // We have to check if the key that was requested or cached corresponds to the one we request for - assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), master_public_nullifying_key_hash); + assert_eq( + poseidon2_hash(keys.master_nullifier_public_key.serialize()), master_public_nullifying_key_hash + ); keys.app_nullifier_secret_key } diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index 5371272bada..142dd835eeb 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -1,4 +1,7 @@ -use dep::protocol_types::{address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}; +use dep::protocol_types::{ + address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, + hash::poseidon2_hash +}; use crate::{ context::PrivateContext, oracle::keys::get_public_keys_and_partial_address, state_vars::{ diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 6ecd924d9ad..84f9be06612 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -37,7 +37,7 @@ unconstrained fn get_nullifier_keys_with_npk_m_h_internal(master_nullifier_publi NullifierKeys { account: AztecAddress::zero(), master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, - app_nullifier_secret_key: result[2], + app_nullifier_secret_key: result[2] } } From 05f8fefeb736e9b8e1e9e66358ccecefa290bf04 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 22:09:25 +0000 Subject: [PATCH 057/125] Fix --- .../pxe/src/simulator_oracle/index.ts | 19 ++++++++++++------- .../simulator/src/acvm/oracle/typed_oracle.ts | 5 +++-- .../simulator/src/client/db_oracle.ts | 6 +++--- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 328e40a835e..6a53667bd7a 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -15,7 +15,7 @@ import { type FunctionSelector, type Header, type L1_TO_L2_MSG_TREE_HEIGHT, - type Point, + type PublicKeys, } from '@aztec/circuits.js'; import { computeL1ToL2MessageNullifier } from '@aztec/circuits.js/hash'; import { type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/abi'; @@ -98,13 +98,18 @@ export class SimulatorOracle implements DBOracle { } // TODO: #5834 - async getPublicKeysForAddress(address: AztecAddress): Promise { - const nullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(address); - const incomingViewingPublicKey = await this.keyStore.getMasterIncomingViewingPublicKey(address); - const outgoingViewingPublicKey = await this.keyStore.getMasterOutgoingViewingPublicKey(address); - const taggingPublicKey = await this.keyStore.getMasterTaggingPublicKey(address); + async getPublicKeysForAddress(address: AztecAddress): Promise { + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(address); + const masterIncomingViewingPublicKey = await this.keyStore.getMasterIncomingViewingPublicKey(address); + const masterOutgoingViewingPublicKey = await this.keyStore.getMasterOutgoingViewingPublicKey(address); + const masterTaggingPublicKey = await this.keyStore.getMasterTaggingPublicKey(address); - return [nullifierPublicKey, incomingViewingPublicKey, outgoingViewingPublicKey, taggingPublicKey]; + return { + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + }; } async getNotes(contractAddress: AztecAddress, storageSlot: Fr, status: NoteStatus) { diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 5ea9023698f..0f78e67550f 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -14,10 +14,11 @@ import { type L1_TO_L2_MSG_TREE_HEIGHT, type PrivateCallStackItem, type PublicCallRequest, + type PublicKeys, } from '@aztec/circuits.js'; import { type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr, type Point } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; /** Nullifier keys which both correspond to the same master nullifier secret key. */ @@ -148,7 +149,7 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('popCapsule'); } - getPublicKeysForAddress(_address: AztecAddress): Promise { + getPublicKeysForAddress(_address: AztecAddress): Promise { throw new OracleMethodNotAvailableError('getPublicKeysForAddress'); } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index b517a53c9fe..28ff000f85a 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -5,10 +5,10 @@ import { type NullifierMembershipWitness, type PublicDataWitness, } from '@aztec/circuit-types'; -import { type CompleteAddress, type Header } from '@aztec/circuits.js'; +import { type CompleteAddress, type Header, type PublicKeys } from '@aztec/circuits.js'; import { type FunctionArtifact, type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { type Fr, type Point } from '@aztec/foundation/fields'; +import { type Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; import { type NoteData, type NullifierKeys } from '../acvm/index.js'; @@ -77,7 +77,7 @@ export interface DBOracle extends CommitmentsDB { * @returns The public keys for a specific address * TODO(#5834): Replace with `getCompleteAddress`. */ - getPublicKeysForAddress(address: AztecAddress): Promise; + getPublicKeysForAddress(address: AztecAddress): Promise; /** * Retrieve nullifier keys associated with a specific account and app/contract address. From f8f27a74a799945c257d18dfe4831c21cdd5bf7a Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 22:35:42 +0000 Subject: [PATCH 058/125] fix --- .../simulator/src/acvm/oracle/oracle.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 02f696f1b77..66f25b06e70 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -1,5 +1,5 @@ import { MerkleTreeId, UnencryptedL2Log } from '@aztec/circuit-types'; -import { type PartialAddress, acvmFieldMessageToString, oracleDebugCallToFormattedStr } from '@aztec/circuits.js'; +import { type PartialAddress, acvmFieldMessageToString, oracleDebugCallToFormattedStr, PublicKeys } from '@aztec/circuits.js'; import { EventSelector, FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, Point } from '@aztec/foundation/fields'; @@ -192,7 +192,7 @@ export class Oracle { } async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { - let publicKeys: Point[] | undefined; + let publicKeys: PublicKeys; let partialAddress: PartialAddress; // TODO #5834: This should be reworked to return the public keys as well @@ -205,10 +205,20 @@ export class Oracle { try { publicKeys = await this.typedOracle.getPublicKeysForAddress(AztecAddress.fromField(fromACVMField(address))); } catch (err) { - publicKeys = Array(4).fill(Point.ZERO); + publicKeys = { + masterNullifierPublicKey: Point.ZERO, + masterIncomingViewingPublicKey: Point.ZERO, + masterOutgoingViewingPublicKey: Point.ZERO, + masterTaggingPublicKey: Point.ZERO, + }; } - const acvmPublicKeys = publicKeys.flatMap(key => key.toFields()); + const acvmPublicKeys = [ + publicKeys.masterNullifierPublicKey.toFields(), + publicKeys.masterIncomingViewingPublicKey.toFields(), + publicKeys.masterOutgoingViewingPublicKey.toFields(), + publicKeys.masterTaggingPublicKey.toFields(), + ].flat(); return [...acvmPublicKeys, partialAddress].map(toACVMField); } From ded1ee3957bd26b10670f38a325bd80453858a5e Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 8 May 2024 22:54:45 +0000 Subject: [PATCH 059/125] format --- yarn-project/simulator/src/acvm/oracle/oracle.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 66f25b06e70..a41d4fd5274 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -1,5 +1,10 @@ import { MerkleTreeId, UnencryptedL2Log } from '@aztec/circuit-types'; -import { type PartialAddress, acvmFieldMessageToString, oracleDebugCallToFormattedStr, PublicKeys } from '@aztec/circuits.js'; +import { + type PartialAddress, + type PublicKeys, + acvmFieldMessageToString, + oracleDebugCallToFormattedStr, +} from '@aztec/circuits.js'; import { EventSelector, FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, Point } from '@aztec/foundation/fields'; From 2f76913fb88921bdcda74556e1053fb577a36cd3 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 9 May 2024 12:52:05 +0000 Subject: [PATCH 060/125] migration notes --- docs/docs/misc/migration_notes.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index c792470b0b5..0ca193b2299 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -6,6 +6,22 @@ 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 + +### [Aztec.nr] Keys: Token note now stores an owner master nullifying public key hash instead of an owner address. + +i.e. + +struct TokenNote { + ```diff + - owner: AztecAddress, + + owner_npk_m_h: Field, + ``` + randomness: Field, +} + +Computing the nullifier similarly changes to use this master nullifying public key hash. + ## 0.38.0 ### [Aztec.nr] Emmiting encrypted logs From 1ce4d637b7190873778a64db7e0c5a9499e3dcd8 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Thu, 9 May 2024 08:38:32 -0500 Subject: [PATCH 061/125] Update migration_notes.md --- docs/docs/misc/migration_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index 0ca193b2299..fc45a8fd1c8 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -13,6 +13,7 @@ Aztec is in full-speed development. Literally every version breaks compatibility i.e. struct TokenNote { + amount: U128, ```diff - owner: AztecAddress, + owner_npk_m_h: Field, From 113b1e9002f6361bde22653cff3ebf096a607098 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 9 May 2024 21:15:50 +0000 Subject: [PATCH 062/125] fmt --- yarn-project/pxe/src/pxe_service/pxe_service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 9c8c24b438d..60b803e153f 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -30,7 +30,7 @@ import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, type PartialAddress, type PrivateKernelTailCircuitPublicInputs, - PublicCallRequest, + type PublicCallRequest, type PublicKeys, computeContractClassId, getContractClassFromArtifact, From e9f232619d5afb6833d48c828d4b53131208cb60 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 18:09:35 +0000 Subject: [PATCH 063/125] Adapting --- docs/docs/misc/migration_notes.md | 2 +- .../aztec/src/context/private_context.nr | 2 +- .../aztec-nr/aztec/src/keys/getters.nr | 12 +++++--- .../aztec/src/oracle/get_public_key.nr | 26 ++++------------- .../aztec-nr/aztec/src/oracle/keys.nr | 19 ++++++++++++ .../aztec/src/oracle/nullifier_key.nr | 14 ++++----- .../token_contract/src/types/balances_map.nr | 6 ++-- .../token_contract/src/types/token_note.nr | 26 ++++++++--------- .../aztec.js/src/wallet/base_wallet.ts | 3 -- .../circuit-types/src/interfaces/pxe.ts | 10 ------- .../end-to-end/src/e2e_2_pxes.test.ts | 29 +++++-------------- .../pxe/src/pxe_service/pxe_service.ts | 14 --------- .../simulator/src/acvm/oracle/oracle.ts | 29 ++++++++++++++----- 13 files changed, 84 insertions(+), 108 deletions(-) diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index d7046b8e3af..7bd56836bfd 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -16,7 +16,7 @@ struct TokenNote { amount: U128, ```diff - owner: AztecAddress, - + owner_npk_m_h: Field, + + npk_m_hash: Field, ``` randomness: Field, } diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index a6362b4019e..fbf2ac6dfab 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -222,7 +222,7 @@ impl PrivateContext { } // TODO: (#6176) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address - pub fn request_nsk_app_with_npk_m_h(&mut self, master_public_nullifying_key_hash: Field) -> Field { + pub fn request_nsk_app_with_npk_m_hash(&mut self, master_public_nullifying_key_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { let keys = get_nullifier_keys_with_npk_m_h(master_public_nullifying_key_hash); let request = NullifierKeyValidationRequest { diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index cd027771574..a08b9069b53 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -1,11 +1,10 @@ use dep::protocol_types::{ - address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, - hash::poseidon2_hash address::{AztecAddress, PublicKeysHash}, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash }; use crate::{ - context::PrivateContext, oracle::keys::get_public_keys_and_partial_address, + context::PrivateContext, + oracle::keys::{get_public_keys_and_partial_address, get_public_keys_and_partial_address_with_npk_m_hash}, state_vars::{ map::derive_storage_slot_in_map, shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter @@ -27,7 +26,7 @@ pub fn get_npk_m(context: &mut PrivateContext, address: AztecAddress) -> Grumpki get_master_key(context, address, NULLIFIER_INDEX) } -pub fn get_npk_m_h(context: &mut PrivateContext, address: AztecAddress) -> Field { +pub fn get_npk_m_hash(context: &mut PrivateContext, address: AztecAddress) -> Field { poseidon2_hash(get_master_key(context, address, NULLIFIER_INDEX).serialize()) } @@ -101,3 +100,8 @@ fn fetch_and_constrain_keys(address: AztecAddress) -> [GrumpkinPoint; 4] { [npk_m, ivpk_m, ovpk_m, tpk_m] } + +pub fn get_ivpk_m_with_npk_m_hash(npk_m_hash: Field) -> GrumpkinPoint { + let result = get_public_keys_and_partial_address_with_npk_m_hash(npk_m_hash); + result.0[1] +} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr index 1028114dc80..c1cf3665a83 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr @@ -1,5 +1,5 @@ -use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}; -use crate::oracle::keys::get_public_keys_and_partial_address; +use dep::protocol_types::{address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint}; +use crate::oracle::keys::{get_public_keys_and_partial_address, get_public_keys_and_partial_address_with_npk_m_hash}; // To be nuked in my next PR: https://github.com/AztecProtocol/aztec-packages/pull/6219 pub fn get_public_key(address: AztecAddress) -> GrumpkinPoint { @@ -8,23 +8,7 @@ pub fn get_public_key(address: AztecAddress) -> GrumpkinPoint { } // TODO(#5901 -> #5834): This should be refactored, would be most effective to do it after new encrypted log scheme, as well as key store pxe separation. -#[oracle(getPublicKeyAndPartialAddressWithNpkMH)] -fn get_public_key_and_partial_address_with_npk_m_h_oracle(master_nullifier_public_key_hash: Field) -> [Field; 3] {} - -unconstrained fn get_public_key_and_partial_address_with_npk_m_h_internal(master_nullifier_public_key_hash: Field) -> [Field; 3] { - get_public_key_and_partial_address_with_npk_m_h_oracle(master_nullifier_public_key_hash) -} - -// TODO (#5901): This is used when we emit encrypted logs and will be changed. -// TODO (#6178): This function should not be contraining things here. -pub fn get_public_key_with_npk_m_h(master_nullifier_public_key_hash: Field) -> GrumpkinPoint { - let result = get_public_key_and_partial_address_with_npk_m_h_internal(master_nullifier_public_key_hash); - let pub_key = GrumpkinPoint::new(result[0], result[1]); - let partial_address = PartialAddress::from_field(result[2]); - - // TODO(#5830): disabling the following constraint until we update the oracle according to the new key scheme - // let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address); - // assert(calculated_address.eq(address)); - - pub_key +pub fn get_public_key_with_npk_m_hash(npk_m_hash: Field) -> GrumpkinPoint { + let result = get_public_keys_and_partial_address_with_npk_m_hash(npk_m_hash); + result.0[1] } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index a985e385e81..3aa89274571 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -20,3 +20,22 @@ fn get_public_keys_and_partial_address(address: AztecAddress) -> ([GrumpkinPoint ([nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key], partial_address) } + +#[oracle(getPublicKeysAndPartialAddressWithNpkMH)] +fn get_public_keys_and_partial_address_with_npk_m_hash_oracle(_npk_m_hash: Field) -> [Field; 9] {} + +unconstrained fn get_public_keys_and_partial_address_with_npk_m_hash_oracle_wrapper(npk_m_hash: Field) -> [Field; 9] { + get_public_keys_and_partial_address_with_npk_m_hash_oracle(npk_m_hash) +} + +fn get_public_keys_and_partial_address_with_npk_m_hash(npk_m_hash: Field) -> ([GrumpkinPoint; 4], PartialAddress) { + let result = get_public_keys_and_partial_address_with_npk_m_hash_oracle_wrapper(npk_m_hash); + + let nullifier_pub_key = GrumpkinPoint::new(result[0], result[1]); + let incoming_pub_key = GrumpkinPoint::new(result[2], result[3]); + let outgoing_pub_key = GrumpkinPoint::new(result[4], result[5]); + let tagging_pub_key = GrumpkinPoint::new(result[6], result[7]); + let partial_address = PartialAddress::from_field(result[8]); + + ([nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key], partial_address) +} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 84f9be06612..4a749c033ad 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -30,10 +30,10 @@ pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { // TODO (#6176): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address #[oracle(getNullifierKeysWithNpkMH)] -fn get_nullifier_keys_with_npk_m_h_oracle(_master_nullifier_public_key_hash: Field) -> [Field; 3] {} +fn get_nullifier_keys_with_npk_m_h_oracle(_npk_m_hash: Field) -> [Field; 3] {} -unconstrained fn get_nullifier_keys_with_npk_m_h_internal(master_nullifier_public_key_hash: Field) -> NullifierKeys { - let result = get_nullifier_keys_with_npk_m_h_oracle(master_nullifier_public_key_hash); +unconstrained fn get_nullifier_keys_with_npk_m_h_internal(npk_m_hash: Field) -> NullifierKeys { + let result = get_nullifier_keys_with_npk_m_h_oracle(npk_m_hash); NullifierKeys { account: AztecAddress::zero(), master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, @@ -42,11 +42,11 @@ unconstrained fn get_nullifier_keys_with_npk_m_h_internal(master_nullifier_publi } // We get the full struct Nullifier Keys here -pub fn get_nullifier_keys_with_npk_m_h(master_nullifier_public_key_hash: Field) -> NullifierKeys { - get_nullifier_keys_with_npk_m_h_internal(master_nullifier_public_key_hash) +pub fn get_nullifier_keys_with_npk_m_h(npk_m_hash: Field) -> NullifierKeys { + get_nullifier_keys_with_npk_m_h_internal(npk_m_hash) } // We are only getting the app_nullifier_secret_key here -pub fn get_nsk_app_with_npk_m_h(master_nullifier_public_key_hash: Field) -> Field { - get_nullifier_keys_with_npk_m_h_internal(master_nullifier_public_key_hash).app_nullifier_secret_key +pub fn get_nsk_app_with_npk_m_hash(npk_m_hash: Field) -> Field { + get_nullifier_keys_with_npk_m_h_internal(npk_m_hash).app_nullifier_secret_key } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index ffe373fc501..6ae314da25c 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -5,7 +5,7 @@ use dep::aztec::prelude::{ use dep::aztec::{ context::{PublicContext, Context}, hash::pedersen_hash, protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, hash::poseidon2_hash}, - note::{note_getter::view_notes, note_getter_options::SortOrder}, keys::getters::get_npk_m_h + note::{note_getter::view_notes, note_getter_options::SortOrder}, keys::getters::get_npk_m_hash }; use crate::types::token_note::{TokenNote, OwnedNote}; @@ -61,9 +61,9 @@ impl BalancesMap { addend: U128 ) where T: NoteInterface + OwnedNote { // We fetch the nullifier public key hash in the registry / from our PXE - let owner_npk_m_h = get_npk_m_h(self.map.context.private.unwrap(), owner); + let owner_npk_m_hash = get_npk_m_hash(self.map.context.private.unwrap(), owner); - let mut addend_note = T::new(addend, owner_npk_m_h); + let mut addend_note = T::new(addend, owner_npk_m_hash); // docs:start:insert self.map.at(owner).insert(&mut addend_note, true); diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 917d98136f0..ef225dc0378 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -2,16 +2,14 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::{ - unsafe_rand::unsafe_rand, nullifier_key::get_nsk_app_with_npk_m_h, - get_public_key::get_public_key_with_npk_m_h -} + keys::getters::get_ivpk_m_with_npk_m_hash, + oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nsk_app_with_npk_m_hash} }; trait OwnedNote { - fn new(amount: U128, owner_npk_m_h: Field) -> Self; + fn new(amount: U128, owner_npk_m_hash: Field) -> Self; fn get_amount(self) -> U128; - fn get_owner_npk_m_h(self) -> Field; + fn get_owner_npk_m_hash(self) -> Field; } global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. @@ -22,7 +20,7 @@ struct TokenNote { amount: U128, // The nullifying public key hash of the person who owns the note. // This is used with the app_nullifier_secret_key to ensure that the note can be privately spent. - owner_npk_m_h: Field, + npk_m_hash: Field, // Randomness of the note to hide its contents randomness: Field, } @@ -31,7 +29,7 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_nsk_app_with_npk_m_h(self.owner_npk_m_h); + let secret = context.request_nsk_app_with_npk_m_hash(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -42,7 +40,7 @@ impl NoteInterface for TokenNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_nsk_app_with_npk_m_h(self.owner_npk_m_h); + let secret = get_nsk_app_with_npk_m_hash(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -55,7 +53,7 @@ impl NoteInterface for TokenNote { // We only bother inserting the note if non-empty to save funds on gas. // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format if !(self.amount == U128::from_integer(0)) { - let encryption_pub_key = get_public_key_with_npk_m_h(self.owner_npk_m_h); + let encryption_pub_key = get_ivpk_m_with_npk_m_hash(self.npk_m_hash); context.emit_encrypted_log( (*context).this_address(), slot, @@ -68,10 +66,10 @@ impl NoteInterface for TokenNote { } impl OwnedNote for TokenNote { - fn new(amount: U128, owner_npk_m_h: Field) -> Self { + fn new(amount: U128, owner_npk_m_hash: Field) -> Self { Self { amount, - owner_npk_m_h, + npk_m_hash: owner_npk_m_hash, randomness: unsafe_rand(), header: NoteHeader::empty(), } @@ -81,7 +79,7 @@ impl OwnedNote for TokenNote { self.amount } - fn get_owner_npk_m_h(self) -> Field { - self.owner_npk_m_h + fn get_owner_npk_m_hash(self) -> Field { + self.npk_m_hash } } diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index a85dfe7ada0..9a2f1aec30f 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -84,9 +84,6 @@ export abstract class BaseWallet implements Wallet { getRegisteredAccount(address: AztecAddress): Promise { return this.pxe.getRegisteredAccount(address); } - getRegisteredAccountPublicKeys(address: AztecAddress): Promise { - return this.pxe.getRegisteredAccountPublicKeys(address); - } getRecipients(): Promise { return this.pxe.getRecipients(); } diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 760580b2ca4..0d26e226e4a 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -97,16 +97,6 @@ export interface PXE { */ getRegisteredAccount(address: AztecAddress): Promise; - /** - * Retrieves the public keys of the account corresponding to the provided aztec address. - * - * @param address - The address of account. - * @returns The public keys of the requested account if found. - * TODO(#5834): refactor complete address and merge with getRegisteredAccount? - * This will change after the re enabling separation of keystore and pxe. We shouldn't need both this function and the above one - */ - getRegisteredAccountPublicKeys(address: AztecAddress): Promise; - /** * Retrieves the recipients added to this PXE Service. * @returns An array of recipients registered on this PXE Service. diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index 79167951f39..6ab0f85dbca 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -119,14 +119,10 @@ describe('e2e_2_pxes', () => { const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); const tokenAddress = tokenInstance.address; - // Get public keys of both accounts - const walletAPublicKeys = await pxeA.getRegisteredAccountPublicKeys(walletA.getAddress()); - const walletBPublicKeys = await pxeB.getRegisteredAccountPublicKeys(walletB.getAddress()); - // Add account B to wallet A - await pxeA.registerRecipient(walletB.getCompleteAddress(), walletBPublicKeys); + await pxeA.registerRecipient(walletB.getCompleteAddress()); // Add account A to wallet B - await pxeB.registerRecipient(walletA.getCompleteAddress(), walletAPublicKeys); + await pxeB.registerRecipient(walletA.getCompleteAddress()); // Add token to PXE B (PXE A already has it because it was deployed through it) await pxeB.registerContract({ @@ -219,14 +215,10 @@ describe('e2e_2_pxes', () => { const tokenInstance = await deployTokenContract(userABalance, walletA.getAddress(), pxeA); const contractWithWalletA = await TokenContract.at(tokenInstance.address, walletA); - // Get public keys of both accounts - const walletAPublicKeys = await pxeA.getRegisteredAccountPublicKeys(walletA.getAddress()); - const walletBPublicKeys = await pxeB.getRegisteredAccountPublicKeys(walletB.getAddress()); - // Add account B to wallet A - await pxeA.registerRecipient(walletB.getCompleteAddress(), walletBPublicKeys); + await pxeA.registerRecipient(walletB.getCompleteAddress()); // Add account A to wallet B - await pxeB.registerRecipient(walletA.getCompleteAddress(), walletAPublicKeys); + await pxeB.registerRecipient(walletA.getCompleteAddress()); // Add token to PXE B (PXE A already has it because it was deployed through it) await pxeB.registerContract({ @@ -276,14 +268,10 @@ describe('e2e_2_pxes', () => { const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); const tokenAddress = tokenInstance.address; - // Get public keys of both accounts - const walletAPublicKeys = await pxeA.getRegisteredAccountPublicKeys(walletA.getAddress()); - const walletBPublicKeys = await pxeB.getRegisteredAccountPublicKeys(walletB.getAddress()); - // Add account B to wallet A - await pxeA.registerRecipient(walletB.getCompleteAddress(), walletBPublicKeys); + await pxeA.registerRecipient(walletB.getCompleteAddress()); // Add account A to wallet B - await pxeB.registerRecipient(walletA.getCompleteAddress(), walletAPublicKeys); + await pxeB.registerRecipient(walletA.getCompleteAddress()); // Check initial balances and logs are as expected await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); @@ -323,11 +311,8 @@ describe('e2e_2_pxes', () => { await sharedAccountOnB.register(); const sharedWalletOnB = await sharedAccountOnB.getWallet(); - // Get the public keys of wallet B - const walletBPublicKeys = await pxeB.getRegisteredAccountPublicKeys(walletB.getAddress()); - // Register wallet B in the pxe of wallet A - await pxeA.registerRecipient(walletB.getCompleteAddress(), walletBPublicKeys); + await pxeA.registerRecipient(walletB.getCompleteAddress()); // deploy the contract on PXE A const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 7244157d4fd..1e2e136a3a4 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -204,20 +204,6 @@ export class PXEService implements PXE { return Promise.resolve(account); } - public async getRegisteredAccountPublicKeys(address: AztecAddress): Promise { - const accounts = await this.keyStore.getAccounts(); - if (!accounts.some(account => account.equals(address))) { - return undefined; - } - - return { - masterNullifierPublicKey: await this.keyStore.getMasterNullifierPublicKey(address), - masterIncomingViewingPublicKey: await this.keyStore.getMasterIncomingViewingPublicKey(address), - masterOutgoingViewingPublicKey: await this.keyStore.getMasterOutgoingViewingPublicKey(address), - masterTaggingPublicKey: await this.keyStore.getMasterTaggingPublicKey(address), - }; - } - public async registerRecipient(recipient: CompleteAddress): Promise { const wasAdded = await this.db.addCompleteAddress(recipient); diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index a66ad99ca7b..e27b63d6c9f 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -64,14 +64,6 @@ export class Oracle { ]; } - // TODO: #5834 Nuke this - async getPublicKeyAndPartialAddressWithNpkMH([masterNullifierPublicKeyHash]: ACVMField[]) { - const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddressWithNpkMH( - fromACVMField(masterNullifierPublicKeyHash), - ); - return [publicKey.x, publicKey.y, partialAddress].map(toACVMField); - } - async getContractInstance([address]: ACVMField[]) { const instance = await this.typedOracle.getContractInstance(AztecAddress.fromField(fromACVMField(address))); @@ -202,6 +194,27 @@ export class Oracle { ].map(toACVMField); } + // TODO: #5834 + async getPublicKeysAndPartialAddressWithNpkMH([masterNullifierPublicKeyHash]: ACVMField[]) { + const parsedNpkMH = fromACVMField(masterNullifierPublicKeyHash); + + const { + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + partialAddress, + } = await this.typedOracle.getCompleteAddressWithNpkMH(parsedNpkMH); + + return [ + ...masterNullifierPublicKey.toFields(), + ...masterIncomingViewingPublicKey.toFields(), + ...masterOutgoingViewingPublicKey.toFields(), + ...masterTaggingPublicKey.toFields(), + partialAddress, + ].map(toACVMField); + } + async getNotes( [storageSlot]: ACVMField[], [numSelects]: ACVMField[], From fe73adba61697c62ec7569cae06b8cf22b66c43c Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 18:22:15 +0000 Subject: [PATCH 064/125] fix --- .../contracts/token_contract/src/types/token_note.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 79d93eacbab..1e91e25121c 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -52,7 +52,7 @@ impl NoteInterface for TokenNote { // We only bother inserting the note if non-empty to save funds on gas. // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format if !(self.amount == U128::from_integer(0)) { - let ivpk_m = get_ivpk_m_with_npk_m_hash(context, self.owner); + let ivpk_m = get_ivpk_m_with_npk_m_hash(self.owner); context.emit_encrypted_log( (*context).this_address(), slot, From eb53c4442e049f3ac91757be1ebdb5ab2a27265a Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 18:26:34 +0000 Subject: [PATCH 065/125] fix --- .../contracts/token_contract/src/types/token_note.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 1e91e25121c..dc997924faf 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -52,7 +52,7 @@ impl NoteInterface for TokenNote { // We only bother inserting the note if non-empty to save funds on gas. // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format if !(self.amount == U128::from_integer(0)) { - let ivpk_m = get_ivpk_m_with_npk_m_hash(self.owner); + let ivpk_m = get_ivpk_m_with_npk_m_hash(self.npk_m_hash); context.emit_encrypted_log( (*context).this_address(), slot, From b6b6969a26d218a16ecf5f7934f8a681b4411306 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 18:34:50 +0000 Subject: [PATCH 066/125] Fixes --- yarn-project/aztec.js/src/wallet/base_wallet.ts | 1 - yarn-project/circuit-types/src/interfaces/pxe.ts | 1 - yarn-project/circuits.js/src/types/public_key.ts | 7 ------- yarn-project/pxe/src/pxe_service/pxe_service.ts | 1 - yarn-project/simulator/src/acvm/oracle/typed_oracle.ts | 1 - yarn-project/simulator/src/client/db_oracle.ts | 2 +- 6 files changed, 1 insertion(+), 12 deletions(-) diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 9a2f1aec30f..89e99c4d2e4 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -20,7 +20,6 @@ import { type CompleteAddress, type Fr, type PartialAddress, - type PublicKeys, } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 0d26e226e4a..2c6f8010523 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -3,7 +3,6 @@ import { type CompleteAddress, type Fr, type PartialAddress, - type PublicKeys, } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; diff --git a/yarn-project/circuits.js/src/types/public_key.ts b/yarn-project/circuits.js/src/types/public_key.ts index 817e08f1e51..0109de4c8ea 100644 --- a/yarn-project/circuits.js/src/types/public_key.ts +++ b/yarn-project/circuits.js/src/types/public_key.ts @@ -2,10 +2,3 @@ import { type Point } from '@aztec/foundation/fields'; /** Represents a user public key. */ export type PublicKey = Point; - -export type PublicKeys = { - masterNullifierPublicKey: Point; - masterIncomingViewingPublicKey: Point; - masterOutgoingViewingPublicKey: Point; - masterTaggingPublicKey: Point; -}; diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 1e2e136a3a4..8769a2d68db 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -31,7 +31,6 @@ import { type PartialAddress, type PrivateKernelTailCircuitPublicInputs, type PublicCallRequest, - type PublicKeys, computeContractClassId, getContractClassFromArtifact, } from '@aztec/circuits.js'; diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 1cb66667b79..208d690909d 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -14,7 +14,6 @@ import { type L1_TO_L2_MSG_TREE_HEIGHT, type PrivateCallStackItem, type PublicCallRequest, - type PublicKeys, } from '@aztec/circuits.js'; import { type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 03eabedf1f8..6b55630fc77 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -5,7 +5,7 @@ import { type NullifierMembershipWitness, type PublicDataWitness, } from '@aztec/circuit-types'; -import { type CompleteAddress, type Header, type PublicKeys } from '@aztec/circuits.js'; +import { type CompleteAddress, type Header } from '@aztec/circuits.js'; import { type FunctionArtifact, type FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { type Fr } from '@aztec/foundation/fields'; From 8ecec72be5f78fdc677e9a8af380b81097ce46c2 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 18:35:18 +0000 Subject: [PATCH 067/125] fix --- docs/docs/misc/migration_notes.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index fab1e9d45a1..bc839e42426 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -29,7 +29,6 @@ Computing the nullifier similarly changes to use this master nullifying public k The type signature for `SharedMutable` changed from `SharedMutable` to `SharedMutable`. The behavior is the same as before, except the delay can now be changed after deployment by calling `schedule_delay_change`. - ### [Aztec.nr] get_public_key oracle replaced with get_ivpk_m When implementing changes according to a [new key scheme](https://yp-aztec.netlify.app/docs/addresses-and-keys/keys) we had to change oracles. From 730c842ef0ff18bddc0cdc24900deb32f6763b51 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 18:46:42 +0000 Subject: [PATCH 068/125] Changes --- .../pxe/src/simulator_oracle/index.ts | 4 ++-- .../simulator/src/acvm/oracle/oracle.ts | 6 +++--- .../simulator/src/acvm/oracle/typed_oracle.ts | 8 ++++---- .../simulator/src/client/db_oracle.ts | 4 ++-- .../simulator/src/client/simulator.test.ts | 2 +- .../simulator/src/client/view_data_oracle.ts | 19 ++++++++++--------- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index bc760337b1f..6cfa3c20492 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -43,7 +43,7 @@ export class SimulatorOracle implements DBOracle { return { masterNullifierPublicKey, appNullifierSecretKey }; } - async getNullifierKeysWithNpkMH( + async getNullifierKeysWithNpkMHash( masterNullifierPublicKeyHash: AztecAddress, contractAddress: AztecAddress, ): Promise { @@ -66,7 +66,7 @@ export class SimulatorOracle implements DBOracle { } // TODO: #5834 - getCompleteAddressWithNpkMH(masterNullifierPublicKeyHash: Fr): Promise { + getCompleteAddressWithNpkMHash(masterNullifierPublicKeyHash: Fr): Promise { const address = this.keyStore.getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash); return this.getCompleteAddress(address); } diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index e27b63d6c9f..a5d06e3c9a4 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -53,8 +53,8 @@ export class Oracle { ]; } - async getNullifierKeysWithNpkMH([masterNullifierPublicKeyHash]: ACVMField[]): Promise { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeysWithNpkMH( + async getNullifierKeysWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise { + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeysWithNpkMHash( fromACVMField(masterNullifierPublicKeyHash), ); return [ @@ -204,7 +204,7 @@ export class Oracle { masterOutgoingViewingPublicKey, masterTaggingPublicKey, partialAddress, - } = await this.typedOracle.getCompleteAddressWithNpkMH(parsedNpkMH); + } = await this.typedOracle.getCompleteAddressWithNpkMHash(parsedNpkMH); return [ ...masterNullifierPublicKey.toFields(), diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 208d690909d..01e811c514e 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -93,8 +93,8 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getNullifierKeys'); } - getNullifierKeysWithNpkMH(_masterNullifierPublicKeyHash: Fr): Promise { - throw new OracleMethodNotAvailableError('getNullifierKeysWithNpkMH'); + getNullifierKeysWithNpkMHash(_masterNullifierPublicKeyHash: Fr): Promise { + throw new OracleMethodNotAvailableError('getNullifierKeysWithNpkMHash'); } getContractInstance(_address: AztecAddress): Promise { @@ -132,8 +132,8 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getCompleteAddress'); } - getCompleteAddressWithNpkMH(_masterNullifierPublicKeyHash: Fr): Promise { - throw new OracleMethodNotAvailableError('getCompleteAddressWithNpkMH'); + getCompleteAddressWithNpkMHash(_masterNullifierPublicKeyHash: Fr): Promise { + throw new OracleMethodNotAvailableError('getCompleteAddressWithNpkMHash'); } getAuthWitness(_messageHash: Fr): Promise { diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 6b55630fc77..f8e073d4a77 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -55,7 +55,7 @@ export interface DBOracle extends CommitmentsDB { * @param masterNullifierPublicKeyHash - Master nullifier public key hash to fetch the complete address for. * @returns A complete address associated with the input master nullifier public key hash. */ - getCompleteAddressWithNpkMH(masterNullifierPublicKeyHash: Fr): Promise; + getCompleteAddressWithNpkMHash(masterNullifierPublicKeyHash: Fr): Promise; /** * Retrieve the auth witness for a given message hash. @@ -89,7 +89,7 @@ export interface DBOracle extends CommitmentsDB { * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - getNullifierKeysWithNpkMH(masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress): Promise; + getNullifierKeysWithNpkMHash(masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 389c9815f87..eabff3637ae 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -43,7 +43,7 @@ describe('Simulator', () => { oracle = mock(); node = mock(); - oracle.getNullifierKeysWithNpkMH.mockResolvedValue({ + oracle.getNullifierKeysWithNpkMHash.mockResolvedValue({ masterNullifierPublicKey: ownerMasterNullifierPublicKey, appNullifierSecretKey, }); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 5a1fbb7744a..819abd1f7bf 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -45,13 +45,13 @@ export class ViewDataOracle extends TypedOracle { } /** - * Retrieve nullifier keys associated with a specific masterNullifierPublicKeyHash and app/contract address. - * @param masterNullifierPublicKeyHash - The master nullifer public key hash. - * @returns A Promise that resolves to nullifier keys of a requested account and contract. - * @throws An error if the account is not registered in the database. + * Retrieve nullifier keys associated with a specific master nullifier public key hash and app/contract address. + * @param npkMHash - The master nullifer public key hash. + * @returns The nullifier keys of an account (specified by a master nullifier public key hash) and contract. + * @throws if the aster nullifier public key hash / account is not registered in the database. */ - public override getNullifierKeysWithNpkMH(masterNullifierPublicKeyHash: Fr): Promise { - return this.db.getNullifierKeysWithNpkMH(masterNullifierPublicKeyHash, this.contractAddress); + public override getNullifierKeysWithNpkMHash(npkMHash: Fr): Promise { + return this.db.getNullifierKeysWithNpkMHash(npkMHash, this.contractAddress); } /** @@ -147,11 +147,12 @@ export class ViewDataOracle extends TypedOracle { /** * Retrieve the complete address associated to a given master nullifier public key hash. - * @param masterNullifierPublicKeyHash - Master nullifier public key hash to fetch the complete address for. + * @param npkMHash - The master nullifer public key hash. * @returns A complete address associated with the input master nullifier public key hash. + * @throws if the aster nullifier public key hash / account is not registered in the database. */ - public override getCompleteAddressWithNpkMH(masterNullifierPublicKeyHash: Fr): Promise { - return this.db.getCompleteAddressWithNpkMH(masterNullifierPublicKeyHash); + public override getCompleteAddressWithNpkMHash(npkMHash: Fr): Promise { + return this.db.getCompleteAddressWithNpkMHash(npkMHash); } /** From 1deda941238a08d7bf62d2fa91d1858e9d3f3480 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 18:48:44 +0000 Subject: [PATCH 069/125] asfd --- yarn-project/simulator/src/client/view_data_oracle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 819abd1f7bf..86ea41af6cb 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -148,7 +148,7 @@ export class ViewDataOracle extends TypedOracle { /** * Retrieve the complete address associated to a given master nullifier public key hash. * @param npkMHash - The master nullifer public key hash. - * @returns A complete address associated with the input master nullifier public key hash. + * @returns The complete address associated with the input master nullifier public key hash. * @throws if the aster nullifier public key hash / account is not registered in the database. */ public override getCompleteAddressWithNpkMHash(npkMHash: Fr): Promise { From 851c53ecab16b84c9962a21caa2384d7f7f6aeb1 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 18:51:42 +0000 Subject: [PATCH 070/125] asdf --- yarn-project/simulator/src/client/db_oracle.ts | 12 ++++++------ .../simulator/src/client/view_data_oracle.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index f8e073d4a77..f9f97cc5684 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -52,8 +52,9 @@ export interface DBOracle extends CommitmentsDB { /** * Retrieve the complete address associated to a given master nullifier public key hash. - * @param masterNullifierPublicKeyHash - Master nullifier public key hash to fetch the complete address for. - * @returns A complete address associated with the input master nullifier public key hash. + * @param npkMHash - The master nullifer public key hash. + * @returns The complete address associated with the input master nullifier public key hash. + * @throws if the master nullifier public key hash / account is not registered in the database. */ getCompleteAddressWithNpkMHash(masterNullifierPublicKeyHash: Fr): Promise; @@ -83,11 +84,10 @@ export interface DBOracle extends CommitmentsDB { /** * Retrieve nullifier keys associated with a specific master nullifier public key hash and app/contract address. - * - * @param masterNullifierPublicKeyHash - The master nullifer public key hash. + * @param npkMHash - The master nullifer public key hash. * @param contractAddress - The contract address. - * @returns A Promise that resolves to nullifier keys of a requested account and contract. - * @throws An error if the account is not registered in the database. + * @returns The nullifier keys of an account (specified by a master nullifier public key hash) and contract. + * @throws if the master nullifier public key hash / account is not registered in the database. */ getNullifierKeysWithNpkMHash(masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress): Promise; diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 86ea41af6cb..9e044dc21b7 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -48,7 +48,7 @@ export class ViewDataOracle extends TypedOracle { * Retrieve nullifier keys associated with a specific master nullifier public key hash and app/contract address. * @param npkMHash - The master nullifer public key hash. * @returns The nullifier keys of an account (specified by a master nullifier public key hash) and contract. - * @throws if the aster nullifier public key hash / account is not registered in the database. + * @throws if the master nullifier public key hash / account is not registered in the database. */ public override getNullifierKeysWithNpkMHash(npkMHash: Fr): Promise { return this.db.getNullifierKeysWithNpkMHash(npkMHash, this.contractAddress); @@ -149,7 +149,7 @@ export class ViewDataOracle extends TypedOracle { * Retrieve the complete address associated to a given master nullifier public key hash. * @param npkMHash - The master nullifer public key hash. * @returns The complete address associated with the input master nullifier public key hash. - * @throws if the aster nullifier public key hash / account is not registered in the database. + * @throws if the master nullifier public key hash / account is not registered in the database. */ public override getCompleteAddressWithNpkMHash(npkMHash: Fr): Promise { return this.db.getCompleteAddressWithNpkMHash(npkMHash); From 5cee1ce14df0b6bb4127960d085268757a0e0d0e Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 19:20:37 +0000 Subject: [PATCH 071/125] Fixes --- .../circuit-types/src/interfaces/pxe.ts | 1 - .../circuit-types/src/keys/key_store.ts | 8 ------- yarn-project/key-store/src/test_key_store.ts | 21 +++---------------- .../pxe/src/database/kv_pxe_database.ts | 13 +++++++++++- yarn-project/pxe/src/database/pxe_database.ts | 7 +++++++ .../pxe/src/simulator_oracle/index.ts | 10 ++++++--- 6 files changed, 29 insertions(+), 31 deletions(-) diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 2c6f8010523..218fcada69d 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -73,7 +73,6 @@ export interface PXE { * in order to be able to encrypt data for this recipient. * * @param recipient - The complete address of the recipient - * @param publicKeys - The public keys of the recipient (see #5834) * @remarks Called recipient because we can only send notes to this account and not receive them via this PXE Service. * This is because we don't have the associated private key and for this reason we can't decrypt * the recipient's notes. We can send notes to this account because we can encrypt them with the recipient's diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index dc34a788672..176c323f7c9 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -117,12 +117,4 @@ export interface KeyStore { * @returns A Promise that resolves to the public keys hash. */ getPublicKeysHash(account: AztecAddress): Promise; - - /** - * Gets the account address for a given master nullifier public key hash. - * @throws If the master nullifier public key hash does not exist in the key store. - * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the address. - * @returns The address for the account. - */ - getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): AztecAddress; } diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 36d727bafa8..0fc60354bc3 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -107,7 +107,7 @@ export class TestKeyStore implements KeyStore { const masterNullifierPublicKeyBuffer = this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-npk_m`) ?? this.#keys.get( - `${this.getAccountAddressForMasterNullifierPublicKeyHashInternal( + `${this.#getAccountAddressForMasterNullifierPublicKeyHash( accountOrMasterNullifierPublicKeyHash, )?.toString()}-npk_m`, ); @@ -181,7 +181,7 @@ export class TestKeyStore implements KeyStore { const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-nsk_m`) ?? this.#keys.get( - `${this.getAccountAddressForMasterNullifierPublicKeyHashInternal( + `${this.#getAccountAddressForMasterNullifierPublicKeyHash( accountOrMasterNullifierPublicKeyHash, )?.toString()}-nsk_m`, ); @@ -319,22 +319,7 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(Fr.fromBuffer(publicKeysHashBuffer)); } - /** - * Gets the account address for a given master nullifier public key hash. - * @throws If the master nullifier public key hash does not exist in the key store. - * @param masterNullifierPublicKeyHash - The master nullifier public key hash for which to retrieve the address. - * @returns The address for the account. - */ - // TODO(#5834): Re-add separation between recipients and accounts in keystore. Refactor this utilizing getAccounts. - public getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr) { - const account = this.getAccountAddressForMasterNullifierPublicKeyHashInternal(masterNullifierPublicKeyHash); - if (!account) { - throw new Error(`Master nullifier public key hash ${masterNullifierPublicKeyHash.toString()} does not exist.`); - } - return account; - } - - getAccountAddressForMasterNullifierPublicKeyHashInternal(masterNullifierPublicKeyHash: Fr): AztecAddress | undefined { + #getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): AztecAddress | undefined { for (const [key, value] of this.#keys.entries()) { if (key.endsWith('-npk_m')) { const computedMasterNullifierPublicKeyHash = poseidon2Hash(Point.fromBuffer(value).toFields()); diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 7452f98f5b9..1d7a4455c60 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -389,8 +389,19 @@ export class KVPxeDatabase implements PxeDatabase { return Promise.resolve(this.#getCompleteAddress(address)); } + getCompleteAddressByNpkMHash(npkMHash: Fr): Promise { + const completeAddresses = this.#getCompleteAddresses(); + + const completeAddress = completeAddresses.find((completeAddress) => poseidon2Hash(completeAddress.masterNullifierPublicKey.toFields()).equals(npkMHash)); + return Promise.resolve(completeAddress); + } + + #getCompleteAddresses(): CompleteAddress[] { + return Array.from(this.#addresses).map(v => CompleteAddress.fromBuffer(v)); + } + getCompleteAddresses(): Promise { - return Promise.resolve(Array.from(this.#addresses).map(v => CompleteAddress.fromBuffer(v))); + return Promise.resolve(this.#getCompleteAddresses()); } getSynchedBlockNumberForPublicKey(publicKey: Point): number | undefined { diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index b95d5e01d8c..1c18fa5e937 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -139,6 +139,13 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD */ getCompleteAddress(address: AztecAddress): Promise; + /** + * Retrieves the complete address corresponding to the provided aztec address. + * @param address - The aztec address of the complete address contract. + * @returns A promise that resolves to a CompleteAddress instance if the address is found, or undefined if not found. + */ + getCompleteAddressByNpkMHash(npkMHash: Fr): Promise; + /** * Retrieves the list of complete address added to this database * @returns A promise that resolves to an array of AztecAddress instances. diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 6cfa3c20492..d4271a88fe0 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -65,10 +65,14 @@ export class SimulatorOracle implements DBOracle { return completeAddress; } - // TODO: #5834 getCompleteAddressWithNpkMHash(masterNullifierPublicKeyHash: Fr): Promise { - const address = this.keyStore.getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash); - return this.getCompleteAddress(address); + const completeAddress = this.db.getCompleteAddressByNpkMHash(masterNullifierPublicKeyHash); + if (!completeAddress) { + throw new Error( + `No public key registered for master nullifier public key hash ${masterNullifierPublicKeyHash.toString()}. Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, + ); + } + return completeAddress; } async getContractInstance(address: AztecAddress): Promise { From a2eed7cc03a5e5516a41ae151733bf562fa1ed43 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 19:24:27 +0000 Subject: [PATCH 072/125] fix --- yarn-project/pxe/src/database/kv_pxe_database.ts | 1 + yarn-project/pxe/src/simulator_oracle/index.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 1d7a4455c60..e26d7f4eaba 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -16,6 +16,7 @@ import { type ContractInstanceWithAddress, SerializableContractInstance } from ' import { DeferredNoteDao } from './deferred_note_dao.js'; import { NoteDao } from './note_dao.js'; import { type PxeDatabase } from './pxe_database.js'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; /** * A PXE database backed by LMDB. diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index d4271a88fe0..5da3b4c5b86 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -65,8 +65,8 @@ export class SimulatorOracle implements DBOracle { return completeAddress; } - getCompleteAddressWithNpkMHash(masterNullifierPublicKeyHash: Fr): Promise { - const completeAddress = this.db.getCompleteAddressByNpkMHash(masterNullifierPublicKeyHash); + async getCompleteAddressWithNpkMHash(masterNullifierPublicKeyHash: Fr): Promise { + const completeAddress = await this.db.getCompleteAddressByNpkMHash(masterNullifierPublicKeyHash); if (!completeAddress) { throw new Error( `No public key registered for master nullifier public key hash ${masterNullifierPublicKeyHash.toString()}. Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, From 1d52a382848419f4829ffa566caa2d717333ed04 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 19:27:15 +0000 Subject: [PATCH 073/125] format --- yarn-project/aztec.js/src/wallet/base_wallet.ts | 7 +------ yarn-project/circuit-types/src/interfaces/pxe.ts | 7 +------ yarn-project/pxe/src/database/kv_pxe_database.ts | 6 ++++-- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 89e99c4d2e4..200ad930dee 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -15,12 +15,7 @@ import { type TxHash, type TxReceipt, } from '@aztec/circuit-types'; -import { - type AztecAddress, - type CompleteAddress, - type Fr, - type PartialAddress, -} from '@aztec/circuits.js'; +import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 218fcada69d..9e01820e4f7 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -1,9 +1,4 @@ -import { - type AztecAddress, - type CompleteAddress, - type Fr, - type PartialAddress, -} from '@aztec/circuits.js'; +import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index e26d7f4eaba..4b14070ea55 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -2,6 +2,7 @@ import { MerkleTreeId, type NoteFilter, NoteStatus, type PublicKey } from '@azte import { AztecAddress, CompleteAddress, Header } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; import { Fr, type Point } from '@aztec/foundation/fields'; import { type AztecArray, @@ -16,7 +17,6 @@ import { type ContractInstanceWithAddress, SerializableContractInstance } from ' import { DeferredNoteDao } from './deferred_note_dao.js'; import { NoteDao } from './note_dao.js'; import { type PxeDatabase } from './pxe_database.js'; -import { poseidon2Hash } from '@aztec/foundation/crypto'; /** * A PXE database backed by LMDB. @@ -393,7 +393,9 @@ export class KVPxeDatabase implements PxeDatabase { getCompleteAddressByNpkMHash(npkMHash: Fr): Promise { const completeAddresses = this.#getCompleteAddresses(); - const completeAddress = completeAddresses.find((completeAddress) => poseidon2Hash(completeAddress.masterNullifierPublicKey.toFields()).equals(npkMHash)); + const completeAddress = completeAddresses.find(completeAddress => + poseidon2Hash(completeAddress.masterNullifierPublicKey.toFields()).equals(npkMHash), + ); return Promise.resolve(completeAddress); } From 679891756b347c20390b6652314a3211598ed773 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 19:34:13 +0000 Subject: [PATCH 074/125] fix --- yarn-project/pxe/src/database/pxe_database.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index 1c18fa5e937..8868ef37cd3 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -140,8 +140,8 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD getCompleteAddress(address: AztecAddress): Promise; /** - * Retrieves the complete address corresponding to the provided aztec address. - * @param address - The aztec address of the complete address contract. + * Retrieves the complete address corresponding to the provided master nullifier public key hash. + * @param npkMHash - The master nullifier public key hash of the account. * @returns A promise that resolves to a CompleteAddress instance if the address is found, or undefined if not found. */ getCompleteAddressByNpkMHash(npkMHash: Fr): Promise; From 0a523d4ae358d0986fb530dcc4615f166877a321 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 19:40:19 +0000 Subject: [PATCH 075/125] fix --- yarn-project/simulator/src/acvm/oracle/oracle.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index a5d06e3c9a4..a5d57529511 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -194,7 +194,6 @@ export class Oracle { ].map(toACVMField); } - // TODO: #5834 async getPublicKeysAndPartialAddressWithNpkMH([masterNullifierPublicKeyHash]: ACVMField[]) { const parsedNpkMH = fromACVMField(masterNullifierPublicKeyHash); From 06c4cc2d9969869fbabb173d1228b0ea67604114 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 19:41:32 +0000 Subject: [PATCH 076/125] fix --- noir-projects/aztec-nr/aztec/src/context/private_context.nr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index dc4d31aa48e..8627d4bd4e4 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -222,9 +222,9 @@ impl PrivateContext { } // TODO: (#6176) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address - pub fn request_nsk_app_with_npk_m_hash(&mut self, master_public_nullifying_key_hash: Field) -> Field { + pub fn request_nsk_app_with_npk_m_hash(&mut self, npk_m_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { - let keys = get_nullifier_keys_with_npk_m_h(master_public_nullifying_key_hash); + let keys = get_nullifier_keys_with_npk_m_h(npk_m_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, app_nullifier_secret_key: keys.app_nullifier_secret_key @@ -241,7 +241,7 @@ impl PrivateContext { // We have to check if the key that was requested or cached corresponds to the one we request for assert_eq( - poseidon2_hash(keys.master_nullifier_public_key.serialize()), master_public_nullifying_key_hash + poseidon2_hash(keys.master_nullifier_public_key.serialize()), npk_m_hash ); keys.app_nullifier_secret_key } From a765ec72d681aca571b64b3c546db016221e734f Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 19:43:40 +0000 Subject: [PATCH 077/125] asdf --- noir-projects/aztec-nr/aztec/src/oracle/keys.nr | 2 +- yarn-project/simulator/src/acvm/oracle/oracle.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 68c302d86b0..ad092525287 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -19,7 +19,7 @@ fn get_public_keys_and_partial_address(address: AztecAddress) -> ([GrumpkinPoint ([nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key], partial_address) } -#[oracle(getPublicKeysAndPartialAddressWithNpkMH)] +#[oracle(getPublicKeysAndPartialAddressWithNpkMHash)] fn get_public_keys_and_partial_address_with_npk_m_hash_oracle(_npk_m_hash: Field) -> [Field; 9] {} unconstrained fn get_public_keys_and_partial_address_with_npk_m_hash_oracle_wrapper(npk_m_hash: Field) -> [Field; 9] { diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index a5d57529511..eeb4c7c3cc2 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -194,7 +194,7 @@ export class Oracle { ].map(toACVMField); } - async getPublicKeysAndPartialAddressWithNpkMH([masterNullifierPublicKeyHash]: ACVMField[]) { + async getPublicKeysAndPartialAddressWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]) { const parsedNpkMH = fromACVMField(masterNullifierPublicKeyHash); const { From 5c634807e530ddb3a57e92f8707fc1368b4b171d Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 19:46:29 +0000 Subject: [PATCH 078/125] fix --- .../aztec-nr/aztec/src/context/private_context.nr | 4 ++-- .../aztec-nr/aztec/src/oracle/nullifier_key.nr | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 8627d4bd4e4..ecf11bdc305 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -5,7 +5,7 @@ use crate::{ oracle::{ arguments, returns, call_private_function::call_private_function_internal, header::get_header_at, logs::emit_encrypted_log, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, - nullifier_key::{get_nullifier_keys, get_nullifier_keys_with_npk_m_h, NullifierKeys}, + nullifier_key::{get_nullifier_keys, get_nullifier_keys_with_npk_m_hash, NullifierKeys}, enqueue_public_function_call::{ enqueue_public_function_call_internal, set_public_teardown_function_call_internal, parse_public_call_stack_item_from_oracle @@ -224,7 +224,7 @@ impl PrivateContext { // TODO: (#6176) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address pub fn request_nsk_app_with_npk_m_hash(&mut self, npk_m_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { - let keys = get_nullifier_keys_with_npk_m_h(npk_m_hash); + let keys = get_nullifier_keys_with_npk_m_hash(npk_m_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, app_nullifier_secret_key: keys.app_nullifier_secret_key diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 4a749c033ad..469b4ff6cc3 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -29,11 +29,11 @@ pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { } // TODO (#6176): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address -#[oracle(getNullifierKeysWithNpkMH)] -fn get_nullifier_keys_with_npk_m_h_oracle(_npk_m_hash: Field) -> [Field; 3] {} +#[oracle(getNullifierKeysWithNpkMHash)] +fn get_nullifier_keys_with_npk_m_hash_oracle(_npk_m_hash: Field) -> [Field; 3] {} -unconstrained fn get_nullifier_keys_with_npk_m_h_internal(npk_m_hash: Field) -> NullifierKeys { - let result = get_nullifier_keys_with_npk_m_h_oracle(npk_m_hash); +unconstrained fn get_nullifier_keys_with_npk_m_hash_internal(npk_m_hash: Field) -> NullifierKeys { + let result = get_nullifier_keys_with_npk_m_hash_oracle(npk_m_hash); NullifierKeys { account: AztecAddress::zero(), master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, @@ -42,11 +42,11 @@ unconstrained fn get_nullifier_keys_with_npk_m_h_internal(npk_m_hash: Field) -> } // We get the full struct Nullifier Keys here -pub fn get_nullifier_keys_with_npk_m_h(npk_m_hash: Field) -> NullifierKeys { - get_nullifier_keys_with_npk_m_h_internal(npk_m_hash) +pub fn get_nullifier_keys_with_npk_m_hash(npk_m_hash: Field) -> NullifierKeys { + get_nullifier_keys_with_npk_m_hash_internal(npk_m_hash) } // We are only getting the app_nullifier_secret_key here pub fn get_nsk_app_with_npk_m_hash(npk_m_hash: Field) -> Field { - get_nullifier_keys_with_npk_m_h_internal(npk_m_hash).app_nullifier_secret_key + get_nullifier_keys_with_npk_m_hash_internal(npk_m_hash).app_nullifier_secret_key } From 993e33dbda7c4df21496276b47a51549f476a01b Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 19:55:18 +0000 Subject: [PATCH 079/125] fix --- noir-projects/aztec-nr/aztec/src/context/private_context.nr | 4 +--- .../contracts/token_contract/src/types/token_note.nr | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index ecf11bdc305..1b286894f3a 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -240,9 +240,7 @@ impl PrivateContext { }; // We have to check if the key that was requested or cached corresponds to the one we request for - assert_eq( - poseidon2_hash(keys.master_nullifier_public_key.serialize()), npk_m_hash - ); + assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), npk_m_hash); keys.app_nullifier_secret_key } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index dc997924faf..fa13976f9d5 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -1,5 +1,6 @@ use dep::aztec::{ - keys::getters::get_ivpk_m_with_npk_m_hash, prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, + keys::getters::get_ivpk_m_with_npk_m_hash, + prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nsk_app_with_npk_m_hash} From 31ec469a7d4fba31eb0421f565435dcbe2136d28 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 20:25:18 +0000 Subject: [PATCH 080/125] Refactors --- .../circuit-types/src/keys/key_store.ts | 4 +-- yarn-project/key-store/src/test_key_store.ts | 28 +++++++-------- .../pxe/src/database/kv_pxe_database.ts | 6 ++-- yarn-project/pxe/src/database/pxe_database.ts | 2 +- .../pxe/src/simulator_oracle/index.ts | 34 ++++--------------- .../simulator/src/acvm/oracle/oracle.ts | 25 +++++++++----- .../simulator/src/acvm/oracle/typed_oracle.ts | 12 ++----- .../simulator/src/client/db_oracle.ts | 21 ++---------- .../simulator/src/client/simulator.test.ts | 2 +- .../simulator/src/client/view_data_oracle.ts | 28 +++------------ 10 files changed, 49 insertions(+), 113 deletions(-) diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 176c323f7c9..3bee8446048 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -37,7 +37,7 @@ export interface KeyStore { * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the master nullifier public key. * @returns The master nullifier public key for the account. */ - getMasterNullifierPublicKey(accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr): Promise; + getMasterNullifierPublicKey(args: { account: AztecAddress } | { npkMHash: Fr }): Promise; /** * Gets the master incoming viewing public key for a given account. @@ -70,7 +70,7 @@ export interface KeyStore { * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ - getAppNullifierSecretKey(accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr, app: AztecAddress): Promise; + getAppNullifierSecretKey(args: { account: AztecAddress } | { npkMHash: Fr }, app: AztecAddress): Promise; /** * Retrieves application incoming viewing secret key. diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 0fc60354bc3..f108bafb74a 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -102,18 +102,16 @@ export class TestKeyStore implements KeyStore { * @returns The master nullifier public key for the account. */ public async getMasterNullifierPublicKey( - accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr, + args: { account: AztecAddress } | { npkMHash: Fr }, ): Promise { - const masterNullifierPublicKeyBuffer = - this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-npk_m`) ?? - this.#keys.get( - `${this.#getAccountAddressForMasterNullifierPublicKeyHash( - accountOrMasterNullifierPublicKeyHash, - )?.toString()}-npk_m`, - ); + const masterNullifierPublicKeyBuffer = 'account' in args ? this.#keys.get(`${args.account.toString()}-npk_m`) : this.#keys.get( + `${this.#getAccountAddressForMasterNullifierPublicKeyHash( + args.npkMHash, + )?.toString()}-npk_m`, + ); if (!masterNullifierPublicKeyBuffer) { throw new Error( - `Account or master nullifier public key hash ${accountOrMasterNullifierPublicKeyHash.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + `${'account' in args ? `Account ${args.account}` : `Master nullifier public key hash ${args.npkMHash}`} does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); @@ -175,19 +173,17 @@ export class TestKeyStore implements KeyStore { * @returns A Promise that resolves to the application nullifier secret key. */ public async getAppNullifierSecretKey( - accountOrMasterNullifierPublicKeyHash: AztecAddress | Fr, + args: { account: AztecAddress } | { npkMHash: Fr }, app: AztecAddress, ): Promise { - const masterNullifierSecretKeyBuffer = - this.#keys.get(`${accountOrMasterNullifierPublicKeyHash.toString()}-nsk_m`) ?? + const masterNullifierSecretKeyBuffer = 'account' in args ? + this.#keys.get(`${args.account.toString()}-nsk_m`) : this.#keys.get( - `${this.#getAccountAddressForMasterNullifierPublicKeyHash( - accountOrMasterNullifierPublicKeyHash, - )?.toString()}-nsk_m`, + `${this.#getAccountAddressForMasterNullifierPublicKeyHash(args.npkMHash)?.toString()}-nsk_m`, ); if (!masterNullifierSecretKeyBuffer) { throw new Error( - `Account or master nullifier public key hash ${accountOrMasterNullifierPublicKeyHash.toString()} does not exist. Registered accounts: ${await this.getAccounts()}.`, + `${'account' in args ? `Account ${args.account}` : `Master nullifier public key hash ${args.npkMHash}`} does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 4b14070ea55..a293ec69e87 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -386,11 +386,11 @@ export class KVPxeDatabase implements PxeDatabase { return value ? CompleteAddress.fromBuffer(value) : undefined; } - getCompleteAddress(address: AztecAddress): Promise { - return Promise.resolve(this.#getCompleteAddress(address)); + getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { + return Promise.resolve('account' in args ? this.#getCompleteAddress(args.account) : this.#getCompleteAddressWithNpkMHash(args.npkMHash)); } - getCompleteAddressByNpkMHash(npkMHash: Fr): Promise { + #getCompleteAddressWithNpkMHash(npkMHash: Fr): Promise { const completeAddresses = this.#getCompleteAddresses(); const completeAddress = completeAddresses.find(completeAddress => diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index 8868ef37cd3..d85921a6ec7 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -137,7 +137,7 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD * @param address - The aztec address of the complete address contract. * @returns A promise that resolves to a CompleteAddress instance if the address is found, or undefined if not found. */ - getCompleteAddress(address: AztecAddress): Promise; + getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise; /** * Retrieves the complete address corresponding to the provided master nullifier public key hash. diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 5da3b4c5b86..8c10abc8aa7 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -37,39 +37,17 @@ export class SimulatorOracle implements DBOracle { private log = createDebugLogger('aztec:pxe:simulator_oracle'), ) {} - async getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise { - const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(accountAddress); - const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(accountAddress, contractAddress); + async getNullifierKeys(args: { account: AztecAddress } | { npkMHash: Fr }, contractAddress: AztecAddress): Promise { + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(args); + const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(args, contractAddress); return { masterNullifierPublicKey, appNullifierSecretKey }; } - async getNullifierKeysWithNpkMHash( - masterNullifierPublicKeyHash: AztecAddress, - contractAddress: AztecAddress, - ): Promise { - const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(masterNullifierPublicKeyHash); - const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey( - masterNullifierPublicKeyHash, - contractAddress, - ); - return { masterNullifierPublicKey, appNullifierSecretKey }; - } - - async getCompleteAddress(address: AztecAddress): Promise { - const completeAddress = await this.db.getCompleteAddress(address); - if (!completeAddress) { - throw new Error( - `No public key registered for address ${address.toString()}. Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, - ); - } - return completeAddress; - } - - async getCompleteAddressWithNpkMHash(masterNullifierPublicKeyHash: Fr): Promise { - const completeAddress = await this.db.getCompleteAddressByNpkMHash(masterNullifierPublicKeyHash); + async getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { + const completeAddress = await this.db.getCompleteAddress(args); if (!completeAddress) { throw new Error( - `No public key registered for master nullifier public key hash ${masterNullifierPublicKeyHash.toString()}. Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, + `No public key registered for ${'account' in args ? `address ${args.account}` : `master nullifier public key hash ${args.npkMHash}`}. Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, ); } return completeAddress; diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index eeb4c7c3cc2..0fda8ac6bb9 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -43,9 +43,9 @@ export class Oracle { } async getNullifierKeys([accountAddress]: ACVMField[]): Promise { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( - fromACVMField(accountAddress), - ); + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys({ + account: fromACVMField(accountAddress), + }); return [ toACVMField(masterNullifierPublicKey.x), toACVMField(masterNullifierPublicKey.y), @@ -53,10 +53,12 @@ export class Oracle { ]; } + // Keeping this oracle separate from above because I don't want an implicit overload in noir code async getNullifierKeysWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeysWithNpkMHash( - fromACVMField(masterNullifierPublicKeyHash), - ); + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys({ + npkMHash: fromACVMField(masterNullifierPublicKeyHash) + }); + return [ toACVMField(masterNullifierPublicKey.x), toACVMField(masterNullifierPublicKey.y), @@ -183,7 +185,9 @@ export class Oracle { masterOutgoingViewingPublicKey, masterTaggingPublicKey, partialAddress, - } = await this.typedOracle.getCompleteAddress(parsedAddress); + } = await this.typedOracle.getCompleteAddress({ + account: parsedAddress, + }); return [ ...masterNullifierPublicKey.toFields(), @@ -194,8 +198,9 @@ export class Oracle { ].map(toACVMField); } + // Keeping this oracle separate from above because I don't want an implicit overload in noir code async getPublicKeysAndPartialAddressWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]) { - const parsedNpkMH = fromACVMField(masterNullifierPublicKeyHash); + const parsedNpkMHash = fromACVMField(masterNullifierPublicKeyHash); const { masterNullifierPublicKey, @@ -203,7 +208,9 @@ export class Oracle { masterOutgoingViewingPublicKey, masterTaggingPublicKey, partialAddress, - } = await this.typedOracle.getCompleteAddressWithNpkMHash(parsedNpkMH); + } = await this.typedOracle.getCompleteAddress({ + npkMHash: parsedNpkMHash, + }); return [ ...masterNullifierPublicKey.toFields(), diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 01e811c514e..5b050be24ab 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -89,14 +89,10 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('unpackReturns'); } - getNullifierKeys(_accountAddress: AztecAddress): Promise { + getNullifierKeys(_args: { account: AztecAddress } | { npkMHash: Fr }): Promise { throw new OracleMethodNotAvailableError('getNullifierKeys'); } - getNullifierKeysWithNpkMHash(_masterNullifierPublicKeyHash: Fr): Promise { - throw new OracleMethodNotAvailableError('getNullifierKeysWithNpkMHash'); - } - getContractInstance(_address: AztecAddress): Promise { throw new OracleMethodNotAvailableError('getContractInstance'); } @@ -128,14 +124,10 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getHeader'); } - getCompleteAddress(_address: AztecAddress): Promise { + getCompleteAddress(_args: { account: AztecAddress } | { npkMHash: Fr }): Promise { throw new OracleMethodNotAvailableError('getCompleteAddress'); } - getCompleteAddressWithNpkMHash(_masterNullifierPublicKeyHash: Fr): Promise { - throw new OracleMethodNotAvailableError('getCompleteAddressWithNpkMHash'); - } - getAuthWitness(_messageHash: Fr): Promise { throw new OracleMethodNotAvailableError('getAuthWitness'); } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index f9f97cc5684..479a945c7a2 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -48,15 +48,7 @@ export interface DBOracle extends CommitmentsDB { * @param address - Address to fetch the pubkey for. * @returns A complete address associated with the input address. */ - getCompleteAddress(address: AztecAddress): Promise; - - /** - * Retrieve the complete address associated to a given master nullifier public key hash. - * @param npkMHash - The master nullifer public key hash. - * @returns The complete address associated with the input master nullifier public key hash. - * @throws if the master nullifier public key hash / account is not registered in the database. - */ - getCompleteAddressWithNpkMHash(masterNullifierPublicKeyHash: Fr): Promise; + getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise; /** * Retrieve the auth witness for a given message hash. @@ -80,16 +72,7 @@ export interface DBOracle extends CommitmentsDB { * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise; - - /** - * Retrieve nullifier keys associated with a specific master nullifier public key hash and app/contract address. - * @param npkMHash - The master nullifer public key hash. - * @param contractAddress - The contract address. - * @returns The nullifier keys of an account (specified by a master nullifier public key hash) and contract. - * @throws if the master nullifier public key hash / account is not registered in the database. - */ - getNullifierKeysWithNpkMHash(masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress): Promise; + getNullifierKeys(args: { account: AztecAddress } | { npkMHash: Fr }, contractAddress: AztecAddress): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index eabff3637ae..0f34bc9cd89 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -43,7 +43,7 @@ describe('Simulator', () => { oracle = mock(); node = mock(); - oracle.getNullifierKeysWithNpkMHash.mockResolvedValue({ + oracle.getNullifierKeys.mockResolvedValue({ masterNullifierPublicKey: ownerMasterNullifierPublicKey, appNullifierSecretKey, }); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 9e044dc21b7..aa25e39c2d5 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -40,18 +40,8 @@ export class ViewDataOracle extends TypedOracle { * @returns A Promise that resolves to nullifier keys of a requested account and contract. * @throws An error if the account is not registered in the database. */ - public override getNullifierKeys(account: AztecAddress): Promise { - return this.db.getNullifierKeys(account, this.contractAddress); - } - - /** - * Retrieve nullifier keys associated with a specific master nullifier public key hash and app/contract address. - * @param npkMHash - The master nullifer public key hash. - * @returns The nullifier keys of an account (specified by a master nullifier public key hash) and contract. - * @throws if the master nullifier public key hash / account is not registered in the database. - */ - public override getNullifierKeysWithNpkMHash(npkMHash: Fr): Promise { - return this.db.getNullifierKeysWithNpkMHash(npkMHash, this.contractAddress); + public override getNullifierKeys(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { + return this.db.getNullifierKeys(args, this.contractAddress); } /** @@ -141,18 +131,8 @@ export class ViewDataOracle extends TypedOracle { * @param address - Address to fetch the complete address for. * @returns A complete address associated with the input address. */ - public override getCompleteAddress(address: AztecAddress): Promise { - return this.db.getCompleteAddress(address); - } - - /** - * Retrieve the complete address associated to a given master nullifier public key hash. - * @param npkMHash - The master nullifer public key hash. - * @returns The complete address associated with the input master nullifier public key hash. - * @throws if the master nullifier public key hash / account is not registered in the database. - */ - public override getCompleteAddressWithNpkMHash(npkMHash: Fr): Promise { - return this.db.getCompleteAddressWithNpkMHash(npkMHash); + public override getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { + return this.db.getCompleteAddress(args); } /** From f418d3e6fd8baf77b7474cfe5231c10aa5d764bd Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 20:36:27 +0000 Subject: [PATCH 081/125] fix comments --- yarn-project/pxe/src/database/pxe_database.ts | 6 +++--- yarn-project/simulator/src/client/db_oracle.ts | 17 ++++++++--------- .../simulator/src/client/view_data_oracle.ts | 15 ++++++++------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index d85921a6ec7..e4c7a351f21 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -133,9 +133,9 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD addCompleteAddress(address: CompleteAddress): Promise; /** - * Retrieves the complete address corresponding to the provided aztec address. - * @param address - The aztec address of the complete address contract. - * @returns A promise that resolves to a CompleteAddress instance if the address is found, or undefined if not found. + * Retrieve the complete address associated to a given address or master nullifier public key hash. + * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @returns A promise that resolves to a CompleteAddress instance if found, or undefined if not found. */ getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise; diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 479a945c7a2..77233eb220a 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -44,9 +44,10 @@ export interface DBOracle extends CommitmentsDB { getContractInstance(address: AztecAddress): Promise; /** - * Retrieve the complete address associated to a given address. - * @param address - Address to fetch the pubkey for. - * @returns A complete address associated with the input address. + * Retrieve the complete address associated to a given address or master nullifier public key hash. + * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @returns A complete address associated with the input address or master nullifier public key hash + * @throws An error if the account is not registered in the database. */ getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise; @@ -65,12 +66,10 @@ export interface DBOracle extends CommitmentsDB { popCapsule(): Promise; /** - * Retrieve nullifier keys associated with a specific account and app/contract address. - * - * @param accountAddress - The account address. - * @param contractAddress - The contract address. - * @returns A Promise that resolves to nullifier keys of a requested account and contract. - * @throws An error if the account is not registered in the database. + * Retrieve nullifier keys associated with a (specific account or master nullifier key hash) and app/contract address. + * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @returns A Promise that resolves to nullifier keys of a (requested account or master nullifier key hash) and contract. + * @throws An error if the nullifier keys associated to account or master nullifier public key hash is not registered in the key store. */ getNullifierKeys(args: { account: AztecAddress } | { npkMHash: Fr }, contractAddress: AztecAddress): Promise; diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index aa25e39c2d5..298d75406b2 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -35,10 +35,10 @@ export class ViewDataOracle extends TypedOracle { } /** - * Retrieve nullifier keys associated with a specific account and app/contract address. - * @param accountAddress - The account address. - * @returns A Promise that resolves to nullifier keys of a requested account and contract. - * @throws An error if the account is not registered in the database. + * Retrieve nullifier keys associated with a (specific account or master nullifier key hash) and app/contract address. + * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @returns A Promise that resolves to nullifier keys of a (requested account or master nullifier key hash) and contract. + * @throws An error if the nullifier keys associated to account or master nullifier public key hash is not registered in the key store. */ public override getNullifierKeys(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { return this.db.getNullifierKeys(args, this.contractAddress); @@ -127,9 +127,10 @@ export class ViewDataOracle extends TypedOracle { } /** - * Retrieve the complete address associated to a given address. - * @param address - Address to fetch the complete address for. - * @returns A complete address associated with the input address. + * Retrieve the complete address associated to a given address or master nullifier public key hash. + * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @returns A complete address associated with the input address or master nullifier public key hash + * @throws An error if the account is not registered in the database. */ public override getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { return this.db.getCompleteAddress(args); From 45119071ea3bcd2ab27a63c3519d4018fe63f9a5 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 20:39:05 +0000 Subject: [PATCH 082/125] asdf --- yarn-project/pxe/src/database/pxe_database.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index e4c7a351f21..8de09765e88 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -139,13 +139,6 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD */ getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise; - /** - * Retrieves the complete address corresponding to the provided master nullifier public key hash. - * @param npkMHash - The master nullifier public key hash of the account. - * @returns A promise that resolves to a CompleteAddress instance if the address is found, or undefined if not found. - */ - getCompleteAddressByNpkMHash(npkMHash: Fr): Promise; - /** * Retrieves the list of complete address added to this database * @returns A promise that resolves to an array of AztecAddress instances. From e9a1007c37c9c2d6b60f7665a07d914ea7f8209b Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 10 May 2024 21:50:11 +0000 Subject: [PATCH 083/125] fmt --- .../key-store/src/test_key_store.test.ts | 4 +- yarn-project/key-store/src/test_key_store.ts | 30 +++++++------- .../pxe/src/database/kv_pxe_database.ts | 4 +- .../src/database/pxe_database_test_suite.ts | 4 +- .../pxe/src/pxe_service/pxe_service.ts | 2 +- .../pxe/src/simulator_oracle/index.ts | 9 ++++- .../pxe/src/synchronizer/synchronizer.ts | 2 +- .../simulator/src/acvm/oracle/oracle.ts | 2 +- .../simulator/src/client/db_oracle.ts | 5 ++- .../src/client/private_execution.test.ts | 40 ++++++++++--------- .../client/unconstrained_execution.test.ts | 6 +-- 11 files changed, 60 insertions(+), 48 deletions(-) diff --git a/yarn-project/key-store/src/test_key_store.test.ts b/yarn-project/key-store/src/test_key_store.test.ts index 2395dbf1472..79da6da8255 100644 --- a/yarn-project/key-store/src/test_key_store.test.ts +++ b/yarn-project/key-store/src/test_key_store.test.ts @@ -16,7 +16,7 @@ describe('TestKeyStore', () => { `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, ); - const masterNullifierPublicKey = await keyStore.getMasterNullifierPublicKey(accountAddress); + const masterNullifierPublicKey = await keyStore.getMasterNullifierPublicKey({ account: accountAddress }); expect(masterNullifierPublicKey.toString()).toMatchInlineSnapshot( `"0x2ef5d15dd65d29546680ab72846fb071f41cb9f2a0212215e6c560e29df4ff650ce764818364b376be92dc2f49577fe440e64a16012584f7c4ee94f7edbc323a"`, ); @@ -44,7 +44,7 @@ describe('TestKeyStore', () => { // Arbitrary app contract address const appAddress = AztecAddress.fromBigInt(624n); - const appNullifierSecretKey = await keyStore.getAppNullifierSecretKey(accountAddress, appAddress); + const appNullifierSecretKey = await keyStore.getAppNullifierSecretKey({ account: accountAddress }, appAddress); expect(appNullifierSecretKey.toString()).toMatchInlineSnapshot( `"0x230a44dfe7cfec7a735c89f7289c5cb5d2c3dc0bf5d3505917fd2476f67873a8"`, ); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index f108bafb74a..8547b5a9a7f 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -101,17 +101,16 @@ export class TestKeyStore implements KeyStore { * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the master nullifier public key. * @returns The master nullifier public key for the account. */ - public async getMasterNullifierPublicKey( - args: { account: AztecAddress } | { npkMHash: Fr }, - ): Promise { - const masterNullifierPublicKeyBuffer = 'account' in args ? this.#keys.get(`${args.account.toString()}-npk_m`) : this.#keys.get( - `${this.#getAccountAddressForMasterNullifierPublicKeyHash( - args.npkMHash, - )?.toString()}-npk_m`, - ); + public async getMasterNullifierPublicKey(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { + const masterNullifierPublicKeyBuffer = + 'account' in args + ? this.#keys.get(`${args.account.toString()}-npk_m`) + : this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(args.npkMHash)?.toString()}-npk_m`); if (!masterNullifierPublicKeyBuffer) { throw new Error( - `${'account' in args ? `Account ${args.account}` : `Master nullifier public key hash ${args.npkMHash}`} does not exist. Registered accounts: ${await this.getAccounts()}.`, + `${ + 'account' in args ? `Account ${args.account}` : `Master nullifier public key hash ${args.npkMHash}` + } does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); @@ -176,14 +175,15 @@ export class TestKeyStore implements KeyStore { args: { account: AztecAddress } | { npkMHash: Fr }, app: AztecAddress, ): Promise { - const masterNullifierSecretKeyBuffer = 'account' in args ? - this.#keys.get(`${args.account.toString()}-nsk_m`) : - this.#keys.get( - `${this.#getAccountAddressForMasterNullifierPublicKeyHash(args.npkMHash)?.toString()}-nsk_m`, - ); + const masterNullifierSecretKeyBuffer = + 'account' in args + ? this.#keys.get(`${args.account.toString()}-nsk_m`) + : this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(args.npkMHash)?.toString()}-nsk_m`); if (!masterNullifierSecretKeyBuffer) { throw new Error( - `${'account' in args ? `Account ${args.account}` : `Master nullifier public key hash ${args.npkMHash}`} does not exist. Registered accounts: ${await this.getAccounts()}.`, + `${ + 'account' in args ? `Account ${args.account}` : `Master nullifier public key hash ${args.npkMHash}` + } does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index a293ec69e87..37a03f30500 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -387,7 +387,9 @@ export class KVPxeDatabase implements PxeDatabase { } getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { - return Promise.resolve('account' in args ? this.#getCompleteAddress(args.account) : this.#getCompleteAddressWithNpkMHash(args.npkMHash)); + return Promise.resolve( + 'account' in args ? this.#getCompleteAddress(args.account) : this.#getCompleteAddressWithNpkMHash(args.npkMHash), + ); } #getCompleteAddressWithNpkMHash(npkMHash: Fr): Promise { diff --git a/yarn-project/pxe/src/database/pxe_database_test_suite.ts b/yarn-project/pxe/src/database/pxe_database_test_suite.ts index 440df3db400..53572441c6d 100644 --- a/yarn-project/pxe/src/database/pxe_database_test_suite.ts +++ b/yarn-project/pxe/src/database/pxe_database_test_suite.ts @@ -209,7 +209,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { it('stores and retrieves addresses', async () => { const address = CompleteAddress.random(); await expect(database.addCompleteAddress(address)).resolves.toBe(true); - await expect(database.getCompleteAddress(address.address)).resolves.toEqual(address); + await expect(database.getCompleteAddress({ account: address.address })).resolves.toEqual(address); }); it('silently ignores an address it already knows about', async () => { @@ -248,7 +248,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { }); it("returns undefined if it doesn't have an address", async () => { - expect(await database.getCompleteAddress(CompleteAddress.random().address)).toBeUndefined(); + expect(await database.getCompleteAddress({ account: CompleteAddress.random().address })).toBeUndefined(); }); }); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 8769a2d68db..8ed1734e82c 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -297,7 +297,7 @@ export class PXEService implements PXE { } public async addNote(note: ExtendedNote) { - const { masterIncomingViewingPublicKey } = (await this.db.getCompleteAddress(note.owner)) ?? {}; + const { masterIncomingViewingPublicKey } = (await this.db.getCompleteAddress({ account: note.owner })) ?? {}; if (!masterIncomingViewingPublicKey) { throw new Error('Unknown account.'); } diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 8c10abc8aa7..ee4fc90be3f 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -37,7 +37,10 @@ export class SimulatorOracle implements DBOracle { private log = createDebugLogger('aztec:pxe:simulator_oracle'), ) {} - async getNullifierKeys(args: { account: AztecAddress } | { npkMHash: Fr }, contractAddress: AztecAddress): Promise { + async getNullifierKeys( + args: { account: AztecAddress } | { npkMHash: Fr }, + contractAddress: AztecAddress, + ): Promise { const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(args); const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(args, contractAddress); return { masterNullifierPublicKey, appNullifierSecretKey }; @@ -47,7 +50,9 @@ export class SimulatorOracle implements DBOracle { const completeAddress = await this.db.getCompleteAddress(args); if (!completeAddress) { throw new Error( - `No public key registered for ${'account' in args ? `address ${args.account}` : `master nullifier public key hash ${args.npkMHash}`}. Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, + `No public key registered for ${ + 'account' in args ? `address ${args.account}` : `master nullifier public key hash ${args.npkMHash}` + }. Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, ); } return completeAddress; diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.ts b/yarn-project/pxe/src/synchronizer/synchronizer.ts index d7da26c991e..5f6cf4c0715 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.ts @@ -281,7 +281,7 @@ export class Synchronizer { * @throws If checking a sync status of account which is not registered. */ public async isAccountStateSynchronized(account: AztecAddress) { - const completeAddress = await this.db.getCompleteAddress(account); + const completeAddress = await this.db.getCompleteAddress({ account }); if (!completeAddress) { throw new Error(`Checking if account is synched is not possible for ${account} because it is not registered.`); } diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 0fda8ac6bb9..8a0448cb190 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -56,7 +56,7 @@ export class Oracle { // Keeping this oracle separate from above because I don't want an implicit overload in noir code async getNullifierKeysWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise { const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys({ - npkMHash: fromACVMField(masterNullifierPublicKeyHash) + npkMHash: fromACVMField(masterNullifierPublicKeyHash), }); return [ diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 77233eb220a..9b9e3f91743 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -71,7 +71,10 @@ export interface DBOracle extends CommitmentsDB { * @returns A Promise that resolves to nullifier keys of a (requested account or master nullifier key hash) and contract. * @throws An error if the nullifier keys associated to account or master nullifier public key hash is not registered in the key store. */ - getNullifierKeys(args: { account: AztecAddress } | { npkMHash: Fr }, contractAddress: AztecAddress): Promise; + getNullifierKeys( + args: { account: AztecAddress } | { npkMHash: Fr }, + contractAddress: AztecAddress, + ): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 7c9666f8317..157688dd4dd 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -190,35 +190,37 @@ describe('Private Execution test suite', () => { beforeEach(async () => { trees = {}; oracle = mock(); - oracle.getNullifierKeys.mockImplementation((accountAddress: AztecAddress, contractAddress: AztecAddress) => { - if (accountAddress.equals(ownerCompleteAddress.address)) { - return Promise.resolve({ - masterNullifierPublicKey: ownerCompleteAddress.masterNullifierPublicKey, - appNullifierSecretKey: computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), - }); - } - if (accountAddress.equals(recipientCompleteAddress.address)) { - return Promise.resolve({ - masterNullifierPublicKey: recipientCompleteAddress.masterNullifierPublicKey, - appNullifierSecretKey: computeAppNullifierSecretKey(recipientMasterNullifierSecretKey, contractAddress), - }); - } - throw new Error(`Unknown address ${accountAddress}`); - }); + oracle.getNullifierKeys.mockImplementation( + (args: { account: AztecAddress } | { npkMHash: Fr }, contractAddress: AztecAddress) => { + if ('account' in args && args.account.equals(ownerCompleteAddress.address)) { + return Promise.resolve({ + masterNullifierPublicKey: ownerCompleteAddress.masterNullifierPublicKey, + appNullifierSecretKey: computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), + }); + } + if ('account' in args && args.account.equals(recipientCompleteAddress.address)) { + return Promise.resolve({ + masterNullifierPublicKey: recipientCompleteAddress.masterNullifierPublicKey, + appNullifierSecretKey: computeAppNullifierSecretKey(recipientMasterNullifierSecretKey, contractAddress), + }); + } + throw new Error(`Unknown ${'account' in args ? 'address' : 'npkMHash'}`); + }, + ); // We call insertLeaves here with no leaves to populate empty public data tree root --> this is necessary to be // able to get ivpk_m during execution await insertLeaves([], 'publicData'); oracle.getHeader.mockResolvedValue(header); - oracle.getCompleteAddress.mockImplementation((address: AztecAddress) => { - if (address.equals(owner)) { + oracle.getCompleteAddress.mockImplementation((args: { account: AztecAddress } | { npkMHash: Fr }) => { + if ('account' in args && args.account.equals(owner)) { return Promise.resolve(ownerCompleteAddress); } - if (address.equals(recipient)) { + if ('account' in args && args.account.equals(recipient)) { return Promise.resolve(recipientCompleteAddress); } - throw new Error(`Unknown address ${address}`); + throw new Error(`Unknown ${'account' in args ? 'address' : 'npkMHash'}`); }); // This oracle gets called when reading ivpk_m from key registry --> we return zero witness indicating that // the keys were not registered. This triggers non-registered keys flow in which getCompleteAddress oracle diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index fe099451a6f..871949ed2e7 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -33,11 +33,11 @@ describe('Unconstrained Execution test suite', () => { const ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSecretKey, Fr.random()); owner = ownerCompleteAddress.address; - oracle.getCompleteAddress.mockImplementation((address: AztecAddress) => { - if (address.equals(owner)) { + oracle.getCompleteAddress.mockImplementation((args: { account: AztecAddress } | { npkMHash: Fr }) => { + if ('account' in args && args.account.equals(owner)) { return Promise.resolve(ownerCompleteAddress); } - throw new Error(`Unknown address ${address}`); + throw new Error(`Unknown ${'account' in args ? 'address' : 'npkMHash'}`); }); }); From 34b8aa124517a57fbc6852044a461d2074fba038 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Sat, 11 May 2024 12:02:24 +0000 Subject: [PATCH 084/125] bump timeouts --- yarn-project/p2p/src/service/data_store.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/p2p/src/service/data_store.test.ts b/yarn-project/p2p/src/service/data_store.test.ts index e718d6737af..5c8e4c541e1 100644 --- a/yarn-project/p2p/src/service/data_store.test.ts +++ b/yarn-project/p2p/src/service/data_store.test.ts @@ -177,7 +177,7 @@ export function interfaceDatastoreTests(test: I afterEach(async () => { await cleanup(store); - }); + }, 15_000); it('simple', async () => { const k = new Key('/z/key'); From 64396072644cf5768b2eb3102c8ba78c346ab778 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Sat, 11 May 2024 12:24:47 +0000 Subject: [PATCH 085/125] Initial --- .../src/core/libraries/ConstantsGen.sol | 93 +++++-------------- .../aztec/src/context/private_context.nr | 36 +++++-- .../aztec/src/oracle/nullifier_key.nr | 12 ++- .../crates/types/src/constants.nr | 6 +- yarn-project/circuits.js/src/constants.gen.ts | 4 +- 5 files changed, 68 insertions(+), 83 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index ac060def61e..4e8bcd0d175 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -25,7 +25,7 @@ library Constants { uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2; uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 2; - uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 1; + uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 16; uint256 internal constant MAX_ENCRYPTED_LOGS_PER_CALL = 4; uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_CALL = 4; uint256 internal constant MAX_NEW_NOTE_HASHES_PER_TX = 64; @@ -38,7 +38,7 @@ library Constants { uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128; uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8; uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 8; - uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 4; + uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 64; uint256 internal constant MAX_ENCRYPTED_LOGS_PER_TX = 8; uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_TX = 8; uint256 internal constant NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; @@ -80,16 +80,11 @@ library Constants { uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS = 3000; uint256 internal constant REGISTERER_PRIVATE_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS = 19; uint256 internal constant REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS = 12; - uint256 internal constant REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE = - 0x6999d1e02b08a447a463563453cb36919c9dd7150336fc7c4d2b52f8; - uint256 internal constant REGISTERER_PRIVATE_FUNCTION_BROADCASTED_MAGIC_VALUE = - 0x1b70e95fde0b70adc30496b90a327af6a5e383e028e7a43211a07bcd; - uint256 internal constant REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = - 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99; - uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = - 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; - uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = - 0x2e9c386f07e22a1d24e677ab70407b2dd0adbc7cafb9c822bf249685d6a2e4cc; + uint256 internal constant REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE = 0x6999d1e02b08a447a463563453cb36919c9dd7150336fc7c4d2b52f8; + uint256 internal constant REGISTERER_PRIVATE_FUNCTION_BROADCASTED_MAGIC_VALUE = 0x1b70e95fde0b70adc30496b90a327af6a5e383e028e7a43211a07bcd; + uint256 internal constant REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99; + uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; + uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = 0x2e9c386f07e22a1d24e677ab70407b2dd0adbc7cafb9c822bf249685d6a2e4cc; uint256 internal constant DEFAULT_GAS_LIMIT = 1_000_000_000; uint256 internal constant DEFAULT_TEARDOWN_GAS_LIMIT = 100_000_000; uint256 internal constant DEFAULT_MAX_FEE_PER_GAS = 10; @@ -97,13 +92,11 @@ library Constants { uint256 internal constant DA_BYTES_PER_FIELD = 32; uint256 internal constant DA_GAS_PER_BYTE = 16; uint256 internal constant FIXED_DA_GAS = 512; - uint256 internal constant CANONICAL_KEY_REGISTRY_ADDRESS = - 0x1585e564a60e6ec974bc151b62705292ebfc75c33341986a47fd9749cedb567e; + uint256 internal constant CANONICAL_KEY_REGISTRY_ADDRESS = 0x1585e564a60e6ec974bc151b62705292ebfc75c33341986a47fd9749cedb567e; uint256 internal constant AZTEC_ADDRESS_LENGTH = 1; uint256 internal constant GAS_FEES_LENGTH = 2; uint256 internal constant GAS_LENGTH = 2; - uint256 internal constant GAS_SETTINGS_LENGTH = - GAS_LENGTH * 2 + GAS_FEES_LENGTH /* inclusion_fee */ + 1; + uint256 internal constant GAS_SETTINGS_LENGTH = GAS_LENGTH * 2 + GAS_FEES_LENGTH + /* inclusion_fee */ 1; uint256 internal constant CALL_CONTEXT_LENGTH = 6; uint256 internal constant CONTENT_COMMITMENT_LENGTH = 4; uint256 internal constant CONTRACT_INSTANCE_LENGTH = 5; @@ -119,8 +112,7 @@ library Constants { uint256 internal constant SCOPED_L2_TO_L1_MESSAGE_LENGTH = L2_TO_L1_MESSAGE_LENGTH + 1; uint256 internal constant MAX_BLOCK_NUMBER_LENGTH = 2; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; - uint256 internal constant SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = - NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; + uint256 internal constant SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; uint256 internal constant READ_REQUEST_LENGTH = 2; uint256 internal constant NOTE_HASH_LENGTH = 2; @@ -129,65 +121,24 @@ library Constants { uint256 internal constant SCOPED_NULLIFIER_LENGTH = NULLIFIER_LENGTH + 1; uint256 internal constant SIDE_EFFECT_LENGTH = 2; uint256 internal constant ROLLUP_VALIDATION_REQUESTS_LENGTH = MAX_BLOCK_NUMBER_LENGTH; - uint256 internal constant STATE_REFERENCE_LENGTH = - APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; + uint256 internal constant STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; uint256 internal constant TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH; uint256 internal constant TX_REQUEST_LENGTH = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; - uint256 internal constant HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH - + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; - uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 3 - + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) - + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) - + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) - + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) - + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL - + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 - + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 - + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) - + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 2 - + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) - + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) - + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) - + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) - + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) - + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) - + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 - + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH - + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH /* revert_code */ + 1 + 2 * GAS_LENGTH /* transaction_fee */ - + 1; - uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = - AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; + uint256 internal constant HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; + uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 3 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; + uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; + uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; uint256 internal constant SCOPED_READ_REQUEST_LEN = READ_REQUEST_LENGTH + 1; uint256 internal constant PUBLIC_DATA_READ_LENGTH = 2; - uint256 internal constant VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH - + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) - + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) - + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) - + (SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX) - + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); + uint256 internal constant VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + (SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 2; - uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX - + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 4 - + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; - uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = - HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH; + uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 4 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; + uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH; uint256 internal constant CALLER_CONTEXT_LENGTH = 2 * AZTEC_ADDRESS_LENGTH; - uint256 internal constant CALL_REQUEST_LENGTH = - 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + 2; - uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = ( - SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX - ) + (SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX) - + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) - + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) - + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + 2 - + (CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) - + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); - uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 - + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH - + CALL_REQUEST_LENGTH; - uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = - 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; + uint256 internal constant CALL_REQUEST_LENGTH = 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + 2; + uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + 2 + (CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); + uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + CALL_REQUEST_LENGTH; + uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 1b286894f3a..9b1909ec72b 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -223,7 +223,11 @@ impl PrivateContext { // TODO: (#6176) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address pub fn request_nsk_app_with_npk_m_hash(&mut self, npk_m_hash: Field) -> Field { - let keys = if self.nullifier_key.is_none() { + let previous_nullifier_key = self.nullifier_key.unwrap_or(NullifierKeys::empty()); + + let keys = if poseidon2_hash(previous_nullifier_key.master_nullifier_public_key.serialize()) == npk_m_hash { + previous_nullifier_key + } else { let keys = get_nullifier_keys_with_npk_m_hash(npk_m_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, @@ -232,16 +236,34 @@ impl PrivateContext { self.nullifier_key_validation_requests.push(request); self.nullifier_key = Option::some(keys); keys - } else { - let keys = self.nullifier_key.unwrap_unchecked(); - // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. - assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); - keys }; - // We have to check if the key that was requested or cached corresponds to the one we request for assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), npk_m_hash); keys.app_nullifier_secret_key + + // if (self.nullfier_key.is_some()) { + + // } + // if (self.nullifier_key.is_none() | ) + // let keys = if self.nullifier_key.is_none() { + // let keys = get_nullifier_keys(npk_m_hash); + // let request = NullifierKeyValidationRequest { + // master_nullifier_public_key: keys.master_nullifier_public_key, + // app_nullifier_secret_key: keys.app_nullifier_secret_key + // }; + // self.nullifier_key_validation_requests.push(request); + // self.nullifier_key = Option::some(keys); + // keys + // } else { + // let keys = self.nullifier_key.unwrap_unchecked(); + // // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. + // assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); + // keys + // }; + + // // We have to check if the key that was requested or cached corresponds to the one we request for + // assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), npk_m_hash); + // keys.app_nullifier_secret_key } // docs:start:context_message_portal diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 469b4ff6cc3..29cc016003a 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey}; +use dep::protocol_types::{address::AztecAddress, traits::Empty, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey}; // Nullifier keys pertaining to a specific account struct NullifierKeys { @@ -20,6 +20,16 @@ unconstrained fn get_nullifier_keys_internal(account: AztecAddress) -> Nullifier } } +impl Empty for NullifierKeys { + fn empty() -> Self { + NullifierKeys { + account: AztecAddress::zero(), + master_nullifier_public_key: GrumpkinPoint::zero(), + app_nullifier_secret_key: 0 + } + } +} + pub fn get_nullifier_keys(account: AztecAddress) -> NullifierKeys { get_nullifier_keys_internal(account) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 84f47f12d87..85917130d02 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -32,7 +32,8 @@ global MAX_PUBLIC_DATA_READS_PER_CALL: u64 = 16; global MAX_NOTE_HASH_READ_REQUESTS_PER_CALL: u64 = 32; global MAX_NULLIFIER_READ_REQUESTS_PER_CALL: u64 = 2; // Change it to a larger value when there's a seperate reset circuit. global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL: u64 = 2; -global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 1; +// THIS SHOULD EQUAL MAX_NEW_NULLIFIERS_PER_CALL +global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 16; global MAX_ENCRYPTED_LOGS_PER_CALL: u64 = 4; // If modifying, update DEPLOYER_CONTRACT_ADDRESS. global MAX_UNENCRYPTED_LOGS_PER_CALL: u64 = 4; // If modifying, update DEPLOYER_CONTRACT_ADDRESS. @@ -47,7 +48,8 @@ global MAX_NEW_L2_TO_L1_MSGS_PER_TX: u64 = 2; global MAX_NOTE_HASH_READ_REQUESTS_PER_TX: u64 = 128; global MAX_NULLIFIER_READ_REQUESTS_PER_TX: u64 = 8; // Change it to a larger value when there's a seperate reset circuit. global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX: u64 = 8; -global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u64 = 4; +// THIS SHOULD EQUAL MAX_NEW_NULLIFIERS_PER_TX +global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u64 = 64; global MAX_ENCRYPTED_LOGS_PER_TX: u64 = 8; global MAX_UNENCRYPTED_LOGS_PER_TX: u64 = 8; global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index e15a83aa388..d6ba7e12482 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -11,7 +11,7 @@ export const MAX_PUBLIC_DATA_READS_PER_CALL = 16; export const MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; export const MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2; export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 2; -export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 1; +export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 16; export const MAX_ENCRYPTED_LOGS_PER_CALL = 4; export const MAX_UNENCRYPTED_LOGS_PER_CALL = 4; export const MAX_NEW_NOTE_HASHES_PER_TX = 64; @@ -24,7 +24,7 @@ export const MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2; export const MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128; export const MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8; export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 8; -export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 4; +export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 64; export const MAX_ENCRYPTED_LOGS_PER_TX = 8; export const MAX_UNENCRYPTED_LOGS_PER_TX = 8; export const NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; From 44f8bf496eb75befd74d1ce9c469e0a4f1601994 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Sat, 11 May 2024 12:25:36 +0000 Subject: [PATCH 086/125] test --- yarn-project/p2p/src/service/data_store.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/p2p/src/service/data_store.test.ts b/yarn-project/p2p/src/service/data_store.test.ts index 5c8e4c541e1..67567750109 100644 --- a/yarn-project/p2p/src/service/data_store.test.ts +++ b/yarn-project/p2p/src/service/data_store.test.ts @@ -177,7 +177,7 @@ export function interfaceDatastoreTests(test: I afterEach(async () => { await cleanup(store); - }, 15_000); + }); it('simple', async () => { const k = new Key('/z/key'); @@ -390,7 +390,7 @@ export function interfaceDatastoreTests(test: I afterEach(async () => { await cleanup(store); - }); + }, 15_000); it('simple', async () => { const b = store.batch(); From e6425cf5508d5e6b6a2c24b43651deb627232ce4 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Sat, 11 May 2024 12:59:47 +0000 Subject: [PATCH 087/125] Fix --- .../src/core/libraries/ConstantsGen.sol | 91 ++++++++++++++----- .../aztec/src/context/private_context.nr | 25 +---- .../crates/types/src/constants.nr | 6 +- 3 files changed, 73 insertions(+), 49 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 4e8bcd0d175..679c7a868ab 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -80,11 +80,16 @@ library Constants { uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS = 3000; uint256 internal constant REGISTERER_PRIVATE_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS = 19; uint256 internal constant REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS = 12; - uint256 internal constant REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE = 0x6999d1e02b08a447a463563453cb36919c9dd7150336fc7c4d2b52f8; - uint256 internal constant REGISTERER_PRIVATE_FUNCTION_BROADCASTED_MAGIC_VALUE = 0x1b70e95fde0b70adc30496b90a327af6a5e383e028e7a43211a07bcd; - uint256 internal constant REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99; - uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; - uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = 0x2e9c386f07e22a1d24e677ab70407b2dd0adbc7cafb9c822bf249685d6a2e4cc; + uint256 internal constant REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE = + 0x6999d1e02b08a447a463563453cb36919c9dd7150336fc7c4d2b52f8; + uint256 internal constant REGISTERER_PRIVATE_FUNCTION_BROADCASTED_MAGIC_VALUE = + 0x1b70e95fde0b70adc30496b90a327af6a5e383e028e7a43211a07bcd; + uint256 internal constant REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = + 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99; + uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = + 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; + uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = + 0x2e9c386f07e22a1d24e677ab70407b2dd0adbc7cafb9c822bf249685d6a2e4cc; uint256 internal constant DEFAULT_GAS_LIMIT = 1_000_000_000; uint256 internal constant DEFAULT_TEARDOWN_GAS_LIMIT = 100_000_000; uint256 internal constant DEFAULT_MAX_FEE_PER_GAS = 10; @@ -92,11 +97,13 @@ library Constants { uint256 internal constant DA_BYTES_PER_FIELD = 32; uint256 internal constant DA_GAS_PER_BYTE = 16; uint256 internal constant FIXED_DA_GAS = 512; - uint256 internal constant CANONICAL_KEY_REGISTRY_ADDRESS = 0x1585e564a60e6ec974bc151b62705292ebfc75c33341986a47fd9749cedb567e; + uint256 internal constant CANONICAL_KEY_REGISTRY_ADDRESS = + 0x1585e564a60e6ec974bc151b62705292ebfc75c33341986a47fd9749cedb567e; uint256 internal constant AZTEC_ADDRESS_LENGTH = 1; uint256 internal constant GAS_FEES_LENGTH = 2; uint256 internal constant GAS_LENGTH = 2; - uint256 internal constant GAS_SETTINGS_LENGTH = GAS_LENGTH * 2 + GAS_FEES_LENGTH + /* inclusion_fee */ 1; + uint256 internal constant GAS_SETTINGS_LENGTH = + GAS_LENGTH * 2 + GAS_FEES_LENGTH /* inclusion_fee */ + 1; uint256 internal constant CALL_CONTEXT_LENGTH = 6; uint256 internal constant CONTENT_COMMITMENT_LENGTH = 4; uint256 internal constant CONTRACT_INSTANCE_LENGTH = 5; @@ -112,7 +119,8 @@ library Constants { uint256 internal constant SCOPED_L2_TO_L1_MESSAGE_LENGTH = L2_TO_L1_MESSAGE_LENGTH + 1; uint256 internal constant MAX_BLOCK_NUMBER_LENGTH = 2; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 3; - uint256 internal constant SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; + uint256 internal constant SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = + NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH + 1; uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; uint256 internal constant READ_REQUEST_LENGTH = 2; uint256 internal constant NOTE_HASH_LENGTH = 2; @@ -121,24 +129,65 @@ library Constants { uint256 internal constant SCOPED_NULLIFIER_LENGTH = NULLIFIER_LENGTH + 1; uint256 internal constant SIDE_EFFECT_LENGTH = 2; uint256 internal constant ROLLUP_VALIDATION_REQUESTS_LENGTH = MAX_BLOCK_NUMBER_LENGTH; - uint256 internal constant STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; + uint256 internal constant STATE_REFERENCE_LENGTH = + APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH; uint256 internal constant TX_CONTEXT_LENGTH = 2 + GAS_SETTINGS_LENGTH; uint256 internal constant TX_REQUEST_LENGTH = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; - uint256 internal constant HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; - uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 3 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; - uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; + uint256 internal constant HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH; + uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 3 + + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + + (NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL) + + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 2 + HEADER_LENGTH + TX_CONTEXT_LENGTH; + uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + 2 + + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + 1 + HEADER_LENGTH + + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH /* revert_code */ + 1 + 2 * GAS_LENGTH /* transaction_fee */ + + 1; + uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = + AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; uint256 internal constant SCOPED_READ_REQUEST_LEN = READ_REQUEST_LENGTH + 1; uint256 internal constant PUBLIC_DATA_READ_LENGTH = 2; - uint256 internal constant VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + (SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); + uint256 internal constant VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + + (SCOPED_NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH * MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX) + + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 2; - uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 4 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; - uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH; + uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 4 + + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; + uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = + HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH; uint256 internal constant CALLER_CONTEXT_LENGTH = 2 * AZTEC_ADDRESS_LENGTH; - uint256 internal constant CALL_REQUEST_LENGTH = 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + 2; - uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + 2 + (CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); - uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + CALL_REQUEST_LENGTH; - uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; + uint256 internal constant CALL_REQUEST_LENGTH = + 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + 2; + uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = ( + SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX + ) + (SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX) + + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + + (SIDE_EFFECT_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + + (SIDE_EFFECT_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + 2 + + (CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); + uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + + CALL_REQUEST_LENGTH; + uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = + 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; @@ -153,4 +202,4 @@ library Constants { uint256 internal constant RECURSIVE_PROOF_LENGTH = 93; uint256 internal constant NESTED_RECURSIVE_PROOF_LENGTH = 109; uint256 internal constant VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; -} +} \ No newline at end of file diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 9b1909ec72b..aea664a8453 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -223,6 +223,7 @@ impl PrivateContext { // TODO: (#6176) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address pub fn request_nsk_app_with_npk_m_hash(&mut self, npk_m_hash: Field) -> Field { + // A value of empty nullifier keys will fail the key validation request. let previous_nullifier_key = self.nullifier_key.unwrap_or(NullifierKeys::empty()); let keys = if poseidon2_hash(previous_nullifier_key.master_nullifier_public_key.serialize()) == npk_m_hash { @@ -240,30 +241,6 @@ impl PrivateContext { assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), npk_m_hash); keys.app_nullifier_secret_key - - // if (self.nullfier_key.is_some()) { - - // } - // if (self.nullifier_key.is_none() | ) - // let keys = if self.nullifier_key.is_none() { - // let keys = get_nullifier_keys(npk_m_hash); - // let request = NullifierKeyValidationRequest { - // master_nullifier_public_key: keys.master_nullifier_public_key, - // app_nullifier_secret_key: keys.app_nullifier_secret_key - // }; - // self.nullifier_key_validation_requests.push(request); - // self.nullifier_key = Option::some(keys); - // keys - // } else { - // let keys = self.nullifier_key.unwrap_unchecked(); - // // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. - // assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); - // keys - // }; - - // // We have to check if the key that was requested or cached corresponds to the one we request for - // assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), npk_m_hash); - // keys.app_nullifier_secret_key } // docs:start:context_message_portal diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 85917130d02..ae53cbdec0a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -32,8 +32,7 @@ global MAX_PUBLIC_DATA_READS_PER_CALL: u64 = 16; global MAX_NOTE_HASH_READ_REQUESTS_PER_CALL: u64 = 32; global MAX_NULLIFIER_READ_REQUESTS_PER_CALL: u64 = 2; // Change it to a larger value when there's a seperate reset circuit. global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL: u64 = 2; -// THIS SHOULD EQUAL MAX_NEW_NULLIFIERS_PER_CALL -global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 16; +global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 16; // THIS SHOULD EQUAL MAX_NEW_NULLIFIERS_PER_CALL global MAX_ENCRYPTED_LOGS_PER_CALL: u64 = 4; // If modifying, update DEPLOYER_CONTRACT_ADDRESS. global MAX_UNENCRYPTED_LOGS_PER_CALL: u64 = 4; // If modifying, update DEPLOYER_CONTRACT_ADDRESS. @@ -48,8 +47,7 @@ global MAX_NEW_L2_TO_L1_MSGS_PER_TX: u64 = 2; global MAX_NOTE_HASH_READ_REQUESTS_PER_TX: u64 = 128; global MAX_NULLIFIER_READ_REQUESTS_PER_TX: u64 = 8; // Change it to a larger value when there's a seperate reset circuit. global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX: u64 = 8; -// THIS SHOULD EQUAL MAX_NEW_NULLIFIERS_PER_TX -global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u64 = 64; +global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u64 = 64; // THIS SHOULD EQUAL MAX_NEW_NULLIFIERS_PER_TX global MAX_ENCRYPTED_LOGS_PER_TX: u64 = 8; global MAX_UNENCRYPTED_LOGS_PER_TX: u64 = 8; global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; From 28e5f1fb7b5b4a5e7b8f85070569fd0d3ba09fdd Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Sat, 11 May 2024 13:01:18 +0000 Subject: [PATCH 088/125] asdf --- l1-contracts/src/core/libraries/ConstantsGen.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 679c7a868ab..2b3a178d134 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -202,4 +202,4 @@ library Constants { uint256 internal constant RECURSIVE_PROOF_LENGTH = 93; uint256 internal constant NESTED_RECURSIVE_PROOF_LENGTH = 109; uint256 internal constant VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; -} \ No newline at end of file +} From 3ef4856f5dc629048ec1cdde5e83c37311cc9b4d Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Sat, 11 May 2024 18:04:15 +0000 Subject: [PATCH 089/125] Initial fix --- .../aztec-nr/address-note/src/address_note.nr | 4 +- .../aztec-nr/aztec/src/encrypted_logs/body.nr | 2 +- .../aztec-nr/aztec/src/keys/getters.nr | 7 +- .../aztec-nr/aztec/src/note/lifecycle.nr | 6 +- .../aztec-nr/aztec/src/note/note_interface.nr | 3 +- .../aztec/src/state_vars/private_immutable.nr | 4 +- .../aztec/src/state_vars/private_mutable.nr | 8 +- .../aztec/src/state_vars/private_set.nr | 7 +- .../src/easy_private_uint.nr | 6 +- .../aztec-nr/value-note/src/utils.nr | 3 +- .../aztec-nr/value-note/src/value_note.nr | 4 +- .../src/subscription_note.nr | 4 +- .../contracts/card_game_contract/src/cards.nr | 4 +- .../contracts/child_contract/src/main.nr | 4 +- .../crowdfunding_contract/src/main.nr | 4 +- .../delegated_on_contract/src/main.nr | 3 +- .../docs_example_contract/src/main.nr | 5 +- .../src/types/card_note.nr | 4 +- .../src/ecdsa_public_key_note.nr | 4 +- .../inclusion_proofs_contract/src/main.nr | 2 +- .../pending_note_hashes_contract/src/main.nr | 7 +- .../src/public_key_note.nr | 4 +- .../contracts/test_contract/src/main.nr | 4 +- .../contracts/test_contract/src/test_note.nr | 4 +- .../src/types/balances_map.nr | 4 +- .../src/types/token_note.nr | 4 +- .../src/types/transparent_note.nr | 4 +- .../token_contract/src/types/balances_map.nr | 6 +- .../token_contract/src/types/token_note.nr | 6 +- .../src/types/transparent_note.nr | 4 +- .../aztec.js/src/wallet/base_wallet.ts | 5 +- .../circuit-types/src/interfaces/pxe.ts | 4 +- .../circuit-types/src/keys/key_store.ts | 3 + yarn-project/circuits.js/src/keys/index.ts | 16 +- .../end-to-end/src/e2e_key_rotation.test.ts | 270 ++++++++++++++++++ yarn-project/key-store/src/test_key_store.ts | 80 ++++-- .../pxe/src/pxe_service/pxe_service.ts | 6 +- 37 files changed, 421 insertions(+), 98 deletions(-) create mode 100644 yarn-project/end-to-end/src/e2e_key_rotation.test.ts diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index 002c56de934..8be63ae4b5a 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -1,6 +1,6 @@ use dep::aztec::{ keys::getters::get_ivpk_m, - protocol_types::{address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER}, + protocol_types::{address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key}, context::PrivateContext, hash::poseidon2_hash @@ -40,7 +40,7 @@ impl NoteInterface for AddressNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { let ivpk_m = get_ivpk_m(context, self.owner); // docs:start:encrypted context.emit_encrypted_log( diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr index 9f490c768e0..6f3d2a06664 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr @@ -93,7 +93,7 @@ mod test { fn compute_nullifier_without_context(self) -> Field {1} - fn broadcast(self, context: &mut PrivateContext, slot: Field) {} + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) {} fn serialize_content(self) -> [Field; ADDRESS_NOTE_LEN] { [self.address.to_field(), self.owner.to_field(), self.randomness]} diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index a08b9069b53..b8a5aa72d1d 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -4,7 +4,7 @@ use dep::protocol_types::{ }; use crate::{ context::PrivateContext, - oracle::keys::{get_public_keys_and_partial_address, get_public_keys_and_partial_address_with_npk_m_hash}, + oracle::keys::get_public_keys_and_partial_address, state_vars::{ map::derive_storage_slot_in_map, shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter @@ -100,8 +100,3 @@ fn fetch_and_constrain_keys(address: AztecAddress) -> [GrumpkinPoint; 4] { [npk_m, ivpk_m, ovpk_m, tpk_m] } - -pub fn get_ivpk_m_with_npk_m_hash(npk_m_hash: Field) -> GrumpkinPoint { - let result = get_public_keys_and_partial_address_with_npk_m_hash(npk_m_hash); - result.0[1] -} diff --git a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr index 537416c1068..47219746139 100644 --- a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr +++ b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr @@ -1,3 +1,4 @@ +use dep::protocol_types::grumpkin_point::GrumpkinPoint; use crate::context::{PrivateContext, PublicContext}; use crate::note::{ note_header::NoteHeader, note_interface::NoteInterface, @@ -9,7 +10,8 @@ pub fn create_note( context: &mut PrivateContext, storage_slot: Field, note: &mut Note, - broadcast: bool + broadcast: bool, + ivpk_m: GrumpkinPoint, ) where Note: NoteInterface { let contract_address = (*context).this_address(); @@ -36,7 +38,7 @@ pub fn create_note( context.push_new_note_hash(inner_note_hash); if broadcast { - Note::broadcast(*note, context, storage_slot); + Note::broadcast(*note, context, storage_slot, ivpk_m); } } diff --git a/noir-projects/aztec-nr/aztec/src/note/note_interface.nr b/noir-projects/aztec-nr/aztec/src/note/note_interface.nr index 3eaf10c0b77..54b6783769a 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_interface.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_interface.nr @@ -1,5 +1,6 @@ use crate::context::PrivateContext; use crate::note::note_header::NoteHeader; +use dep::protocol_types::grumpkin_point::GrumpkinPoint; // docs:start:note_interface trait NoteInterface { @@ -7,7 +8,7 @@ trait NoteInterface { fn compute_nullifier_without_context(self) -> Field; - fn broadcast(self, context: &mut PrivateContext, slot: Field) -> (); + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) -> (); // Autogenerated by the #[aztec(note)] macro unless it is overridden by a custom implementation fn serialize_content(self) -> [Field; N]; diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr index 67a0268f58b..146d1e51b85 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{address::AztecAddress, constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::pedersen_hash}; +use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::pedersen_hash}; use crate::context::{PrivateContext, Context}; use crate::note::{ @@ -53,7 +53,7 @@ impl PrivateImmutable { let nullifier = self.compute_initialization_nullifier(); context.push_new_nullifier(nullifier, 0); - create_note(context, self.storage_slot, note, broadcast); + create_note(context, self.storage_slot, note, broadcast, GrumpkinPoint::zero()); } // docs:end:initialize diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index 06942a2cbd0..14202e0d1ba 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{address::AztecAddress, constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::pedersen_hash}; +use dep::protocol_types::{address::AztecAddress, constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::pedersen_hash}; use crate::context::{PrivateContext, PublicContext, Context}; use crate::note::{ @@ -55,7 +55,7 @@ impl PrivateMutable { let nullifier = self.compute_initialization_nullifier(); context.push_new_nullifier(nullifier, 0); - create_note(context, self.storage_slot, note, broadcast); + create_note(context, self.storage_slot, note, broadcast, GrumpkinPoint::zero()); } // docs:end:initialize @@ -68,7 +68,7 @@ impl PrivateMutable { destroy_note(context, prev_note); // Add replacement note. - create_note(context, self.storage_slot, new_note, broadcast); + create_note(context, self.storage_slot, new_note, broadcast, GrumpkinPoint::zero()); } // docs:end:replace @@ -82,7 +82,7 @@ impl PrivateMutable { // Add the same note again. // Because a nonce is added to every note in the kernel, its nullifier will be different. - create_note(context, self.storage_slot, &mut note, broadcast); + create_note(context, self.storage_slot, &mut note, broadcast, GrumpkinPoint::zero()); note } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr index 716a6588355..a7bb310462e 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, abis::read_request::ReadRequest}; +use dep::protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, abis::read_request::ReadRequest, grumpkin_point::GrumpkinPoint}; use crate::context::{PrivateContext, PublicContext, Context}; use crate::note::{ constants::MAX_NOTES_PER_PAGE, lifecycle::{create_note, create_note_hash_from_public, destroy_note}, @@ -25,12 +25,13 @@ impl PrivateSet { } // docs:end:new // docs:start:insert - pub fn insert(self, note: &mut Note, broadcast: bool) where Note: NoteInterface { + pub fn insert(self, note: &mut Note, broadcast: bool, ivpk_m: GrumpkinPoint) where Note: NoteInterface { create_note( self.context.private.unwrap(), self.storage_slot, note, - broadcast + broadcast, + ivpk_m, ); } // docs:end:insert diff --git a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr index f6a4c9ebce2..134707cafaa 100644 --- a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr +++ b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr @@ -1,5 +1,5 @@ use dep::aztec::{ - protocol_types::address::AztecAddress, context::Context, + protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}, context::Context, note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet }; use dep::value_note::{filter::filter_notes_min_sum, value_note::ValueNote}; @@ -27,7 +27,7 @@ impl EasyPrivateUint { // Insert the new note to the owner's set of notes. // docs:start:insert - self.set.insert(&mut addend_note, true); + self.set.insert(&mut addend_note, true, GrumpkinPoint::zero()); // docs:end:insert } @@ -63,6 +63,6 @@ impl EasyPrivateUint { // Creates change note for the owner. let result_value = minuend - subtrahend; let mut result_note = ValueNote::new(result_value as Field, owner); - self.set.insert(&mut result_note, result_value != 0); + self.set.insert(&mut result_note, result_value != 0, GrumpkinPoint::zero()); } } diff --git a/noir-projects/aztec-nr/value-note/src/utils.nr b/noir-projects/aztec-nr/value-note/src/utils.nr index 8d88fc6ef0a..618467f5fc7 100644 --- a/noir-projects/aztec-nr/value-note/src/utils.nr +++ b/noir-projects/aztec-nr/value-note/src/utils.nr @@ -1,5 +1,6 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, PrivateSet, NoteGetterOptions}; use dep::aztec::note::note_getter_options::SortOrder; +use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; use crate::{filter::filter_notes_min_sum, value_note::{ValueNote, VALUE_NOTE_LEN}}; // Sort the note values (0th field) in descending order. @@ -13,7 +14,7 @@ pub fn create_note_getter_options_for_decreasing_balance(amount: Field) -> NoteG pub fn increment(balance: PrivateSet, amount: Field, recipient: AztecAddress) { let mut note = ValueNote::new(amount, recipient); // Insert the new note to the owner's set of notes and emit the log if value is non-zero. - balance.insert(&mut note, amount != 0); + balance.insert(&mut note, amount != 0, GrumpkinPoint::zero()); } // Find some of the `owner`'s notes whose values add up to the `amount`. diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index ac790864aa8..537188b20bb 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -1,6 +1,6 @@ use dep::aztec::{ keys::getters::get_ivpk_m, - protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}, constants::GENERATOR_INDEX__NOTE_NULLIFIER}, + protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}, constants::GENERATOR_INDEX__NOTE_NULLIFIER}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key}, hash::poseidon2_hash, context::PrivateContext @@ -43,7 +43,7 @@ impl NoteInterface for ValueNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { let ivpk_m = get_ivpk_m(context, self.owner); context.emit_encrypted_log( (*context).this_address(), diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index 665393b166f..33dbc4a5347 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -1,6 +1,6 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, NoteHeader, NoteInterface}; use dep::aztec::{ - keys::getters::get_ivpk_m, protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, + keys::getters::get_ivpk_m, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, oracle::{nullifier_key::get_app_nullifier_secret_key} }; @@ -38,7 +38,7 @@ impl NoteInterface for SubscriptionNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { let ivpk_m = get_ivpk_m(context, self.owner); context.emit_encrypted_log( (*context).this_address(), 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 c43ba634b10..7fef21cb7bd 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 @@ -1,7 +1,7 @@ use dep::aztec::prelude::{AztecAddress, FunctionSelector, PrivateContext, NoteHeader, NoteGetterOptions, NoteViewerOptions}; use dep::aztec::{ - protocol_types::{traits::{ToField, Serialize, FromField}, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}, + protocol_types::{traits::{ToField, Serialize, FromField}, grumpkin_point::GrumpkinPoint, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}, context::{PublicContext, Context}, note::note_getter::view_notes, state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE }; @@ -105,7 +105,7 @@ impl Deck { let mut inserted_cards = &[]; for card in cards { let mut card_note = CardNote::from_card(card, owner); - self.set.insert(&mut card_note.note, true); + self.set.insert(&mut card_note.note, true, GrumpkinPoint::zero()); inserted_cards = inserted_cards.push_back(card_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 75cfe1a1673..b952f604edb 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -4,7 +4,7 @@ contract Child { use dep::aztec::{ context::{PublicContext, Context, gas::GasOpts}, - protocol_types::{abis::{call_context::CallContext}}, + protocol_types::{abis::call_context::CallContext, grumpkin_point::GrumpkinPoint}, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader} }; use dep::value_note::value_note::ValueNote; @@ -52,7 +52,7 @@ contract Child { #[aztec(private)] fn private_set_value(new_value: Field, owner: AztecAddress) -> Field { let mut note = ValueNote::new(new_value, owner); - storage.a_private_value.insert(&mut note, true); + storage.a_private_value.insert(&mut note, true, GrumpkinPoint::zero()); new_value } diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 38fb7984a38..d3c1e859d62 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -4,7 +4,7 @@ contract Crowdfunding { // docs:start:all-deps use dep::aztec::{ - protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize}, + protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize, grumpkin_point::GrumpkinPoint}, state_vars::{PrivateSet, PublicImmutable, SharedImmutable} }; use dep::value_note::value_note::ValueNote; @@ -84,7 +84,7 @@ contract Crowdfunding { // 3) Create a value note for the donor so that he can later on claim a rewards token in the Claim // contract by proving that the hash of this note exists in the note hash tree. let mut note = ValueNote::new(amount as Field, context.msg_sender()); - storage.donation_receipts.insert(&mut note, true); + storage.donation_receipts.insert(&mut note, true, GrumpkinPoint::zero()); } // docs:end:donate diff --git a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr index e6f093e569d..1f5f5e37807 100644 --- a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr @@ -4,6 +4,7 @@ contract DelegatedOn { AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PublicMutable, PrivateSet, PrivateContext }; + use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; use dep::value_note::value_note::ValueNote; #[aztec(storage)] @@ -15,7 +16,7 @@ contract DelegatedOn { #[aztec(private)] fn private_set_value(new_value: Field, owner: AztecAddress) -> Field { let mut note = ValueNote::new(new_value, owner); - storage.a_private_value.insert(&mut note, true); + storage.a_private_value.insert(&mut note, true, GrumpkinPoint::zero()); new_value } 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 e36efb875bc..db3e77992e9 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 @@ -19,6 +19,7 @@ contract DocsExample { PrivateSet, SharedImmutable, Deserialize }; use dep::aztec::{note::note_getter_options::Comparator, context::{PublicContext, Context}}; + use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; // 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}, leader::Leader}; @@ -183,14 +184,14 @@ contract DocsExample { fn insert_notes(amounts: [u8; 3]) { for i in 0..amounts.len() { let mut note = CardNote::new(amounts[i], 1, context.msg_sender()); - storage.set.insert(&mut note, true); + storage.set.insert(&mut note, true, GrumpkinPoint::zero()); } } #[aztec(private)] fn insert_note(amount: u8, randomness: Field) { let mut note = CardNote::new(amount, randomness, context.msg_sender()); - storage.set.insert(&mut note, true); + storage.set.insert(&mut note, true, GrumpkinPoint::zero()); } // docs:start:state_vars-NoteGetterOptionsComparatorExampleNoir diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index aa2fea463d4..98be0c72f0c 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -2,7 +2,7 @@ use dep::aztec::prelude::{AztecAddress, NoteInterface, NoteHeader, PrivateContex use dep::aztec::{ keys::getters::get_ivpk_m, note::{utils::compute_note_hash_for_consumption}, oracle::nullifier_key::get_app_nullifier_secret_key, hash::poseidon2_hash, - protocol_types::{traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER} + protocol_types::{traits::Empty, grumpkin_point::GrumpkinPoint, constants::GENERATOR_INDEX__NOTE_NULLIFIER} }; // Shows how to create a custom note @@ -46,7 +46,7 @@ impl NoteInterface for CardNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { let ivpk_m = get_ivpk_m(context, self.owner); context.emit_encrypted_log( (*context).this_address(), diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr index eaadbbc60ac..26f42d437c5 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr @@ -3,7 +3,7 @@ use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteInterf use dep::aztec::{ keys::getters::get_ivpk_m, note::utils::compute_note_hash_for_consumption, oracle::nullifier_key::get_app_nullifier_secret_key, hash::poseidon2_hash, - protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} }; global ECDSA_PUBLIC_KEY_NOTE_LEN: Field = 5; @@ -84,7 +84,7 @@ impl NoteInterface for EcdsaPublicKeyNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { let ivpk_m = get_ivpk_m(context, self.owner); context.emit_encrypted_log( (*context).this_address(), 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 3e1112ff07b..bcebe616f7b 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 @@ -45,7 +45,7 @@ contract InclusionProofs { fn create_note(owner: AztecAddress, value: Field) { let owner_private_values = storage.private_values.at(owner); let mut note = ValueNote::new(value, owner); - owner_private_values.insert(&mut note, true); + owner_private_values.insert(&mut note, true, GrumpkinPoint::zero()); } // docs:end:create_note diff --git a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr index 9cce1d75274..aed23961f04 100644 --- a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr @@ -7,6 +7,7 @@ contract PendingNoteHashes { use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, Map, PrivateSet}; use dep::value_note::{balance_utils, filter::filter_notes_min_sum, value_note::{VALUE_NOTE_LEN, ValueNote}}; use dep::aztec::context::{PublicContext, Context}; + use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; #[aztec(storage)] struct Storage { @@ -25,7 +26,7 @@ contract PendingNoteHashes { let mut note = ValueNote::new(amount, owner); // Insert note - owner_balance.insert(&mut note, true); + owner_balance.insert(&mut note, true, GrumpkinPoint::zero()); let options = NoteGetterOptions::with_filter(filter_notes_min_sum, amount); // get note inserted above @@ -54,7 +55,7 @@ contract PendingNoteHashes { // Insert note let mut note = ValueNote::new(amount, owner); - owner_balance.insert(&mut note, true); + owner_balance.insert(&mut note, true, GrumpkinPoint::zero()); 0 } @@ -70,7 +71,7 @@ contract PendingNoteHashes { let mut note = ValueNote::new(amount, owner); // Insert note - owner_balance.insert(&mut note, true); + owner_balance.insert(&mut note, true, GrumpkinPoint::zero()); } // Nested/inner function to get a note and confirm it matches the expected value diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index 74812ec7465..a1ec911d20e 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -2,7 +2,7 @@ use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContex use dep::aztec::{ keys::getters::get_ivpk_m, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, oracle::{nullifier_key::get_app_nullifier_secret_key}, - protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} }; global PUBLIC_KEY_NOTE_LEN: Field = 3; @@ -38,7 +38,7 @@ impl NoteInterface for PublicKeyNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { let ivpk_m = get_ivpk_m(context, self.owner); context.emit_encrypted_log( (*context).this_address(), 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 2a248a7eaf2..aed17162366 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -82,7 +82,7 @@ contract Test { ); let mut note = ValueNote::new(value, owner); - create_note(&mut context, storage_slot, &mut note, true); + create_note(&mut context, storage_slot, &mut note, true, GrumpkinPoint::zero()); } #[aztec(private)] @@ -259,7 +259,7 @@ contract Test { Test::at(context.this_address()).call_create_note(value, owner, storage_slot).call(&mut context); storage_slot += 1; let mut note = ValueNote::new(value + 1, owner); - create_note(&mut context, storage_slot, &mut note, true); + create_note(&mut context, storage_slot, &mut note, true, GrumpkinPoint::zero()); storage_slot += 1; Test::at(context.this_address()).call_create_note(value + 2, owner, storage_slot).call(&mut context); } diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr index 17f2d2d244d..228f406c63e 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr @@ -1,6 +1,6 @@ use dep::aztec::{ note::{note_header::NoteHeader, note_interface::NoteInterface}, hash::pedersen_hash, - context::PrivateContext + context::PrivateContext, protocol_types::grumpkin_point::GrumpkinPoint }; global TEST_NOTE_LEN: Field = 1; @@ -26,7 +26,7 @@ impl NoteInterface for TestNote { 0 } - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { assert( false, "TestNote does not support broadcast. Add it to PXE directly using the `.addNote` function." ); diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr index db69c2a8c1b..06eaad9512f 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr @@ -1,6 +1,6 @@ use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, NoteGetterOptions, NoteViewerOptions, PrivateSet, Map}; use dep::aztec::{ - context::Context, protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}, + context::Context, protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, grumpkin_point::GrumpkinPoint}, note::{note_getter::view_notes, note_getter_options::SortOrder} }; use crate::types::token_note::{TokenNote, OwnedNote}; @@ -59,7 +59,7 @@ impl BalancesMap { let mut addend_note = T::new(addend, owner); // docs:start:insert - self.map.at(owner).insert(&mut addend_note, true); + self.map.at(owner).insert(&mut addend_note, true, GrumpkinPoint::zero()); // docs:end:insert } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index 8492b92a1fc..82db1ae86ff 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -1,6 +1,6 @@ use dep::aztec::{ keys::getters::get_ivpk_m, prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, - protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key} }; @@ -49,7 +49,7 @@ impl NoteInterface for TokenNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { // We only bother inserting the note if non-empty to save funds on gas. if !(self.amount == U128::from_integer(0)) { let ivpk_m = get_ivpk_m(context, self.owner); diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr index d5cf7197cef..fde5c301099 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr @@ -2,7 +2,7 @@ use dep::aztec::{ note::{note_getter_options::PropertySelector, utils::compute_note_hash_for_consumption}, hash::poseidon2_hash, prelude::{NoteHeader, NoteInterface, PrivateContext}, - protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} }; global TRANSPARENT_NOTE_LEN: Field = 2; @@ -59,7 +59,7 @@ impl NoteInterface for TransparentNote { ]) } - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { assert(false, "TransparentNote does not support broadcast"); } } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 6ae314da25c..c636829cd48 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -5,7 +5,7 @@ use dep::aztec::prelude::{ use dep::aztec::{ context::{PublicContext, Context}, hash::pedersen_hash, protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, hash::poseidon2_hash}, - note::{note_getter::view_notes, note_getter_options::SortOrder}, keys::getters::get_npk_m_hash + note::{note_getter::view_notes, note_getter_options::SortOrder}, keys::getters::{get_npk_m_hash, get_ivpk_m} }; use crate::types::token_note::{TokenNote, OwnedNote}; @@ -62,11 +62,11 @@ impl BalancesMap { ) where T: NoteInterface + OwnedNote { // We fetch the nullifier public key hash in the registry / from our PXE let owner_npk_m_hash = get_npk_m_hash(self.map.context.private.unwrap(), owner); - + let owner_ivpk_m = get_ivpk_m(self.map.context.private.unwrap(), owner); let mut addend_note = T::new(addend, owner_npk_m_hash); // docs:start:insert - self.map.at(owner).insert(&mut addend_note, true); + self.map.at(owner).insert(&mut addend_note, true, owner_ivpk_m); // docs:end:insert } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index fa13976f9d5..4db92e7f61d 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -1,7 +1,6 @@ use dep::aztec::{ - keys::getters::get_ivpk_m_with_npk_m_hash, prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, - protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nsk_app_with_npk_m_hash} }; @@ -49,11 +48,10 @@ impl NoteInterface for TokenNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { // We only bother inserting the note if non-empty to save funds on gas. // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format if !(self.amount == U128::from_integer(0)) { - let ivpk_m = get_ivpk_m_with_npk_m_hash(self.npk_m_hash); context.emit_encrypted_log( (*context).this_address(), slot, diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr index d5cf7197cef..fde5c301099 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr @@ -2,7 +2,7 @@ use dep::aztec::{ note::{note_getter_options::PropertySelector, utils::compute_note_hash_for_consumption}, hash::poseidon2_hash, prelude::{NoteHeader, NoteInterface, PrivateContext}, - protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} }; global TRANSPARENT_NOTE_LEN: Field = 2; @@ -59,7 +59,7 @@ impl NoteInterface for TransparentNote { ]) } - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { assert(false, "TransparentNote does not support broadcast"); } } diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 200ad930dee..a1979a19af6 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -15,7 +15,7 @@ import { type TxHash, type TxReceipt, } from '@aztec/circuit-types'; -import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; +import { Fq, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -69,6 +69,9 @@ export abstract class BaseWallet implements Wallet { registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise { return this.pxe.registerAccount(secretKey, partialAddress); } + rotateMasterNullifierKey(account: AztecAddress, secretKey: Fq): Promise { + return this.pxe.rotateMasterNullifierKey(account, secretKey); + } registerRecipient(account: CompleteAddress): Promise { return this.pxe.registerRecipient(account); } diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 9e01820e4f7..f6c8d8772a2 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -1,4 +1,4 @@ -import { type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; +import { Fq, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -61,6 +61,8 @@ export interface PXE { */ registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise; + rotateMasterNullifierKey(account: AztecAddress, secretKey: Fq): Promise; + /** * Registers a recipient in PXE. This is required when sending encrypted notes to * a user who hasn't deployed their account contract yet. Since their account is not deployed, their diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 3bee8446048..45e665dbcc6 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -1,4 +1,5 @@ import { + Fq, type AztecAddress, type CompleteAddress, type Fr, @@ -117,4 +118,6 @@ export interface KeyStore { * @returns A Promise that resolves to the public keys hash. */ getPublicKeysHash(account: AztecAddress): Promise; + + rotateMasterNullifierKey(account: AztecAddress, secretKey: Fq): Promise; } diff --git a/yarn-project/circuits.js/src/keys/index.ts b/yarn-project/circuits.js/src/keys/index.ts index 11fd962e75e..de18c817457 100644 --- a/yarn-project/circuits.js/src/keys/index.ts +++ b/yarn-project/circuits.js/src/keys/index.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { poseidon2Hash, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; -import { type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; +import { Fq, type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; import { Grumpkin } from '../barretenberg/crypto/grumpkin/index.js'; import { GeneratorIndex } from '../constants.gen.js'; @@ -44,13 +44,17 @@ export function computeAddress(publicKeysHash: Fr, partialAddress: Fr) { return AztecAddress.fromField(addressFr); } +export function derivePublicKeyFromSecretKey(secretKey: Fq) { + const curve = new Grumpkin(); + return curve.mul(curve.generator(), secretKey); +} + /** * Computes secret and public keys and public keys hash from a secret key. * @param secretKey - The secret key to derive keys from. * @returns The derived keys. */ export function deriveKeys(secretKey: Fr) { - const curve = new Grumpkin(); // First we derive master secret keys - we use sha512 here because this derivation will never take place // in a circuit const masterNullifierSecretKey = deriveMasterNullifierSecretKey(secretKey); @@ -59,10 +63,10 @@ export function deriveKeys(secretKey: Fr) { const masterTaggingSecretKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.TSK_M]); // Then we derive master public keys - const masterNullifierPublicKey = curve.mul(curve.generator(), masterNullifierSecretKey); - const masterIncomingViewingPublicKey = curve.mul(curve.generator(), masterIncomingViewingSecretKey); - const masterOutgoingViewingPublicKey = curve.mul(curve.generator(), masterOutgoingViewingSecretKey); - const masterTaggingPublicKey = curve.mul(curve.generator(), masterTaggingSecretKey); + const masterNullifierPublicKey = derivePublicKeyFromSecretKey(masterNullifierSecretKey); + const masterIncomingViewingPublicKey = derivePublicKeyFromSecretKey(masterIncomingViewingSecretKey); + const masterOutgoingViewingPublicKey = derivePublicKeyFromSecretKey(masterOutgoingViewingSecretKey); + const masterTaggingPublicKey = derivePublicKeyFromSecretKey(masterTaggingSecretKey); // We hash the public keys to get the public keys hash const publicKeysHash = computePublicKeysHash( diff --git a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts new file mode 100644 index 00000000000..9c4ac11b1ac --- /dev/null +++ b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts @@ -0,0 +1,270 @@ +import { getUnsafeSchnorrAccount } from '@aztec/accounts/single_key'; +import { createAccounts } from '@aztec/accounts/testing'; +import { + type AztecAddress, + type AztecNode, + type DebugLogger, + ExtendedNote, + Fr, + Note, + type PXE, + type Wallet, + computeSecretHash, + retryUntil, + Fq, +} from '@aztec/aztec.js'; +import { ChildContract, KeyRegistryContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; + +import { jest } from '@jest/globals'; + +import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup, setupPXEService } from './fixtures/utils.js'; +import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; +import { derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; + +const TIMEOUT = 120_000; + +describe('e2e_2_pxes', () => { + jest.setTimeout(TIMEOUT); + + let aztecNode: AztecNode | undefined; + let pxeA: PXE; + let pxeB: PXE; + let walletA: Wallet; + let walletB: Wallet; + let logger: DebugLogger; + let teardownA: () => Promise; + let teardownB: () => Promise; + + let keyRegistryWithA: KeyRegistryContract; + let keyRegistryWithB: KeyRegistryContract; + + let testContract: TestContract; + + const SHARED_MUTABLE_DELAY = 5 + 3; + + beforeEach(async () => { + ({ + aztecNode, + pxe: pxeA, + wallets: [walletA], + logger, + teardown: teardownA, + } = await setup(1)); + + ({ pxe: pxeB, teardown: teardownB } = await setupPXEService(aztecNode!, {}, undefined, true)); + + [walletB] = await createAccounts(pxeB, 1); + keyRegistryWithA = await KeyRegistryContract.at(getCanonicalKeyRegistryAddress(), walletA); + keyRegistryWithB = await KeyRegistryContract.at(getCanonicalKeyRegistryAddress(), walletB); + + testContract = await TestContract.deploy(walletA).send().deployed(); + }); + + afterEach(async () => { + await teardownB(); + await teardownA(); + }); + + const awaitUserSynchronized = async (wallet: Wallet, owner: AztecAddress) => { + const isUserSynchronized = async () => { + return await wallet.isAccountStateSynchronized(owner); + }; + await retryUntil(isUserSynchronized, `synch of user ${owner.toString()}`, 10); + }; + + const crossDelay = async () => { + for (let i = 0; i < SHARED_MUTABLE_DELAY; i++) { + // We send arbitrary tx to mine a block + await testContract.methods.emit_unencrypted(0).send().wait(); + } + }; + + + const expectTokenBalance = async ( + wallet: Wallet, + tokenAddress: AztecAddress, + owner: AztecAddress, + expectedBalance: bigint, + checkIfSynchronized = true, + ) => { + if (checkIfSynchronized) { + // First wait until the corresponding PXE has synchronized the account + await awaitUserSynchronized(wallet, owner); + } + + // Then check the balance + const contractWithWallet = await TokenContract.at(tokenAddress, wallet); + const balance = await contractWithWallet.methods.balance_of_private(owner).simulate({ from: owner }); + logger.info(`Account ${owner} balance: ${balance}`); + expect(balance).toBe(expectedBalance); + }; + + const deployTokenContract = async (initialAdminBalance: bigint, admin: AztecAddress, pxe: PXE) => { + logger.info(`Deploying Token contract...`); + const contract = await TokenContract.deploy(walletA, admin, 'TokenName', 'TokenSymbol', 18).send().deployed(); + + if (initialAdminBalance > 0n) { + await mintTokens(contract, admin, initialAdminBalance, pxe); + } + + logger.info('L2 contract deployed'); + + return contract.instance; + }; + + const mintTokens = async (contract: TokenContract, recipient: AztecAddress, balance: bigint, pxe: PXE) => { + const secret = Fr.random(); + const secretHash = computeSecretHash(secret); + + const receipt = await contract.methods.mint_private(balance, secretHash).send().wait(); + + const note = new Note([new Fr(balance), secretHash]); + const extendedNote = new ExtendedNote( + note, + recipient, + contract.address, + TokenContract.storage.pending_shields.slot, + TokenContract.notes.TransparentNote.id, + receipt.txHash, + ); + await pxe.addNote(extendedNote); + + await contract.methods.redeem_shield(recipient, balance, secret).send().wait(); + }; + + // it('transfers funds from user A to B via PXE A followed by transfer from B to A via PXE B', async () => { + // const initialBalance = 987n; + // const transferAmount1 = 654n; + // const transferAmount2 = 323n; + + // const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); + // const tokenAddress = tokenInstance.address; + + // // Add account B to wallet A + // await pxeA.registerRecipient(walletB.getCompleteAddress()); + // // Add account A to wallet B + // await pxeB.registerRecipient(walletA.getCompleteAddress()); + + // // Add token to PXE B (PXE A already has it because it was deployed through it) + // await pxeB.registerContract({ + // artifact: TokenContract.artifact, + // instance: tokenInstance, + // }); + + // // Check initial balances and logs are as expected + // await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); + // await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); + // await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1); + + // // Transfer funds from A to B via PXE A + // const contractWithWalletA = await TokenContract.at(tokenAddress, walletA); + // await contractWithWalletA.methods + // .transfer(walletA.getAddress(), walletB.getAddress(), transferAmount1, 0) + // .send() + // .wait(); + + // // Check balances and logs are as expected + // await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transferAmount1); + // await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1); + // await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); + + // // Transfer funds from B to A via PXE B + // const contractWithWalletB = await TokenContract.at(tokenAddress, walletB); + // await contractWithWalletB.methods + // .transfer(walletB.getAddress(), walletA.getAddress(), transferAmount2, 0) + // .send() + // .wait({ interval: 0.1 }); + + // // Check balances and logs are as expected + // await expectTokenBalance( + // walletA, + // tokenAddress, + // walletA.getAddress(), + // initialBalance - transferAmount1 + transferAmount2, + // ); + // await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1 - transferAmount2); + // await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); + // }); + + it('rotates key', async () => { + const initialBalance = 987n; + const transferAmount1 = 654n; + // const transferAmount2 = 323n; + + const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); + const tokenAddress = tokenInstance.address; + + // Add account B to wallet A + await pxeA.registerRecipient(walletB.getCompleteAddress()); + // Add account A to wallet B + await pxeB.registerRecipient(walletA.getCompleteAddress()); + + // Add token to PXE B (PXE A already has it because it was deployed through it) + await pxeB.registerContract({ + artifact: TokenContract.artifact, + instance: tokenInstance, + }); + + // Check initial balances and logs are as expected + await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); + await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); + await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1); + + // Transfer funds from A to B via PXE A + const contractWithWalletA = await TokenContract.at(tokenAddress, walletA); + await contractWithWalletA.methods + .transfer(walletA.getAddress(), walletB.getAddress(), transferAmount1, 0) + .send() + .wait(); + + // Check balances and logs are as expected + await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transferAmount1); + await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1); + await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); + + // Rotates B key + const newNskM = Fq.random(); + const newNpkM = derivePublicKeyFromSecretKey(newNskM); + await pxeB.rotateMasterNullifierKey(walletB.getAddress(), newNskM); + + await keyRegistryWithB.methods.rotate_npk_m(walletB.getAddress(), newNpkM, 0).send().wait(); + await crossDelay(); + + // Transfer funds from A to B via PXE A + await contractWithWalletA.methods + .transfer(walletA.getAddress(), walletB.getAddress(), 123, 0) + .send() + .wait(); + + await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transferAmount1 - 123n); + await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1 + 123n); + // await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); + + // Transfer funds from B to A via PXE B + const contractWithWalletB = await TokenContract.at(tokenAddress, walletB); + await contractWithWalletB.methods + .transfer(walletB.getAddress(), walletA.getAddress(), transferAmount1 + 123n, 0) + .send() + .wait({ interval: 0.1 }); + + await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); + await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); + + // // Check balances and logs are as expected + // await expectTokenBalance( + // walletA, + // tokenAddress, + // walletA.getAddress(), + // initialBalance, + // ); + // await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); + }, 600_000); + + + const awaitServerSynchronized = async (server: PXE) => { + const isServerSynchronized = async () => { + return await server.isGlobalStateSynchronized(); + }; + await retryUntil(isServerSynchronized, 'server sync', 10); + }; +}); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 8547b5a9a7f..1dee8efa577 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -11,6 +11,8 @@ import { computeAddress, computeAppNullifierSecretKey, deriveKeys, + Fq, + derivePublicKeyFromSecretKey, } from '@aztec/circuits.js'; import { poseidon2Hash } from '@aztec/foundation/crypto'; import { type AztecKVStore, type AztecMap } from '@aztec/kv-store'; @@ -21,9 +23,11 @@ import { type AztecKVStore, type AztecMap } from '@aztec/kv-store'; */ export class TestKeyStore implements KeyStore { #keys: AztecMap; + #rotatedKeys: AztecMap; constructor(database: AztecKVStore) { this.#keys = database.openMap('key_store'); + this.#rotatedKeys = database.openMap('key_store_rotated_keys'); } /** @@ -102,10 +106,14 @@ export class TestKeyStore implements KeyStore { * @returns The master nullifier public key for the account. */ public async getMasterNullifierPublicKey(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { - const masterNullifierPublicKeyBuffer = - 'account' in args - ? this.#keys.get(`${args.account.toString()}-npk_m`) - : this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(args.npkMHash)?.toString()}-npk_m`); + let masterNullifierPublicKeyBuffer; + if ('account' in args) { + // Get most recent rotated or non-rotated + masterNullifierPublicKeyBuffer = this.#rotatedKeys.get(`${args.account.toString()}-npk_m-${this.#rotatedNullifierKeyCount(args.account) - 1}`) ?? this.#keys.get(`${args.account}-npk_m`); + } else { + ({ value: masterNullifierPublicKeyBuffer } = this.#getMapMetadataForMasterNullifierPublicKeyHash(args.npkMHash)); + } + if (!masterNullifierPublicKeyBuffer) { throw new Error( `${ @@ -175,10 +183,19 @@ export class TestKeyStore implements KeyStore { args: { account: AztecAddress } | { npkMHash: Fr }, app: AztecAddress, ): Promise { - const masterNullifierSecretKeyBuffer = - 'account' in args - ? this.#keys.get(`${args.account.toString()}-nsk_m`) - : this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(args.npkMHash)?.toString()}-nsk_m`); + let masterNullifierSecretKeyBuffer: Buffer | undefined; + if ('account' in args) { + // Get most recent rotated or non-rotated + masterNullifierSecretKeyBuffer = this.#rotatedKeys.get(`${args.account.toString()}-nsk_m-${this.#rotatedNullifierKeyCount(args.account) - 1}`) ?? this.#keys.get(`${args.account}-nsk_m`); + } else { + const { key } = this.#getMapMetadataForMasterNullifierPublicKeyHash(args.npkMHash); + const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); + + // #rotatedKeys has a suffix of -${index}, thus there will never be a clash, i.e. using a key in rotated keys will always return undefined if trying to retrieve something in keys + // and using a key in #keys will always return undefined when searching in #rotatedKeys + masterNullifierSecretKeyBuffer = this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); + } + if (!masterNullifierSecretKeyBuffer) { throw new Error( `${ @@ -186,6 +203,7 @@ export class TestKeyStore implements KeyStore { } does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } + const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); const appNullifierSecretKey = computeAppNullifierSecretKey(masterNullifierSecretKey, app); return Promise.resolve(appNullifierSecretKey); @@ -253,14 +271,14 @@ export class TestKeyStore implements KeyStore { */ public getMasterNullifierSecretKeyForPublicKey(masterNullifierPublicKey: PublicKey): Promise { // We iterate over the map keys to find the account address that corresponds to the provided public key - for (const [key, value] of this.#keys.entries()) { - if (value.equals(masterNullifierPublicKey.toBuffer()) && key.endsWith('-npk_m')) { - // We extract the account address from the map key - const accountAddress = key.split('-')[0]; - // We fetch the secret key and return it - const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountAddress.toString()}-nsk_m`); + for (const [key, value] of [...this.#keys.entries(), ...this.#rotatedKeys.entries()]) { + if (value.equals(masterNullifierPublicKey.toBuffer())) { + const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); + + const masterNullifierSecretKeyBuffer = this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); + if (!masterNullifierSecretKeyBuffer) { - throw new Error(`Could not find master nullifier secret key for account ${accountAddress.toString()}`); + throw new Error(`Could not find master nullifier secret key for master nullifier public key ${masterNullifierPublicKey.toString()}`); } return Promise.resolve(GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer)); } @@ -315,18 +333,36 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(Fr.fromBuffer(publicKeysHashBuffer)); } - #getAccountAddressForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr): AztecAddress | undefined { - for (const [key, value] of this.#keys.entries()) { - if (key.endsWith('-npk_m')) { + #getMapMetadataForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr) { + for (const [key, value] of [...this.#keys.entries(), ...this.#rotatedKeys.entries()]) { + if (key.includes('-npk_m')) { const computedMasterNullifierPublicKeyHash = poseidon2Hash(Point.fromBuffer(value).toFields()); if (computedMasterNullifierPublicKeyHash.equals(masterNullifierPublicKeyHash)) { - // We extract the account address from the map key - const accountAddress = key.split('-')[0]; - return AztecAddress.fromString(accountAddress); + return { key, value } } } } - return undefined; + throw new Error(`Master nullifier public key hash ${masterNullifierPublicKeyHash} does not exist.`); + } + + public async rotateMasterNullifierKey(account: AztecAddress, newSecretKey: Fq = Fq.random()) { + const storedAccounts = await this.getAccounts(); + + if (!storedAccounts.some(storedAccount => storedAccount.equals(account))) { + throw new Error('Account does not exist'); + } + + const newPublicKey = derivePublicKeyFromSecretKey(newSecretKey); + + const previouslyRotatedNumber = this.#rotatedNullifierKeyCount(account); + await this.#rotatedKeys.set(`${account.toString()}-nsk_m-${previouslyRotatedNumber}`, newSecretKey.toBuffer()); + await this.#rotatedKeys.set(`${account.toString()}-npk_m-${previouslyRotatedNumber}`, newPublicKey.toBuffer()); + } + + #rotatedNullifierKeyCount(account: AztecAddress): number { + const allRotatedMapKeys = Array.from(this.#rotatedKeys.keys()); + const existingKeys = allRotatedMapKeys.filter(key => key.startsWith(`${account.toString()}-nsk_m`)); + return existingKeys.length; } } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 8ed1734e82c..b056e474334 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -37,7 +37,7 @@ import { import { computeNoteHashNonce, siloNullifier } from '@aztec/circuits.js/hash'; import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection'; -import { Fr } from '@aztec/foundation/fields'; +import { Fq, Fr } from '@aztec/foundation/fields'; import { SerialQueue } from '@aztec/foundation/fifo'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; @@ -187,6 +187,10 @@ export class PXEService implements PXE { return accountCompleteAddress; } + public async rotateMasterNullifierKey(account: AztecAddress, secretKey: Fq = Fq.random()): Promise { + await this.keyStore.rotateMasterNullifierKey(account, secretKey); + } + public async getRegisteredAccounts(): Promise { // Get complete addresses of both the recipients and the accounts const completeAddresses = await this.db.getCompleteAddresses(); From 3287585d5164dddb7408813155986f91dac63179 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 13 May 2024 17:18:18 +0000 Subject: [PATCH 090/125] fixing --- noir-projects/aztec-nr/aztec/src/keys/getters.nr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index 57f067e9209..aaaa560f061 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -1,6 +1,6 @@ -use dep::protocol_types::{address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint}; +use dep::protocol_types::{address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}; use crate::{ - context::PrivateContext, oracle::keys::get_public_keys_and_partial_address, + context::PrivateContext, oracle::keys::{get_public_keys_and_partial_address, get_public_keys_and_partial_address_with_npk_m_hash}, keys::public_keys::{PublicKeys, NULLIFIER_INDEX, INCOMING_INDEX}, state_vars::{ map::derive_storage_slot_in_map, From dc1476a5cd3bd2a4ea31c1106baaebc447cf6d6a Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 13 May 2024 17:40:51 +0000 Subject: [PATCH 091/125] format --- noir-projects/aztec-nr/aztec/src/keys/getters.nr | 8 ++++++-- yarn-project/pxe/src/database/kv_pxe_database.ts | 2 +- yarn-project/pxe/src/pxe_service/pxe_service.ts | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index aaaa560f061..443700f5f60 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -1,6 +1,10 @@ -use dep::protocol_types::{address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}; +use dep::protocol_types::{ + address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, + hash::poseidon2_hash +}; use crate::{ - context::PrivateContext, oracle::keys::{get_public_keys_and_partial_address, get_public_keys_and_partial_address_with_npk_m_hash}, + context::PrivateContext, + oracle::keys::{get_public_keys_and_partial_address, get_public_keys_and_partial_address_with_npk_m_hash}, keys::public_keys::{PublicKeys, NULLIFIER_INDEX, INCOMING_INDEX}, state_vars::{ map::derive_storage_slot_in_map, diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index dbdd0b11034..408030b214d 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -396,7 +396,7 @@ export class KVPxeDatabase implements PxeDatabase { const completeAddresses = this.#getCompleteAddresses(); const completeAddress = completeAddresses.find(completeAddress => - poseidon2Hash(completeAddress.masterNullifierPublicKey.toFields()).equals(npkMHash), + poseidon2Hash(completeAddress.publicKeys.masterNullifierPublicKey.toFields()).equals(npkMHash), ); return Promise.resolve(completeAddress); } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 6a2333a71df..3475d1dc983 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -301,7 +301,7 @@ export class PXEService implements PXE { } public async addNote(note: ExtendedNote) { - const owner = await this.db.getCompleteAddress({ account: note.owner }) ?? {}; + const owner = await this.db.getCompleteAddress({ account: note.owner }); if (!owner) { throw new Error(`Unknown account: ${note.owner.toString()}`); } From 95906c454a15e3b759bb25dfdca8d9b99d3baf92 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 13 May 2024 18:32:19 +0000 Subject: [PATCH 092/125] format --- noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 29cc016003a..e50ef9a1d96 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -1,4 +1,7 @@ -use dep::protocol_types::{address::AztecAddress, traits::Empty, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey}; +use dep::protocol_types::{ + address::AztecAddress, traits::Empty, grumpkin_point::GrumpkinPoint, + grumpkin_private_key::GrumpkinPrivateKey +}; // Nullifier keys pertaining to a specific account struct NullifierKeys { From d3fd00dd0f9bfb82218468cbf6fca8ee4c435686 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 13 May 2024 18:57:50 +0000 Subject: [PATCH 093/125] format --- .../aztec-nr/address-note/src/address_note.nr | 5 +++- .../aztec-nr/aztec/src/note/lifecycle.nr | 2 +- .../aztec/src/state_vars/private_immutable.nr | 13 +++++++-- .../aztec/src/state_vars/private_mutable.nr | 29 ++++++++++++++++--- .../aztec/src/state_vars/private_set.nr | 14 +++++++-- .../aztec-nr/value-note/src/value_note.nr | 5 +++- .../src/subscription_note.nr | 3 +- .../contracts/card_game_contract/src/cards.nr | 5 +++- .../crowdfunding_contract/src/main.nr | 5 +++- .../contracts/test_contract/src/main.nr | 16 ++++++++-- .../src/types/balances_map.nr | 3 +- .../token_contract/src/types/balances_map.nr | 3 +- .../aztec.js/src/wallet/base_wallet.ts | 2 +- .../circuit-types/src/interfaces/pxe.ts | 2 +- .../circuit-types/src/keys/key_store.ts | 2 +- yarn-project/circuits.js/src/keys/index.ts | 4 +-- .../end-to-end/src/e2e_key_rotation.test.ts | 27 ++++------------- yarn-project/key-store/src/test_key_store.ts | 22 +++++++++----- 18 files changed, 110 insertions(+), 52 deletions(-) diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index 8be63ae4b5a..33abadeed8c 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -1,6 +1,9 @@ use dep::aztec::{ keys::getters::get_ivpk_m, - protocol_types::{address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, + protocol_types::{ + address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER, + grumpkin_point::GrumpkinPoint +}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key}, context::PrivateContext, hash::poseidon2_hash diff --git a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr index 47219746139..af461ff44cb 100644 --- a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr +++ b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr @@ -11,7 +11,7 @@ pub fn create_note( storage_slot: Field, note: &mut Note, broadcast: bool, - ivpk_m: GrumpkinPoint, + ivpk_m: GrumpkinPoint ) where Note: NoteInterface { let contract_address = (*context).this_address(); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr index 146d1e51b85..7990ce4c74d 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr @@ -1,4 +1,7 @@ -use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::pedersen_hash}; +use dep::protocol_types::{ + address::AztecAddress, grumpkin_point::GrumpkinPoint, + constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::pedersen_hash +}; use crate::context::{PrivateContext, Context}; use crate::note::{ @@ -53,7 +56,13 @@ impl PrivateImmutable { let nullifier = self.compute_initialization_nullifier(); context.push_new_nullifier(nullifier, 0); - create_note(context, self.storage_slot, note, broadcast, GrumpkinPoint::zero()); + create_note( + context, + self.storage_slot, + note, + broadcast, + GrumpkinPoint::zero() + ); } // docs:end:initialize diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index 14202e0d1ba..1a46c8fd278 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -1,4 +1,7 @@ -use dep::protocol_types::{address::AztecAddress, constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::pedersen_hash}; +use dep::protocol_types::{ + address::AztecAddress, constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, + grumpkin_point::GrumpkinPoint, hash::pedersen_hash +}; use crate::context::{PrivateContext, PublicContext, Context}; use crate::note::{ @@ -55,7 +58,13 @@ impl PrivateMutable { let nullifier = self.compute_initialization_nullifier(); context.push_new_nullifier(nullifier, 0); - create_note(context, self.storage_slot, note, broadcast, GrumpkinPoint::zero()); + create_note( + context, + self.storage_slot, + note, + broadcast, + GrumpkinPoint::zero() + ); } // docs:end:initialize @@ -68,7 +77,13 @@ impl PrivateMutable { destroy_note(context, prev_note); // Add replacement note. - create_note(context, self.storage_slot, new_note, broadcast, GrumpkinPoint::zero()); + create_note( + context, + self.storage_slot, + new_note, + broadcast, + GrumpkinPoint::zero() + ); } // docs:end:replace @@ -82,7 +97,13 @@ impl PrivateMutable { // Add the same note again. // Because a nonce is added to every note in the kernel, its nullifier will be different. - create_note(context, self.storage_slot, &mut note, broadcast, GrumpkinPoint::zero()); + create_note( + context, + self.storage_slot, + &mut note, + broadcast, + GrumpkinPoint::zero() + ); note } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr index a7bb310462e..012facf8591 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr @@ -1,4 +1,7 @@ -use dep::protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, abis::read_request::ReadRequest, grumpkin_point::GrumpkinPoint}; +use dep::protocol_types::{ + constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, abis::read_request::ReadRequest, + grumpkin_point::GrumpkinPoint +}; use crate::context::{PrivateContext, PublicContext, Context}; use crate::note::{ constants::MAX_NOTES_PER_PAGE, lifecycle::{create_note, create_note_hash_from_public, destroy_note}, @@ -25,13 +28,18 @@ impl PrivateSet { } // docs:end:new // docs:start:insert - pub fn insert(self, note: &mut Note, broadcast: bool, ivpk_m: GrumpkinPoint) where Note: NoteInterface { + pub fn insert( + self, + note: &mut Note, + broadcast: bool, + ivpk_m: GrumpkinPoint + ) where Note: NoteInterface { create_note( self.context.private.unwrap(), self.storage_slot, note, broadcast, - ivpk_m, + ivpk_m ); } // docs:end:insert diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 537188b20bb..23cf026766a 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -1,6 +1,9 @@ use dep::aztec::{ keys::getters::get_ivpk_m, - protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}, constants::GENERATOR_INDEX__NOTE_NULLIFIER}, + protocol_types::{ + address::AztecAddress, grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}, + constants::GENERATOR_INDEX__NOTE_NULLIFIER +}, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key}, hash::poseidon2_hash, context::PrivateContext diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index 33dbc4a5347..79aa05dcfd4 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -1,6 +1,7 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, NoteHeader, NoteInterface}; use dep::aztec::{ - keys::getters::get_ivpk_m, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, + keys::getters::get_ivpk_m, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, oracle::{nullifier_key::get_app_nullifier_secret_key} }; 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 7fef21cb7bd..8f74a60118b 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 @@ -1,7 +1,10 @@ use dep::aztec::prelude::{AztecAddress, FunctionSelector, PrivateContext, NoteHeader, NoteGetterOptions, NoteViewerOptions}; use dep::aztec::{ - protocol_types::{traits::{ToField, Serialize, FromField}, grumpkin_point::GrumpkinPoint, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}, + protocol_types::{ + traits::{ToField, Serialize, FromField}, grumpkin_point::GrumpkinPoint, + constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL +}, context::{PublicContext, Context}, note::note_getter::view_notes, state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE }; diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index d3c1e859d62..7cfc6ea0fd7 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -4,7 +4,10 @@ contract Crowdfunding { // docs:start:all-deps use dep::aztec::{ - protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize, grumpkin_point::GrumpkinPoint}, + protocol_types::{ + abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize, + grumpkin_point::GrumpkinPoint + }, state_vars::{PrivateSet, PublicImmutable, SharedImmutable} }; use dep::value_note::value_note::ValueNote; 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 aed17162366..f03f4618683 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -82,7 +82,13 @@ contract Test { ); let mut note = ValueNote::new(value, owner); - create_note(&mut context, storage_slot, &mut note, true, GrumpkinPoint::zero()); + create_note( + &mut context, + storage_slot, + &mut note, + true, + GrumpkinPoint::zero() + ); } #[aztec(private)] @@ -259,7 +265,13 @@ contract Test { Test::at(context.this_address()).call_create_note(value, owner, storage_slot).call(&mut context); storage_slot += 1; let mut note = ValueNote::new(value + 1, owner); - create_note(&mut context, storage_slot, &mut note, true, GrumpkinPoint::zero()); + create_note( + &mut context, + storage_slot, + &mut note, + true, + GrumpkinPoint::zero() + ); storage_slot += 1; Test::at(context.this_address()).call_create_note(value + 2, owner, storage_slot).call(&mut context); } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr index 06eaad9512f..3e0b538fd18 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr @@ -1,6 +1,7 @@ use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, NoteGetterOptions, NoteViewerOptions, PrivateSet, Map}; use dep::aztec::{ - context::Context, protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, grumpkin_point::GrumpkinPoint}, + context::Context, + protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, grumpkin_point::GrumpkinPoint}, note::{note_getter::view_notes, note_getter_options::SortOrder} }; use crate::types::token_note::{TokenNote, OwnedNote}; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index c636829cd48..0179edf37a7 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -5,7 +5,8 @@ use dep::aztec::prelude::{ use dep::aztec::{ context::{PublicContext, Context}, hash::pedersen_hash, protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, hash::poseidon2_hash}, - note::{note_getter::view_notes, note_getter_options::SortOrder}, keys::getters::{get_npk_m_hash, get_ivpk_m} + note::{note_getter::view_notes, note_getter_options::SortOrder}, + keys::getters::{get_npk_m_hash, get_ivpk_m} }; use crate::types::token_note::{TokenNote, OwnedNote}; diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index a1979a19af6..e94c9920359 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -15,7 +15,7 @@ import { type TxHash, type TxReceipt, } from '@aztec/circuit-types'; -import { Fq, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; +import { type AztecAddress, type CompleteAddress, type Fq, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index f6c8d8772a2..0ad069a0ceb 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -1,4 +1,4 @@ -import { Fq, type AztecAddress, type CompleteAddress, type Fr, type PartialAddress } from '@aztec/circuits.js'; +import { type AztecAddress, type CompleteAddress, type Fq, type Fr, type PartialAddress } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts'; import { type NodeInfo } from '@aztec/types/interfaces'; diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 45e665dbcc6..6391f20c659 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -1,7 +1,7 @@ import { - Fq, type AztecAddress, type CompleteAddress, + type Fq, type Fr, type GrumpkinPrivateKey, type PartialAddress, diff --git a/yarn-project/circuits.js/src/keys/index.ts b/yarn-project/circuits.js/src/keys/index.ts index cfea5c7193e..a994d96e5ae 100644 --- a/yarn-project/circuits.js/src/keys/index.ts +++ b/yarn-project/circuits.js/src/keys/index.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { poseidon2Hash, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; -import { Fq, type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; +import { type Fq, type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; import { Grumpkin } from '../barretenberg/crypto/grumpkin/index.js'; import { GeneratorIndex } from '../constants.gen.js'; @@ -54,7 +54,7 @@ export function deriveKeys(secretKey: Fr) { const masterTaggingPublicKey = derivePublicKeyFromSecretKey(masterTaggingSecretKey); // We hash the public keys to get the public keys hash - const publicKeysHash = computePublicKeysHash( + const publicKeys = new PublicKeys( masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, diff --git a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts index 9c4ac11b1ac..f1a5809d01f 100644 --- a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts @@ -1,25 +1,24 @@ -import { getUnsafeSchnorrAccount } from '@aztec/accounts/single_key'; import { createAccounts } from '@aztec/accounts/testing'; import { type AztecAddress, type AztecNode, type DebugLogger, ExtendedNote, + Fq, Fr, Note, type PXE, type Wallet, computeSecretHash, retryUntil, - Fq, } from '@aztec/aztec.js'; -import { ChildContract, KeyRegistryContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; +import { derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; +import { KeyRegistryContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; +import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; import { jest } from '@jest/globals'; import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup, setupPXEService } from './fixtures/utils.js'; -import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; -import { derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; const TIMEOUT = 120_000; @@ -35,7 +34,6 @@ describe('e2e_2_pxes', () => { let teardownA: () => Promise; let teardownB: () => Promise; - let keyRegistryWithA: KeyRegistryContract; let keyRegistryWithB: KeyRegistryContract; let testContract: TestContract; @@ -54,7 +52,6 @@ describe('e2e_2_pxes', () => { ({ pxe: pxeB, teardown: teardownB } = await setupPXEService(aztecNode!, {}, undefined, true)); [walletB] = await createAccounts(pxeB, 1); - keyRegistryWithA = await KeyRegistryContract.at(getCanonicalKeyRegistryAddress(), walletA); keyRegistryWithB = await KeyRegistryContract.at(getCanonicalKeyRegistryAddress(), walletB); testContract = await TestContract.deploy(walletA).send().deployed(); @@ -79,7 +76,6 @@ describe('e2e_2_pxes', () => { } }; - const expectTokenBalance = async ( wallet: Wallet, tokenAddress: AztecAddress, @@ -231,10 +227,7 @@ describe('e2e_2_pxes', () => { await crossDelay(); // Transfer funds from A to B via PXE A - await contractWithWalletA.methods - .transfer(walletA.getAddress(), walletB.getAddress(), 123, 0) - .send() - .wait(); + await contractWithWalletA.methods.transfer(walletA.getAddress(), walletB.getAddress(), 123, 0).send().wait(); await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transferAmount1 - 123n); await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1 + 123n); @@ -249,7 +242,7 @@ describe('e2e_2_pxes', () => { await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); - + // // Check balances and logs are as expected // await expectTokenBalance( // walletA, @@ -259,12 +252,4 @@ describe('e2e_2_pxes', () => { // ); // await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); }, 600_000); - - - const awaitServerSynchronized = async (server: PXE) => { - const isServerSynchronized = async () => { - return await server.isGlobalStateSynchronized(); - }; - await retryUntil(isServerSynchronized, 'server sync', 10); - }; }); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index b217f00b7fc..17bc4b2c2f8 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -2,6 +2,7 @@ import { type KeyStore, type PublicKey } from '@aztec/circuit-types'; import { AztecAddress, CompleteAddress, + Fq, Fr, GeneratorIndex, type GrumpkinPrivateKey, @@ -11,7 +12,6 @@ import { computeAddress, computeAppNullifierSecretKey, deriveKeys, - Fq, derivePublicKeyFromSecretKey, } from '@aztec/circuits.js'; import { poseidon2Hash } from '@aztec/foundation/crypto'; @@ -97,7 +97,9 @@ export class TestKeyStore implements KeyStore { let masterNullifierPublicKeyBuffer; if ('account' in args) { // Get most recent rotated or non-rotated - masterNullifierPublicKeyBuffer = this.#rotatedKeys.get(`${args.account.toString()}-npk_m-${this.#rotatedNullifierKeyCount(args.account) - 1}`) ?? this.#keys.get(`${args.account}-npk_m`); + masterNullifierPublicKeyBuffer = + this.#rotatedKeys.get(`${args.account.toString()}-npk_m-${this.#rotatedNullifierKeyCount(args.account) - 1}`) ?? + this.#keys.get(`${args.account}-npk_m`); } else { ({ value: masterNullifierPublicKeyBuffer } = this.#getMapMetadataForMasterNullifierPublicKeyHash(args.npkMHash)); } @@ -174,14 +176,17 @@ export class TestKeyStore implements KeyStore { let masterNullifierSecretKeyBuffer: Buffer | undefined; if ('account' in args) { // Get most recent rotated or non-rotated - masterNullifierSecretKeyBuffer = this.#rotatedKeys.get(`${args.account.toString()}-nsk_m-${this.#rotatedNullifierKeyCount(args.account) - 1}`) ?? this.#keys.get(`${args.account}-nsk_m`); + masterNullifierSecretKeyBuffer = + this.#rotatedKeys.get(`${args.account.toString()}-nsk_m-${this.#rotatedNullifierKeyCount(args.account) - 1}`) ?? + this.#keys.get(`${args.account}-nsk_m`); } else { const { key } = this.#getMapMetadataForMasterNullifierPublicKeyHash(args.npkMHash); const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); // #rotatedKeys has a suffix of -${index}, thus there will never be a clash, i.e. using a key in rotated keys will always return undefined if trying to retrieve something in keys // and using a key in #keys will always return undefined when searching in #rotatedKeys - masterNullifierSecretKeyBuffer = this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); + masterNullifierSecretKeyBuffer = + this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); } if (!masterNullifierSecretKeyBuffer) { @@ -263,10 +268,13 @@ export class TestKeyStore implements KeyStore { if (value.equals(masterNullifierPublicKey.toBuffer())) { const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); - const masterNullifierSecretKeyBuffer = this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); + const masterNullifierSecretKeyBuffer = + this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); if (!masterNullifierSecretKeyBuffer) { - throw new Error(`Could not find master nullifier secret key for master nullifier public key ${masterNullifierPublicKey.toString()}`); + throw new Error( + `Could not find master nullifier secret key for master nullifier public key ${masterNullifierPublicKey.toString()}`, + ); } return Promise.resolve(GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer)); } @@ -326,7 +334,7 @@ export class TestKeyStore implements KeyStore { if (key.includes('-npk_m')) { const computedMasterNullifierPublicKeyHash = poseidon2Hash(Point.fromBuffer(value).toFields()); if (computedMasterNullifierPublicKeyHash.equals(masterNullifierPublicKeyHash)) { - return { key, value } + return { key, value }; } } } From c8885c76a3f2f1f6b9c609287e95397dccb5e372 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 13 May 2024 19:01:42 +0000 Subject: [PATCH 094/125] Some comments --- .../end-to-end/src/e2e_key_rotation.test.ts | 63 ------------------- 1 file changed, 63 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts index f1a5809d01f..6c3f3b5c406 100644 --- a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts @@ -128,60 +128,6 @@ describe('e2e_2_pxes', () => { await contract.methods.redeem_shield(recipient, balance, secret).send().wait(); }; - // it('transfers funds from user A to B via PXE A followed by transfer from B to A via PXE B', async () => { - // const initialBalance = 987n; - // const transferAmount1 = 654n; - // const transferAmount2 = 323n; - - // const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); - // const tokenAddress = tokenInstance.address; - - // // Add account B to wallet A - // await pxeA.registerRecipient(walletB.getCompleteAddress()); - // // Add account A to wallet B - // await pxeB.registerRecipient(walletA.getCompleteAddress()); - - // // Add token to PXE B (PXE A already has it because it was deployed through it) - // await pxeB.registerContract({ - // artifact: TokenContract.artifact, - // instance: tokenInstance, - // }); - - // // Check initial balances and logs are as expected - // await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); - // await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); - // await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1); - - // // Transfer funds from A to B via PXE A - // const contractWithWalletA = await TokenContract.at(tokenAddress, walletA); - // await contractWithWalletA.methods - // .transfer(walletA.getAddress(), walletB.getAddress(), transferAmount1, 0) - // .send() - // .wait(); - - // // Check balances and logs are as expected - // await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transferAmount1); - // await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1); - // await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); - - // // Transfer funds from B to A via PXE B - // const contractWithWalletB = await TokenContract.at(tokenAddress, walletB); - // await contractWithWalletB.methods - // .transfer(walletB.getAddress(), walletA.getAddress(), transferAmount2, 0) - // .send() - // .wait({ interval: 0.1 }); - - // // Check balances and logs are as expected - // await expectTokenBalance( - // walletA, - // tokenAddress, - // walletA.getAddress(), - // initialBalance - transferAmount1 + transferAmount2, - // ); - // await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1 - transferAmount2); - // await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); - // }); - it('rotates key', async () => { const initialBalance = 987n; const transferAmount1 = 654n; @@ -242,14 +188,5 @@ describe('e2e_2_pxes', () => { await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); - - // // Check balances and logs are as expected - // await expectTokenBalance( - // walletA, - // tokenAddress, - // walletA.getAddress(), - // initialBalance, - // ); - // await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); }, 600_000); }); From a3e0af3de2dad2487d1d6123c15f474b1f9f2894 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 13 May 2024 20:03:58 +0000 Subject: [PATCH 095/125] Pass noir tests --- .../crates/types/src/abis/private_call_stack_item.nr | 2 +- .../crates/types/src/abis/private_circuit_public_inputs.nr | 2 +- .../__snapshots__/private_call_stack_item.test.ts.snap | 4 ++-- .../__snapshots__/private_circuit_public_inputs.test.ts.snap | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index a24fd6e9881..567fc77e834 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x2a1bab3d40feb5234df51a7a6665998920119fd60f5c1e4d9ff3f1128a5f8f81; + let test_data_empty_hash = 0x0aee93406538a326693a1605c59c2bf63c4263805268c76e468951384b1d3ef3; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index fe7429aef2a..c5da6df2355 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -215,6 +215,6 @@ fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x09cc3ed80b2171f093828087431d66777514912b4e7baddb418ab5f1ddbbfd5a; + let test_data_empty_hash = 0x29a90633db4700d98105131501f5de7097b5cb5c46ad44e613bbc0663e600837; assert_eq(hash, test_data_empty_hash); } diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index 279a77f9b5f..9dfbaea9463 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x2a1bab3d40feb5234df51a7a6665998920119fd60f5c1e4d9ff3f1128a5f8f81>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x0aee93406538a326693a1605c59c2bf63c4263805268c76e468951384b1d3ef3>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x1368f96c8d186bfc35d8dc71a0ac006d12e25cfa9fdf12bd3bd5af001049933f>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x25185e63e0746f9bfd7bac9053ee5b735a6da9fcd9a7a3d15b68e1b41c244db8>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 54ef2021ca4..c04d9b9c25f 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x09cc3ed80b2171f093828087431d66777514912b4e7baddb418ab5f1ddbbfd5a>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x29a90633db4700d98105131501f5de7097b5cb5c46ad44e613bbc0663e600837>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x03dee3f2b52e26410a7a69b1c67e7aee5012d9acd53c85f72ab83917e1f4a8f6>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x007a35fde9fcf49b0f155581b07e0bd5e537f5ca70852deb9b335428aff0749a>`; From af8a7e9813a23001e2717a04b54467f87a1bdcfd Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 13 May 2024 20:06:46 +0000 Subject: [PATCH 096/125] Fix --- noir-projects/aztec-nr/aztec/src/context/private_context.nr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index aea664a8453..c4bc8559298 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -214,7 +214,8 @@ impl PrivateContext { } else { let keys = self.nullifier_key.unwrap_unchecked(); // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. - assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); + // This will be fixed in my next PR in the stack + // assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); assert(keys.account == account, "Cannot query nullifier key for more than one account per call"); keys }; From 23b721cc8039306b63f63c02cbe5e4b836235a93 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 13 May 2024 21:21:44 +0000 Subject: [PATCH 097/125] fix --- noir-projects/aztec-nr/tests/src/mock/test_note.nr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/tests/src/mock/test_note.nr b/noir-projects/aztec-nr/tests/src/mock/test_note.nr index 17f6d968d36..1af2d366a86 100644 --- a/noir-projects/aztec-nr/tests/src/mock/test_note.nr +++ b/noir-projects/aztec-nr/tests/src/mock/test_note.nr @@ -1,5 +1,5 @@ use dep::aztec::context::PrivateContext; -use dep::aztec::note::{note_header::NoteHeader, note_interface::NoteInterface}; +use dep::aztec::{note::{note_header::NoteHeader, note_interface::NoteInterface}, protocol_types::grumpkin_point::GrumpkinPoint}; global TEST_NOTE_LENGTH = 1; @@ -44,7 +44,7 @@ impl NoteInterface for TestNote { 0 } - fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { assert( false, "TestNote does not support broadcast." ); From 53c72e18aa205874574f6991ecaae69f2c15ed3e Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 13 May 2024 22:07:19 +0000 Subject: [PATCH 098/125] fmt --- noir-projects/aztec-nr/tests/src/mock/test_note.nr | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/tests/src/mock/test_note.nr b/noir-projects/aztec-nr/tests/src/mock/test_note.nr index 1af2d366a86..3aadf5fdd94 100644 --- a/noir-projects/aztec-nr/tests/src/mock/test_note.nr +++ b/noir-projects/aztec-nr/tests/src/mock/test_note.nr @@ -1,5 +1,8 @@ use dep::aztec::context::PrivateContext; -use dep::aztec::{note::{note_header::NoteHeader, note_interface::NoteInterface}, protocol_types::grumpkin_point::GrumpkinPoint}; +use dep::aztec::{ + note::{note_header::NoteHeader, note_interface::NoteInterface}, + protocol_types::grumpkin_point::GrumpkinPoint +}; global TEST_NOTE_LENGTH = 1; From f014dded6585c2912f860a374d6b9e0226f7c591 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 14 May 2024 10:10:33 +0000 Subject: [PATCH 099/125] Addressing comments --- noir-projects/aztec-nr/aztec/src/keys/getters.nr | 2 +- noir-projects/aztec-nr/aztec/src/oracle/keys.nr | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index 443700f5f60..41be7f71073 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -91,5 +91,5 @@ fn fetch_and_constrain_keys(address: AztecAddress) -> PublicKeys { pub fn get_ivpk_m_with_npk_m_hash(npk_m_hash: Field) -> GrumpkinPoint { let result = get_public_keys_and_partial_address_with_npk_m_hash(npk_m_hash); - result.0[1] + result.0.ivpk_m } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 2cb9063ba53..451d9bbff63 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -30,14 +30,17 @@ unconstrained fn get_public_keys_and_partial_address_with_npk_m_hash_oracle_wrap get_public_keys_and_partial_address_with_npk_m_hash_oracle(npk_m_hash) } -fn get_public_keys_and_partial_address_with_npk_m_hash(npk_m_hash: Field) -> ([GrumpkinPoint; 4], PartialAddress) { +fn get_public_keys_and_partial_address_with_npk_m_hash(npk_m_hash: Field) -> (PublicKeys, PartialAddress) { let result = get_public_keys_and_partial_address_with_npk_m_hash_oracle_wrapper(npk_m_hash); - let nullifier_pub_key = GrumpkinPoint::new(result[0], result[1]); - let incoming_pub_key = GrumpkinPoint::new(result[2], result[3]); - let outgoing_pub_key = GrumpkinPoint::new(result[4], result[5]); - let tagging_pub_key = GrumpkinPoint::new(result[6], result[7]); + let keys = PublicKeys { + npk_m: GrumpkinPoint::new(result[0], result[1]), + ivpk_m: GrumpkinPoint::new(result[2], result[3]), + ovpk_m: GrumpkinPoint::new(result[4], result[5]), + tpk_m: GrumpkinPoint::new(result[6], result[7]) + }; + let partial_address = PartialAddress::from_field(result[8]); - ([nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key], partial_address) + (keys, partial_address) } From 84e53c383b0a1f731e8381b5bf990a519d3e8174 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 14 May 2024 10:53:23 +0000 Subject: [PATCH 100/125] Addressing comments --- .../circuit-types/src/keys/key_store.ts | 4 +-- .../key-store/src/test_key_store.test.ts | 4 +-- yarn-project/key-store/src/test_key_store.ts | 26 +++++++------------ .../pxe/src/database/kv_pxe_database.ts | 5 ++-- yarn-project/pxe/src/database/pxe_database.ts | 4 +-- .../src/database/pxe_database_test_suite.ts | 4 +-- .../pxe/src/pxe_service/pxe_service.ts | 2 +- .../pxe/src/simulator_oracle/index.ts | 15 +++++------ .../pxe/src/synchronizer/synchronizer.ts | 2 +- .../simulator/src/acvm/oracle/oracle.ts | 16 +++--------- .../simulator/src/acvm/oracle/typed_oracle.ts | 4 +-- .../simulator/src/client/db_oracle.ts | 8 +++--- .../src/client/private_execution.test.ts | 16 ++++++------ .../client/unconstrained_execution.test.ts | 6 ++--- .../simulator/src/client/view_data_oracle.ts | 12 ++++----- 15 files changed, 56 insertions(+), 72 deletions(-) diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 3bee8446048..9d42da54332 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -37,7 +37,7 @@ export interface KeyStore { * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the master nullifier public key. * @returns The master nullifier public key for the account. */ - getMasterNullifierPublicKey(args: { account: AztecAddress } | { npkMHash: Fr }): Promise; + getMasterNullifierPublicKey(accountOrNpkMHash: AztecAddress | Fr): Promise; /** * Gets the master incoming viewing public key for a given account. @@ -70,7 +70,7 @@ export interface KeyStore { * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ - getAppNullifierSecretKey(args: { account: AztecAddress } | { npkMHash: Fr }, app: AztecAddress): Promise; + getAppNullifierSecretKey(accountOrNpkMHash: AztecAddress | Fr, app: AztecAddress): Promise; /** * Retrieves application incoming viewing secret key. diff --git a/yarn-project/key-store/src/test_key_store.test.ts b/yarn-project/key-store/src/test_key_store.test.ts index 79da6da8255..2395dbf1472 100644 --- a/yarn-project/key-store/src/test_key_store.test.ts +++ b/yarn-project/key-store/src/test_key_store.test.ts @@ -16,7 +16,7 @@ describe('TestKeyStore', () => { `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, ); - const masterNullifierPublicKey = await keyStore.getMasterNullifierPublicKey({ account: accountAddress }); + const masterNullifierPublicKey = await keyStore.getMasterNullifierPublicKey(accountAddress); expect(masterNullifierPublicKey.toString()).toMatchInlineSnapshot( `"0x2ef5d15dd65d29546680ab72846fb071f41cb9f2a0212215e6c560e29df4ff650ce764818364b376be92dc2f49577fe440e64a16012584f7c4ee94f7edbc323a"`, ); @@ -44,7 +44,7 @@ describe('TestKeyStore', () => { // Arbitrary app contract address const appAddress = AztecAddress.fromBigInt(624n); - const appNullifierSecretKey = await keyStore.getAppNullifierSecretKey({ account: accountAddress }, appAddress); + const appNullifierSecretKey = await keyStore.getAppNullifierSecretKey(accountAddress, appAddress); expect(appNullifierSecretKey.toString()).toMatchInlineSnapshot( `"0x230a44dfe7cfec7a735c89f7289c5cb5d2c3dc0bf5d3505917fd2476f67873a8"`, ); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 13ce01a399b..17b8486d94c 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -89,16 +89,13 @@ export class TestKeyStore implements KeyStore { * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the master nullifier public key. * @returns The master nullifier public key for the account. */ - public async getMasterNullifierPublicKey(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { - const masterNullifierPublicKeyBuffer = - 'account' in args - ? this.#keys.get(`${args.account.toString()}-npk_m`) - : this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(args.npkMHash)?.toString()}-npk_m`); + public async getMasterNullifierPublicKey(accountOrNpkMHash: AztecAddress | Fr): Promise { + const masterNullifierPublicKeyBuffer = this.#keys.get(`${accountOrNpkMHash.toString()}-npk_m`) ?? + this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(accountOrNpkMHash)?.toString()}-npk_m`); + if (!masterNullifierPublicKeyBuffer) { throw new Error( - `${ - 'account' in args ? `Account ${args.account}` : `Master nullifier public key hash ${args.npkMHash}` - } does not exist. Registered accounts: ${await this.getAccounts()}.`, + `Account or master nullifier public key hash ${accountOrNpkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); @@ -160,18 +157,15 @@ export class TestKeyStore implements KeyStore { * @returns A Promise that resolves to the application nullifier secret key. */ public async getAppNullifierSecretKey( - args: { account: AztecAddress } | { npkMHash: Fr }, + accountOrNpkMHash: AztecAddress | Fr, app: AztecAddress, ): Promise { - const masterNullifierSecretKeyBuffer = - 'account' in args - ? this.#keys.get(`${args.account.toString()}-nsk_m`) - : this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(args.npkMHash)?.toString()}-nsk_m`); + const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountOrNpkMHash.toString()}-nsk_m`) ?? + this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(accountOrNpkMHash)?.toString()}-nsk_m`); + if (!masterNullifierSecretKeyBuffer) { throw new Error( - `${ - 'account' in args ? `Account ${args.account}` : `Master nullifier public key hash ${args.npkMHash}` - } does not exist. Registered accounts: ${await this.getAccounts()}.`, + `Account or master nullifier public key hash ${accountOrNpkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 408030b214d..07a116bfe1c 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -386,9 +386,8 @@ export class KVPxeDatabase implements PxeDatabase { return value ? CompleteAddress.fromBuffer(value) : undefined; } - getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { - return Promise.resolve( - 'account' in args ? this.#getCompleteAddress(args.account) : this.#getCompleteAddressWithNpkMHash(args.npkMHash), + getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise { + return Promise.resolve(this.#getCompleteAddress(accountOrNpkMHash) ?? this.#getCompleteAddressWithNpkMHash(accountOrNpkMHash), ); } diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index 8de09765e88..b39fa385a8c 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -134,10 +134,10 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD /** * Retrieve the complete address associated to a given address or master nullifier public key hash. - * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @param accountOrNpkMHash - account - the address or npkMHash - the master nullifier public key hash * @returns A promise that resolves to a CompleteAddress instance if found, or undefined if not found. */ - getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise; + getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise; /** * Retrieves the list of complete address added to this database diff --git a/yarn-project/pxe/src/database/pxe_database_test_suite.ts b/yarn-project/pxe/src/database/pxe_database_test_suite.ts index f4976faaa8e..df865b2b2ba 100644 --- a/yarn-project/pxe/src/database/pxe_database_test_suite.ts +++ b/yarn-project/pxe/src/database/pxe_database_test_suite.ts @@ -215,7 +215,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { it('stores and retrieves addresses', async () => { const address = CompleteAddress.random(); await expect(database.addCompleteAddress(address)).resolves.toBe(true); - await expect(database.getCompleteAddress({ account: address.address })).resolves.toEqual(address); + await expect(database.getCompleteAddress(address.address)).resolves.toEqual(address); }); it('silently ignores an address it already knows about', async () => { @@ -251,7 +251,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { }); it("returns undefined if it doesn't have an address", async () => { - expect(await database.getCompleteAddress({ account: CompleteAddress.random().address })).toBeUndefined(); + expect(await database.getCompleteAddress(CompleteAddress.random().address)).toBeUndefined(); }); }); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 3475d1dc983..575a8019fff 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -301,7 +301,7 @@ export class PXEService implements PXE { } public async addNote(note: ExtendedNote) { - const owner = await this.db.getCompleteAddress({ account: note.owner }); + const owner = await this.db.getCompleteAddress(note.owner); if (!owner) { throw new Error(`Unknown account: ${note.owner.toString()}`); } diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index ee4fc90be3f..66c0faac41e 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -38,21 +38,20 @@ export class SimulatorOracle implements DBOracle { ) {} async getNullifierKeys( - args: { account: AztecAddress } | { npkMHash: Fr }, + accountOrNpkMHash: AztecAddress | Fr, contractAddress: AztecAddress, ): Promise { - const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(args); - const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(args, contractAddress); + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(accountOrNpkMHash); + const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(accountOrNpkMHash, contractAddress); return { masterNullifierPublicKey, appNullifierSecretKey }; } - async getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { - const completeAddress = await this.db.getCompleteAddress(args); + async getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise { + const completeAddress = await this.db.getCompleteAddress(accountOrNpkMHash); if (!completeAddress) { throw new Error( - `No public key registered for ${ - 'account' in args ? `address ${args.account}` : `master nullifier public key hash ${args.npkMHash}` - }. Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, + `No public key registered for address or master nullifier public key hash ${accountOrNpkMHash}. + Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, ); } return completeAddress; diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.ts b/yarn-project/pxe/src/synchronizer/synchronizer.ts index 1ced609d3f6..527fe3d9a47 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.ts @@ -281,7 +281,7 @@ export class Synchronizer { * @throws If checking a sync status of account which is not registered. */ public async isAccountStateSynchronized(account: AztecAddress) { - const completeAddress = await this.db.getCompleteAddress({ account }); + const completeAddress = await this.db.getCompleteAddress(account); if (!completeAddress) { throw new Error(`Checking if account is synched is not possible for ${account} because it is not registered.`); } diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 09b87d9a55c..fd568d1e003 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -43,9 +43,7 @@ export class Oracle { } async getNullifierKeys([accountAddress]: ACVMField[]): Promise { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys({ - account: fromACVMField(accountAddress), - }); + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys(fromACVMField(accountAddress)); return [ toACVMField(masterNullifierPublicKey.x), toACVMField(masterNullifierPublicKey.y), @@ -55,9 +53,7 @@ export class Oracle { // Keeping this oracle separate from above because I don't want an implicit overload in noir code async getNullifierKeysWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys({ - npkMHash: fromACVMField(masterNullifierPublicKeyHash), - }); + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys(fromACVMField(masterNullifierPublicKeyHash)); return [ toACVMField(masterNullifierPublicKey.x), @@ -179,9 +175,7 @@ export class Oracle { async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { const parsedAddress = AztecAddress.fromField(fromACVMField(address)); - const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress({ - account: parsedAddress, - }); + const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress(parsedAddress); return [...publicKeys.toFields(), partialAddress].map(toACVMField); } @@ -189,9 +183,7 @@ export class Oracle { // Keeping this oracle separate from above because I don't want an implicit overload in noir code async getPublicKeysAndPartialAddressWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]) { const parsedNpkMHash = fromACVMField(masterNullifierPublicKeyHash); - const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress({ - npkMHash: parsedNpkMHash, - }); + const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress(parsedNpkMHash); return [...publicKeys.toFields(), partialAddress].map(toACVMField); } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 5b050be24ab..13f4ca59500 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -89,7 +89,7 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('unpackReturns'); } - getNullifierKeys(_args: { account: AztecAddress } | { npkMHash: Fr }): Promise { + getNullifierKeys(_accountOrNpkMHash: AztecAddress | Fr): Promise { throw new OracleMethodNotAvailableError('getNullifierKeys'); } @@ -124,7 +124,7 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getHeader'); } - getCompleteAddress(_args: { account: AztecAddress } | { npkMHash: Fr }): Promise { + getCompleteAddress(_accountOrNpkMHash: AztecAddress | Fr): Promise { throw new OracleMethodNotAvailableError('getCompleteAddress'); } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 9b9e3f91743..7b702e85ca6 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -45,11 +45,11 @@ export interface DBOracle extends CommitmentsDB { /** * Retrieve the complete address associated to a given address or master nullifier public key hash. - * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @param accountOrNpkMHash - account - the address or npkMHash - the master nullifier public key hash * @returns A complete address associated with the input address or master nullifier public key hash * @throws An error if the account is not registered in the database. */ - getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise; + getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise; /** * Retrieve the auth witness for a given message hash. @@ -67,12 +67,12 @@ export interface DBOracle extends CommitmentsDB { /** * Retrieve nullifier keys associated with a (specific account or master nullifier key hash) and app/contract address. - * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @param accountOrNpkMHash - account - the address or npkMHash - the master nullifier public key hash * @returns A Promise that resolves to nullifier keys of a (requested account or master nullifier key hash) and contract. * @throws An error if the nullifier keys associated to account or master nullifier public key hash is not registered in the key store. */ getNullifierKeys( - args: { account: AztecAddress } | { npkMHash: Fr }, + accountOrNpkMHash: AztecAddress | Fr, contractAddress: AztecAddress, ): Promise; diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 464858d6b22..25b21cb887e 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -191,20 +191,20 @@ describe('Private Execution test suite', () => { trees = {}; oracle = mock(); oracle.getNullifierKeys.mockImplementation( - (args: { account: AztecAddress } | { npkMHash: Fr }, contractAddress: AztecAddress) => { - if ('account' in args && args.account.equals(ownerCompleteAddress.address)) { + (accountOrNpkMHash: AztecAddress | Fr, contractAddress: AztecAddress) => { + if (accountOrNpkMHash.equals(ownerCompleteAddress.address)) { return Promise.resolve({ masterNullifierPublicKey: ownerCompleteAddress.publicKeys.masterNullifierPublicKey, appNullifierSecretKey: computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), }); } - if ('account' in args && args.account.equals(recipientCompleteAddress.address)) { + if (accountOrNpkMHash.equals(recipientCompleteAddress.address)) { return Promise.resolve({ masterNullifierPublicKey: recipientCompleteAddress.publicKeys.masterNullifierPublicKey, appNullifierSecretKey: computeAppNullifierSecretKey(recipientMasterNullifierSecretKey, contractAddress), }); } - throw new Error(`Unknown ${'account' in args ? 'address' : 'npkMHash'}`); + throw new Error(`Unknown address ${accountOrNpkMHash}`); }, ); @@ -213,14 +213,14 @@ describe('Private Execution test suite', () => { await insertLeaves([], 'publicData'); oracle.getHeader.mockResolvedValue(header); - oracle.getCompleteAddress.mockImplementation((args: { account: AztecAddress } | { npkMHash: Fr }) => { - if ('account' in args && args.account.equals(owner)) { + oracle.getCompleteAddress.mockImplementation((accountOrNpkMHash: AztecAddress | Fr) => { + if (accountOrNpkMHash.equals(owner)) { return Promise.resolve(ownerCompleteAddress); } - if ('account' in args && args.account.equals(recipient)) { + if (accountOrNpkMHash.equals(recipient)) { return Promise.resolve(recipientCompleteAddress); } - throw new Error(`Unknown ${'account' in args ? 'address' : 'npkMHash'}`); + throw new Error(`Unknown address ${accountOrNpkMHash}`); }); // This oracle gets called when reading ivpk_m from key registry --> we return zero witness indicating that // the keys were not registered. This triggers non-registered keys flow in which getCompleteAddress oracle diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index 871949ed2e7..3d1b69cb0ca 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -33,11 +33,11 @@ describe('Unconstrained Execution test suite', () => { const ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSecretKey, Fr.random()); owner = ownerCompleteAddress.address; - oracle.getCompleteAddress.mockImplementation((args: { account: AztecAddress } | { npkMHash: Fr }) => { - if ('account' in args && args.account.equals(owner)) { + oracle.getCompleteAddress.mockImplementation((accountOrNpkMHash: AztecAddress | Fr) => { + if (accountOrNpkMHash.equals(owner)) { return Promise.resolve(ownerCompleteAddress); } - throw new Error(`Unknown ${'account' in args ? 'address' : 'npkMHash'}`); + throw new Error(`Unknown address ${accountOrNpkMHash}`); }); }); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 298d75406b2..d0b959c0fbf 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -36,12 +36,12 @@ export class ViewDataOracle extends TypedOracle { /** * Retrieve nullifier keys associated with a (specific account or master nullifier key hash) and app/contract address. - * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @param accountOrNpkMHash - account - the address or npkMHash - the master nullifier public key hash * @returns A Promise that resolves to nullifier keys of a (requested account or master nullifier key hash) and contract. * @throws An error if the nullifier keys associated to account or master nullifier public key hash is not registered in the key store. */ - public override getNullifierKeys(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { - return this.db.getNullifierKeys(args, this.contractAddress); + public override getNullifierKeys(accountOrNpkMHash: AztecAddress | Fr): Promise { + return this.db.getNullifierKeys(accountOrNpkMHash, this.contractAddress); } /** @@ -128,12 +128,12 @@ export class ViewDataOracle extends TypedOracle { /** * Retrieve the complete address associated to a given address or master nullifier public key hash. - * @param args - contains account - the address or npkMHash - the master nullifier public key hash + * @param accountOrNpkMHash - account - the address or npkMHash - the master nullifier public key hash * @returns A complete address associated with the input address or master nullifier public key hash * @throws An error if the account is not registered in the database. */ - public override getCompleteAddress(args: { account: AztecAddress } | { npkMHash: Fr }): Promise { - return this.db.getCompleteAddress(args); + public override getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise { + return this.db.getCompleteAddress(accountOrNpkMHash); } /** From fee5a59f1a6bc50b4a7458764c3d9d79406dbc63 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Tue, 14 May 2024 05:54:34 -0500 Subject: [PATCH 101/125] Apply suggestions from Jan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- noir-projects/aztec-nr/aztec/src/context/private_context.nr | 2 +- noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr | 4 ++-- yarn-project/key-store/src/test_key_store.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 1b286894f3a..ced5e581804 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -221,7 +221,7 @@ impl PrivateContext { keys.app_nullifier_secret_key } - // TODO: (#6176) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address + // TODO(#5630) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address pub fn request_nsk_app_with_npk_m_hash(&mut self, npk_m_hash: Field) -> Field { let keys = if self.nullifier_key.is_none() { let keys = get_nullifier_keys_with_npk_m_hash(npk_m_hash); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index 469b4ff6cc3..c15e36bc6db 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -2,7 +2,7 @@ use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, // Nullifier keys pertaining to a specific account struct NullifierKeys { - // TODO (#6176): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address + // TODO(#5630): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address account: AztecAddress, master_nullifier_public_key: GrumpkinPoint, app_nullifier_secret_key: Field, @@ -28,7 +28,7 @@ pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { get_nullifier_keys_internal(account).app_nullifier_secret_key } -// TODO (#6176): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address +// TODO(#5630): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address #[oracle(getNullifierKeysWithNpkMHash)] fn get_nullifier_keys_with_npk_m_hash_oracle(_npk_m_hash: Field) -> [Field; 3] {} diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 17b8486d94c..da66925b30e 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -57,7 +57,7 @@ export class TestKeyStore implements KeyStore { // We save the keys to db associated with the account address await this.#keys.set(`${accountAddress.toString()}-public_keys_hash`, publicKeysHash.toBuffer()); - // Naming of keys is as follows ${from}-${to}_${any modifiers (m = master, h = hash)} + // Naming of keys is as follows ${from}-${to}_m await this.#keys.set(`${accountAddress.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer()); From 071e7c41b3aad12c08cc3b7d1b1acac79b70a84a Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 14 May 2024 11:39:34 +0000 Subject: [PATCH 102/125] format --- .../circuit-types/src/keys/key_store.ts | 4 ++-- yarn-project/key-store/src/test_key_store.ts | 17 ++++++++--------- .../pxe/src/database/kv_pxe_database.ts | 3 ++- yarn-project/pxe/src/simulator_oracle/index.ts | 5 +---- .../simulator/src/acvm/oracle/oracle.ts | 8 ++++++-- yarn-project/simulator/src/client/db_oracle.ts | 5 +---- 6 files changed, 20 insertions(+), 22 deletions(-) diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 9d42da54332..db0da3f21ec 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -34,7 +34,7 @@ export interface KeyStore { /** * Gets the master nullifier public key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the master nullifier public key. + * @param accountOrNpkMHash - account - the address or npkMHash - the master nullifier public key hash * @returns The master nullifier public key for the account. */ getMasterNullifierPublicKey(accountOrNpkMHash: AztecAddress | Fr): Promise; @@ -66,7 +66,7 @@ export interface KeyStore { /** * Derives and returns the application nullifier secret key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the application nullifier secret key. + * @param accountOrNpkMHash - account - the address or npkMHash - the master nullifier public key hash * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index da66925b30e..f5f417da192 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -86,12 +86,13 @@ export class TestKeyStore implements KeyStore { /** * Gets the master nullifier public key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the master nullifier public key. + * @param accountOrNpkMHash - account - the address or npkMHash - the master nullifier public key hash * @returns The master nullifier public key for the account. */ public async getMasterNullifierPublicKey(accountOrNpkMHash: AztecAddress | Fr): Promise { - const masterNullifierPublicKeyBuffer = this.#keys.get(`${accountOrNpkMHash.toString()}-npk_m`) ?? - this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(accountOrNpkMHash)?.toString()}-npk_m`); + const masterNullifierPublicKeyBuffer = + this.#keys.get(`${accountOrNpkMHash.toString()}-npk_m`) ?? + this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(accountOrNpkMHash)?.toString()}-npk_m`); if (!masterNullifierPublicKeyBuffer) { throw new Error( @@ -152,15 +153,13 @@ export class TestKeyStore implements KeyStore { /** * Derives and returns the application nullifier secret key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param account or master nullifier public key hash - The account address or master nullifier public key hash for which to retrieve the application nullifier secret key. + * @param accountOrNpkMHash - account - the address or npkMHash - the master nullifier public key hash * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ - public async getAppNullifierSecretKey( - accountOrNpkMHash: AztecAddress | Fr, - app: AztecAddress, - ): Promise { - const masterNullifierSecretKeyBuffer = this.#keys.get(`${accountOrNpkMHash.toString()}-nsk_m`) ?? + public async getAppNullifierSecretKey(accountOrNpkMHash: AztecAddress | Fr, app: AztecAddress): Promise { + const masterNullifierSecretKeyBuffer = + this.#keys.get(`${accountOrNpkMHash.toString()}-nsk_m`) ?? this.#keys.get(`${this.#getAccountAddressForMasterNullifierPublicKeyHash(accountOrNpkMHash)?.toString()}-nsk_m`); if (!masterNullifierSecretKeyBuffer) { diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 07a116bfe1c..2de3eaff5b2 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -387,7 +387,8 @@ export class KVPxeDatabase implements PxeDatabase { } getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise { - return Promise.resolve(this.#getCompleteAddress(accountOrNpkMHash) ?? this.#getCompleteAddressWithNpkMHash(accountOrNpkMHash), + return Promise.resolve( + this.#getCompleteAddress(accountOrNpkMHash) ?? this.#getCompleteAddressWithNpkMHash(accountOrNpkMHash), ); } diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 66c0faac41e..e598a1c49e9 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -37,10 +37,7 @@ export class SimulatorOracle implements DBOracle { private log = createDebugLogger('aztec:pxe:simulator_oracle'), ) {} - async getNullifierKeys( - accountOrNpkMHash: AztecAddress | Fr, - contractAddress: AztecAddress, - ): Promise { + async getNullifierKeys(accountOrNpkMHash: AztecAddress | Fr, contractAddress: AztecAddress): Promise { const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(accountOrNpkMHash); const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(accountOrNpkMHash, contractAddress); return { masterNullifierPublicKey, appNullifierSecretKey }; diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index fd568d1e003..d57338e2592 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -43,7 +43,9 @@ export class Oracle { } async getNullifierKeys([accountAddress]: ACVMField[]): Promise { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys(fromACVMField(accountAddress)); + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( + fromACVMField(accountAddress), + ); return [ toACVMField(masterNullifierPublicKey.x), toACVMField(masterNullifierPublicKey.y), @@ -53,7 +55,9 @@ export class Oracle { // Keeping this oracle separate from above because I don't want an implicit overload in noir code async getNullifierKeysWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys(fromACVMField(masterNullifierPublicKeyHash)); + const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( + fromACVMField(masterNullifierPublicKeyHash), + ); return [ toACVMField(masterNullifierPublicKey.x), diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 7b702e85ca6..1588e3e7f45 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -71,10 +71,7 @@ export interface DBOracle extends CommitmentsDB { * @returns A Promise that resolves to nullifier keys of a (requested account or master nullifier key hash) and contract. * @throws An error if the nullifier keys associated to account or master nullifier public key hash is not registered in the key store. */ - getNullifierKeys( - accountOrNpkMHash: AztecAddress | Fr, - contractAddress: AztecAddress, - ): Promise; + getNullifierKeys(accountOrNpkMHash: AztecAddress | Fr, contractAddress: AztecAddress): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. From 7fb86705c42674a1192d8f7ab9bfd34cb1031cf9 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 14 May 2024 19:48:44 +0000 Subject: [PATCH 103/125] Working --- .../aztec-nr/address-note/src/address_note.nr | 17 +++---- .../aztec/src/context/private_context.nr | 30 ++--------- .../aztec-nr/aztec/src/encrypted_logs/body.nr | 2 +- .../aztec-nr/aztec/src/keys/getters.nr | 15 +++++- .../aztec-nr/aztec/src/oracle/keys.nr | 22 -------- .../aztec/src/oracle/nullifier_key.nr | 41 +++------------ .../aztec/src/state_vars/private_immutable.nr | 4 +- .../aztec/src/state_vars/private_mutable.nr | 12 ++--- .../src/easy_private_uint.nr | 17 ++++--- .../aztec-nr/value-note/src/utils.nr | 25 ++++++---- .../aztec-nr/value-note/src/value_note.nr | 18 +++---- .../app_subscription_contract/src/main.nr | 15 +++--- .../src/subscription_note.nr | 17 +++---- .../benchmarking_contract/src/main.nr | 4 +- .../contracts/card_game_contract/src/cards.nr | 26 ++++++---- .../contracts/child_contract/src/main.nr | 16 ++++-- .../contracts/claim_contract/src/main.nr | 6 ++- .../crowdfunding_contract/src/main.nr | 8 +-- .../delegated_on_contract/src/main.nr | 22 +++++--- .../contracts/delegator_contract/src/main.nr | 16 +++--- .../docs_example_contract/src/main.nr | 46 +++++++++++------ .../docs_example_contract/src/options.nr | 30 ++++++----- .../src/types/card_note.nr | 16 +++--- .../easy_private_voting_contract/src/main.nr | 5 +- .../src/ecdsa_public_key_note.nr | 20 ++++---- .../ecdsa_account_contract/src/main.nr | 8 ++- .../contracts/escrow_contract/src/main.nr | 9 +++- .../inclusion_proofs_contract/src/main.nr | 36 ++++++++----- .../pending_note_hashes_contract/src/main.nr | 24 ++++++--- .../schnorr_account_contract/src/main.nr | 8 ++- .../src/public_key_note.nr | 19 ++++--- .../stateful_test_contract/src/main.nr | 12 ++--- .../contracts/test_contract/src/main.nr | 19 ++++--- .../src/types/balances_map.nr | 19 ++++--- .../src/types/token_note.nr | 33 ++++++------ .../token_contract/src/types/token_note.nr | 6 +-- .../src/e2e_crowdfunding_and_claim.test.ts | 3 +- .../src/e2e_delegate_calls/delegate.test.ts | 9 ++-- .../simulator/src/acvm/oracle/oracle.ts | 22 +------- .../src/client/private_execution.test.ts | 50 +++++++++---------- 40 files changed, 379 insertions(+), 348 deletions(-) diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index 33abadeed8c..1e749f904fd 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -1,11 +1,10 @@ use dep::aztec::{ - keys::getters::get_ivpk_m, protocol_types::{ address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint }, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key}, + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, context::PrivateContext, hash::poseidon2_hash }; @@ -16,7 +15,8 @@ global ADDRESS_NOTE_LEN: Field = 3; #[aztec(note)] struct AddressNote { address: AztecAddress, - owner: AztecAddress, + // The nullifying public key hash is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + npk_m_hash: Field, randomness: Field, } @@ -24,7 +24,7 @@ impl NoteInterface for AddressNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -34,7 +34,7 @@ impl NoteInterface for AddressNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -43,8 +43,7 @@ impl NoteInterface for AddressNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { - let ivpk_m = get_ivpk_m(context, self.owner); + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { // docs:start:encrypted context.emit_encrypted_log( (*context).this_address(), @@ -58,9 +57,9 @@ impl NoteInterface for AddressNote { } impl AddressNote { - pub fn new(address: AztecAddress, owner: AztecAddress) -> Self { + pub fn new(address: AztecAddress, npk_m_hash: Field) -> Self { let randomness = unsafe_rand(); - AddressNote { address, owner, randomness, header: NoteHeader::empty() } + AddressNote { address, npk_m_hash, randomness, header: NoteHeader::empty() } } // docs:end:address_note_def } diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index a085ade631d..f5b770b19b6 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -1,11 +1,11 @@ use crate::{ context::{inputs::PrivateContextInputs, interface::ContextInterface}, + keys::getters::get_nullifier_keys, messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher, compute_encrypted_log_hash, compute_unencrypted_log_hash}, oracle::{ - arguments, returns, call_private_function::call_private_function_internal, header::get_header_at, + nullifier_key::NullifierKeys,arguments, returns, call_private_function::call_private_function_internal, header::get_header_at, logs::emit_encrypted_log, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, - nullifier_key::{get_nullifier_keys, get_nullifier_keys_with_npk_m_hash, NullifierKeys}, enqueue_public_function_call::{ enqueue_public_function_call_internal, set_public_teardown_function_call_internal, parse_public_call_stack_item_from_oracle @@ -204,36 +204,14 @@ impl PrivateContext { self.nullifier_read_requests.push(request); } - pub fn request_app_nullifier_secret_key(&mut self, account: AztecAddress) -> Field { - let keys = if self.nullifier_key.is_none() { - let keys = get_nullifier_keys(account); - let request = NullifierKeyValidationRequest { - master_nullifier_public_key: keys.master_nullifier_public_key, - app_nullifier_secret_key: keys.app_nullifier_secret_key - }; - self.nullifier_key_validation_requests.push(request); - self.nullifier_key = Option::some(keys); - keys - } else { - let keys = self.nullifier_key.unwrap_unchecked(); - // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached. - // This will be fixed in my next PR in the stack - // assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1); - assert(keys.account == account, "Cannot query nullifier key for more than one account per call"); - keys - }; - keys.app_nullifier_secret_key - } - - // TODO(#5630) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address - pub fn request_nsk_app_with_npk_m_hash(&mut self, npk_m_hash: Field) -> Field { + pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field { // A value of empty nullifier keys will fail the key validation request. let previous_nullifier_key = self.nullifier_key.unwrap_or(NullifierKeys::empty()); let keys = if poseidon2_hash(previous_nullifier_key.master_nullifier_public_key.serialize()) == npk_m_hash { previous_nullifier_key } else { - let keys = get_nullifier_keys_with_npk_m_hash(npk_m_hash); + let keys = get_nullifier_keys(npk_m_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: keys.master_nullifier_public_key, app_nullifier_secret_key: keys.app_nullifier_secret_key diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr index 6f3d2a06664..a93a3dab46b 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr @@ -67,7 +67,7 @@ mod test { use crate::{ note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key}, + oracle::unsafe_rand::unsafe_rand, context::PrivateContext, hash::poseidon2_hash }; diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index 1a67b9609ab..0c9a79b0326 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -4,7 +4,7 @@ use dep::protocol_types::{ }; use crate::{ context::PrivateContext, - oracle::keys::{get_public_keys_and_partial_address, get_public_keys_and_partial_address_with_npk_m_hash}, + oracle::{keys::get_public_keys_and_partial_address, nullifier_key::{NullifierKeys, get_nullifier_keys as get_nullifier_keys_oracle}}, keys::public_keys::{PublicKeys, NULLIFIER_INDEX, INCOMING_INDEX}, state_vars::{ map::derive_storage_slot_in_map, @@ -88,3 +88,16 @@ fn fetch_and_constrain_keys(address: AztecAddress) -> PublicKeys { public_keys } + +// We get the full struct Nullifier Keys here +pub fn get_nullifier_keys(npk_m_hash: Field) -> NullifierKeys { + let nullifier_keys = get_nullifier_keys_oracle(npk_m_hash); + assert_eq(poseidon2_hash(nullifier_keys.master_nullifier_public_key.serialize()), npk_m_hash); + + nullifier_keys +} + +// We are only getting the app_nullifier_secret_key here +pub fn get_nsk_app(npk_m_hash: Field) -> Field { + get_nullifier_keys(npk_m_hash).app_nullifier_secret_key +} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 451d9bbff63..c3c191b6ba5 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -22,25 +22,3 @@ fn get_public_keys_and_partial_address(address: AztecAddress) -> (PublicKeys, Pa (keys, partial_address) } - -#[oracle(getPublicKeysAndPartialAddressWithNpkMHash)] -fn get_public_keys_and_partial_address_with_npk_m_hash_oracle(_npk_m_hash: Field) -> [Field; 9] {} - -unconstrained fn get_public_keys_and_partial_address_with_npk_m_hash_oracle_wrapper(npk_m_hash: Field) -> [Field; 9] { - get_public_keys_and_partial_address_with_npk_m_hash_oracle(npk_m_hash) -} - -fn get_public_keys_and_partial_address_with_npk_m_hash(npk_m_hash: Field) -> (PublicKeys, PartialAddress) { - let result = get_public_keys_and_partial_address_with_npk_m_hash_oracle_wrapper(npk_m_hash); - - let keys = PublicKeys { - npk_m: GrumpkinPoint::new(result[0], result[1]), - ivpk_m: GrumpkinPoint::new(result[2], result[3]), - ovpk_m: GrumpkinPoint::new(result[4], result[5]), - tpk_m: GrumpkinPoint::new(result[6], result[7]) - }; - - let partial_address = PartialAddress::from_field(result[8]); - - (keys, partial_address) -} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index ecaa5e2dc85..bf5b6fdf47d 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -5,61 +5,32 @@ use dep::protocol_types::{ // Nullifier keys pertaining to a specific account struct NullifierKeys { - // TODO(#5630): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address - account: AztecAddress, master_nullifier_public_key: GrumpkinPoint, app_nullifier_secret_key: Field, } -#[oracle(getNullifierKeys)] -fn get_nullifier_keys_oracle(_account: AztecAddress) -> [Field; 3] {} - -unconstrained fn get_nullifier_keys_internal(account: AztecAddress) -> NullifierKeys { - let result = get_nullifier_keys_oracle(account); - NullifierKeys { - account, - master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, - app_nullifier_secret_key: result[2] - } -} - impl Empty for NullifierKeys { fn empty() -> Self { NullifierKeys { - account: AztecAddress::zero(), master_nullifier_public_key: GrumpkinPoint::zero(), app_nullifier_secret_key: 0 } } } -pub fn get_nullifier_keys(account: AztecAddress) -> NullifierKeys { - get_nullifier_keys_internal(account) -} - -pub fn get_app_nullifier_secret_key(account: AztecAddress) -> Field { - get_nullifier_keys_internal(account).app_nullifier_secret_key -} - // TODO(#5630): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address -#[oracle(getNullifierKeysWithNpkMHash)] -fn get_nullifier_keys_with_npk_m_hash_oracle(_npk_m_hash: Field) -> [Field; 3] {} +#[oracle(getNullifierKeys)] +fn get_nullifier_keys_oracle(_npk_m_hash: Field) -> [Field; 3] {} -unconstrained fn get_nullifier_keys_with_npk_m_hash_internal(npk_m_hash: Field) -> NullifierKeys { - let result = get_nullifier_keys_with_npk_m_hash_oracle(npk_m_hash); +unconstrained fn get_nullifier_keys_internal(npk_m_hash: Field) -> NullifierKeys { + let result = get_nullifier_keys_oracle(npk_m_hash); NullifierKeys { - account: AztecAddress::zero(), master_nullifier_public_key: GrumpkinPoint { x: result[0], y: result[1] }, app_nullifier_secret_key: result[2] } } // We get the full struct Nullifier Keys here -pub fn get_nullifier_keys_with_npk_m_hash(npk_m_hash: Field) -> NullifierKeys { - get_nullifier_keys_with_npk_m_hash_internal(npk_m_hash) -} - -// We are only getting the app_nullifier_secret_key here -pub fn get_nsk_app_with_npk_m_hash(npk_m_hash: Field) -> Field { - get_nullifier_keys_with_npk_m_hash_internal(npk_m_hash).app_nullifier_secret_key +pub fn get_nullifier_keys(npk_m_hash: Field) -> NullifierKeys { + get_nullifier_keys_internal(npk_m_hash) } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr index 7990ce4c74d..317b222be7b 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr @@ -49,7 +49,7 @@ impl PrivateImmutable { // docs:end:is_initialized // docs:start:initialize - pub fn initialize(self, note: &mut Note, broadcast: bool) where Note: NoteInterface { + pub fn initialize(self, note: &mut Note, broadcast: bool, ivpk_m: GrumpkinPoint) where Note: NoteInterface { let context = self.context.unwrap(); // Nullify the storage slot. @@ -61,7 +61,7 @@ impl PrivateImmutable { self.storage_slot, note, broadcast, - GrumpkinPoint::zero() + ivpk_m, ); } // docs:end:initialize diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index 1a46c8fd278..1a4538a5a42 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -51,7 +51,7 @@ impl PrivateMutable { // docs:end:is_initialized // docs:start:initialize - pub fn initialize(self, note: &mut Note, broadcast: bool) where Note: NoteInterface { + pub fn initialize(self, note: &mut Note, broadcast: bool, ivpk_m: GrumpkinPoint) where Note: NoteInterface { let context = self.context.unwrap(); // Nullify the storage slot. @@ -63,13 +63,13 @@ impl PrivateMutable { self.storage_slot, note, broadcast, - GrumpkinPoint::zero() + ivpk_m, ); } // docs:end:initialize // docs:start:replace - pub fn replace(self, new_note: &mut Note, broadcast: bool) where Note: NoteInterface { + pub fn replace(self, new_note: &mut Note, broadcast: bool, ivpk_m: GrumpkinPoint) where Note: NoteInterface { let context = self.context.unwrap(); let prev_note: Note = get_note(context, self.storage_slot); @@ -82,13 +82,13 @@ impl PrivateMutable { self.storage_slot, new_note, broadcast, - GrumpkinPoint::zero() + ivpk_m, ); } // docs:end:replace // docs:start:get_note - pub fn get_note(self, broadcast: bool) -> Note where Note: NoteInterface { + pub fn get_note(self, broadcast: bool, ivpk_m: GrumpkinPoint) -> Note where Note: NoteInterface { let context = self.context.unwrap(); let mut note = get_note(context, self.storage_slot); @@ -102,7 +102,7 @@ impl PrivateMutable { self.storage_slot, &mut note, broadcast, - GrumpkinPoint::zero() + ivpk_m, ); note diff --git a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr index 134707cafaa..84d8c637fd4 100644 --- a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr +++ b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr @@ -1,6 +1,6 @@ use dep::aztec::{ protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}, context::Context, - note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet + note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet, keys::getters::{get_npk_m_hash, get_ivpk_m} }; use dep::value_note::{filter::filter_notes_min_sum, value_note::ValueNote}; @@ -22,12 +22,14 @@ impl EasyPrivateUint { pub fn add(self, addend: u64, owner: AztecAddress) { assert(self.context.public.is_none(), "EasyPrivateUint::add can be called from private only."); + let owner_npk_m_hash = get_npk_m_hash(self.context.private.unwrap(), owner); + let owner_ivpk_m = get_ivpk_m(self.context.private.unwrap(), owner); // Creates new note for the owner. - let mut addend_note = ValueNote::new(addend as Field, owner); + let mut addend_note = ValueNote::new(addend as Field, owner_npk_m_hash); // Insert the new note to the owner's set of notes. // docs:start:insert - self.set.insert(&mut addend_note, true, GrumpkinPoint::zero()); + self.set.insert(&mut addend_note, true, owner_ivpk_m); // docs:end:insert } @@ -35,6 +37,9 @@ impl EasyPrivateUint { pub fn sub(self, subtrahend: u64, owner: AztecAddress) { assert(self.context.public.is_none(), "EasyPrivateUint::sub can be called from private only."); + let owner_npk_m_hash = get_npk_m_hash(self.context.private.unwrap(), owner); + let owner_ivpk_m = get_ivpk_m(self.context.private.unwrap(), owner); + // docs:start:get_notes let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend as Field); let maybe_notes = self.set.get_notes(options); @@ -47,7 +52,7 @@ impl EasyPrivateUint { // Ensure the notes are actually owned by the owner (to prevent user from generating a valid proof while // spending someone else's notes). - assert(note.owner.eq(owner)); + assert(note.npk_m_hash.eq(owner_npk_m_hash)); // Removes the note from the owner's set of notes. // docs:start:remove @@ -62,7 +67,7 @@ impl EasyPrivateUint { // Creates change note for the owner. let result_value = minuend - subtrahend; - let mut result_note = ValueNote::new(result_value as Field, owner); - self.set.insert(&mut result_note, result_value != 0, GrumpkinPoint::zero()); + let mut result_note = ValueNote::new(result_value as Field, owner_npk_m_hash); + self.set.insert(&mut result_note, result_value != 0, owner_ivpk_m); } } diff --git a/noir-projects/aztec-nr/value-note/src/utils.nr b/noir-projects/aztec-nr/value-note/src/utils.nr index 618467f5fc7..3186094a875 100644 --- a/noir-projects/aztec-nr/value-note/src/utils.nr +++ b/noir-projects/aztec-nr/value-note/src/utils.nr @@ -1,6 +1,7 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, PrivateSet, NoteGetterOptions}; use dep::aztec::note::note_getter_options::SortOrder; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; +use dep::aztec::keys::getters::{get_npk_m_hash, get_ivpk_m}; use crate::{filter::filter_notes_min_sum, value_note::{ValueNote, VALUE_NOTE_LEN}}; // Sort the note values (0th field) in descending order. @@ -11,18 +12,21 @@ pub fn create_note_getter_options_for_decreasing_balance(amount: Field) -> NoteG // Creates a new note for the recipient. // Inserts it to the recipient's set of notes. -pub fn increment(balance: PrivateSet, amount: Field, recipient: AztecAddress) { - let mut note = ValueNote::new(amount, recipient); +pub fn increment(mut context: PrivateContext, balance: PrivateSet, amount: Field, recipient: AztecAddress) { + let recipient_npk_m_hash = get_npk_m_hash(&mut context, recipient); + let recipient_ivpk_m = get_ivpk_m(&mut context, recipient); + + let mut note = ValueNote::new(amount, recipient_npk_m_hash); // Insert the new note to the owner's set of notes and emit the log if value is non-zero. - balance.insert(&mut note, amount != 0, GrumpkinPoint::zero()); + balance.insert(&mut note, amount != 0, recipient_ivpk_m); } // Find some of the `owner`'s notes whose values add up to the `amount`. // Remove those notes. // If the value of the removed notes exceeds the requested `amount`, create a new note containing the excess value, so that exactly `amount` is removed. // Fail if the sum of the selected notes is less than the amount. -pub fn decrement(balance: PrivateSet, amount: Field, owner: AztecAddress) { - let sum = decrement_by_at_most(balance, amount, owner); +pub fn decrement(mut context: PrivateContext, balance: PrivateSet, amount: Field, owner: AztecAddress) { + let sum = decrement_by_at_most(context, balance, amount, owner); assert(sum == amount, "Balance too low"); } @@ -35,6 +39,7 @@ pub fn decrement(balance: PrivateSet, amount: Field, owner: AztecAddr // // It returns the decremented amount, which should be less than or equal to max_amount. pub fn decrement_by_at_most( + mut context: PrivateContext, balance: PrivateSet, max_amount: Field, owner: AztecAddress @@ -45,7 +50,7 @@ pub fn decrement_by_at_most( let mut decremented = 0; for i in 0..opt_notes.len() { if opt_notes[i].is_some() { - decremented += destroy_note(balance, owner, opt_notes[i].unwrap_unchecked()); + decremented += destroy_note(context, balance, owner, opt_notes[i].unwrap_unchecked()); } } @@ -55,17 +60,19 @@ pub fn decrement_by_at_most( change_value = decremented - max_amount; decremented -= change_value; } - increment(balance, change_value, owner); + increment(context, balance, change_value, owner); decremented } // Removes the note from the owner's set of notes. // Returns the value of the destroyed note. -pub fn destroy_note(balance: PrivateSet, owner: AztecAddress, note: ValueNote) -> Field { +pub fn destroy_note(mut context: PrivateContext, balance: PrivateSet, owner: AztecAddress, note: ValueNote) -> Field { // Ensure the note is actually owned by the owner (to prevent user from generating a valid proof while // spending someone else's notes). - assert(note.owner.eq(owner)); + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + + assert(note.npk_m_hash.eq(owner_npk_m_hash)); balance.remove(note); diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 23cf026766a..73e29c159e3 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -5,7 +5,7 @@ use dep::aztec::{ constants::GENERATOR_INDEX__NOTE_NULLIFIER }, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key}, + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, hash::poseidon2_hash, context::PrivateContext }; @@ -15,7 +15,8 @@ global VALUE_NOTE_LEN: Field = 3; // 3 plus a header. #[aztec(note)] struct ValueNote { value: Field, - owner: AztecAddress, + // The nullifying public key hash is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + npk_m_hash: Field, randomness: Field, } // docs:end:value-note-def @@ -25,7 +26,7 @@ impl NoteInterface for ValueNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -37,7 +38,7 @@ impl NoteInterface for ValueNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -46,8 +47,7 @@ impl NoteInterface for ValueNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { - let ivpk_m = get_ivpk_m(context, self.owner); + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { context.emit_encrypted_log( (*context).this_address(), slot, @@ -59,10 +59,10 @@ impl NoteInterface for ValueNote { } impl ValueNote { - pub fn new(value: Field, owner: AztecAddress) -> Self { + pub fn new(value: Field, npk_m_hash: Field) -> Self { let randomness = unsafe_rand(); let header = NoteHeader::empty(); - ValueNote { value, owner, randomness, header } + ValueNote { value, npk_m_hash, randomness, header } } } @@ -70,6 +70,6 @@ impl Serialize<7> for ValueNote { fn serialize(self) -> [Field; 7] { let header = self.header.serialize(); - [self.value, self.owner.to_field(), self.randomness, header[0], header[1], header[2], header[3]] + [self.value, self.npk_m_hash, self.randomness, header[0], header[1], header[2], header[3]] } } diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index 03cd9da4ba7..4abdf53d038 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -9,7 +9,7 @@ contract AppSubscription { AztecAddress, FunctionSelector, PrivateContext, NoteHeader, Map, PrivateMutable, PublicMutable, SharedImmutable }, - protocol_types::traits::is_empty + protocol_types::traits::is_empty, keys::getters::{get_npk_m_hash, get_ivpk_m}, }, authwit::{account::AccountActions, auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit}, gas_token::GasToken, token::Token @@ -36,12 +36,13 @@ contract AppSubscription { fn entrypoint(payload: DAppPayload, user_address: AztecAddress) { assert(context.msg_sender().to_field() == 0); assert_current_call_valid_authwit(&mut context, user_address); + let subscriber_ivpk_m = get_ivpk_m(&mut context, user_address); - let mut note = storage.subscriptions.at(user_address).get_note(false); + let mut note = storage.subscriptions.at(user_address).get_note(false, subscriber_ivpk_m); assert(note.remaining_txs as u64 > 0, "you're out of txs"); note.remaining_txs -= 1; - storage.subscriptions.at(user_address).replace(&mut note, true); + storage.subscriptions.at(user_address).replace(&mut note, true, subscriber_ivpk_m); let gas_limit = storage.gas_token_limit_per_tx.read_private(); context.set_public_teardown_function( @@ -108,12 +109,14 @@ contract AppSubscription { // Assert that the given expiry_block_number < current_block_number + SUBSCRIPTION_DURATION_IN_BLOCKS. AppSubscription::at(context.this_address()).assert_block_number(expiry_block_number).static_enqueue(&mut context); + let subscriber_npk_m_hash = get_npk_m_hash(&mut context, subscriber_address); + let subscriber_ivpk_m = get_ivpk_m(&mut context, subscriber_address); - let mut subscription_note = SubscriptionNote::new(subscriber_address, expiry_block_number, tx_count); + let mut subscription_note = SubscriptionNote::new(subscriber_npk_m_hash, expiry_block_number, tx_count); if (!is_initialized(subscriber_address)) { - storage.subscriptions.at(subscriber_address).initialize(&mut subscription_note, true); + storage.subscriptions.at(subscriber_address).initialize(&mut subscription_note, true, subscriber_ivpk_m); } else { - storage.subscriptions.at(subscriber_address).replace(&mut subscription_note, true) + storage.subscriptions.at(subscriber_address).replace(&mut subscription_note, true, subscriber_ivpk_m) } } diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index 79aa05dcfd4..6675f56f95f 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -2,8 +2,7 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, NoteHeader, NoteInterfac use dep::aztec::{ keys::getters::get_ivpk_m, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, - note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::{nullifier_key::get_app_nullifier_secret_key} + note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, keys::getters::get_nsk_app, }; global SUBSCRIPTION_NOTE_LEN: Field = 3; @@ -12,7 +11,8 @@ global SUBSCRIPTION_NOTE_LEN: Field = 3; // TODO: Do we need to include a nonce, in case we want to read/nullify/recreate with the same pubkey value? #[aztec(note)] struct SubscriptionNote { - owner: AztecAddress, + // The nullifying public key hash is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + npk_m_hash: Field, expiry_block_number: Field, remaining_txs: Field, } @@ -20,7 +20,7 @@ struct SubscriptionNote { impl NoteInterface for SubscriptionNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -30,7 +30,7 @@ impl NoteInterface for SubscriptionNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -39,8 +39,7 @@ impl NoteInterface for SubscriptionNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { - let ivpk_m = get_ivpk_m(context, self.owner); + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { context.emit_encrypted_log( (*context).this_address(), slot, @@ -52,7 +51,7 @@ impl NoteInterface for SubscriptionNote { } impl SubscriptionNote { - pub fn new(owner: AztecAddress, expiry_block_number: Field, remaining_txs: Field) -> Self { - SubscriptionNote { owner, expiry_block_number, remaining_txs, header: NoteHeader::empty() } + pub fn new(npk_m_hash: Field, expiry_block_number: Field, remaining_txs: Field) -> Self { + SubscriptionNote { npk_m_hash, expiry_block_number, remaining_txs, header: NoteHeader::empty() } } } 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 a8b9f34d36b..1a81cef4ff6 100644 --- a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr @@ -18,7 +18,7 @@ contract Benchmarking { // Creates a new value note for the target owner. Use this method to seed an initial set of notes. #[aztec(private)] fn create_note(owner: AztecAddress, value: Field) { - increment(storage.notes.at(owner), value, owner); + increment(context, storage.notes.at(owner), value, owner); } // Deletes a note at a specific index in the set and creates a new one with the same value. @@ -33,7 +33,7 @@ contract Benchmarking { let notes = owner_notes.get_notes(getter_options.set_limit(1).set_offset(index)); let note = notes[0].unwrap_unchecked(); owner_notes.remove(note); - increment(owner_notes, note.value, owner); + increment(context, owner_notes, note.value, owner); } // Reads and writes to public storage and enqueues a call to another public function. 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 8f74a60118b..e45a53bd36b 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 @@ -3,8 +3,9 @@ use dep::aztec::prelude::{AztecAddress, FunctionSelector, PrivateContext, NoteHe use dep::aztec::{ protocol_types::{ traits::{ToField, Serialize, FromField}, grumpkin_point::GrumpkinPoint, - constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL + constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, }, + keys::getters::{get_npk_m_hash, get_ivpk_m}, context::{PublicContext, Context}, note::note_getter::view_notes, state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE }; @@ -52,13 +53,13 @@ struct CardNote { } impl CardNote { - fn new(strength: u32, points: u32, owner: AztecAddress) -> Self { + fn new(strength: u32, points: u32, npk_m_hash: Field) -> Self { let card = Card { strength, points }; - CardNote::from_card(card, owner) + CardNote::from_card(card, npk_m_hash) } - pub fn from_card(card: Card, owner: AztecAddress) -> CardNote { - CardNote { card, note: ValueNote::new(card.to_field(), owner) } + pub fn from_card(card: Card, npk_m_hash: Field) -> CardNote { + CardNote { card, note: ValueNote::new(card.to_field(), npk_m_hash) } } pub fn from_note(note: ValueNote) -> CardNote { @@ -105,10 +106,13 @@ impl Deck { pub fn add_cards(&mut self, cards: [Card; N], owner: AztecAddress) -> [CardNote] { let _context = self.set.context.private.unwrap(); + let owner_npk_m_hash = get_npk_m_hash(self.set.context.private.unwrap(), owner); + let owner_ivpk_m = get_ivpk_m(self.set.context.private.unwrap(), owner); + let mut inserted_cards = &[]; for card in cards { - let mut card_note = CardNote::from_card(card, owner); - self.set.insert(&mut card_note.note, true, GrumpkinPoint::zero()); + let mut card_note = CardNote::from_card(card, owner_npk_m_hash); + self.set.insert(&mut card_note.note, true, owner_ivpk_m); inserted_cards = inserted_cards.push_back(card_note); } @@ -116,6 +120,8 @@ impl Deck { } pub fn get_cards(&mut self, cards: [Card; N], owner: AztecAddress) -> [CardNote; N] { + let owner_npk_m_hash = get_npk_m_hash(self.set.context.private.unwrap(), owner); + let options = NoteGetterOptions::with_filter(filter_cards, cards); let maybe_notes = self.set.get_notes(options); let mut found_cards = [Option::none(); N]; @@ -124,7 +130,7 @@ impl Deck { let card_note = CardNote::from_note(maybe_notes[i].unwrap_unchecked()); // Ensure the notes are actually owned by the owner (to prevent user from generating a valid proof while // spending someone else's notes). - assert(card_note.note.owner.eq(owner)); + assert(card_note.note.npk_m_hash.eq(owner_npk_m_hash)); for j in 0..cards.len() { if found_cards[j].is_none() @@ -171,8 +177,10 @@ pub fn get_pack_cards( owner: AztecAddress, context: &mut PrivateContext ) -> [Card; PACK_CARDS] { + let owner_npk_m_hash = get_npk_m_hash(context, owner); + // generate pseudo randomness deterministically from 'seed' and user secret - let secret = context.request_app_nullifier_secret_key(owner); + let secret = context.request_nsk_app(owner_npk_m_hash); let mix = secret + seed; let mix_bytes: [u8; 32] = mix.to_le_bytes(32).as_array(); let random_bytes = std::hash::sha256(mix_bytes); 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 b952f604edb..4249bfc382f 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -5,7 +5,8 @@ contract Child { use dep::aztec::{ context::{PublicContext, Context, gas::GasOpts}, protocol_types::{abis::call_context::CallContext, grumpkin_point::GrumpkinPoint}, - note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader} + note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, + keys::getters::{get_npk_m_hash, get_ivpk_m}, }; use dep::value_note::value_note::ValueNote; @@ -51,17 +52,22 @@ contract Child { #[aztec(private)] fn private_set_value(new_value: Field, owner: AztecAddress) -> Field { - let mut note = ValueNote::new(new_value, owner); - storage.a_private_value.insert(&mut note, true, GrumpkinPoint::zero()); + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let owner_ivpk_m = get_ivpk_m(&mut context, owner); + + let mut note = ValueNote::new(new_value, owner_npk_m_hash); + storage.a_private_value.insert(&mut note, true, owner_ivpk_m); new_value } #[aztec(private)] fn private_get_value(amount: Field, owner: AztecAddress) -> Field { + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let mut options = NoteGetterOptions::new(); options = options.select(ValueNote::properties().value, amount, Option::none()).select( - ValueNote::properties().owner, - owner.to_field(), + ValueNote::properties().npk_m_hash, + owner_npk_m_hash, Option::none() ).set_limit(1); let notes = storage.a_private_value.get_notes(options); diff --git a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr index 090ea87a0a0..f04e1b8fe53 100644 --- a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr @@ -2,7 +2,7 @@ contract Claim { use dep::aztec::{ history::note_inclusion::prove_note_inclusion, protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}, - state_vars::SharedImmutable + state_vars::SharedImmutable, keys::getters::get_npk_m_hash }; use dep::value_note::value_note::ValueNote; use dep::token::Token; @@ -29,7 +29,9 @@ contract Claim { assert( target_address == proof_note.header.contract_address, "Note does not correspond to the target contract" ); - assert_eq(proof_note.owner, context.msg_sender(), "Note does not belong to the sender"); + + let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + assert_eq(proof_note.npk_m_hash, msg_sender_npk_m_hash, "Note does not belong to the sender"); // 2) Prove that the note hash exists in the note hash tree prove_note_inclusion(proof_note, context); diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 7cfc6ea0fd7..06b956b73f8 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -8,7 +8,7 @@ contract Crowdfunding { abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize, grumpkin_point::GrumpkinPoint }, - state_vars::{PrivateSet, PublicImmutable, SharedImmutable} + state_vars::{PrivateSet, PublicImmutable, SharedImmutable}, keys::getters::{get_npk_m_hash, get_ivpk_m} }; use dep::value_note::value_note::ValueNote; use dep::token::Token; @@ -86,8 +86,10 @@ contract Crowdfunding { // 3) Create a value note for the donor so that he can later on claim a rewards token in the Claim // contract by proving that the hash of this note exists in the note hash tree. - let mut note = ValueNote::new(amount as Field, context.msg_sender()); - storage.donation_receipts.insert(&mut note, true, GrumpkinPoint::zero()); + let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + let msg_sender_ivpk_m = get_ivpk_m(&mut context, context.msg_sender()); + let mut note = ValueNote::new(amount as Field, msg_sender_npk_m_hash); + storage.donation_receipts.insert(&mut note, true, msg_sender_ivpk_m); } // docs:end:donate diff --git a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr index 1f5f5e37807..506c1b97bc3 100644 --- a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr @@ -4,7 +4,7 @@ contract DelegatedOn { AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PublicMutable, PrivateSet, PrivateContext }; - use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; + use dep::aztec::{protocol_types::grumpkin_point::GrumpkinPoint, keys::getters::{get_npk_m_hash, get_ivpk_m}}; use dep::value_note::value_note::ValueNote; #[aztec(storage)] @@ -15,8 +15,11 @@ contract DelegatedOn { #[aztec(private)] fn private_set_value(new_value: Field, owner: AztecAddress) -> Field { - let mut note = ValueNote::new(new_value, owner); - storage.a_private_value.insert(&mut note, true, GrumpkinPoint::zero()); + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let owner_ivpk_m = get_ivpk_m(&mut context, owner); + + let mut note = ValueNote::new(new_value, owner_npk_m_hash); + storage.a_private_value.insert(&mut note, true, owner_ivpk_m); new_value } @@ -26,14 +29,17 @@ contract DelegatedOn { new_value } - unconstrained fn view_private_value(amount: Field, owner: AztecAddress) -> pub Field { - let mut options = NoteViewerOptions::new(); + #[aztec(private)] + fn get_private_value(amount: Field, owner: AztecAddress) -> pub Field { + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + + let mut options = NoteGetterOptions::new(); options = options.select(ValueNote::properties().value, amount, Option::none()).select( - ValueNote::properties().owner, - owner.to_field(), + ValueNote::properties().npk_m_hash, + owner_npk_m_hash, Option::none() ).set_limit(1); - let notes = storage.a_private_value.view_notes(options); + let notes = storage.a_private_value.get_notes(options); notes[0].unwrap_unchecked().value } diff --git a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr index b7f7592350a..65d2c64890e 100644 --- a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr @@ -1,6 +1,7 @@ // A contract used along with `Parent` contract to test nested calls. contract Delegator { - use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteViewerOptions, PublicMutable, PrivateSet, Deserialize}; + use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PublicMutable, PrivateSet, Deserialize}; + use dep::aztec::keys::getters::get_npk_m_hash; use dep::value_note::value_note::ValueNote; use dep::delegated_on::DelegatedOn; @@ -30,14 +31,17 @@ contract Delegator { DelegatedOn::at(target_contract).public_set_value(value).delegate_call(&mut context) } - unconstrained fn view_private_value(amount: Field, owner: AztecAddress) -> pub Field { - let mut options = NoteViewerOptions::new(); + #[aztec(private)] + fn get_private_value(amount: Field, owner: AztecAddress) -> pub Field { + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + + let mut options = NoteGetterOptions::new(); options = options.select(ValueNote::properties().value, amount, Option::none()).select( - ValueNote::properties().owner, - owner.to_field(), + ValueNote::properties().npk_m_hash, + owner_npk_m_hash, Option::none() ).set_limit(1); - let notes = storage.a_private_value.view_notes(options); + let notes = storage.a_private_value.get_notes(options); notes[0].unwrap_unchecked().value } 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 db3e77992e9..3015678f3f1 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 @@ -18,7 +18,7 @@ contract DocsExample { PrivateContext, Map, PublicMutable, PublicImmutable, PrivateMutable, PrivateImmutable, PrivateSet, SharedImmutable, Deserialize }; - use dep::aztec::{note::note_getter_options::Comparator, context::{PublicContext, Context}}; + use dep::aztec::{note::note_getter_options::Comparator, context::{PublicContext, Context}, keys::getters::{get_npk_m_hash, get_ivpk_m}}; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; // how to import methods from other files/folders within your workspace use crate::options::create_account_card_getter_options; @@ -167,31 +167,43 @@ contract DocsExample { // docs:start:initialize-private-mutable #[aztec(private)] fn initialize_private_immutable(randomness: Field, points: u8) { - let mut new_card = CardNote::new(points, randomness, context.msg_sender()); - storage.private_immutable.initialize(&mut new_card, true); + let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + let msg_sender_ivpk_m = get_ivpk_m(&mut context, context.msg_sender()); + + let mut new_card = CardNote::new(points, randomness, msg_sender_npk_m_hash); + storage.private_immutable.initialize(&mut new_card, true, msg_sender_ivpk_m); } // docs:end:initialize-private-mutable #[aztec(private)] // msg_sender() is 0 at deploy time. So created another function fn initialize_private(randomness: Field, points: u8) { - let mut legendary_card = CardNote::new(points, randomness, context.msg_sender()); + let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + let msg_sender_ivpk_m = get_ivpk_m(&mut context, context.msg_sender()); + + let mut legendary_card = CardNote::new(points, randomness, msg_sender_npk_m_hash); // create and broadcast note - storage.legendary_card.initialize(&mut legendary_card, true); + storage.legendary_card.initialize(&mut legendary_card, true, msg_sender_ivpk_m); } #[aztec(private)] fn insert_notes(amounts: [u8; 3]) { + let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + let msg_sender_ivpk_m = get_ivpk_m(&mut context, context.msg_sender()); + for i in 0..amounts.len() { - let mut note = CardNote::new(amounts[i], 1, context.msg_sender()); - storage.set.insert(&mut note, true, GrumpkinPoint::zero()); + let mut note = CardNote::new(amounts[i], 1, msg_sender_npk_m_hash); + storage.set.insert(&mut note, true, msg_sender_ivpk_m); } } #[aztec(private)] fn insert_note(amount: u8, randomness: Field) { - let mut note = CardNote::new(amount, randomness, context.msg_sender()); - storage.set.insert(&mut note, true, GrumpkinPoint::zero()); + let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + let msg_sender_ivpk_m = get_ivpk_m(&mut context, context.msg_sender()); + + let mut note = CardNote::new(amount, randomness, msg_sender_npk_m_hash); + storage.set.insert(&mut note, true, msg_sender_ivpk_m); } // docs:start:state_vars-NoteGetterOptionsComparatorExampleNoir @@ -211,8 +223,11 @@ contract DocsExample { #[aztec(private)] fn update_legendary_card(randomness: Field, points: u8) { - let mut new_card = CardNote::new(points, randomness, context.msg_sender()); - storage.legendary_card.replace(&mut new_card, true); + let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + let msg_sender_ivpk_m = get_ivpk_m(&mut context, context.msg_sender()); + + let mut new_card = CardNote::new(points, randomness, msg_sender_npk_m_hash); + storage.legendary_card.replace(&mut new_card, true, msg_sender_ivpk_m); DocsExample::at(context.this_address()).update_leader(context.msg_sender(), points).enqueue(&mut context); } @@ -222,14 +237,17 @@ contract DocsExample { // Also serves as a e2e test that you can `get_note()` and then `replace()` // docs:start:state_vars-PrivateMutableGet - let card = storage.legendary_card.get_note(false); + let card = storage.legendary_card.get_note(false, GrumpkinPoint::zero()); // docs:end:state_vars-PrivateMutableGet let points = card.points + 1; - let mut new_card = CardNote::new(points, card.randomness, context.msg_sender()); + let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + let msg_sender_ivpk_m = get_ivpk_m(&mut context, context.msg_sender()); + + let mut new_card = CardNote::new(points, card.randomness, msg_sender_npk_m_hash); // docs:start:state_vars-PrivateMutableReplace - storage.legendary_card.replace(&mut new_card, true); + storage.legendary_card.replace(&mut new_card, true, msg_sender_ivpk_m); // docs:end:state_vars-PrivateMutableReplace DocsExample::at(context.this_address()).update_leader(context.msg_sender(), points).enqueue(&mut context); diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr index 7421112c715..6461b21b74e 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr @@ -8,13 +8,13 @@ use dep::aztec::note::note_getter_options::{Sort, SortOrder}; // docs:start:state_vars-NoteGetterOptionsSelectSortOffset pub fn create_account_card_getter_options( - account: AztecAddress, + account_npk_m_hash: Field, offset: u32 ) -> NoteGetterOptions { let mut options = NoteGetterOptions::new(); options.select( - CardNote::properties().owner, - account.to_field(), + CardNote::properties().npk_m_hash, + account_npk_m_hash, Option::none() ).sort(CardNote::properties().points, SortOrder.DESC).set_offset(offset) } @@ -24,12 +24,12 @@ pub fn create_account_card_getter_options( pub fn create_exact_card_getter_options( points: u8, secret: Field, - account: AztecAddress + account_npk_m_hash: Field, ) -> NoteGetterOptions { let mut options = NoteGetterOptions::new(); options.select(CardNote::properties().points, points as Field, Option::none()).select(CardNote::properties().randomness, secret, Option::none()).select( - CardNote::properties().owner, - account.to_field(), + CardNote::properties().npk_m_hash, + account_npk_m_hash, Option::none() ) } @@ -53,21 +53,25 @@ pub fn filter_min_points( // docs:end:state_vars-OptionFilter // docs:start:state_vars-NoteGetterOptionsFilter -pub fn create_account_cards_with_min_points_getter_options(account: AztecAddress, min_points: u8) -> NoteGetterOptions { +pub fn create_account_cards_with_min_points_getter_options( + account_npk_m_hash: Field, min_points: u8 +) -> NoteGetterOptions { NoteGetterOptions::with_filter(filter_min_points, min_points).select( - CardNote::properties().owner, - account.to_field(), - Option::none() + CardNote::properties().npk_m_hash, + account_npk_m_hash, + Option::none(), ).sort(CardNote::properties().points, SortOrder.ASC) } // docs:end:state_vars-NoteGetterOptionsFilter // docs:start:state_vars-NoteGetterOptionsPickOne -pub fn create_largest_account_card_getter_options(account: AztecAddress) -> NoteGetterOptions { +pub fn create_largest_account_card_getter_options( + account_npk_m_hash: Field, +) -> NoteGetterOptions { let mut options = NoteGetterOptions::new(); options.select( - CardNote::properties().owner, - account.to_field(), + CardNote::properties().npk_m_hash, + account_npk_m_hash, Option::none() ).sort(CardNote::properties().points, SortOrder.DESC).set_limit(1) } diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index 98be0c72f0c..025b32b747f 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -1,7 +1,7 @@ use dep::aztec::prelude::{AztecAddress, NoteInterface, NoteHeader, PrivateContext}; use dep::aztec::{ keys::getters::get_ivpk_m, note::{utils::compute_note_hash_for_consumption}, - oracle::nullifier_key::get_app_nullifier_secret_key, hash::poseidon2_hash, + keys::getters::get_nsk_app, hash::poseidon2_hash, protocol_types::{traits::Empty, grumpkin_point::GrumpkinPoint, constants::GENERATOR_INDEX__NOTE_NULLIFIER} }; @@ -14,20 +14,21 @@ global CARD_NOTE_LEN: Field = 3; struct CardNote { points: u8, randomness: Field, - owner: AztecAddress, + // The nullifying public key hash is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + npk_m_hash: Field, } // docs:end:state_vars-CardNote impl CardNote { - pub fn new(points: u8, randomness: Field, owner: AztecAddress) -> Self { - CardNote { points, randomness, owner, header: NoteHeader::empty() } + pub fn new(points: u8, randomness: Field, npk_m_hash: Field) -> Self { + CardNote { points, randomness, npk_m_hash, header: NoteHeader::empty() } } } impl NoteInterface for CardNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -37,7 +38,7 @@ impl NoteInterface for CardNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -46,8 +47,7 @@ impl NoteInterface for CardNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { - let ivpk_m = get_ivpk_m(context, self.owner); + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { context.emit_encrypted_log( (*context).this_address(), slot, 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 6924ca2b328..48261564783 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 @@ -4,7 +4,7 @@ contract EasyPrivateVoting { AztecAddress, FunctionSelector, NoteHeader, NoteInterface, NoteGetterOptions, PrivateContext, Map, PublicMutable }; - use dep::aztec::context::Context; + use dep::aztec::{context::Context, keys::getters::get_npk_m_hash}; // docs:end:imports // docs:start:storage_struct #[aztec(storage)] @@ -27,7 +27,8 @@ contract EasyPrivateVoting { // docs:start:cast_vote #[aztec(private)] // annotation to mark function as private and expose private context fn cast_vote(candidate: Field) { - let secret = context.request_app_nullifier_secret_key(context.msg_sender()); // get secret key of caller of function + let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + let secret = context.request_nsk_app(msg_sender_npk_m_hash); // get secret key of caller of function let nullifier = dep::std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret context.push_new_nullifier(nullifier, 0); // push nullifier EasyPrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue(&mut context); diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr index 26f42d437c5..94ec509a7b8 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr @@ -2,7 +2,7 @@ use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteInterf use dep::aztec::{ keys::getters::get_ivpk_m, note::utils::compute_note_hash_for_consumption, - oracle::nullifier_key::get_app_nullifier_secret_key, hash::poseidon2_hash, + keys::getters::get_nsk_app, hash::poseidon2_hash, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} }; @@ -14,7 +14,8 @@ global ECDSA_PUBLIC_KEY_NOTE_LEN: Field = 5; struct EcdsaPublicKeyNote { x: [u8; 32], y: [u8; 32], - owner: AztecAddress, // We store the owner address only to get the secret key to compute the nullifier + // We store the npk_m_hash only to get the secret key to compute the nullifier + npk_m_hash: Field, } impl NoteInterface for EcdsaPublicKeyNote { @@ -40,7 +41,7 @@ impl NoteInterface for EcdsaPublicKeyNote { let last_x = self.x[31] as Field; let last_y = self.y[31] as Field; - [x, last_x, y, last_y, self.owner.to_field()] + [x, last_x, y, last_y, self.npk_m_hash] } // Cannot use the automatic deserialization for the aforementioned reasons @@ -60,12 +61,12 @@ impl NoteInterface for EcdsaPublicKeyNote { } y[31] = serialized_note[3].to_be_bytes(32)[31]; - EcdsaPublicKeyNote { x, y, owner: AztecAddress::from_field(serialized_note[4]), header: NoteHeader::empty() } + EcdsaPublicKeyNote { x, y, npk_m_hash: serialized_note[4], header: NoteHeader::empty() } } fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -75,7 +76,7 @@ impl NoteInterface for EcdsaPublicKeyNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -84,8 +85,7 @@ impl NoteInterface for EcdsaPublicKeyNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { - let ivpk_m = get_ivpk_m(context, self.owner); + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { context.emit_encrypted_log( (*context).this_address(), slot, @@ -97,7 +97,7 @@ impl NoteInterface for EcdsaPublicKeyNote { } impl EcdsaPublicKeyNote { - pub fn new(x: [u8; 32], y: [u8; 32], owner: AztecAddress) -> Self { - EcdsaPublicKeyNote { x, y, owner, header: NoteHeader::empty() } + pub fn new(x: [u8; 32], y: [u8; 32], npk_m_hash: Field) -> Self { + EcdsaPublicKeyNote { x, y, npk_m_hash, header: NoteHeader::empty() } } } 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 89da4adddb8..0a967637e31 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 @@ -6,6 +6,7 @@ contract EcdsaAccount { use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, PrivateImmutable}; use dep::aztec::protocol_types::abis::call_context::CallContext; + use dep::aztec::keys::getters::{get_npk_m_hash, get_ivpk_m}; use dep::std; use dep::aztec::context::Context; @@ -28,8 +29,11 @@ contract EcdsaAccount { #[aztec(initializer)] fn constructor(signing_pub_key_x: [u8; 32], signing_pub_key_y: [u8; 32]) { let this = context.this_address(); - let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this); - storage.public_key.initialize(&mut pub_key_note, true); + let this_npk_m_hash = get_npk_m_hash(&mut context, this); + let this_ivpk_m = get_ivpk_m(&mut context, this); + + let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash); + storage.public_key.initialize(&mut pub_key_note, true, this_ivpk_m); } // Note: If you globally change the entrypoint signature don't forget to update default_entrypoint.ts 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 ae45b80b6e5..7f04b26caed 100644 --- a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr @@ -4,6 +4,8 @@ contract Escrow { use dep::aztec::context::{PublicContext, Context}; + use dep::aztec::keys::getters::{get_npk_m_hash, get_ivpk_m}; + use dep::address_note::address_note::AddressNote; use dep::token::Token; @@ -17,8 +19,11 @@ contract Escrow { #[aztec(private)] #[aztec(initializer)] fn constructor(owner: AztecAddress) { - let mut note = AddressNote::new(owner, owner); - storage.owner.initialize(&mut note, true); + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let owner_ivpk_m = get_ivpk_m(&mut context, owner); + + let mut note = AddressNote::new(owner, owner_npk_m_hash); + storage.owner.initialize(&mut note, true, owner_ivpk_m); } // Withdraws balance. Requires that msg.sender is the owner. 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 bcebe616f7b..5a9336c0ca7 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 @@ -6,7 +6,7 @@ contract InclusionProofs { }; use dep::aztec::protocol_types::{grumpkin_point::GrumpkinPoint, contract_class_id::ContractClassId}; - use dep::aztec::{context::Context, note::note_getter_options::NoteStatus}; + use dep::aztec::{context::Context, note::note_getter_options::NoteStatus, keys::getters::{get_npk_m_hash, get_ivpk_m}}; // docs:start:imports use dep::aztec::history::{ contract_inclusion::{ @@ -44,8 +44,11 @@ contract InclusionProofs { #[aztec(private)] fn create_note(owner: AztecAddress, value: Field) { let owner_private_values = storage.private_values.at(owner); - let mut note = ValueNote::new(value, owner); - owner_private_values.insert(&mut note, true, GrumpkinPoint::zero()); + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let owner_ivpk_m = get_ivpk_m(&mut context, owner); + + let mut note = ValueNote::new(value, owner_npk_m_hash); + owner_private_values.insert(&mut note, true, owner_ivpk_m); } // docs:end:create_note @@ -56,13 +59,15 @@ contract InclusionProofs { block_number: u32, // The block at which we'll prove that the note exists nullified: bool ) { + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // docs:start:get_note_from_pxe // 1) Get the note from PXE. let private_values = storage.private_values.at(owner); let mut options = NoteGetterOptions::new(); options = options.select( - ValueNote::properties().owner, - owner.to_field(), + ValueNote::properties().npk_m_hash, + owner_npk_m_hash, Option::none() ).set_limit(1); if (nullified) { @@ -88,7 +93,8 @@ contract InclusionProofs { use_block_number: bool, block_number: u32 // The block at which we'll prove that the note exists ) { - let mut note = ValueNote::new(1, owner); + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let mut note = ValueNote::new(1, owner_npk_m_hash); if (use_block_number) { prove_note_inclusion_at(note, block_number, context); @@ -108,12 +114,14 @@ contract InclusionProofs { // because PXE performs note commitment inclusion check when you add a new note). fail_case: bool ) { + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // 2) Get the note from PXE let private_values = storage.private_values.at(owner); let mut options = NoteGetterOptions::new(); options = options.select( - ValueNote::properties().owner, - owner.to_field(), + ValueNote::properties().npk_m_hash, + owner_npk_m_hash, Option::none() ).set_limit(1); if (fail_case) { @@ -139,12 +147,14 @@ contract InclusionProofs { block_number: u32, // The block at which we'll prove that the note exists and is not nullified nullified: bool ) { + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // 1) Get the note from PXE. let private_values = storage.private_values.at(owner); let mut options = NoteGetterOptions::new(); options = options.select( - ValueNote::properties().owner, - owner.to_field(), + ValueNote::properties().npk_m_hash, + owner_npk_m_hash, Option::none() ).set_limit(1); if (nullified) { @@ -166,11 +176,13 @@ contract InclusionProofs { // docs:start:nullify_note #[aztec(private)] fn nullify_note(owner: AztecAddress) { + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let private_values = storage.private_values.at(owner); let mut options = NoteGetterOptions::new(); options = options.select( - ValueNote::properties().owner, - owner.to_field(), + ValueNote::properties().npk_m_hash, + owner_npk_m_hash, Option::none() ).set_limit(1); let notes = private_values.get_notes(options); diff --git a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr index aed23961f04..213dbc91661 100644 --- a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr @@ -7,6 +7,7 @@ contract PendingNoteHashes { use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, Map, PrivateSet}; use dep::value_note::{balance_utils, filter::filter_notes_min_sum, value_note::{VALUE_NOTE_LEN, ValueNote}}; use dep::aztec::context::{PublicContext, Context}; + use dep::aztec::keys::getters::{get_npk_m_hash, get_ivpk_m}; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; #[aztec(storage)] @@ -23,10 +24,14 @@ contract PendingNoteHashes { #[aztec(private)] fn test_insert_then_get_then_nullify_flat(amount: Field, owner: AztecAddress) -> Field { let owner_balance = storage.balances.at(owner); - let mut note = ValueNote::new(amount, owner); + + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let owner_ivpk_m = get_ivpk_m(&mut context, owner); + + let mut note = ValueNote::new(amount, owner_npk_m_hash); // Insert note - owner_balance.insert(&mut note, true, GrumpkinPoint::zero()); + owner_balance.insert(&mut note, true, owner_ivpk_m); let options = NoteGetterOptions::with_filter(filter_notes_min_sum, amount); // get note inserted above @@ -53,9 +58,12 @@ contract PendingNoteHashes { assert(maybe_notes[0].is_none()); assert(maybe_notes[1].is_none()); + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let owner_ivpk_m = get_ivpk_m(&mut context, owner); + // Insert note - let mut note = ValueNote::new(amount, owner); - owner_balance.insert(&mut note, true, GrumpkinPoint::zero()); + let mut note = ValueNote::new(amount, owner_npk_m_hash); + owner_balance.insert(&mut note, true, owner_ivpk_m); 0 } @@ -68,10 +76,14 @@ contract PendingNoteHashes { #[aztec(private)] fn insert_note(amount: Field, owner: AztecAddress) { let owner_balance = storage.balances.at(owner); - let mut note = ValueNote::new(amount, owner); + + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let owner_ivpk_m = get_ivpk_m(&mut context, owner); + + let mut note = ValueNote::new(amount, owner_npk_m_hash); // Insert note - owner_balance.insert(&mut note, true, GrumpkinPoint::zero()); + owner_balance.insert(&mut note, true, owner_ivpk_m); } // Nested/inner function to get a note and confirm it matches the expected value 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 b7e0f890eb0..6bff06003ce 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 @@ -13,6 +13,7 @@ contract SchnorrAccount { auth_witness::get_auth_witness }; use dep::aztec::hash::compute_siloed_nullifier; + use dep::aztec::keys::getters::{get_ivpk_m, get_npk_m_hash}; use dep::aztec::oracle::get_nullifier_membership_witness::get_low_nullifier_membership_witness; use crate::public_key_note::{PublicKeyNote, PUBLIC_KEY_NOTE_LEN}; @@ -30,9 +31,12 @@ contract SchnorrAccount { #[aztec(initializer)] fn constructor(signing_pub_key_x: Field, signing_pub_key_y: Field) { let this = context.this_address(); + let this_npk_m_hash = get_npk_m_hash(&mut context, this); + let this_ivpk_m = get_ivpk_m(&mut context, this); + // docs:start:initialize - let mut pub_key_note = PublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this); - storage.signing_public_key.initialize(&mut pub_key_note, true); + let mut pub_key_note = PublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash); + storage.signing_public_key.initialize(&mut pub_key_note, true, this_ivpk_m); // docs:end:initialize } diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index a1ec911d20e..75ea16c0178 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -1,8 +1,7 @@ use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}; use dep::aztec::{ - keys::getters::get_ivpk_m, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::{nullifier_key::get_app_nullifier_secret_key}, - protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} + note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, + keys::getters::get_nsk_app, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, }; global PUBLIC_KEY_NOTE_LEN: Field = 3; @@ -13,13 +12,14 @@ global PUBLIC_KEY_NOTE_LEN: Field = 3; struct PublicKeyNote { x: Field, y: Field, - owner: AztecAddress, // We store the owner address only to get the secret key to compute the nullifier and to broadcast + // We store the npk_m_hash only to get the secret key to compute the nullifier + npk_m_hash: Field, } impl NoteInterface for PublicKeyNote { fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -29,7 +29,7 @@ impl NoteInterface for PublicKeyNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -38,8 +38,7 @@ impl NoteInterface for PublicKeyNote { } // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, _ivpk_m: GrumpkinPoint) { - let ivpk_m = get_ivpk_m(context, self.owner); + fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { context.emit_encrypted_log( (*context).this_address(), slot, @@ -51,7 +50,7 @@ impl NoteInterface for PublicKeyNote { } impl PublicKeyNote { - pub fn new(x: Field, y: Field, owner: AztecAddress) -> Self { - PublicKeyNote { x, y, owner, header: NoteHeader::empty() } + pub fn new(x: Field, y: Field, npk_m_hash: Field) -> Self { + PublicKeyNote { x, y, npk_m_hash, header: NoteHeader::empty() } } } 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 db8efde4a25..dce2a46dbd3 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 @@ -37,7 +37,7 @@ contract StatefulTest { fn create_note(owner: AztecAddress, value: Field) { if (value != 0) { let loc = storage.notes.at(owner); - increment(loc, value, owner); + increment(context, loc, value, owner); } } @@ -46,7 +46,7 @@ contract StatefulTest { fn create_note_no_init_check(owner: AztecAddress, value: Field) { if (value != 0) { let loc = storage.notes.at(owner); - increment(loc, value, owner); + increment(context, loc, value, owner); } } @@ -56,10 +56,10 @@ contract StatefulTest { let sender = context.msg_sender(); let sender_notes = storage.notes.at(sender); - decrement(sender_notes, amount, sender); + decrement(context, sender_notes, amount, sender); let recipient_notes = storage.notes.at(recipient); - increment(recipient_notes, amount, recipient); + increment(context, recipient_notes, amount, recipient); } #[aztec(private)] @@ -68,10 +68,10 @@ contract StatefulTest { let sender = context.msg_sender(); let sender_notes = storage.notes.at(sender); - decrement(sender_notes, amount, sender); + decrement(context, sender_notes, amount, sender); let recipient_notes = storage.notes.at(recipient); - increment(recipient_notes, amount, recipient); + increment(context, recipient_notes, amount, recipient); } #[aztec(public)] 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 21397be5465..594339693e3 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::aztec::state_vars::{shared_mutable::SharedMutablePrivateGetter, map::derive_storage_slot_in_map}; use dep::aztec::{ - keys::getters::{get_npk_m, get_ivpk_m}, + keys::getters::{get_npk_m, get_ivpk_m, get_npk_m_hash}, context::{Context, inputs::private_context_inputs::PrivateContextInputs}, hash::{pedersen_hash, compute_secret_hash, ArgsHasher}, note::{ @@ -81,13 +81,16 @@ contract Test { storage_slot != storage.example_constant.get_storage_slot(), "this storage slot is reserved for example_constant" ); - let mut note = ValueNote::new(value, owner); + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let owner_ivpk_m = get_ivpk_m(&mut context, owner); + + let mut note = ValueNote::new(value, owner_npk_m_hash); create_note( &mut context, storage_slot, &mut note, true, - GrumpkinPoint::zero() + owner_ivpk_m, ); } @@ -264,13 +267,17 @@ contract Test { let mut storage_slot = storage.example_constant.get_storage_slot() + 1; Test::at(context.this_address()).call_create_note(value, owner, storage_slot).call(&mut context); storage_slot += 1; - let mut note = ValueNote::new(value + 1, owner); + + let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + let owner_ivpk_m = get_ivpk_m(&mut context, owner); + + let mut note = ValueNote::new(value + 1, owner_npk_m_hash); create_note( &mut context, storage_slot, &mut note, true, - GrumpkinPoint::zero() + owner_ivpk_m, ); storage_slot += 1; Test::at(context.this_address()).call_create_note(value + 2, owner, storage_slot).call(&mut context); @@ -345,7 +352,7 @@ contract Test { #[aztec(private)] fn set_constant(value: Field) { let mut note = TestNote::new(value); - storage.example_constant.initialize(&mut note, false); + storage.example_constant.initialize(&mut note, false, GrumpkinPoint::zero()); } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr index 3e0b538fd18..0179edf37a7 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr @@ -1,8 +1,12 @@ -use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, NoteGetterOptions, NoteViewerOptions, PrivateSet, Map}; +use dep::aztec::prelude::{ + AztecAddress, NoteGetterOptions, NoteViewerOptions, NoteHeader, NoteInterface, PrivateContext, + PrivateSet, Map +}; use dep::aztec::{ - context::Context, - protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, grumpkin_point::GrumpkinPoint}, - note::{note_getter::view_notes, note_getter_options::SortOrder} + context::{PublicContext, Context}, hash::pedersen_hash, + protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, hash::poseidon2_hash}, + note::{note_getter::view_notes, note_getter_options::SortOrder}, + keys::getters::{get_npk_m_hash, get_ivpk_m} }; use crate::types::token_note::{TokenNote, OwnedNote}; @@ -57,10 +61,13 @@ impl BalancesMap { owner: AztecAddress, addend: U128 ) where T: NoteInterface + OwnedNote { - let mut addend_note = T::new(addend, owner); + // We fetch the nullifier public key hash in the registry / from our PXE + let owner_npk_m_hash = get_npk_m_hash(self.map.context.private.unwrap(), owner); + let owner_ivpk_m = get_ivpk_m(self.map.context.private.unwrap(), owner); + let mut addend_note = T::new(addend, owner_npk_m_hash); // docs:start:insert - self.map.at(owner).insert(&mut addend_note, true, GrumpkinPoint::zero()); + self.map.at(owner).insert(&mut addend_note, true, owner_ivpk_m); // docs:end:insert } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index 82db1ae86ff..b2e88a3ae77 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -1,27 +1,26 @@ use dep::aztec::{ - keys::getters::get_ivpk_m, prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, + prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_app_nullifier_secret_key} + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, }; trait OwnedNote { - fn new(amount: U128, owner: AztecAddress) -> Self; + fn new(amount: U128, owner_npk_m_hash: Field) -> Self; fn get_amount(self) -> U128; - fn get_owner(self) -> AztecAddress; + fn get_owner_npk_m_hash(self) -> Field; } global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. #[aztec(note)] struct TokenNote { - // the amount of tokens in the note + // The amount of tokens in the note amount: U128, - // the provider of secrets for the nullifier. The owner (recipient) to ensure that the note - // can be privately spent. When nullifier secret and encryption private key is same - // we can simply use the owner for this one. - owner: AztecAddress, - // randomness of the note to hide contents. + // The nullifying public key hash of the person who owns the note. + // This is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + npk_m_hash: Field, + // Randomness of the note to hide its contents randomness: Field, } @@ -29,7 +28,7 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_app_nullifier_secret_key(self.owner); + let secret = context.request_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -40,7 +39,7 @@ impl NoteInterface for TokenNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_app_nullifier_secret_key(self.owner); + let secret = get_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -51,8 +50,8 @@ impl NoteInterface for TokenNote { // Broadcasts the note as an encrypted log on L1. fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) { // We only bother inserting the note if non-empty to save funds on gas. + // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format if !(self.amount == U128::from_integer(0)) { - let ivpk_m = get_ivpk_m(context, self.owner); context.emit_encrypted_log( (*context).this_address(), slot, @@ -65,10 +64,10 @@ impl NoteInterface for TokenNote { } impl OwnedNote for TokenNote { - fn new(amount: U128, owner: AztecAddress) -> Self { + fn new(amount: U128, owner_npk_m_hash: Field) -> Self { Self { amount, - owner, + npk_m_hash: owner_npk_m_hash, randomness: unsafe_rand(), header: NoteHeader::empty(), } @@ -78,7 +77,7 @@ impl OwnedNote for TokenNote { self.amount } - fn get_owner(self) -> AztecAddress { - self.owner + fn get_owner_npk_m_hash(self) -> Field { + self.npk_m_hash } } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 4db92e7f61d..b2e88a3ae77 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -2,7 +2,7 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::{unsafe_rand::unsafe_rand, nullifier_key::get_nsk_app_with_npk_m_hash} + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, }; trait OwnedNote { @@ -28,7 +28,7 @@ impl NoteInterface for TokenNote { // docs:start:nullifier fn compute_nullifier(self, context: &mut PrivateContext) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = context.request_nsk_app_with_npk_m_hash(self.npk_m_hash); + let secret = context.request_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, @@ -39,7 +39,7 @@ impl NoteInterface for TokenNote { fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_consumption(self); - let secret = get_nsk_app_with_npk_m_hash(self.npk_m_hash); + let secret = get_nsk_app(self.npk_m_hash); poseidon2_hash([ note_hash_for_nullify, secret, diff --git a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts index 97a91be1e12..2dedcbade81 100644 --- a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts +++ b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts @@ -188,7 +188,8 @@ describe('e2e_crowdfunding_and_claim', () => { nonce: noteNonces[0], }, value: extendedNote.note.items[0], - owner: extendedNote.note.items[1], + // eslint-disable-next-line camelcase + npk_m_hash: extendedNote.note.items[1], randomness: extendedNote.note.items[2], }; }; diff --git a/yarn-project/end-to-end/src/e2e_delegate_calls/delegate.test.ts b/yarn-project/end-to-end/src/e2e_delegate_calls/delegate.test.ts index 9f6890efb00..60117019d07 100644 --- a/yarn-project/end-to-end/src/e2e_delegate_calls/delegate.test.ts +++ b/yarn-project/end-to-end/src/e2e_delegate_calls/delegate.test.ts @@ -24,14 +24,13 @@ describe('e2e_delegate_calls', () => { .wait(); const delegatorValue = await delegatorContract.methods - .view_private_value(sentValue, wallet.getCompleteAddress().address) + .get_private_value(sentValue, wallet.getCompleteAddress().address) .simulate(); - const delegatedOnValue = await delegatedOnContract.methods - .view_private_value(sentValue, wallet.getCompleteAddress().address) - .simulate(); + await expect( + delegatedOnContract.methods.get_private_value(sentValue, wallet.getCompleteAddress().address).simulate(), + ).rejects.toThrow(`Assertion failed: Cannot return zero notes 'num_notes != 0'`); - expect(delegatedOnValue).toEqual(0n); expect(delegatorValue).toEqual(sentValue); }); diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index d57338e2592..6c3ddd57d81 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -42,19 +42,7 @@ export class Oracle { return unpacked.map(toACVMField); } - async getNullifierKeys([accountAddress]: ACVMField[]): Promise { - const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( - fromACVMField(accountAddress), - ); - return [ - toACVMField(masterNullifierPublicKey.x), - toACVMField(masterNullifierPublicKey.y), - toACVMField(appNullifierSecretKey), - ]; - } - - // Keeping this oracle separate from above because I don't want an implicit overload in noir code - async getNullifierKeysWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]): Promise { + async getNullifierKeys([masterNullifierPublicKeyHash]: ACVMField[]): Promise { const { masterNullifierPublicKey, appNullifierSecretKey } = await this.typedOracle.getNullifierKeys( fromACVMField(masterNullifierPublicKeyHash), ); @@ -184,14 +172,6 @@ export class Oracle { return [...publicKeys.toFields(), partialAddress].map(toACVMField); } - // Keeping this oracle separate from above because I don't want an implicit overload in noir code - async getPublicKeysAndPartialAddressWithNpkMHash([masterNullifierPublicKeyHash]: ACVMField[]) { - const parsedNpkMHash = fromACVMField(masterNullifierPublicKeyHash); - const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress(parsedNpkMHash); - - return [...publicKeys.toFields(), partialAddress].map(toACVMField); - } - async getNotes( [storageSlot]: ACVMField[], [numSelects]: ACVMField[], diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 25b21cb887e..dc6425b9fc6 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -141,7 +141,7 @@ describe('Private Execution test suite', () => { // Create a new snapshot. const newSnap = new AppendOnlyTreeSnapshot(Fr.fromBuffer(tree.getRoot(true)), Number(tree.getNumLeaves(true))); - if (name === 'noteHash' || name === 'l1ToL2Messages' || 'publicData') { + if (name === 'noteHash' || name === 'l1ToL2Messages' || name === 'publicData') { header = new Header( header.lastArchive, header.contentCommitment, @@ -190,37 +190,35 @@ describe('Private Execution test suite', () => { beforeEach(async () => { trees = {}; oracle = mock(); - oracle.getNullifierKeys.mockImplementation( - (accountOrNpkMHash: AztecAddress | Fr, contractAddress: AztecAddress) => { - if (accountOrNpkMHash.equals(ownerCompleteAddress.address)) { - return Promise.resolve({ - masterNullifierPublicKey: ownerCompleteAddress.publicKeys.masterNullifierPublicKey, - appNullifierSecretKey: computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), - }); - } - if (accountOrNpkMHash.equals(recipientCompleteAddress.address)) { - return Promise.resolve({ - masterNullifierPublicKey: recipientCompleteAddress.publicKeys.masterNullifierPublicKey, - appNullifierSecretKey: computeAppNullifierSecretKey(recipientMasterNullifierSecretKey, contractAddress), - }); - } - throw new Error(`Unknown address ${accountOrNpkMHash}`); - }, - ); + oracle.getNullifierKeys.mockImplementation((masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress) => { + if (masterNullifierPublicKeyHash.equals(poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()))) { + return Promise.resolve({ + masterNullifierPublicKey: ownerCompleteAddress.publicKeys.masterNullifierPublicKey, + appNullifierSecretKey: computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), + }); + } + if (masterNullifierPublicKeyHash.equals(poseidon2Hash(recipientCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()))) { + return Promise.resolve({ + masterNullifierPublicKey: recipientCompleteAddress.publicKeys.masterNullifierPublicKey, + appNullifierSecretKey: computeAppNullifierSecretKey(recipientMasterNullifierSecretKey, contractAddress), + }); + } + throw new Error(`Unknown master nullifier public key hash: ${masterNullifierPublicKeyHash}`); + }); // We call insertLeaves here with no leaves to populate empty public data tree root --> this is necessary to be // able to get ivpk_m during execution await insertLeaves([], 'publicData'); oracle.getHeader.mockResolvedValue(header); - oracle.getCompleteAddress.mockImplementation((accountOrNpkMHash: AztecAddress | Fr) => { - if (accountOrNpkMHash.equals(owner)) { + oracle.getCompleteAddress.mockImplementation((address: AztecAddress) => { + if (address.equals(owner)) { return Promise.resolve(ownerCompleteAddress); } - if (accountOrNpkMHash.equals(recipient)) { + if (address.equals(recipient)) { return Promise.resolve(recipientCompleteAddress); } - throw new Error(`Unknown address ${accountOrNpkMHash}`); + throw new Error(`Unknown address: ${address}`); }); // This oracle gets called when reading ivpk_m from key registry --> we return zero witness indicating that // the keys were not registered. This triggers non-registered keys flow in which getCompleteAddress oracle @@ -282,7 +280,7 @@ describe('Private Execution test suite', () => { const mockFirstNullifier = new Fr(1111); let currentNoteIndex = 0n; - const buildNote = (amount: bigint, owner: AztecAddress, storageSlot: Fr, noteTypeId: Fr) => { + const buildNote = (amount: bigint, ownerNpkMH: Fr, storageSlot: Fr, noteTypeId: Fr) => { // WARNING: this is not actually how nonces are computed! // For the purpose of this test we use a mocked firstNullifier and and a random number // to compute the nonce. Proper nonces are only enforced later by the kernel/later circuits @@ -293,7 +291,7 @@ describe('Private Execution test suite', () => { // `hash(firstNullifier, noteHashIndex)` const noteHashIndex = randomInt(1); // mock index in TX's final newNoteHashes array const nonce = computeNoteHashNonce(mockFirstNullifier, noteHashIndex); - const note = new Note([new Fr(amount), owner.toField(), Fr.random()]); + const note = new Note([new Fr(amount), ownerNpkMH, Fr.random()]); const innerNoteHash = pedersenHash(note.items); return { contractAddress, @@ -394,7 +392,7 @@ describe('Private Execution test suite', () => { const noteTypeId = StatefulTestContractArtifact.notes['ValueNote'].id; - const notes = [buildNote(60n, owner, storageSlot, noteTypeId), buildNote(80n, owner, storageSlot, noteTypeId)]; + const notes = [buildNote(60n, poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), storageSlot, noteTypeId), buildNote(80n, poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), storageSlot, noteTypeId)]; oracle.getNotes.mockResolvedValue(notes); const consumedNotes = await asyncMap(notes, ({ nonce, note }) => @@ -451,7 +449,7 @@ describe('Private Execution test suite', () => { const storageSlot = computeSlotForMapping(new Fr(1n), owner); const noteTypeId = StatefulTestContractArtifact.notes['ValueNote'].id; - const notes = [buildNote(balance, owner, storageSlot, noteTypeId)]; + const notes = [buildNote(balance, poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), storageSlot, noteTypeId)]; oracle.getNotes.mockResolvedValue(notes); const consumedNotes = await asyncMap(notes, ({ nonce, note }) => From 348b371a72500ffadbea14a3cf5cb70dc64e102d Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 14 May 2024 19:55:06 +0000 Subject: [PATCH 104/125] renaming --- .../aztec/src/context/private_context.nr | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index a085ade631d..5a9cc592526 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -228,23 +228,23 @@ impl PrivateContext { // TODO(#5630) Replace request_app_nullifier_secret_key above with this once we no longer get app nullifier secret key with address pub fn request_nsk_app_with_npk_m_hash(&mut self, npk_m_hash: Field) -> Field { // A value of empty nullifier keys will fail the key validation request. - let previous_nullifier_key = self.nullifier_key.unwrap_or(NullifierKeys::empty()); + let cached_nullifier_keys = self.nullifier_key.unwrap_or(NullifierKeys::empty()); - let keys = if poseidon2_hash(previous_nullifier_key.master_nullifier_public_key.serialize()) == npk_m_hash { - previous_nullifier_key + let nullifier_keys = if poseidon2_hash(cached_nullifier_keys.master_nullifier_public_key.serialize()) == npk_m_hash { + cached_nullifier_keys } else { - let keys = get_nullifier_keys_with_npk_m_hash(npk_m_hash); + let fetched_nullifier_keys = get_nullifier_keys_with_npk_m_hash(npk_m_hash); let request = NullifierKeyValidationRequest { - master_nullifier_public_key: keys.master_nullifier_public_key, - app_nullifier_secret_key: keys.app_nullifier_secret_key + master_nullifier_public_key: fetched_nullifier_keys.master_nullifier_public_key, + app_nullifier_secret_key: fetched_nullifier_keys.app_nullifier_secret_key }; self.nullifier_key_validation_requests.push(request); - self.nullifier_key = Option::some(keys); - keys + self.nullifier_key = Option::some(fetched_nullifier_keys); + fetched_nullifier_keys }; - assert_eq(poseidon2_hash(keys.master_nullifier_public_key.serialize()), npk_m_hash); - keys.app_nullifier_secret_key + assert_eq(poseidon2_hash(nullifier_keys.master_nullifier_public_key.serialize()), npk_m_hash); + nullifier_keys.app_nullifier_secret_key } // docs:start:context_message_portal From 7cffd0feaaab8708999c92cea77b0bd140ef43a8 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 10:45:41 +0000 Subject: [PATCH 105/125] fixing conflicts / formatting --- .../aztec-nr/address-note/src/address_note.nr | 4 +- .../aztec/src/context/private_context.nr | 8 ++-- .../aztec-nr/aztec/src/encrypted_logs/body.nr | 3 +- .../aztec-nr/aztec/src/keys/getters.nr | 5 ++- .../aztec/src/state_vars/private_immutable.nr | 15 +++---- .../aztec/src/state_vars/private_mutable.nr | 44 +++++++++---------- .../src/easy_private_uint.nr | 3 +- .../aztec-nr/value-note/src/utils.nr | 21 +++++++-- .../aztec-nr/value-note/src/value_note.nr | 4 +- .../app_subscription_contract/src/main.nr | 2 +- .../src/subscription_note.nr | 2 +- .../contracts/card_game_contract/src/cards.nr | 7 ++- .../contracts/child_contract/src/main.nr | 2 +- .../crowdfunding_contract/src/main.nr | 3 +- .../docs_example_contract/src/main.nr | 5 ++- .../docs_example_contract/src/options.nr | 12 ++--- .../src/public_key_note.nr | 4 +- .../contracts/test_contract/src/main.nr | 16 +------ .../src/types/token_note.nr | 2 +- .../token_contract/src/types/token_note.nr | 2 +- yarn-project/key-store/src/test_key_store.ts | 11 +++-- .../src/client/private_execution.test.ts | 38 +++++++++++++--- 22 files changed, 122 insertions(+), 91 deletions(-) diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index 1e749f904fd..d71ff647109 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -4,8 +4,8 @@ use dep::aztec::{ grumpkin_point::GrumpkinPoint }, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, - context::PrivateContext, hash::poseidon2_hash + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, context::PrivateContext, + hash::poseidon2_hash }; global ADDRESS_NOTE_LEN: Field = 3; diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 395e742de54..c9aa5fa5e61 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -1,10 +1,10 @@ use crate::{ context::{inputs::PrivateContextInputs, interface::ContextInterface}, - keys::getters::get_nullifier_keys, - messaging::process_l1_to_l2_message, + keys::getters::get_nullifier_keys, messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher, compute_encrypted_log_hash, compute_unencrypted_log_hash}, oracle::{ - nullifier_key::NullifierKeys,arguments, returns, call_private_function::call_private_function_internal, header::get_header_at, + nullifier_key::NullifierKeys, arguments, returns, + call_private_function::call_private_function_internal, header::get_header_at, logs::emit_encrypted_log, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, enqueue_public_function_call::{ enqueue_public_function_call_internal, set_public_teardown_function_call_internal, @@ -215,7 +215,7 @@ impl PrivateContext { let nullifier_keys = if poseidon2_hash(cached_nullifier_keys.master_nullifier_public_key.serialize()) == npk_m_hash { cached_nullifier_keys } else { - let fetched_nullifier_keys = get_nullifier_keys_with_npk_m_hash(npk_m_hash); + let fetched_nullifier_keys = get_nullifier_keys(npk_m_hash); let request = NullifierKeyValidationRequest { master_nullifier_public_key: fetched_nullifier_keys.master_nullifier_public_key, app_nullifier_secret_key: fetched_nullifier_keys.app_nullifier_secret_key diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr index a93a3dab46b..05e49217fe7 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/body.nr @@ -67,8 +67,7 @@ mod test { use crate::{ note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::unsafe_rand::unsafe_rand, - context::PrivateContext, hash::poseidon2_hash + oracle::unsafe_rand::unsafe_rand, context::PrivateContext, hash::poseidon2_hash }; struct AddressNote { diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index 0c9a79b0326..6fab5705194 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -4,7 +4,10 @@ use dep::protocol_types::{ }; use crate::{ context::PrivateContext, - oracle::{keys::get_public_keys_and_partial_address, nullifier_key::{NullifierKeys, get_nullifier_keys as get_nullifier_keys_oracle}}, + oracle::{ + keys::get_public_keys_and_partial_address, + nullifier_key::{NullifierKeys, get_nullifier_keys as get_nullifier_keys_oracle} +}, keys::public_keys::{PublicKeys, NULLIFIER_INDEX, INCOMING_INDEX}, state_vars::{ map::derive_storage_slot_in_map, diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr index 317b222be7b..56c55a1384c 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr @@ -49,20 +49,19 @@ impl PrivateImmutable { // docs:end:is_initialized // docs:start:initialize - pub fn initialize(self, note: &mut Note, broadcast: bool, ivpk_m: GrumpkinPoint) where Note: NoteInterface { + pub fn initialize( + self, + note: &mut Note, + broadcast: bool, + ivpk_m: GrumpkinPoint + ) where Note: NoteInterface { let context = self.context.unwrap(); // Nullify the storage slot. let nullifier = self.compute_initialization_nullifier(); context.push_new_nullifier(nullifier, 0); - create_note( - context, - self.storage_slot, - note, - broadcast, - ivpk_m, - ); + create_note(context, self.storage_slot, note, broadcast, ivpk_m); } // docs:end:initialize diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index 1a4538a5a42..a4908c37553 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -51,25 +51,29 @@ impl PrivateMutable { // docs:end:is_initialized // docs:start:initialize - pub fn initialize(self, note: &mut Note, broadcast: bool, ivpk_m: GrumpkinPoint) where Note: NoteInterface { + pub fn initialize( + self, + note: &mut Note, + broadcast: bool, + ivpk_m: GrumpkinPoint + ) where Note: NoteInterface { let context = self.context.unwrap(); // Nullify the storage slot. let nullifier = self.compute_initialization_nullifier(); context.push_new_nullifier(nullifier, 0); - create_note( - context, - self.storage_slot, - note, - broadcast, - ivpk_m, - ); + create_note(context, self.storage_slot, note, broadcast, ivpk_m); } // docs:end:initialize // docs:start:replace - pub fn replace(self, new_note: &mut Note, broadcast: bool, ivpk_m: GrumpkinPoint) where Note: NoteInterface { + pub fn replace( + self, + new_note: &mut Note, + broadcast: bool, + ivpk_m: GrumpkinPoint + ) where Note: NoteInterface { let context = self.context.unwrap(); let prev_note: Note = get_note(context, self.storage_slot); @@ -77,18 +81,16 @@ impl PrivateMutable { destroy_note(context, prev_note); // Add replacement note. - create_note( - context, - self.storage_slot, - new_note, - broadcast, - ivpk_m, - ); + create_note(context, self.storage_slot, new_note, broadcast, ivpk_m); } // docs:end:replace // docs:start:get_note - pub fn get_note(self, broadcast: bool, ivpk_m: GrumpkinPoint) -> Note where Note: NoteInterface { + pub fn get_note( + self, + broadcast: bool, + ivpk_m: GrumpkinPoint + ) -> Note where Note: NoteInterface { let context = self.context.unwrap(); let mut note = get_note(context, self.storage_slot); @@ -97,13 +99,7 @@ impl PrivateMutable { // Add the same note again. // Because a nonce is added to every note in the kernel, its nullifier will be different. - create_note( - context, - self.storage_slot, - &mut note, - broadcast, - ivpk_m, - ); + create_note(context, self.storage_slot, &mut note, broadcast, ivpk_m); note } diff --git a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr index 84d8c637fd4..e11a3484eb7 100644 --- a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr +++ b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr @@ -1,6 +1,7 @@ use dep::aztec::{ protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}, context::Context, - note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet, keys::getters::{get_npk_m_hash, get_ivpk_m} + note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet, + keys::getters::{get_npk_m_hash, get_ivpk_m} }; use dep::value_note::{filter::filter_notes_min_sum, value_note::ValueNote}; diff --git a/noir-projects/aztec-nr/value-note/src/utils.nr b/noir-projects/aztec-nr/value-note/src/utils.nr index 3186094a875..c142d95e66b 100644 --- a/noir-projects/aztec-nr/value-note/src/utils.nr +++ b/noir-projects/aztec-nr/value-note/src/utils.nr @@ -12,7 +12,12 @@ pub fn create_note_getter_options_for_decreasing_balance(amount: Field) -> NoteG // Creates a new note for the recipient. // Inserts it to the recipient's set of notes. -pub fn increment(mut context: PrivateContext, balance: PrivateSet, amount: Field, recipient: AztecAddress) { +pub fn increment( + mut context: PrivateContext, + balance: PrivateSet, + amount: Field, + recipient: AztecAddress +) { let recipient_npk_m_hash = get_npk_m_hash(&mut context, recipient); let recipient_ivpk_m = get_ivpk_m(&mut context, recipient); @@ -25,7 +30,12 @@ pub fn increment(mut context: PrivateContext, balance: PrivateSet, am // Remove those notes. // If the value of the removed notes exceeds the requested `amount`, create a new note containing the excess value, so that exactly `amount` is removed. // Fail if the sum of the selected notes is less than the amount. -pub fn decrement(mut context: PrivateContext, balance: PrivateSet, amount: Field, owner: AztecAddress) { +pub fn decrement( + mut context: PrivateContext, + balance: PrivateSet, + amount: Field, + owner: AztecAddress +) { let sum = decrement_by_at_most(context, balance, amount, owner); assert(sum == amount, "Balance too low"); } @@ -67,7 +77,12 @@ pub fn decrement_by_at_most( // Removes the note from the owner's set of notes. // Returns the value of the destroyed note. -pub fn destroy_note(mut context: PrivateContext, balance: PrivateSet, owner: AztecAddress, note: ValueNote) -> Field { +pub fn destroy_note( + mut context: PrivateContext, + balance: PrivateSet, + owner: AztecAddress, + note: ValueNote +) -> Field { // Ensure the note is actually owned by the owner (to prevent user from generating a valid proof while // spending someone else's notes). let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 73e29c159e3..9a4b19e570d 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -5,8 +5,8 @@ use dep::aztec::{ constants::GENERATOR_INDEX__NOTE_NULLIFIER }, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, - hash::poseidon2_hash, context::PrivateContext + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, hash::poseidon2_hash, + context::PrivateContext }; global VALUE_NOTE_LEN: Field = 3; // 3 plus a header. diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index 02c74da32ed..f0a7ebed371 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -9,7 +9,7 @@ contract AppSubscription { AztecAddress, FunctionSelector, PrivateContext, NoteHeader, Map, PrivateMutable, PublicMutable, SharedImmutable }, - protocol_types::traits::is_empty, keys::getters::{get_npk_m_hash, get_ivpk_m}, + protocol_types::traits::is_empty, keys::getters::{get_npk_m_hash, get_ivpk_m} }, authwit::{account::AccountActions, auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit}, gas_token::GasToken, token::Token diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index 6675f56f95f..9da4e7d6828 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -2,7 +2,7 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, NoteHeader, NoteInterfac use dep::aztec::{ keys::getters::get_ivpk_m, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, - note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, keys::getters::get_nsk_app, + note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, keys::getters::get_nsk_app }; global SUBSCRIPTION_NOTE_LEN: Field = 3; 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 e45a53bd36b..43ec4efdf02 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 @@ -3,11 +3,10 @@ use dep::aztec::prelude::{AztecAddress, FunctionSelector, PrivateContext, NoteHe use dep::aztec::{ protocol_types::{ traits::{ToField, Serialize, FromField}, grumpkin_point::GrumpkinPoint, - constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL }, - keys::getters::{get_npk_m_hash, get_ivpk_m}, - context::{PublicContext, Context}, note::note_getter::view_notes, state_vars::PrivateSet, - note::constants::MAX_NOTES_PER_PAGE + keys::getters::{get_npk_m_hash, get_ivpk_m}, context::{PublicContext, Context}, + note::note_getter::view_notes, state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE }; use dep::std; use dep::std::{option::Option}; 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 4249bfc382f..e05623a233e 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -6,7 +6,7 @@ contract Child { context::{PublicContext, Context, gas::GasOpts}, protocol_types::{abis::call_context::CallContext, grumpkin_point::GrumpkinPoint}, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, - keys::getters::{get_npk_m_hash, get_ivpk_m}, + keys::getters::{get_npk_m_hash, get_ivpk_m} }; use dep::value_note::value_note::ValueNote; diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 06b956b73f8..9eef23a50bd 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -8,7 +8,8 @@ contract Crowdfunding { abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize, grumpkin_point::GrumpkinPoint }, - state_vars::{PrivateSet, PublicImmutable, SharedImmutable}, keys::getters::{get_npk_m_hash, get_ivpk_m} + state_vars::{PrivateSet, PublicImmutable, SharedImmutable}, + keys::getters::{get_npk_m_hash, get_ivpk_m} }; use dep::value_note::value_note::ValueNote; use dep::token::Token; 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 3015678f3f1..d2ed49d84ec 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 @@ -18,7 +18,10 @@ contract DocsExample { PrivateContext, Map, PublicMutable, PublicImmutable, PrivateMutable, PrivateImmutable, PrivateSet, SharedImmutable, Deserialize }; - use dep::aztec::{note::note_getter_options::Comparator, context::{PublicContext, Context}, keys::getters::{get_npk_m_hash, get_ivpk_m}}; + use dep::aztec::{ + note::note_getter_options::Comparator, context::{PublicContext, Context}, + keys::getters::{get_npk_m_hash, get_ivpk_m} + }; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; // how to import methods from other files/folders within your workspace use crate::options::create_account_card_getter_options; diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr index 6461b21b74e..ca5c22d9afc 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr @@ -24,7 +24,7 @@ pub fn create_account_card_getter_options( pub fn create_exact_card_getter_options( points: u8, secret: Field, - account_npk_m_hash: Field, + account_npk_m_hash: Field ) -> NoteGetterOptions { let mut options = NoteGetterOptions::new(); options.select(CardNote::properties().points, points as Field, Option::none()).select(CardNote::properties().randomness, secret, Option::none()).select( @@ -53,21 +53,17 @@ pub fn filter_min_points( // docs:end:state_vars-OptionFilter // docs:start:state_vars-NoteGetterOptionsFilter -pub fn create_account_cards_with_min_points_getter_options( - account_npk_m_hash: Field, min_points: u8 -) -> NoteGetterOptions { +pub fn create_account_cards_with_min_points_getter_options(account_npk_m_hash: Field, min_points: u8) -> NoteGetterOptions { NoteGetterOptions::with_filter(filter_min_points, min_points).select( CardNote::properties().npk_m_hash, account_npk_m_hash, - Option::none(), + Option::none() ).sort(CardNote::properties().points, SortOrder.ASC) } // docs:end:state_vars-NoteGetterOptionsFilter // docs:start:state_vars-NoteGetterOptionsPickOne -pub fn create_largest_account_card_getter_options( - account_npk_m_hash: Field, -) -> NoteGetterOptions { +pub fn create_largest_account_card_getter_options(account_npk_m_hash: Field) -> NoteGetterOptions { let mut options = NoteGetterOptions::new(); options.select( CardNote::properties().npk_m_hash, diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index 75ea16c0178..7da24c0af7b 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -1,7 +1,7 @@ use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}; use dep::aztec::{ - note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - keys::getters::get_nsk_app, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, + note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, keys::getters::get_nsk_app, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} }; global PUBLIC_KEY_NOTE_LEN: Field = 3; 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 3329c48ce8a..83f19970a86 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -85,13 +85,7 @@ contract Test { let owner_ivpk_m = get_ivpk_m(&mut context, owner); let mut note = ValueNote::new(value, owner_npk_m_hash); - create_note( - &mut context, - storage_slot, - &mut note, - true, - owner_ivpk_m, - ); + create_note(&mut context, storage_slot, &mut note, true, owner_ivpk_m); } #[aztec(private)] @@ -277,13 +271,7 @@ contract Test { let owner_ivpk_m = get_ivpk_m(&mut context, owner); let mut note = ValueNote::new(value + 1, owner_npk_m_hash); - create_note( - &mut context, - storage_slot, - &mut note, - true, - owner_ivpk_m, - ); + create_note(&mut context, storage_slot, &mut note, true, owner_ivpk_m); storage_slot += 1; Test::at(context.this_address()).call_create_note(value + 2, owner, storage_slot).call(&mut context); } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index b2e88a3ae77..3a99e4e0131 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -2,7 +2,7 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app }; trait OwnedNote { diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index b2e88a3ae77..3a99e4e0131 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -2,7 +2,7 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app }; trait OwnedNote { diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index ee1b8089fd5..a5426b9e740 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -95,7 +95,9 @@ export class TestKeyStore implements KeyStore { */ public async getMasterNullifierPublicKey(accountOrNpkMHash: AztecAddress | Fr): Promise { const masterNullifierPublicKeyBuffer = - this.#rotatedKeys.get(`${accountOrNpkMHash.toString()}-npk_m-${this.#rotatedNullifierKeyCount(accountOrNpkMHash) - 1}`) ?? + this.#rotatedKeys.get( + `${accountOrNpkMHash.toString()}-npk_m-${this.#rotatedNullifierKeyCount(accountOrNpkMHash) - 1}`, + ) ?? this.#keys.get(`${accountOrNpkMHash}-npk_m`) ?? this.#getMapMetadataForMasterNullifierPublicKeyHash(accountOrNpkMHash).value; @@ -164,12 +166,13 @@ export class TestKeyStore implements KeyStore { */ public async getAppNullifierSecretKey(accountOrNpkMHash: AztecAddress | Fr, app: AztecAddress): Promise { let masterNullifierSecretKeyBuffer = - this.#rotatedKeys.get(`${accountOrNpkMHash.toString()}-nsk_m-${this.#rotatedNullifierKeyCount(accountOrNpkMHash) - 1}`) ?? - this.#keys.get(`${accountOrNpkMHash}-nsk_m`); + this.#rotatedKeys.get( + `${accountOrNpkMHash.toString()}-nsk_m-${this.#rotatedNullifierKeyCount(accountOrNpkMHash) - 1}`, + ) ?? this.#keys.get(`${accountOrNpkMHash}-nsk_m`); if (!masterNullifierSecretKeyBuffer) { const { key } = this.#getMapMetadataForMasterNullifierPublicKeyHash(accountOrNpkMHash); const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); - + // #rotatedKeys has a suffix of -${index}, thus there will never be a clash, i.e. using a key in rotated keys will always return undefined if trying to retrieve something in keys // and using a key in #keys will always return undefined when searching in #rotatedKeys masterNullifierSecretKeyBuffer = diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 5805dfc351a..3bc690b0fac 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -141,7 +141,7 @@ describe('Private Execution test suite', () => { // Create a new snapshot. const newSnap = new AppendOnlyTreeSnapshot(Fr.fromBuffer(tree.getRoot(true)), Number(tree.getNumLeaves(true))); - if (name === 'noteHash' || name === 'l1ToL2Messages' || name === 'publicData') { + if (name === 'noteHash' || name === 'l1ToL2Messages' || name === 'publicData') { header = new Header( header.lastArchive, header.contentCommitment, @@ -191,13 +191,21 @@ describe('Private Execution test suite', () => { trees = {}; oracle = mock(); oracle.getNullifierKeys.mockImplementation((masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress) => { - if (masterNullifierPublicKeyHash.equals(poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()))) { + if ( + masterNullifierPublicKeyHash.equals( + poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + ) + ) { return Promise.resolve({ masterNullifierPublicKey: ownerCompleteAddress.publicKeys.masterNullifierPublicKey, appNullifierSecretKey: computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), }); } - if (masterNullifierPublicKeyHash.equals(poseidon2Hash(recipientCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()))) { + if ( + masterNullifierPublicKeyHash.equals( + poseidon2Hash(recipientCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + ) + ) { return Promise.resolve({ masterNullifierPublicKey: recipientCompleteAddress.publicKeys.masterNullifierPublicKey, appNullifierSecretKey: computeAppNullifierSecretKey(recipientMasterNullifierSecretKey, contractAddress), @@ -392,7 +400,20 @@ describe('Private Execution test suite', () => { const noteTypeId = StatefulTestContractArtifact.notes['ValueNote'].id; - const notes = [buildNote(60n, poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), storageSlot, noteTypeId), buildNote(80n, poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), storageSlot, noteTypeId)]; + const notes = [ + buildNote( + 60n, + poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + storageSlot, + noteTypeId, + ), + buildNote( + 80n, + poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + storageSlot, + noteTypeId, + ), + ]; oracle.getNotes.mockResolvedValue(notes); const consumedNotes = await asyncMap(notes, ({ nonce, note }) => @@ -449,7 +470,14 @@ describe('Private Execution test suite', () => { const storageSlot = computeSlotForMapping(new Fr(1n), owner); const noteTypeId = StatefulTestContractArtifact.notes['ValueNote'].id; - const notes = [buildNote(balance, poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), storageSlot, noteTypeId)]; + const notes = [ + buildNote( + balance, + poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + storageSlot, + noteTypeId, + ), + ]; oracle.getNotes.mockResolvedValue(notes); const consumedNotes = await asyncMap(notes, ({ nonce, note }) => From 9c91b242021c029c9bacdaf97d6d01a4101c57ca Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 11:02:07 +0000 Subject: [PATCH 106/125] fix snapshots --- .../crates/types/src/abis/private_call_stack_item.nr | 2 +- .../crates/types/src/abis/private_circuit_public_inputs.nr | 2 +- .../__snapshots__/private_call_stack_item.test.ts.snap | 4 ++-- .../__snapshots__/private_circuit_public_inputs.test.ts.snap | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index 567fc77e834..6c9f5e003d7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x0aee93406538a326693a1605c59c2bf63c4263805268c76e468951384b1d3ef3; + let test_data_empty_hash = 0x092493dbe24afc80afb32c5ba43dde1eb447a66f88a36676a63cdd04f21636ad; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index 5334731ed29..c9b97cbcc0a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -221,6 +221,6 @@ fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x29a90633db4700d98105131501f5de7097b5cb5c46ad44e613bbc0663e600837; + let test_data_empty_hash = 0x2a6e17b55aa91be7eb562d5fcf1bd67a0abed9098ec2d1a9c7e68541e7518326; assert_eq(hash, test_data_empty_hash); } diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index 9dfbaea9463..161ec6eecc5 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x0aee93406538a326693a1605c59c2bf63c4263805268c76e468951384b1d3ef3>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x092493dbe24afc80afb32c5ba43dde1eb447a66f88a36676a63cdd04f21636ad>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x25185e63e0746f9bfd7bac9053ee5b735a6da9fcd9a7a3d15b68e1b41c244db8>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x0a3f795ce85d43fddedcde7711982cf50382e3da1c0ad7afbbc2cb7a219a46c3>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 9e61ea8a4bb..b741933be5b 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x29a90633db4700d98105131501f5de7097b5cb5c46ad44e613bbc0663e600837>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x2a6e17b55aa91be7eb562d5fcf1bd67a0abed9098ec2d1a9c7e68541e7518326>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x007a35fde9fcf49b0f155581b07e0bd5e537f5ca70852deb9b335428aff0749a>`; \ No newline at end of file +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x112e706493a7ca33bb253550f8c1e4822c8193e4e2367aefda0f40fba4063455>`; \ No newline at end of file From 0d72bf44315c667db114c352f07f86eafc8cb0c2 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 11:27:25 +0000 Subject: [PATCH 107/125] yarn test --- yarn-project/simulator/src/client/simulator.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 5eb1ecde8d4..02070c73f89 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -9,7 +9,7 @@ import { import { ABIParameterVisibility, type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { poseidon2Hash } from '@aztec/foundation/crypto'; -import { Fr } from '@aztec/foundation/fields'; +import { Fr, type Point } from '@aztec/foundation/fields'; import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -22,7 +22,7 @@ describe('Simulator', () => { let node: MockProxy; let simulator: AcirSimulator; - let owner: AztecAddress; + let ownerMasterNullifierPublicKey: Point; let contractAddress: AztecAddress; let appNullifierSecretKey: Fr; @@ -30,14 +30,13 @@ describe('Simulator', () => { const ownerSk = Fr.fromString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); const allOwnerKeys = deriveKeys(ownerSk); - const ownerMasterNullifierPublicKey = allOwnerKeys.publicKeys.masterNullifierPublicKey; + ownerMasterNullifierPublicKey = allOwnerKeys.publicKeys.masterNullifierPublicKey; const ownerMasterNullifierSecretKey = allOwnerKeys.masterNullifierSecretKey; contractAddress = AztecAddress.random(); const ownerPartialAddress = Fr.random(); const ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSk, ownerPartialAddress); - owner = ownerCompleteAddress.address; appNullifierSecretKey = computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress); @@ -58,7 +57,8 @@ describe('Simulator', () => { const storageSlot = TokenContractArtifact.storageLayout['balances'].slot; const noteTypeId = TokenContractArtifact.notes['TokenNote'].id; - const createNote = (amount = 123n) => new Note([new Fr(amount), owner.toField(), Fr.random()]); + const createNote = (amount = 123n) => + new Note([new Fr(amount), poseidon2Hash(ownerMasterNullifierPublicKey.toFields()), Fr.random()]); it('should compute note hashes and nullifier', async () => { oracle.getFunctionArtifactByName.mockResolvedValue(artifact); From 657d5cf69fdb0b0883ca9d746739f0a6d345b391 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 12:57:02 +0000 Subject: [PATCH 108/125] Addressing comments --- .../aztec-nr/aztec/src/oracle/nullifier_key.nr | 1 - yarn-project/circuits.js/src/keys/index.ts | 6 +++++- yarn-project/pxe/src/database/kv_pxe_database.ts | 5 ++--- .../src/client/private_execution.test.ts | 15 ++++++++------- .../simulator/src/client/simulator.test.ts | 4 ++-- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr index bf5b6fdf47d..1d8fd94052f 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr @@ -18,7 +18,6 @@ impl Empty for NullifierKeys { } } -// TODO(#5630): Replace get_nullifier_keys above with this once we no longer get nullifier keys with address #[oracle(getNullifierKeys)] fn get_nullifier_keys_oracle(_npk_m_hash: Field) -> [Field; 3] {} diff --git a/yarn-project/circuits.js/src/keys/index.ts b/yarn-project/circuits.js/src/keys/index.ts index a994d96e5ae..597cec1119e 100644 --- a/yarn-project/circuits.js/src/keys/index.ts +++ b/yarn-project/circuits.js/src/keys/index.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { poseidon2Hash, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; -import { type Fq, type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; +import { type Point, type Fq, type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; import { Grumpkin } from '../barretenberg/crypto/grumpkin/index.js'; import { GeneratorIndex } from '../constants.gen.js'; @@ -34,6 +34,10 @@ export function derivePublicKeyFromSecretKey(secretKey: Fq) { return curve.mul(curve.generator(), secretKey); } +export function computeNpkMHash(npkM: Point) { + return poseidon2Hash(npkM.toFields()); +} + /** * Computes secret and public keys and public keys hash from a secret key. * @param secretKey - The secret key to derive keys from. diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 2de3eaff5b2..7192b8f869b 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -1,8 +1,7 @@ import { MerkleTreeId, type NoteFilter, NoteStatus, type PublicKey } from '@aztec/circuit-types'; -import { AztecAddress, CompleteAddress, Header } from '@aztec/circuits.js'; +import { AztecAddress, CompleteAddress, Header, computeNpkMHash } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; -import { poseidon2Hash } from '@aztec/foundation/crypto'; import { Fr, type Point } from '@aztec/foundation/fields'; import { type AztecArray, @@ -396,7 +395,7 @@ export class KVPxeDatabase implements PxeDatabase { const completeAddresses = this.#getCompleteAddresses(); const completeAddress = completeAddresses.find(completeAddress => - poseidon2Hash(completeAddress.publicKeys.masterNullifierPublicKey.toFields()).equals(npkMHash), + computeNpkMHash(completeAddress.publicKeys.masterNullifierPublicKey).equals(npkMHash), ); return Promise.resolve(completeAddress); } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 3bc690b0fac..d44609e0d34 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -29,6 +29,7 @@ import { deriveKeys, getContractInstanceFromDeployParams, getNonEmptyItems, + computeNpkMHash, } from '@aztec/circuits.js'; import { computeNoteHashNonce, computeSecretHash, computeVarArgsHash } from '@aztec/circuits.js/hash'; import { makeHeader } from '@aztec/circuits.js/testing'; @@ -193,7 +194,7 @@ describe('Private Execution test suite', () => { oracle.getNullifierKeys.mockImplementation((masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress) => { if ( masterNullifierPublicKeyHash.equals( - poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey), ) ) { return Promise.resolve({ @@ -203,7 +204,7 @@ describe('Private Execution test suite', () => { } if ( masterNullifierPublicKeyHash.equals( - poseidon2Hash(recipientCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + computeNpkMHash(recipientCompleteAddress.publicKeys.masterNullifierPublicKey), ) ) { return Promise.resolve({ @@ -288,7 +289,7 @@ describe('Private Execution test suite', () => { const mockFirstNullifier = new Fr(1111); let currentNoteIndex = 0n; - const buildNote = (amount: bigint, ownerNpkMH: Fr, storageSlot: Fr, noteTypeId: Fr) => { + const buildNote = (amount: bigint, ownerNpkMHash: Fr, storageSlot: Fr, noteTypeId: Fr) => { // WARNING: this is not actually how nonces are computed! // For the purpose of this test we use a mocked firstNullifier and and a random number // to compute the nonce. Proper nonces are only enforced later by the kernel/later circuits @@ -299,7 +300,7 @@ describe('Private Execution test suite', () => { // `hash(firstNullifier, noteHashIndex)` const noteHashIndex = randomInt(1); // mock index in TX's final newNoteHashes array const nonce = computeNoteHashNonce(mockFirstNullifier, noteHashIndex); - const note = new Note([new Fr(amount), ownerNpkMH, Fr.random()]); + const note = new Note([new Fr(amount), ownerNpkMHash, Fr.random()]); const innerNoteHash = pedersenHash(note.items); return { contractAddress, @@ -403,13 +404,13 @@ describe('Private Execution test suite', () => { const notes = [ buildNote( 60n, - poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey), storageSlot, noteTypeId, ), buildNote( 80n, - poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey), storageSlot, noteTypeId, ), @@ -473,7 +474,7 @@ describe('Private Execution test suite', () => { const notes = [ buildNote( balance, - poseidon2Hash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.toFields()), + computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey), storageSlot, noteTypeId, ), diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 02070c73f89..4954e69f216 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -1,5 +1,5 @@ import { type AztecNode, CompleteAddress, Note } from '@aztec/circuit-types'; -import { GeneratorIndex, computeAppNullifierSecretKey, deriveKeys } from '@aztec/circuits.js'; +import { GeneratorIndex, computeAppNullifierSecretKey, computeNpkMHash, deriveKeys } from '@aztec/circuits.js'; import { computeInnerNoteHash, computeNoteContentHash, @@ -58,7 +58,7 @@ describe('Simulator', () => { const noteTypeId = TokenContractArtifact.notes['TokenNote'].id; const createNote = (amount = 123n) => - new Note([new Fr(amount), poseidon2Hash(ownerMasterNullifierPublicKey.toFields()), Fr.random()]); + new Note([new Fr(amount), computeNpkMHash(ownerMasterNullifierPublicKey), Fr.random()]); it('should compute note hashes and nullifier', async () => { oracle.getFunctionArtifactByName.mockResolvedValue(artifact); From 5e5214b63b74295e8cae64b2f5e099874f0156c8 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 12:58:22 +0000 Subject: [PATCH 109/125] format --- yarn-project/circuits.js/src/keys/index.ts | 2 +- yarn-project/simulator/src/client/private_execution.test.ts | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/yarn-project/circuits.js/src/keys/index.ts b/yarn-project/circuits.js/src/keys/index.ts index 597cec1119e..2d0d4a374ef 100644 --- a/yarn-project/circuits.js/src/keys/index.ts +++ b/yarn-project/circuits.js/src/keys/index.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { poseidon2Hash, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; -import { type Point, type Fq, type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; +import { type Fq, type Fr, type GrumpkinScalar, type Point } from '@aztec/foundation/fields'; import { Grumpkin } from '../barretenberg/crypto/grumpkin/index.js'; import { GeneratorIndex } from '../constants.gen.js'; diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index d44609e0d34..e01bfacdbf8 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -26,10 +26,10 @@ import { StateReference, TxContext, computeAppNullifierSecretKey, + computeNpkMHash, deriveKeys, getContractInstanceFromDeployParams, getNonEmptyItems, - computeNpkMHash, } from '@aztec/circuits.js'; import { computeNoteHashNonce, computeSecretHash, computeVarArgsHash } from '@aztec/circuits.js/hash'; import { makeHeader } from '@aztec/circuits.js/testing'; @@ -193,9 +193,7 @@ describe('Private Execution test suite', () => { oracle = mock(); oracle.getNullifierKeys.mockImplementation((masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress) => { if ( - masterNullifierPublicKeyHash.equals( - computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey), - ) + masterNullifierPublicKeyHash.equals(computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey)) ) { return Promise.resolve({ masterNullifierPublicKey: ownerCompleteAddress.publicKeys.masterNullifierPublicKey, From c126db85ceb99772a85b89f1f9566009c7e3839c Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 13:21:53 +0000 Subject: [PATCH 110/125] Addressing comments --- yarn-project/pxe/src/simulator_oracle/index.ts | 6 +++--- yarn-project/simulator/src/acvm/oracle/typed_oracle.ts | 2 +- yarn-project/simulator/src/client/db_oracle.ts | 6 +++--- yarn-project/simulator/src/client/view_data_oracle.ts | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index e598a1c49e9..782496bef8f 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -37,9 +37,9 @@ export class SimulatorOracle implements DBOracle { private log = createDebugLogger('aztec:pxe:simulator_oracle'), ) {} - async getNullifierKeys(accountOrNpkMHash: AztecAddress | Fr, contractAddress: AztecAddress): Promise { - const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(accountOrNpkMHash); - const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(accountOrNpkMHash, contractAddress); + async getNullifierKeys(npkMHash: Fr, contractAddress: AztecAddress): Promise { + const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(npkMHash); + const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(npkMHash, contractAddress); return { masterNullifierPublicKey, appNullifierSecretKey }; } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 7da764e01ff..e4627cf30a9 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -89,7 +89,7 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('unpackReturns'); } - getNullifierKeys(_accountOrNpkMHash: AztecAddress | Fr): Promise { + getNullifierKeys(_npkMHash: Fr): Promise { throw new OracleMethodNotAvailableError('getNullifierKeys'); } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 13bc8a9c7d4..76cc6f4b837 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -66,12 +66,12 @@ export interface DBOracle extends CommitmentsDB { popCapsule(): Promise; /** - * Retrieve nullifier keys associated with a specific account or master nullifier public key and app address. - * @param accountOrNpkMHash - account address or master nullifier public key hash. + * Retrieve nullifier keys associated with a specific master nullifier public key and app address. + * @param npkMHash - master nullifier public key hash. * @returns A Promise that resolves to nullifier keys. * @throws If the nullifier keys are not registered in the key store. */ - getNullifierKeys(accountOrNpkMHash: AztecAddress | Fr, contractAddress: AztecAddress): Promise; + getNullifierKeys(npkMHash: Fr, contractAddress: AztecAddress): Promise; /** * Retrieves a set of notes stored in the database for a given contract address and storage slot. diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index bca1a2b0697..a8e5ec9f509 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -35,13 +35,13 @@ export class ViewDataOracle extends TypedOracle { } /** - * Retrieve nullifier keys associated with a specific account or master nullifier public key and app address. - * @param accountOrNpkMHash - account address or master nullifier public key hash. + * Retrieve nullifier keys associated with a specific master nullifier public key and app address. + * @param npkMHash - master nullifier public key hash. * @returns A Promise that resolves to nullifier keys. * @throws If the nullifier keys are not registered in the key store. */ - public override getNullifierKeys(accountOrNpkMHash: AztecAddress | Fr): Promise { - return this.db.getNullifierKeys(accountOrNpkMHash, this.contractAddress); + public override getNullifierKeys(npkMHash: Fr): Promise { + return this.db.getNullifierKeys(npkMHash, this.contractAddress); } /** From ef9ed1f7d8d71a107ee07353ee071bb13070d3b6 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 13:56:56 +0000 Subject: [PATCH 111/125] Addressing feedback --- .../pxe/src/database/kv_pxe_database.ts | 23 ++----------------- yarn-project/pxe/src/database/pxe_database.ts | 8 +++---- .../pxe/src/simulator_oracle/index.ts | 6 ++--- .../simulator/src/acvm/oracle/typed_oracle.ts | 2 +- .../simulator/src/client/db_oracle.ts | 6 ++--- .../client/unconstrained_execution.test.ts | 6 ++--- .../simulator/src/client/view_data_oracle.ts | 8 +++---- 7 files changed, 20 insertions(+), 39 deletions(-) diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 7192b8f869b..b251c05e5c2 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -375,7 +375,7 @@ export class KVPxeDatabase implements PxeDatabase { }); } - #getCompleteAddress(address: AztecAddress): CompleteAddress | undefined { + getCompleteAddress(address: AztecAddress): CompleteAddress | undefined { const index = this.#addressIndex.get(address.toString()); if (typeof index === 'undefined') { return undefined; @@ -385,27 +385,8 @@ export class KVPxeDatabase implements PxeDatabase { return value ? CompleteAddress.fromBuffer(value) : undefined; } - getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise { - return Promise.resolve( - this.#getCompleteAddress(accountOrNpkMHash) ?? this.#getCompleteAddressWithNpkMHash(accountOrNpkMHash), - ); - } - - #getCompleteAddressWithNpkMHash(npkMHash: Fr): Promise { - const completeAddresses = this.#getCompleteAddresses(); - - const completeAddress = completeAddresses.find(completeAddress => - computeNpkMHash(completeAddress.publicKeys.masterNullifierPublicKey).equals(npkMHash), - ); - return Promise.resolve(completeAddress); - } - - #getCompleteAddresses(): CompleteAddress[] { - return Array.from(this.#addresses).map(v => CompleteAddress.fromBuffer(v)); - } - getCompleteAddresses(): Promise { - return Promise.resolve(this.#getCompleteAddresses()); + return Promise.resolve(Array.from(this.#addresses).map(v => CompleteAddress.fromBuffer(v))); } getSynchedBlockNumberForPublicKey(publicKey: Point): number | undefined { diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index 13c930b2b92..fcefa622ecc 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -133,14 +133,14 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD addCompleteAddress(address: CompleteAddress): Promise; /** - * Retrieve the complete address associated to a given address or master nullifier public key hash. - * @param accountOrNpkMHash - account address or master nullifier public key hash. + * Retrieve the complete address associated to a given address. + * @param account - account address. * @returns A promise that resolves to a CompleteAddress instance if found, or undefined if not found. */ - getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise; + getCompleteAddress(account: AztecAddress): Promise; /** - * Retrieves the list of complete address added to this database + * Retrieves the list of complete addresses added to this database * @returns A promise that resolves to an array of AztecAddress instances. */ getCompleteAddresses(): Promise; diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 782496bef8f..0aafc050919 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -43,11 +43,11 @@ export class SimulatorOracle implements DBOracle { return { masterNullifierPublicKey, appNullifierSecretKey }; } - async getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise { - const completeAddress = await this.db.getCompleteAddress(accountOrNpkMHash); + async getCompleteAddress(account: AztecAddress): Promise { + const completeAddress = await this.db.getCompleteAddress(account); if (!completeAddress) { throw new Error( - `No public key registered for address or master nullifier public key hash ${accountOrNpkMHash}. + `No public key registered for address ${account}. Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/developers/debugging/aztecnr-errors#simulation-error-No-public-key-registered-for-address-0x0-Register-it-by-calling-pxeregisterRecipient-or-pxeregisterAccount`, ); } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index e4627cf30a9..4a910040384 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -124,7 +124,7 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getHeader'); } - getCompleteAddress(_accountOrNpkMHash: AztecAddress | Fr): Promise { + getCompleteAddress(_account: AztecAddress): Promise { throw new OracleMethodNotAvailableError('getCompleteAddress'); } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 76cc6f4b837..2a4543c24cf 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -44,12 +44,12 @@ export interface DBOracle extends CommitmentsDB { getContractInstance(address: AztecAddress): Promise; /** - * Retrieve the complete address associated to a given address or master nullifier public key hash. - * @param accountOrNpkMHash - account address or master nullifier public key hash. + * Retrieve the complete address associated to a given address. + * @param account - account address. * @returns A complete address associated with the input address or master nullifier public key hash * @throws An error if the account is not registered in the database. */ - getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise; + getCompleteAddress(account: AztecAddress): Promise; /** * Retrieve the auth witness for a given message hash. diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index 3d1b69cb0ca..9077aa0489e 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -33,11 +33,11 @@ describe('Unconstrained Execution test suite', () => { const ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSecretKey, Fr.random()); owner = ownerCompleteAddress.address; - oracle.getCompleteAddress.mockImplementation((accountOrNpkMHash: AztecAddress | Fr) => { - if (accountOrNpkMHash.equals(owner)) { + oracle.getCompleteAddress.mockImplementation((account: AztecAddress) => { + if (account.equals(owner)) { return Promise.resolve(ownerCompleteAddress); } - throw new Error(`Unknown address ${accountOrNpkMHash}`); + throw new Error(`Unknown address ${account}`); }); }); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index a8e5ec9f509..9314945644a 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -127,13 +127,13 @@ export class ViewDataOracle extends TypedOracle { } /** - * Retrieve the complete address associated to a given address or master nullifier public key hash. - * @param accountOrNpkMHash - account address or master nullifier public key hash. + * Retrieve the complete address associated to a given address. + * @param account - account address. * @returns A complete address associated with the input address or master nullifier public key hash * @throws An error if the account is not registered in the database. */ - public override getCompleteAddress(accountOrNpkMHash: AztecAddress | Fr): Promise { - return this.db.getCompleteAddress(accountOrNpkMHash); + public override getCompleteAddress(account: AztecAddress): Promise { + return this.db.getCompleteAddress(account); } /** From bd788a067cbfedb23fc85df50661e8190385e115 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 14:02:58 +0000 Subject: [PATCH 112/125] comments --- yarn-project/pxe/src/database/kv_pxe_database.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index b251c05e5c2..a54d1f2db04 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -375,7 +375,7 @@ export class KVPxeDatabase implements PxeDatabase { }); } - getCompleteAddress(address: AztecAddress): CompleteAddress | undefined { + #getCompleteAddress(address: AztecAddress): CompleteAddress | undefined { const index = this.#addressIndex.get(address.toString()); if (typeof index === 'undefined') { return undefined; @@ -385,6 +385,10 @@ export class KVPxeDatabase implements PxeDatabase { return value ? CompleteAddress.fromBuffer(value) : undefined; } + getCompleteAddress(account: AztecAddress): Promise { + return Promise.resolve(this.#getCompleteAddress(account)); + } + getCompleteAddresses(): Promise { return Promise.resolve(Array.from(this.#addresses).map(v => CompleteAddress.fromBuffer(v))); } From 3e953666b74b67827ceb9b7c25870314f2416375 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 14:33:21 +0000 Subject: [PATCH 113/125] fix --- yarn-project/pxe/src/database/kv_pxe_database.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index a54d1f2db04..f17bc651823 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -1,5 +1,5 @@ import { MerkleTreeId, type NoteFilter, NoteStatus, type PublicKey } from '@aztec/circuit-types'; -import { AztecAddress, CompleteAddress, Header, computeNpkMHash } from '@aztec/circuits.js'; +import { AztecAddress, CompleteAddress, Header } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; import { Fr, type Point } from '@aztec/foundation/fields'; From 0cfb14e74b96e6f36ad60f2231864fe40ceaf78b Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 14:59:37 +0000 Subject: [PATCH 114/125] address comments --- .../circuit-types/src/keys/key_store.ts | 8 ++-- .../key-store/src/test_key_store.test.ts | 13 +++++-- yarn-project/key-store/src/test_key_store.ts | 37 +++++++------------ 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 32336a6889e..3ece2e176bc 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -35,10 +35,10 @@ export interface KeyStore { /** * Gets the master nullifier public key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param accountOrNpkMHash - account address or master nullifier public key hash. + * @param npkMHash - master nullifier public key hash. * @returns The master nullifier public key for the account. */ - getMasterNullifierPublicKey(accountOrNpkMHash: AztecAddress | Fr): Promise; + getMasterNullifierPublicKey(npkMHash: Fr): Promise; /** * Gets the master incoming viewing public key for a given account. @@ -67,11 +67,11 @@ export interface KeyStore { /** * Derives and returns the application nullifier secret key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param accountOrNpkMHash - account address or master nullifier public key hash. + * @param npkMHash - master nullifier public key hash. * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ - getAppNullifierSecretKey(accountOrNpkMHash: AztecAddress | Fr, app: AztecAddress): Promise; + getAppNullifierSecretKey(npkMHash: Fr, app: AztecAddress): Promise; /** * Retrieves application incoming viewing secret key. diff --git a/yarn-project/key-store/src/test_key_store.test.ts b/yarn-project/key-store/src/test_key_store.test.ts index 2395dbf1472..7f704e9819c 100644 --- a/yarn-project/key-store/src/test_key_store.test.ts +++ b/yarn-project/key-store/src/test_key_store.test.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr } from '@aztec/circuits.js'; +import { AztecAddress, Fr, computeNpkMHash, deriveKeys, derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; import { openTmpStore } from '@aztec/kv-store/utils'; import { TestKeyStore } from './test_key_store.js'; @@ -9,6 +9,10 @@ describe('TestKeyStore', () => { // Arbitrary fixed values const sk = new Fr(8923n); + const keys = deriveKeys(sk); + const derivedMasterNullifierPublicKey = derivePublicKeyFromSecretKey(keys.masterNullifierSecretKey); + const computedMasterNullifierPublicKeyHash = computeNpkMHash(derivedMasterNullifierPublicKey); + const partialAddress = new Fr(243523n); const { address: accountAddress } = await keyStore.addAccount(sk, partialAddress); @@ -16,7 +20,7 @@ describe('TestKeyStore', () => { `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, ); - const masterNullifierPublicKey = await keyStore.getMasterNullifierPublicKey(accountAddress); + const masterNullifierPublicKey = await keyStore.getMasterNullifierPublicKey(computedMasterNullifierPublicKeyHash); expect(masterNullifierPublicKey.toString()).toMatchInlineSnapshot( `"0x2ef5d15dd65d29546680ab72846fb071f41cb9f2a0212215e6c560e29df4ff650ce764818364b376be92dc2f49577fe440e64a16012584f7c4ee94f7edbc323a"`, ); @@ -44,7 +48,10 @@ describe('TestKeyStore', () => { // Arbitrary app contract address const appAddress = AztecAddress.fromBigInt(624n); - const appNullifierSecretKey = await keyStore.getAppNullifierSecretKey(accountAddress, appAddress); + const appNullifierSecretKey = await keyStore.getAppNullifierSecretKey( + computedMasterNullifierPublicKeyHash, + appAddress, + ); expect(appNullifierSecretKey.toString()).toMatchInlineSnapshot( `"0x230a44dfe7cfec7a735c89f7289c5cb5d2c3dc0bf5d3505917fd2476f67873a8"`, ); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index a5426b9e740..6962fd12da2 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -90,20 +90,15 @@ export class TestKeyStore implements KeyStore { /** * Gets the master nullifier public key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param accountOrNpkMHash - account address or master nullifier public key hash. + * @param npkMHash - master nullifier public key hash. * @returns The master nullifier public key for the account. */ - public async getMasterNullifierPublicKey(accountOrNpkMHash: AztecAddress | Fr): Promise { - const masterNullifierPublicKeyBuffer = - this.#rotatedKeys.get( - `${accountOrNpkMHash.toString()}-npk_m-${this.#rotatedNullifierKeyCount(accountOrNpkMHash) - 1}`, - ) ?? - this.#keys.get(`${accountOrNpkMHash}-npk_m`) ?? - this.#getMapMetadataForMasterNullifierPublicKeyHash(accountOrNpkMHash).value; + public async getMasterNullifierPublicKey(npkMHash: Fr): Promise { + const masterNullifierPublicKeyBuffer = this.#getMapMetadataForMasterNullifierPublicKeyHash(npkMHash).value; if (!masterNullifierPublicKeyBuffer) { throw new Error( - `Account or master nullifier public key hash ${accountOrNpkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, + `Master nullifier public key hash ${npkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); @@ -160,28 +155,22 @@ export class TestKeyStore implements KeyStore { /** * Derives and returns the application nullifier secret key for a given account or master nullifier public key hash. * @throws If the account does not exist in the key store. - * @param accountOrNpkMHash - account address or master nullifier public key hash. + * @param npkMHash - account address or master nullifier public key hash. * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ - public async getAppNullifierSecretKey(accountOrNpkMHash: AztecAddress | Fr, app: AztecAddress): Promise { - let masterNullifierSecretKeyBuffer = - this.#rotatedKeys.get( - `${accountOrNpkMHash.toString()}-nsk_m-${this.#rotatedNullifierKeyCount(accountOrNpkMHash) - 1}`, - ) ?? this.#keys.get(`${accountOrNpkMHash}-nsk_m`); - if (!masterNullifierSecretKeyBuffer) { - const { key } = this.#getMapMetadataForMasterNullifierPublicKeyHash(accountOrNpkMHash); - const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); + public async getAppNullifierSecretKey(npkMHash: Fr, app: AztecAddress): Promise { + const { key } = this.#getMapMetadataForMasterNullifierPublicKeyHash(npkMHash); + const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); - // #rotatedKeys has a suffix of -${index}, thus there will never be a clash, i.e. using a key in rotated keys will always return undefined if trying to retrieve something in keys - // and using a key in #keys will always return undefined when searching in #rotatedKeys - masterNullifierSecretKeyBuffer = - this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); - } + // #rotatedKeys has a suffix of -${index}, thus there will never be a clash, i.e. using a key in rotated keys will always return undefined if trying to retrieve something in keys + // and using a key in #keys will always return undefined when searching in #rotatedKeys + const masterNullifierSecretKeyBuffer = + this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); if (!masterNullifierSecretKeyBuffer) { throw new Error( - `Account or master nullifier public key hash ${accountOrNpkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, + `Master nullifier public key hash ${npkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } From 870e03c1baf8550441a6766cd81c696e7dad4a50 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 15:03:59 +0000 Subject: [PATCH 115/125] comments --- yarn-project/circuit-types/src/keys/key_store.ts | 8 ++++---- yarn-project/key-store/src/test_key_store.ts | 10 +++++----- yarn-project/simulator/src/client/db_oracle.ts | 2 +- yarn-project/simulator/src/client/view_data_oracle.ts | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 3ece2e176bc..8914cee9b07 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -33,8 +33,8 @@ export interface KeyStore { getAccounts(): Promise; /** - * Gets the master nullifier public key for a given account or master nullifier public key hash. - * @throws If the account does not exist in the key store. + * Gets the master nullifier public key for a given master nullifier public key hash. + * @throws If the account corresponding to the master nullifier public key hash does not exist in the key store. * @param npkMHash - master nullifier public key hash. * @returns The master nullifier public key for the account. */ @@ -65,8 +65,8 @@ export interface KeyStore { getMasterTaggingPublicKey(account: AztecAddress): Promise; /** - * Derives and returns the application nullifier secret key for a given account or master nullifier public key hash. - * @throws If the account does not exist in the key store. + * Derives and returns the application nullifier secret key for a given master nullifier public key hash. + * @throws If the account corresponding to the master nullifier public key hash does not exist in the key store. * @param npkMHash - master nullifier public key hash. * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 6962fd12da2..0296ed47b1f 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -88,8 +88,8 @@ export class TestKeyStore implements KeyStore { } /** - * Gets the master nullifier public key for a given account or master nullifier public key hash. - * @throws If the account does not exist in the key store. + * Gets the master nullifier public key for a given master nullifier public key hash. + * @throws If the account corresponding to the master nullifier public key hash does not exist in the key store. * @param npkMHash - master nullifier public key hash. * @returns The master nullifier public key for the account. */ @@ -153,9 +153,9 @@ export class TestKeyStore implements KeyStore { } /** - * Derives and returns the application nullifier secret key for a given account or master nullifier public key hash. - * @throws If the account does not exist in the key store. - * @param npkMHash - account address or master nullifier public key hash. + * Derives and returns the application nullifier secret key for a given master nullifier public key hash. + * @throws If the account corresponding to the master nullifier public key hash does not exist in the key store. + * @param npkMHash - master nullifier public key hash. * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 2a4543c24cf..cd3f69fa3f4 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -46,7 +46,7 @@ export interface DBOracle extends CommitmentsDB { /** * Retrieve the complete address associated to a given address. * @param account - account address. - * @returns A complete address associated with the input address or master nullifier public key hash + * @returns A complete address associated with the input address * @throws An error if the account is not registered in the database. */ getCompleteAddress(account: AztecAddress): Promise; diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 9314945644a..df1528faba4 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -129,7 +129,7 @@ export class ViewDataOracle extends TypedOracle { /** * Retrieve the complete address associated to a given address. * @param account - account address. - * @returns A complete address associated with the input address or master nullifier public key hash + * @returns A complete address associated with the input address * @throws An error if the account is not registered in the database. */ public override getCompleteAddress(account: AztecAddress): Promise { From f4dc806ee6a5b58f944de4b65ab8951ee1d87ab5 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 15:15:18 +0000 Subject: [PATCH 116/125] comment --- yarn-project/circuit-types/src/keys/key_store.ts | 4 ++-- yarn-project/key-store/src/test_key_store.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn-project/circuit-types/src/keys/key_store.ts b/yarn-project/circuit-types/src/keys/key_store.ts index 8914cee9b07..1dbeeb7831c 100644 --- a/yarn-project/circuit-types/src/keys/key_store.ts +++ b/yarn-project/circuit-types/src/keys/key_store.ts @@ -35,7 +35,7 @@ export interface KeyStore { /** * Gets the master nullifier public key for a given master nullifier public key hash. * @throws If the account corresponding to the master nullifier public key hash does not exist in the key store. - * @param npkMHash - master nullifier public key hash. + * @param npkMHash - The master nullifier public key hash. * @returns The master nullifier public key for the account. */ getMasterNullifierPublicKey(npkMHash: Fr): Promise; @@ -67,7 +67,7 @@ export interface KeyStore { /** * Derives and returns the application nullifier secret key for a given master nullifier public key hash. * @throws If the account corresponding to the master nullifier public key hash does not exist in the key store. - * @param npkMHash - master nullifier public key hash. + * @param npkMHash - The master nullifier public key hash. * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 0296ed47b1f..5d5023762eb 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -90,7 +90,7 @@ export class TestKeyStore implements KeyStore { /** * Gets the master nullifier public key for a given master nullifier public key hash. * @throws If the account corresponding to the master nullifier public key hash does not exist in the key store. - * @param npkMHash - master nullifier public key hash. + * @param npkMHash - The master nullifier public key hash. * @returns The master nullifier public key for the account. */ public async getMasterNullifierPublicKey(npkMHash: Fr): Promise { @@ -155,7 +155,7 @@ export class TestKeyStore implements KeyStore { /** * Derives and returns the application nullifier secret key for a given master nullifier public key hash. * @throws If the account corresponding to the master nullifier public key hash does not exist in the key store. - * @param npkMHash - master nullifier public key hash. + * @param npkMHash - The master nullifier public key hash. * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ From e4866ebcaf7e37ae2225890f8005ac1b58325aec Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 16:19:24 +0000 Subject: [PATCH 117/125] Comments --- .../contracts/app_subscription_contract/src/main.nr | 8 +++++--- yarn-project/pxe/src/database/pxe_database.ts | 2 +- yarn-project/simulator/src/client/db_oracle.ts | 6 +++--- yarn-project/simulator/src/client/view_data_oracle.ts | 6 +++--- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index f0a7ebed371..25bcda79fc0 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -9,7 +9,8 @@ contract AppSubscription { AztecAddress, FunctionSelector, PrivateContext, NoteHeader, Map, PrivateMutable, PublicMutable, SharedImmutable }, - protocol_types::traits::is_empty, keys::getters::{get_npk_m_hash, get_ivpk_m} + protocol_types::{traits::is_empty, grumpkin_point::GrumpkinPoint}, + keys::getters::{get_npk_m_hash, get_ivpk_m} }, authwit::{account::AccountActions, auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit}, gas_token::GasToken, token::Token @@ -36,12 +37,13 @@ contract AppSubscription { fn entrypoint(payload: DAppPayload, user_address: AztecAddress) { assert(context.msg_sender().to_field() == 0); assert_current_call_valid_authwit(&mut context, user_address); - let subscriber_ivpk_m = get_ivpk_m(&mut context, user_address); - let mut note = storage.subscriptions.at(user_address).get_note(false, subscriber_ivpk_m); + let mut note = storage.subscriptions.at(user_address).get_note(false, GrumpkinPoint::zero()); assert(note.remaining_txs as u64 > 0, "you're out of txs"); note.remaining_txs -= 1; + + let subscriber_ivpk_m = get_ivpk_m(&mut context, user_address); storage.subscriptions.at(user_address).replace(&mut note, true, subscriber_ivpk_m); context.set_as_fee_payer(); diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index fcefa622ecc..e37d8fc7069 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -134,7 +134,7 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD /** * Retrieve the complete address associated to a given address. - * @param account - account address. + * @param account - The account address. * @returns A promise that resolves to a CompleteAddress instance if found, or undefined if not found. */ getCompleteAddress(account: AztecAddress): Promise; diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index cd3f69fa3f4..f36616c2303 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -45,8 +45,8 @@ export interface DBOracle extends CommitmentsDB { /** * Retrieve the complete address associated to a given address. - * @param account - account address. - * @returns A complete address associated with the input address + * @param account - The account address. + * @returns A complete address associated with the input address. * @throws An error if the account is not registered in the database. */ getCompleteAddress(account: AztecAddress): Promise; @@ -67,7 +67,7 @@ export interface DBOracle extends CommitmentsDB { /** * Retrieve nullifier keys associated with a specific master nullifier public key and app address. - * @param npkMHash - master nullifier public key hash. + * @param npkMHash - The master nullifier public key hash. * @returns A Promise that resolves to nullifier keys. * @throws If the nullifier keys are not registered in the key store. */ diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index df1528faba4..68479c6266b 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -36,7 +36,7 @@ export class ViewDataOracle extends TypedOracle { /** * Retrieve nullifier keys associated with a specific master nullifier public key and app address. - * @param npkMHash - master nullifier public key hash. + * @param npkMHash - The master nullifier public key hash. * @returns A Promise that resolves to nullifier keys. * @throws If the nullifier keys are not registered in the key store. */ @@ -128,8 +128,8 @@ export class ViewDataOracle extends TypedOracle { /** * Retrieve the complete address associated to a given address. - * @param account - account address. - * @returns A complete address associated with the input address + * @param account - The account address. + * @returns A complete address associated with the input address. * @throws An error if the account is not registered in the database. */ public override getCompleteAddress(account: AztecAddress): Promise { From 3bdc06352502df41228a27ead0b60d5ebfb8494a Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 16:31:41 +0000 Subject: [PATCH 118/125] comment --- yarn-project/end-to-end/src/e2e_key_rotation.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts index 6c3f3b5c406..9b6e9c98311 100644 --- a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts @@ -22,7 +22,7 @@ import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup, setupPXEService } f const TIMEOUT = 120_000; -describe('e2e_2_pxes', () => { +describe('e2e_key_rotation', () => { jest.setTimeout(TIMEOUT); let aztecNode: AztecNode | undefined; From 7d8864e98ae17bf9dc45b506ec4bb469ea2ee882 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 19:54:26 +0000 Subject: [PATCH 119/125] Addressing comments --- .../aztec-nr/address-note/src/address_note.nr | 2 +- .../aztec-nr/aztec/src/context/private_context.nr | 8 ++++---- .../aztec/src/encrypted_logs/incoming_body.nr | 2 +- noir-projects/aztec-nr/aztec/src/hash.nr | 2 +- noir-projects/aztec-nr/aztec/src/keys/getters.nr | 7 +++---- noir-projects/aztec-nr/aztec/src/oracle.nr | 2 +- .../oracle/{nullifier_key.nr => nullifier_keys.nr} | 0 .../easy-private-state/src/easy_private_uint.nr | 11 +++++++---- noir-projects/aztec-nr/value-note/src/utils.nr | 1 + noir-projects/aztec-nr/value-note/src/value_note.nr | 2 +- .../src/subscription_note.nr | 2 +- .../contracts/card_game_contract/src/cards.nr | 7 ++++--- .../contracts/claim_contract/src/main.nr | 2 ++ .../contracts/delegated_on_contract/src/main.nr | 1 + .../contracts/delegator_contract/src/main.nr | 1 + .../docs_example_contract/src/types/card_note.nr | 2 +- .../easy_private_voting_contract/src/main.nr | 1 + .../contracts/inclusion_proofs_contract/src/main.nr | 4 ++++ .../contracts/stateful_test_contract/src/main.nr | 1 + .../src/types/balances_map.nr | 10 ++++++---- .../token_blacklist_contract/src/types/token_note.nr | 3 +-- .../token_contract/src/types/balances_map.nr | 10 ++++++---- .../contracts/token_contract/src/types/token_note.nr | 3 +-- .../crates/types/src/grumpkin_point.nr | 8 +++++++- yarn-project/end-to-end/src/e2e_key_rotation.test.ts | 7 ++++++- 25 files changed, 63 insertions(+), 36 deletions(-) rename noir-projects/aztec-nr/aztec/src/oracle/{nullifier_key.nr => nullifier_keys.nr} (100%) diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index d71ff647109..4618fd26b3f 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -15,7 +15,7 @@ global ADDRESS_NOTE_LEN: Field = 3; #[aztec(note)] struct AddressNote { address: AztecAddress, - // The nullifying public key hash is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. npk_m_hash: Field, randomness: Field, } diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index d92e1dd61a8..ce7987cf015 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -3,7 +3,7 @@ use crate::{ keys::getters::get_nullifier_keys, messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher, compute_encrypted_log_hash, compute_unencrypted_log_hash}, oracle::{ - nullifier_key::NullifierKeys, arguments, returns, + nullifier_keys::NullifierKeys, arguments, returns, call_private_function::call_private_function_internal, header::get_header_at, logs::emit_encrypted_log, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, enqueue_public_function_call::{ @@ -31,7 +31,7 @@ use dep::protocol_types::{ contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, - traits::{is_empty, Deserialize, Empty}, hash::poseidon2_hash + traits::{is_empty, Deserialize, Empty} }; // When finished, one can call .finish() to convert back to the abi @@ -207,7 +207,7 @@ impl PrivateContext { // A value of empty nullifier keys will fail the key validation request. let cached_nullifier_keys = self.nullifier_key.unwrap_or(NullifierKeys::empty()); - let nullifier_keys = if poseidon2_hash(cached_nullifier_keys.master_nullifier_public_key.serialize()) == npk_m_hash { + let nullifier_keys = if cached_nullifier_keys.master_nullifier_public_key.hash() == npk_m_hash { cached_nullifier_keys } else { let fetched_nullifier_keys = get_nullifier_keys(npk_m_hash); @@ -220,7 +220,7 @@ impl PrivateContext { fetched_nullifier_keys }; - assert_eq(poseidon2_hash(nullifier_keys.master_nullifier_public_key.serialize()), npk_m_hash); + assert_eq(nullifier_keys.master_nullifier_public_key.hash(), npk_m_hash); nullifier_keys.app_nullifier_secret_key } diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr index 58e8d2f79bf..a0de2ac6e56 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr @@ -67,7 +67,7 @@ mod test { use crate::{ note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::unsafe_rand::unsafe_rand, context::PrivateContext, hash::poseidon2_hash + oracle::unsafe_rand::unsafe_rand, context::PrivateContext, }; struct AddressNote { diff --git a/noir-projects/aztec-nr/aztec/src/hash.nr b/noir-projects/aztec-nr/aztec/src/hash.nr index 989ecfb0f31..f0abd4912e1 100644 --- a/noir-projects/aztec-nr/aztec/src/hash.nr +++ b/noir-projects/aztec-nr/aztec/src/hash.nr @@ -4,7 +4,7 @@ use dep::protocol_types::{ GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT, GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH }, - traits::Hash, hash::{pedersen_hash, poseidon2_hash, silo_nullifier, sha256_to_field} + traits::Hash, hash::{pedersen_hash, silo_nullifier, sha256_to_field} }; use crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}; diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index 6fab5705194..523c6ed4f5a 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -1,12 +1,11 @@ use dep::protocol_types::{ address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, - hash::poseidon2_hash }; use crate::{ context::PrivateContext, oracle::{ keys::get_public_keys_and_partial_address, - nullifier_key::{NullifierKeys, get_nullifier_keys as get_nullifier_keys_oracle} + nullifier_keys::{NullifierKeys, get_nullifier_keys as get_nullifier_keys_oracle} }, keys::public_keys::{PublicKeys, NULLIFIER_INDEX, INCOMING_INDEX}, state_vars::{ @@ -22,7 +21,7 @@ pub fn get_npk_m(context: &mut PrivateContext, address: AztecAddress) -> Grumpki } pub fn get_npk_m_hash(context: &mut PrivateContext, address: AztecAddress) -> Field { - poseidon2_hash(get_master_key(context, address, NULLIFIER_INDEX).serialize()) + get_master_key(context, address, NULLIFIER_INDEX).hash() } pub fn get_ivpk_m(context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint { @@ -95,7 +94,7 @@ fn fetch_and_constrain_keys(address: AztecAddress) -> PublicKeys { // We get the full struct Nullifier Keys here pub fn get_nullifier_keys(npk_m_hash: Field) -> NullifierKeys { let nullifier_keys = get_nullifier_keys_oracle(npk_m_hash); - assert_eq(poseidon2_hash(nullifier_keys.master_nullifier_public_key.serialize()), npk_m_hash); + assert_eq(nullifier_keys.master_nullifier_public_key.hash(), npk_m_hash); nullifier_keys } diff --git a/noir-projects/aztec-nr/aztec/src/oracle.nr b/noir-projects/aztec-nr/aztec/src/oracle.nr index 59031fcdb9f..2d3cc6dd1f9 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle.nr @@ -11,7 +11,7 @@ mod get_nullifier_membership_witness; mod get_public_data_witness; mod get_membership_witness; mod keys; -mod nullifier_key; +mod nullifier_keys; mod get_sibling_path; mod unsafe_rand; mod enqueue_public_function_call; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr b/noir-projects/aztec-nr/aztec/src/oracle/nullifier_keys.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr rename to noir-projects/aztec-nr/aztec/src/oracle/nullifier_keys.nr diff --git a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr index e11a3484eb7..af6a3609ea6 100644 --- a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr +++ b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr @@ -22,9 +22,10 @@ impl EasyPrivateUint { // Very similar to `value_note::utils::increment`. pub fn add(self, addend: u64, owner: AztecAddress) { assert(self.context.public.is_none(), "EasyPrivateUint::add can be called from private only."); + let context = self.context.private.unwrap(); - let owner_npk_m_hash = get_npk_m_hash(self.context.private.unwrap(), owner); - let owner_ivpk_m = get_ivpk_m(self.context.private.unwrap(), owner); + let owner_npk_m_hash = get_npk_m_hash(context, owner); + let owner_ivpk_m = get_ivpk_m(context, owner); // Creates new note for the owner. let mut addend_note = ValueNote::new(addend as Field, owner_npk_m_hash); @@ -37,9 +38,10 @@ impl EasyPrivateUint { // Very similar to `value_note::utils::decrement`. pub fn sub(self, subtrahend: u64, owner: AztecAddress) { assert(self.context.public.is_none(), "EasyPrivateUint::sub can be called from private only."); + let context = self.context.private.unwrap(); - let owner_npk_m_hash = get_npk_m_hash(self.context.private.unwrap(), owner); - let owner_ivpk_m = get_ivpk_m(self.context.private.unwrap(), owner); + let owner_npk_m_hash = get_npk_m_hash(context, owner); + let owner_ivpk_m = get_ivpk_m(context, owner); // docs:start:get_notes let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend as Field); @@ -53,6 +55,7 @@ impl EasyPrivateUint { // Ensure the notes are actually owned by the owner (to prevent user from generating a valid proof while // spending someone else's notes). + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to pass this assert after rotating key assert(note.npk_m_hash.eq(owner_npk_m_hash)); // Removes the note from the owner's set of notes. diff --git a/noir-projects/aztec-nr/value-note/src/utils.nr b/noir-projects/aztec-nr/value-note/src/utils.nr index c142d95e66b..80392c24b2f 100644 --- a/noir-projects/aztec-nr/value-note/src/utils.nr +++ b/noir-projects/aztec-nr/value-note/src/utils.nr @@ -87,6 +87,7 @@ pub fn destroy_note( // spending someone else's notes). let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to pass this after rotating keys. assert(note.npk_m_hash.eq(owner_npk_m_hash)); balance.remove(note); diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 9a4b19e570d..bac3c043465 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -15,7 +15,7 @@ global VALUE_NOTE_LEN: Field = 3; // 3 plus a header. #[aztec(note)] struct ValueNote { value: Field, - // The nullifying public key hash is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. npk_m_hash: Field, randomness: Field, } diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index 9da4e7d6828..4c968e4f6a1 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -11,7 +11,7 @@ global SUBSCRIPTION_NOTE_LEN: Field = 3; // TODO: Do we need to include a nonce, in case we want to read/nullify/recreate with the same pubkey value? #[aztec(note)] struct SubscriptionNote { - // The nullifying public key hash is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. npk_m_hash: Field, expiry_block_number: Field, remaining_txs: Field, 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 43ec4efdf02..72f51f7fd57 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 @@ -103,10 +103,10 @@ impl Deck { } pub fn add_cards(&mut self, cards: [Card; N], owner: AztecAddress) -> [CardNote] { - let _context = self.set.context.private.unwrap(); + let context = self.set.context.private.unwrap(); - let owner_npk_m_hash = get_npk_m_hash(self.set.context.private.unwrap(), owner); - let owner_ivpk_m = get_ivpk_m(self.set.context.private.unwrap(), owner); + let owner_npk_m_hash = get_npk_m_hash(context, owner); + let owner_ivpk_m = get_ivpk_m(context, owner); let mut inserted_cards = &[]; for card in cards { @@ -129,6 +129,7 @@ impl Deck { let card_note = CardNote::from_note(maybe_notes[i].unwrap_unchecked()); // Ensure the notes are actually owned by the owner (to prevent user from generating a valid proof while // spending someone else's notes). + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to pass this assert after rotating keys. assert(card_note.note.npk_m_hash.eq(owner_npk_m_hash)); for j in 0..cards.len() { diff --git a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr index f04e1b8fe53..72f80b872a4 100644 --- a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr @@ -31,6 +31,8 @@ contract Claim { ); let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to pass this assert after key rotation. assert_eq(proof_note.npk_m_hash, msg_sender_npk_m_hash, "Note does not belong to the sender"); // 2) Prove that the note hash exists in the note hash tree diff --git a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr index 506c1b97bc3..f38d4bff58c 100644 --- a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr @@ -33,6 +33,7 @@ contract DelegatedOn { fn get_private_value(amount: Field, owner: AztecAddress) -> pub Field { let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to find any notes after rotating key. let mut options = NoteGetterOptions::new(); options = options.select(ValueNote::properties().value, amount, Option::none()).select( ValueNote::properties().npk_m_hash, diff --git a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr index 65d2c64890e..023974cd81f 100644 --- a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr @@ -35,6 +35,7 @@ contract Delegator { fn get_private_value(amount: Field, owner: AztecAddress) -> pub Field { let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to find any notes after rotating key. let mut options = NoteGetterOptions::new(); options = options.select(ValueNote::properties().value, amount, Option::none()).select( ValueNote::properties().npk_m_hash, diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index 025b32b747f..1a1e343f3e8 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -14,7 +14,7 @@ global CARD_NOTE_LEN: Field = 3; struct CardNote { points: u8, randomness: Field, - // The nullifying public key hash is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. npk_m_hash: Field, } // docs:end:state_vars-CardNote 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 48261564783..ba4656e8fbb 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 @@ -28,6 +28,7 @@ contract EasyPrivateVoting { #[aztec(private)] // annotation to mark function as private and expose private context fn cast_vote(candidate: Field) { let msg_sender_npk_m_hash = get_npk_m_hash(&mut context, context.msg_sender()); + // TODO (#6312): This will break with key rotation. Fix this. Can vote multiple times by rotating keys. let secret = context.request_nsk_app(msg_sender_npk_m_hash); // get secret key of caller of function let nullifier = dep::std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret context.push_new_nullifier(nullifier, 0); // push nullifier 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 5a9336c0ca7..47cd407a002 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 @@ -61,6 +61,7 @@ contract InclusionProofs { ) { let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to find any notes after rotating key. // docs:start:get_note_from_pxe // 1) Get the note from PXE. let private_values = storage.private_values.at(owner); @@ -116,6 +117,7 @@ contract InclusionProofs { ) { let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to find any notes after rotating key. // 2) Get the note from PXE let private_values = storage.private_values.at(owner); let mut options = NoteGetterOptions::new(); @@ -149,6 +151,7 @@ contract InclusionProofs { ) { let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to find any notes after rotating key. // 1) Get the note from PXE. let private_values = storage.private_values.at(owner); let mut options = NoteGetterOptions::new(); @@ -178,6 +181,7 @@ contract InclusionProofs { fn nullify_note(owner: AztecAddress) { let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to find any notes after rotating key. let private_values = storage.private_values.at(owner); let mut options = NoteGetterOptions::new(); options = options.select( 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 dce2a46dbd3..db8c9965eb2 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 @@ -46,6 +46,7 @@ contract StatefulTest { fn create_note_no_init_check(owner: AztecAddress, value: Field) { if (value != 0) { let loc = storage.notes.at(owner); + // TODO (#6312): This will break with key rotation. Fix this. Will not be able to spend / increment any notes after rotating key. increment(context, loc, value, owner); } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr index 0179edf37a7..e405431cd3b 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr @@ -4,7 +4,7 @@ use dep::aztec::prelude::{ }; use dep::aztec::{ context::{PublicContext, Context}, hash::pedersen_hash, - protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, hash::poseidon2_hash}, + protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, note::{note_getter::view_notes, note_getter_options::SortOrder}, keys::getters::{get_npk_m_hash, get_ivpk_m} }; @@ -61,9 +61,11 @@ impl BalancesMap { owner: AztecAddress, addend: U128 ) where T: NoteInterface + OwnedNote { - // We fetch the nullifier public key hash in the registry / from our PXE - let owner_npk_m_hash = get_npk_m_hash(self.map.context.private.unwrap(), owner); - let owner_ivpk_m = get_ivpk_m(self.map.context.private.unwrap(), owner); + let context = self.map.context.private.unwrap(); + let owner_ivpk_m = get_ivpk_m(context, owner); + + // We fetch the nullifier public key hash from the registry / from our PXE + let owner_npk_m_hash = get_npk_m_hash(context, owner); let mut addend_note = T::new(addend, owner_npk_m_hash); // docs:start:insert diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index 3a99e4e0131..8d55016e035 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -17,8 +17,7 @@ global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. struct TokenNote { // The amount of tokens in the note amount: U128, - // The nullifying public key hash of the person who owns the note. - // This is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. npk_m_hash: Field, // Randomness of the note to hide its contents randomness: Field, diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 0179edf37a7..e405431cd3b 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -4,7 +4,7 @@ use dep::aztec::prelude::{ }; use dep::aztec::{ context::{PublicContext, Context}, hash::pedersen_hash, - protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, hash::poseidon2_hash}, + protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, note::{note_getter::view_notes, note_getter_options::SortOrder}, keys::getters::{get_npk_m_hash, get_ivpk_m} }; @@ -61,9 +61,11 @@ impl BalancesMap { owner: AztecAddress, addend: U128 ) where T: NoteInterface + OwnedNote { - // We fetch the nullifier public key hash in the registry / from our PXE - let owner_npk_m_hash = get_npk_m_hash(self.map.context.private.unwrap(), owner); - let owner_ivpk_m = get_ivpk_m(self.map.context.private.unwrap(), owner); + let context = self.map.context.private.unwrap(); + let owner_ivpk_m = get_ivpk_m(context, owner); + + // We fetch the nullifier public key hash from the registry / from our PXE + let owner_npk_m_hash = get_npk_m_hash(context, owner); let mut addend_note = T::new(addend, owner_npk_m_hash); // docs:start:insert diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 3a99e4e0131..8d55016e035 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -17,8 +17,7 @@ global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. struct TokenNote { // The amount of tokens in the note amount: U128, - // The nullifying public key hash of the person who owns the note. - // This is used with the app_nullifier_secret_key to ensure that the note can be privately spent. + // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. npk_m_hash: Field, // Randomness of the note to hide its contents randomness: Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr b/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr index 467a022947b..a7caaa39751 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr @@ -1,4 +1,4 @@ -use crate::traits::{Serialize, Deserialize}; +use crate::{traits::{Serialize, Deserialize, Hash}, hash::poseidon2_hash}; use dep::std::cmp::Eq; global GRUMPKIN_POINT_SERIALIZED_LEN: Field = 2; @@ -30,6 +30,12 @@ impl Eq for GrumpkinPoint { } } +impl Hash for GrumpkinPoint { + fn hash(self) -> Field { + poseidon2_hash(self.serialize()) + } +} + impl GrumpkinPoint { pub fn new(x: Field, y: Field) -> Self { Self { x, y } diff --git a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts index 9b6e9c98311..6c9cf81a2e6 100644 --- a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts @@ -128,7 +128,12 @@ describe('e2e_key_rotation', () => { await contract.methods.redeem_shield(recipient, balance, secret).send().wait(); }; - it('rotates key', async () => { + it(`We test key rotation in four steps. + 1. We transfer funds from A to B. + 2. We rotate B's keys by calling rotateMasterNullifierKey on our wallet and by calling rotate_npk_m on the Key Registry. + 3. After the key rotation has been applied, we then transfer more funds from A to B. + 4. We finally send all of the funds back from B to A, proving that all the funds sent before and after key rotation are spendable, + and that we are able to spend notes associated with different nullifying keys`, async () => { const initialBalance = 987n; const transferAmount1 = 654n; // const transferAmount2 = 323n; From b805a8d1edd75ce3603491ba94b1e964472c0241 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 20:07:29 +0000 Subject: [PATCH 120/125] format --- .../aztec-nr/aztec/src/encrypted_logs/incoming_body.nr | 2 +- noir-projects/aztec-nr/aztec/src/keys/getters.nr | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr index a0de2ac6e56..ee99daf8943 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr @@ -67,7 +67,7 @@ mod test { use crate::{ note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::unsafe_rand::unsafe_rand, context::PrivateContext, + oracle::unsafe_rand::unsafe_rand, context::PrivateContext }; struct AddressNote { diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index 523c6ed4f5a..267a7a58457 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -1,6 +1,4 @@ -use dep::protocol_types::{ - address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint, -}; +use dep::protocol_types::{address::AztecAddress, constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint}; use crate::{ context::PrivateContext, oracle::{ From 0294174b2aa5111c5317694dd3b9d57043ed84b5 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 20:29:34 +0000 Subject: [PATCH 121/125] fix/ format --- noir-projects/aztec-nr/address-note/src/address_note.nr | 5 ++--- noir-projects/aztec-nr/value-note/src/value_note.nr | 5 ++--- .../app_subscription_contract/src/subscription_note.nr | 4 ++-- .../contracts/docs_example_contract/src/types/card_note.nr | 7 +++++-- .../ecdsa_account_contract/src/ecdsa_public_key_note.nr | 4 ++-- .../schnorr_account_contract/src/public_key_note.nr | 4 ++-- .../token_blacklist_contract/src/types/token_note.nr | 6 +++--- .../token_blacklist_contract/src/types/transparent_note.nr | 4 ++-- .../contracts/token_contract/src/types/token_note.nr | 6 +++--- .../contracts/token_contract/src/types/transparent_note.nr | 4 ++-- 10 files changed, 25 insertions(+), 24 deletions(-) diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index 4618fd26b3f..8480c0cce7a 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -1,11 +1,10 @@ use dep::aztec::{ protocol_types::{ address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER, - grumpkin_point::GrumpkinPoint + grumpkin_point::GrumpkinPoint, hash::poseidon2_hash }, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, context::PrivateContext, - hash::poseidon2_hash + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, context::PrivateContext }; global ADDRESS_NOTE_LEN: Field = 3; diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index bac3c043465..0d98dec28a7 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -2,11 +2,10 @@ use dep::aztec::{ keys::getters::get_ivpk_m, protocol_types::{ address::AztecAddress, grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}, - constants::GENERATOR_INDEX__NOTE_NULLIFIER + constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash }, note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, - oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, hash::poseidon2_hash, - context::PrivateContext + oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, context::PrivateContext }; global VALUE_NOTE_LEN: Field = 3; // 3 plus a header. diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index 4c968e4f6a1..49e8bc43652 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -1,8 +1,8 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, NoteHeader, NoteInterface}; use dep::aztec::{ keys::getters::get_ivpk_m, - protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, - note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, keys::getters::get_nsk_app + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}, + note::utils::compute_note_hash_for_consumption, keys::getters::get_nsk_app }; global SUBSCRIPTION_NOTE_LEN: Field = 3; diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index 1a1e343f3e8..5f57d70fa5a 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -1,8 +1,11 @@ use dep::aztec::prelude::{AztecAddress, NoteInterface, NoteHeader, PrivateContext}; use dep::aztec::{ keys::getters::get_ivpk_m, note::{utils::compute_note_hash_for_consumption}, - keys::getters::get_nsk_app, hash::poseidon2_hash, - protocol_types::{traits::Empty, grumpkin_point::GrumpkinPoint, constants::GENERATOR_INDEX__NOTE_NULLIFIER} + keys::getters::get_nsk_app, + protocol_types::{ + traits::Empty, grumpkin_point::GrumpkinPoint, constants::GENERATOR_INDEX__NOTE_NULLIFIER, + hash::poseidon2_hash +} }; // Shows how to create a custom note diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr index 94ec509a7b8..0a9d4aa2497 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr @@ -2,8 +2,8 @@ use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteInterf use dep::aztec::{ keys::getters::get_ivpk_m, note::utils::compute_note_hash_for_consumption, - keys::getters::get_nsk_app, hash::poseidon2_hash, - protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} + keys::getters::get_nsk_app, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash} }; global ECDSA_PUBLIC_KEY_NOTE_LEN: Field = 5; diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index 7da24c0af7b..71601730d87 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -1,7 +1,7 @@ use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}; use dep::aztec::{ - note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, keys::getters::get_nsk_app, - protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} + note::utils::compute_note_hash_for_consumption, keys::getters::get_nsk_app, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash} }; global PUBLIC_KEY_NOTE_LEN: Field = 3; diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index 8d55016e035..b5df8c9ba14 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -1,8 +1,8 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, - protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, - note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}, + note::utils::compute_note_hash_for_consumption, oracle::unsafe_rand::unsafe_rand, + keys::getters::get_nsk_app }; trait OwnedNote { diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr index fde5c301099..061ca460642 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr @@ -1,8 +1,8 @@ // docs:start:token_types_all use dep::aztec::{ note::{note_getter_options::PropertySelector, utils::compute_note_hash_for_consumption}, - hash::poseidon2_hash, prelude::{NoteHeader, NoteInterface, PrivateContext}, - protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} + prelude::{NoteHeader, NoteInterface, PrivateContext}, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash} }; global TRANSPARENT_NOTE_LEN: Field = 2; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 8d55016e035..b5df8c9ba14 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -1,8 +1,8 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, - protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint}, - note::utils::compute_note_hash_for_consumption, hash::poseidon2_hash, - oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}, + note::utils::compute_note_hash_for_consumption, oracle::unsafe_rand::unsafe_rand, + keys::getters::get_nsk_app }; trait OwnedNote { diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr index fde5c301099..061ca460642 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr @@ -1,8 +1,8 @@ // docs:start:token_types_all use dep::aztec::{ note::{note_getter_options::PropertySelector, utils::compute_note_hash_for_consumption}, - hash::poseidon2_hash, prelude::{NoteHeader, NoteInterface, PrivateContext}, - protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint} + prelude::{NoteHeader, NoteInterface, PrivateContext}, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash} }; global TRANSPARENT_NOTE_LEN: Field = 2; From 2d2455e47ba4a2a3fe098bad0441488da4480c14 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 22:01:43 +0000 Subject: [PATCH 122/125] Addressing comments --- .../key-store/src/test_key_store.test.ts | 83 +++++++++++++- yarn-project/key-store/src/test_key_store.ts | 106 +++++++++++++----- 2 files changed, 162 insertions(+), 27 deletions(-) diff --git a/yarn-project/key-store/src/test_key_store.test.ts b/yarn-project/key-store/src/test_key_store.test.ts index 7f704e9819c..22a6f07d420 100644 --- a/yarn-project/key-store/src/test_key_store.test.ts +++ b/yarn-project/key-store/src/test_key_store.test.ts @@ -1,4 +1,12 @@ -import { AztecAddress, Fr, computeNpkMHash, deriveKeys, derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; +import { + AztecAddress, + Fq, + Fr, + computeAppNullifierSecretKey, + computeNpkMHash, + deriveKeys, + derivePublicKeyFromSecretKey, +} from '@aztec/circuits.js'; import { openTmpStore } from '@aztec/kv-store/utils'; import { TestKeyStore } from './test_key_store.js'; @@ -78,4 +86,77 @@ describe('TestKeyStore', () => { `"0x0fde74d5e504c73b58aad420dd72590fc6004571411e7f77c45378714195a52b"`, ); }); + + it('nullifier key rotation tests', async () => { + const keyStore = new TestKeyStore(openTmpStore()); + + // Arbitrary fixed values + const sk = new Fr(8923n); + const partialAddress = new Fr(243523n); + + const { address: accountAddress } = await keyStore.addAccount(sk, partialAddress); + expect(accountAddress.toString()).toMatchInlineSnapshot( + `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, + ); + + // Arbitrary fixed values + const newMasterNullifierSecretKeys = [new Fq(420n), new Fq(69n), new Fq(42069n)]; + const newDerivedMasterNullifierPublicKeys = [ + derivePublicKeyFromSecretKey(newMasterNullifierSecretKeys[0]), + derivePublicKeyFromSecretKey(newMasterNullifierSecretKeys[1]), + derivePublicKeyFromSecretKey(newMasterNullifierSecretKeys[2]), + ]; + + const newComputedMasterNullifierPublicKeyHashes = [ + computeNpkMHash(newDerivedMasterNullifierPublicKeys[0]), + computeNpkMHash(newDerivedMasterNullifierPublicKeys[1]), + computeNpkMHash(newDerivedMasterNullifierPublicKeys[2]), + ]; + + // We rotate our nullifier key + await keyStore.rotateMasterNullifierKey(accountAddress, newMasterNullifierSecretKeys[0]); + await keyStore.rotateMasterNullifierKey(accountAddress, newMasterNullifierSecretKeys[1]); + await keyStore.rotateMasterNullifierKey(accountAddress, newMasterNullifierSecretKeys[2]); + + // We make sure we can get master nullifier public keys with master nullifier public key hashes + expect(await keyStore.getMasterNullifierPublicKey(newComputedMasterNullifierPublicKeyHashes[2])).toEqual( + newDerivedMasterNullifierPublicKeys[2], + ); + expect(await keyStore.getMasterNullifierPublicKey(newComputedMasterNullifierPublicKeyHashes[1])).toEqual( + newDerivedMasterNullifierPublicKeys[1], + ); + expect(await keyStore.getMasterNullifierPublicKey(newComputedMasterNullifierPublicKeyHashes[0])).toEqual( + newDerivedMasterNullifierPublicKeys[0], + ); + + // Arbitrary app contract address + const appAddress = AztecAddress.fromBigInt(624n); + + // We make sure we can get app nullifier secret keys with master nullifier public key hashes + const appNullifierSecretKey0 = await keyStore.getAppNullifierSecretKey( + newComputedMasterNullifierPublicKeyHashes[0], + appAddress, + ); + expect(appNullifierSecretKey0.toString()).toMatchInlineSnapshot( + `"0x296e42f1039b62290372d608fcab55b00a3f96c1c8aa347b2a830639c5a12757"`, + ); + const appNullifierSecretKey1 = await keyStore.getAppNullifierSecretKey( + newComputedMasterNullifierPublicKeyHashes[1], + appAddress, + ); + expect(appNullifierSecretKey1.toString()).toMatchInlineSnapshot( + `"0x019f2a705b68683f1d86da639a543411fa779af41896c3920d0c2d5226c686dd"`, + ); + const appNullifierSecretKey2 = await keyStore.getAppNullifierSecretKey( + newComputedMasterNullifierPublicKeyHashes[2], + appAddress, + ); + expect(appNullifierSecretKey2.toString()).toMatchInlineSnapshot( + `"0x117445c8819c06b9a0889e5cce1f550e32ec6993c23f57bc9fc5cda05df520ae"`, + ); + + expect(appNullifierSecretKey0).toEqual(computeAppNullifierSecretKey(newMasterNullifierSecretKeys[0], appAddress)); + expect(appNullifierSecretKey1).toEqual(computeAppNullifierSecretKey(newMasterNullifierSecretKeys[1], appAddress)); + expect(appNullifierSecretKey2).toEqual(computeAppNullifierSecretKey(newMasterNullifierSecretKeys[2], appAddress)); + }); }); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 5d5023762eb..9d85b602fb1 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -94,14 +94,14 @@ export class TestKeyStore implements KeyStore { * @returns The master nullifier public key for the account. */ public async getMasterNullifierPublicKey(npkMHash: Fr): Promise { - const masterNullifierPublicKeyBuffer = this.#getMapMetadataForMasterNullifierPublicKeyHash(npkMHash).value; + const masterNullifierPublicKeyBuffer = this.#getPublicKey(npkMHash); if (!masterNullifierPublicKeyBuffer) { throw new Error( `Master nullifier public key hash ${npkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } - return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer)); + return Promise.resolve(masterNullifierPublicKeyBuffer); } /** @@ -160,21 +160,13 @@ export class TestKeyStore implements KeyStore { * @returns A Promise that resolves to the application nullifier secret key. */ public async getAppNullifierSecretKey(npkMHash: Fr, app: AztecAddress): Promise { - const { key } = this.#getMapMetadataForMasterNullifierPublicKeyHash(npkMHash); - const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); - - // #rotatedKeys has a suffix of -${index}, thus there will never be a clash, i.e. using a key in rotated keys will always return undefined if trying to retrieve something in keys - // and using a key in #keys will always return undefined when searching in #rotatedKeys - const masterNullifierSecretKeyBuffer = - this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); - - if (!masterNullifierSecretKeyBuffer) { + const masterNullifierSecretKey = this.#getSecretKey(npkMHash); + if (!masterNullifierSecretKey) { throw new Error( `Master nullifier public key hash ${npkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, ); } - const masterNullifierSecretKey = GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer); const appNullifierSecretKey = computeAppNullifierSecretKey(masterNullifierSecretKey, app); return Promise.resolve(appNullifierSecretKey); } @@ -306,17 +298,67 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(Fr.fromBuffer(publicKeysHashBuffer)); } - #getMapMetadataForMasterNullifierPublicKeyHash(masterNullifierPublicKeyHash: Fr) { - for (const [key, value] of [...this.#keys.entries(), ...this.#rotatedKeys.entries()]) { + #getPublicKey(npkMHash: Fr): PublicKey | undefined { + for (const [key, value] of this.#keys.entries()) { + if (key.includes('-npk_m')) { + const masterNullifierPublicKey = Point.fromBuffer(value); + const computedMasterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { + return masterNullifierPublicKey; + } + } + } + for (const [key, value] of this.#rotatedKeys.entries()) { + if (key.includes('-npk_m')) { + const numKeys = value.byteLength / Point.SIZE_IN_BYTES; + for (let i = 0; i < numKeys; i++) { + const masterNullifierPublicKey = Point.fromBuffer( + value.subarray(i * Point.SIZE_IN_BYTES, (i + 1) * Point.SIZE_IN_BYTES), + ); + const computedMasterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { + return masterNullifierPublicKey; + } + } + } + } + + return undefined; + } + + #getSecretKey(npkMHash: Fr): Fq | undefined { + for (const [key, value] of this.#keys.entries()) { + if (key.includes('-npk_m')) { + const masterNullifierPublicKey = Point.fromBuffer(value); + const computedMasterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { + const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); + + return GrumpkinScalar.fromBuffer(this.#keys.get(mapKeyForNullifierSecretKey)!); + } + } + } + for (const [key, value] of this.#rotatedKeys.entries()) { if (key.includes('-npk_m')) { - const computedMasterNullifierPublicKeyHash = poseidon2Hash(Point.fromBuffer(value).toFields()); - if (computedMasterNullifierPublicKeyHash.equals(masterNullifierPublicKeyHash)) { - return { key, value }; + const numKeys = value.byteLength / Point.SIZE_IN_BYTES; + for (let i = 0; i < numKeys; i++) { + const masterNullifierPublicKey = Point.fromBuffer( + value.subarray(i * Point.SIZE_IN_BYTES, (i + 1) * Point.SIZE_IN_BYTES), + ); + const computedMasterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { + const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); + const nullifierSecretKeyBuffer = this.#rotatedKeys.get(mapKeyForNullifierSecretKey); + + return GrumpkinScalar.fromBuffer( + nullifierSecretKeyBuffer!.subarray(i * Fq.SIZE_IN_BYTES, (i + 1) * Fq.SIZE_IN_BYTES), + ); + } } } } - throw new Error(`Master nullifier public key hash ${masterNullifierPublicKeyHash} does not exist.`); + return undefined; } public async rotateMasterNullifierKey(account: AztecAddress, newSecretKey: Fq = Fq.random()) { @@ -328,14 +370,26 @@ export class TestKeyStore implements KeyStore { const newPublicKey = derivePublicKeyFromSecretKey(newSecretKey); - const previouslyRotatedNumber = this.#rotatedNullifierKeyCount(account); - await this.#rotatedKeys.set(`${account.toString()}-nsk_m-${previouslyRotatedNumber}`, newSecretKey.toBuffer()); - await this.#rotatedKeys.set(`${account.toString()}-npk_m-${previouslyRotatedNumber}`, newPublicKey.toBuffer()); - } + const [previousRotatedNskM, previousRotatedNpkM] = [ + this.#rotatedKeys.get(`${account.toString()}-nsk_m-r`), + this.#rotatedKeys.get(`${account.toString()}-npk_m-r`), + ]; + if (!previousRotatedNskM != !previousRotatedNpkM) { + throw new Error('The nullifier public key is defined, but the secret key is undefined, or vice versa'); + } - #rotatedNullifierKeyCount(account: AztecAddress): number { - const allRotatedMapKeys = Array.from(this.#rotatedKeys.keys()); - const existingKeys = allRotatedMapKeys.filter(key => key.startsWith(`${account.toString()}-nsk_m`)); - return existingKeys.length; + if (previousRotatedNskM === undefined || previousRotatedNpkM === undefined) { + await this.#rotatedKeys.set(`${account.toString()}-nsk_m-r`, newSecretKey.toBuffer()); + await this.#rotatedKeys.set(`${account.toString()}-npk_m-r`, newPublicKey.toBuffer()); + } else { + await this.#rotatedKeys.set( + `${account.toString()}-nsk_m-r`, + Buffer.concat([previousRotatedNskM, newSecretKey.toBuffer()]), + ); + await this.#rotatedKeys.set( + `${account.toString()}-npk_m-r`, + Buffer.concat([previousRotatedNpkM, newPublicKey.toBuffer()]), + ); + } } } From efc5428e39a2315fefd50d11b896ae90bd840152 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 15 May 2024 22:29:44 +0000 Subject: [PATCH 123/125] Impl hash on Point --- yarn-project/circuits.js/src/keys/index.ts | 6 +--- yarn-project/foundation/src/fields/point.ts | 5 +++ .../key-store/src/test_key_store.test.ts | 9 +++--- yarn-project/key-store/src/test_key_store.ts | 8 ++--- .../src/client/private_execution.test.ts | 32 +++---------------- .../simulator/src/client/simulator.test.ts | 5 ++- 6 files changed, 21 insertions(+), 44 deletions(-) diff --git a/yarn-project/circuits.js/src/keys/index.ts b/yarn-project/circuits.js/src/keys/index.ts index 2d0d4a374ef..a994d96e5ae 100644 --- a/yarn-project/circuits.js/src/keys/index.ts +++ b/yarn-project/circuits.js/src/keys/index.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { poseidon2Hash, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; -import { type Fq, type Fr, type GrumpkinScalar, type Point } from '@aztec/foundation/fields'; +import { type Fq, type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; import { Grumpkin } from '../barretenberg/crypto/grumpkin/index.js'; import { GeneratorIndex } from '../constants.gen.js'; @@ -34,10 +34,6 @@ export function derivePublicKeyFromSecretKey(secretKey: Fq) { return curve.mul(curve.generator(), secretKey); } -export function computeNpkMHash(npkM: Point) { - return poseidon2Hash(npkM.toFields()); -} - /** * Computes secret and public keys and public keys hash from a secret key. * @param secretKey - The secret key to derive keys from. diff --git a/yarn-project/foundation/src/fields/point.ts b/yarn-project/foundation/src/fields/point.ts index dfb5065c03d..9fd8e8fdf03 100644 --- a/yarn-project/foundation/src/fields/point.ts +++ b/yarn-project/foundation/src/fields/point.ts @@ -1,3 +1,4 @@ +import { poseidon2Hash } from '../crypto/index.js'; import { BufferReader, FieldReader, serializeToBuffer } from '../serialize/index.js'; import { Fr } from './fields.js'; @@ -129,6 +130,10 @@ export class Point { isZero() { return this.x.isZero() && this.y.isZero(); } + + hash() { + return poseidon2Hash(this.toFields()); + } } /** diff --git a/yarn-project/key-store/src/test_key_store.test.ts b/yarn-project/key-store/src/test_key_store.test.ts index 22a6f07d420..1dde6a3f02b 100644 --- a/yarn-project/key-store/src/test_key_store.test.ts +++ b/yarn-project/key-store/src/test_key_store.test.ts @@ -3,7 +3,6 @@ import { Fq, Fr, computeAppNullifierSecretKey, - computeNpkMHash, deriveKeys, derivePublicKeyFromSecretKey, } from '@aztec/circuits.js'; @@ -19,7 +18,7 @@ describe('TestKeyStore', () => { const sk = new Fr(8923n); const keys = deriveKeys(sk); const derivedMasterNullifierPublicKey = derivePublicKeyFromSecretKey(keys.masterNullifierSecretKey); - const computedMasterNullifierPublicKeyHash = computeNpkMHash(derivedMasterNullifierPublicKey); + const computedMasterNullifierPublicKeyHash = derivedMasterNullifierPublicKey.hash(); const partialAddress = new Fr(243523n); @@ -108,9 +107,9 @@ describe('TestKeyStore', () => { ]; const newComputedMasterNullifierPublicKeyHashes = [ - computeNpkMHash(newDerivedMasterNullifierPublicKeys[0]), - computeNpkMHash(newDerivedMasterNullifierPublicKeys[1]), - computeNpkMHash(newDerivedMasterNullifierPublicKeys[2]), + newDerivedMasterNullifierPublicKeys[0].hash(), + newDerivedMasterNullifierPublicKeys[1].hash(), + newDerivedMasterNullifierPublicKeys[2].hash(), ]; // We rotate our nullifier key diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 9d85b602fb1..1b4b220f1b6 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -302,7 +302,7 @@ export class TestKeyStore implements KeyStore { for (const [key, value] of this.#keys.entries()) { if (key.includes('-npk_m')) { const masterNullifierPublicKey = Point.fromBuffer(value); - const computedMasterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + const computedMasterNullifierPublicKeyHash = masterNullifierPublicKey.hash(); if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { return masterNullifierPublicKey; } @@ -315,7 +315,7 @@ export class TestKeyStore implements KeyStore { const masterNullifierPublicKey = Point.fromBuffer( value.subarray(i * Point.SIZE_IN_BYTES, (i + 1) * Point.SIZE_IN_BYTES), ); - const computedMasterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + const computedMasterNullifierPublicKeyHash = masterNullifierPublicKey.hash(); if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { return masterNullifierPublicKey; } @@ -330,7 +330,7 @@ export class TestKeyStore implements KeyStore { for (const [key, value] of this.#keys.entries()) { if (key.includes('-npk_m')) { const masterNullifierPublicKey = Point.fromBuffer(value); - const computedMasterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + const computedMasterNullifierPublicKeyHash = masterNullifierPublicKey.hash(); if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); @@ -345,7 +345,7 @@ export class TestKeyStore implements KeyStore { const masterNullifierPublicKey = Point.fromBuffer( value.subarray(i * Point.SIZE_IN_BYTES, (i + 1) * Point.SIZE_IN_BYTES), ); - const computedMasterNullifierPublicKeyHash = poseidon2Hash(masterNullifierPublicKey.toFields()); + const computedMasterNullifierPublicKeyHash = masterNullifierPublicKey.hash(); if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); const nullifierSecretKeyBuffer = this.#rotatedKeys.get(mapKeyForNullifierSecretKey); diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index b0bc6ef632d..e3f6bd825f6 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -26,7 +26,6 @@ import { StateReference, TxContext, computeAppNullifierSecretKey, - computeNpkMHash, deriveKeys, getContractInstanceFromDeployParams, getNonEmptyItems, @@ -192,19 +191,13 @@ describe('Private Execution test suite', () => { trees = {}; oracle = mock(); oracle.getNullifierKeys.mockImplementation((masterNullifierPublicKeyHash: Fr, contractAddress: AztecAddress) => { - if ( - masterNullifierPublicKeyHash.equals(computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey)) - ) { + if (masterNullifierPublicKeyHash.equals(ownerCompleteAddress.publicKeys.masterNullifierPublicKey.hash())) { return Promise.resolve({ masterNullifierPublicKey: ownerCompleteAddress.publicKeys.masterNullifierPublicKey, appNullifierSecretKey: computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), }); } - if ( - masterNullifierPublicKeyHash.equals( - computeNpkMHash(recipientCompleteAddress.publicKeys.masterNullifierPublicKey), - ) - ) { + if (masterNullifierPublicKeyHash.equals(recipientCompleteAddress.publicKeys.masterNullifierPublicKey.hash())) { return Promise.resolve({ masterNullifierPublicKey: recipientCompleteAddress.publicKeys.masterNullifierPublicKey, appNullifierSecretKey: computeAppNullifierSecretKey(recipientMasterNullifierSecretKey, contractAddress), @@ -400,18 +393,8 @@ describe('Private Execution test suite', () => { const noteTypeId = StatefulTestContractArtifact.notes['ValueNote'].id; const notes = [ - buildNote( - 60n, - computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey), - storageSlot, - noteTypeId, - ), - buildNote( - 80n, - computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey), - storageSlot, - noteTypeId, - ), + buildNote(60n, ownerCompleteAddress.publicKeys.masterNullifierPublicKey.hash(), storageSlot, noteTypeId), + buildNote(80n, ownerCompleteAddress.publicKeys.masterNullifierPublicKey.hash(), storageSlot, noteTypeId), ]; oracle.getNotes.mockResolvedValue(notes); @@ -470,12 +453,7 @@ describe('Private Execution test suite', () => { const noteTypeId = StatefulTestContractArtifact.notes['ValueNote'].id; const notes = [ - buildNote( - balance, - computeNpkMHash(ownerCompleteAddress.publicKeys.masterNullifierPublicKey), - storageSlot, - noteTypeId, - ), + buildNote(balance, ownerCompleteAddress.publicKeys.masterNullifierPublicKey.hash(), storageSlot, noteTypeId), ]; oracle.getNotes.mockResolvedValue(notes); diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 4954e69f216..f4cdbd7c97b 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -1,5 +1,5 @@ import { type AztecNode, CompleteAddress, Note } from '@aztec/circuit-types'; -import { GeneratorIndex, computeAppNullifierSecretKey, computeNpkMHash, deriveKeys } from '@aztec/circuits.js'; +import { GeneratorIndex, computeAppNullifierSecretKey, deriveKeys } from '@aztec/circuits.js'; import { computeInnerNoteHash, computeNoteContentHash, @@ -57,8 +57,7 @@ describe('Simulator', () => { const storageSlot = TokenContractArtifact.storageLayout['balances'].slot; const noteTypeId = TokenContractArtifact.notes['TokenNote'].id; - const createNote = (amount = 123n) => - new Note([new Fr(amount), computeNpkMHash(ownerMasterNullifierPublicKey), Fr.random()]); + const createNote = (amount = 123n) => new Note([new Fr(amount), ownerMasterNullifierPublicKey.hash(), Fr.random()]); it('should compute note hashes and nullifier', async () => { oracle.getFunctionArtifactByName.mockResolvedValue(artifact); From 6989d9f4cc00d5319e7cfa9176c25930dfc960c3 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 16 May 2024 08:11:28 +0000 Subject: [PATCH 124/125] key store refactor --- yarn-project/key-store/src/test_key_store.ts | 266 +++++++++++-------- 1 file changed, 149 insertions(+), 117 deletions(-) diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 1b4b220f1b6..6e5416be404 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -23,11 +23,9 @@ import { type AztecKVStore, type AztecMap } from '@aztec/kv-store'; */ export class TestKeyStore implements KeyStore { #keys: AztecMap; - #rotatedKeys: AztecMap; constructor(database: AztecKVStore) { this.#keys = database.openMap('key_store'); - this.#rotatedKeys = database.openMap('key_store_rotated_keys'); } /** @@ -62,16 +60,23 @@ export class TestKeyStore implements KeyStore { await this.#keys.set(`${accountAddress.toString()}-public_keys_hash`, publicKeysHash.toBuffer()); // Naming of keys is as follows ${from}-${to}_m - await this.#keys.set(`${accountAddress.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer()); + // The key of the following is different from the others because the buffer can store multiple keys + await this.#keys.set(`${accountAddress.toString()}-ns_keys_m`, masterNullifierSecretKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-npk_m`, publicKeys.masterNullifierPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-np_keys_m`, publicKeys.masterNullifierPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, publicKeys.masterIncomingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, publicKeys.masterOutgoingViewingPublicKey.toBuffer()); await this.#keys.set(`${accountAddress.toString()}-tpk_m`, publicKeys.masterTaggingPublicKey.toBuffer()); + // We store a npk_m_hash-account_address map to make address easy to obtain with the hash later on + await this.#keys.set( + `${publicKeys.masterNullifierPublicKey.hash().toString()}-npk_m_hash`, + accountAddress.toBuffer(), + ); + // At last, we return the newly derived account address return Promise.resolve(new CompleteAddress(accountAddress, publicKeys, partialAddress)); } @@ -82,8 +87,8 @@ export class TestKeyStore implements KeyStore { */ public getAccounts(): Promise { const allMapKeys = Array.from(this.#keys.keys()); - // We return account addresses based on the map keys that end with '-nsk_m' - const accounts = allMapKeys.filter(key => key.endsWith('-nsk_m')).map(key => key.split('-')[0]); + // We return account addresses based on the map keys that end with '-ivsk_m' + const accounts = allMapKeys.filter(key => key.endsWith('-ivsk_m')).map(key => key.split('-')[0]); return Promise.resolve(accounts.map(account => AztecAddress.fromString(account))); } @@ -93,15 +98,38 @@ export class TestKeyStore implements KeyStore { * @param npkMHash - The master nullifier public key hash. * @returns The master nullifier public key for the account. */ - public async getMasterNullifierPublicKey(npkMHash: Fr): Promise { - const masterNullifierPublicKeyBuffer = this.#getPublicKey(npkMHash); + public getMasterNullifierPublicKey(npkMHash: Fr): Promise { + // Get the address for npk_m_hash + const accountAddressBuffer = this.#keys.get(`${npkMHash.toString()}-npk_m_hash`); + if (!accountAddressBuffer) { + throw new Error(`Could no find address for master nullifier public key hash ${npkMHash}.`); + } + const accountAddress = AztecAddress.fromBuffer(accountAddressBuffer); - if (!masterNullifierPublicKeyBuffer) { + // Get the master nullifier public keys buffer for the account + const masterNullifierPublicKeysBuffer = this.#keys.get(`${accountAddress.toString()}-np_keys_m`); + if (!masterNullifierPublicKeysBuffer) { throw new Error( - `Master nullifier public key hash ${npkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, + `Could not find master nullifier public key for account ${accountAddress.toString()} whose address was successfully obtained with npk_m_hash ${npkMHash.toString()}.`, + ); + } + + // We check that the buffer's length is a multiple of Point.SIZE_IN_BYTES + if (masterNullifierPublicKeysBuffer.byteLength % Point.SIZE_IN_BYTES !== 0) { + throw new Error("Master nullifier public key buffer's length is not a multiple of Point.SIZE_IN_BYTES."); + } + + // Now we iterate over the public keys in the buffer to find the one that matches the hash + const numKeys = masterNullifierPublicKeysBuffer.byteLength / Point.SIZE_IN_BYTES; + for (let i = 0; i < numKeys; i++) { + const masterNullifierPublicKey = Point.fromBuffer( + masterNullifierPublicKeysBuffer.subarray(i * Point.SIZE_IN_BYTES, (i + 1) * Point.SIZE_IN_BYTES), ); + if (masterNullifierPublicKey.hash().equals(npkMHash)) { + return Promise.resolve(masterNullifierPublicKey); + } } - return Promise.resolve(masterNullifierPublicKeyBuffer); + throw new Error(`Could not find master nullifier public key for npk_m_hash ${npkMHash.toString()}.`); } /** @@ -159,16 +187,41 @@ export class TestKeyStore implements KeyStore { * @param app - The application address to retrieve the nullifier secret key for. * @returns A Promise that resolves to the application nullifier secret key. */ - public async getAppNullifierSecretKey(npkMHash: Fr, app: AztecAddress): Promise { - const masterNullifierSecretKey = this.#getSecretKey(npkMHash); - if (!masterNullifierSecretKey) { + public getAppNullifierSecretKey(npkMHash: Fr, app: AztecAddress): Promise { + // First we get the account address for npk_m_hash + const accountAddressBuffer = this.#keys.get(`${npkMHash.toString()}-npk_m_hash`); + if (!accountAddressBuffer) { + throw new Error(`Could no find address for master nullifier public key hash ${npkMHash}.`); + } + + // Now we get the master nullifier secret keys for the account + const masterNullifierSecretKeysBuffer = this.#keys.get( + `${AztecAddress.fromBuffer(accountAddressBuffer).toString()}-ns_keys_m`, + ); + if (!masterNullifierSecretKeysBuffer) { throw new Error( - `Master nullifier public key hash ${npkMHash} does not exist. Registered accounts: ${await this.getAccounts()}.`, + `Could not find master nullifier secret keys for account ${AztecAddress.fromBuffer( + accountAddressBuffer, + ).toString()}`, ); } - const appNullifierSecretKey = computeAppNullifierSecretKey(masterNullifierSecretKey, app); - return Promise.resolve(appNullifierSecretKey); + // Now we iterate over all the secret keys to find the one that matches the hash + const numKeys = masterNullifierSecretKeysBuffer.byteLength / GrumpkinScalar.SIZE_IN_BYTES; + for (let i = 0; i < numKeys; i++) { + const secretKey = GrumpkinScalar.fromBuffer( + masterNullifierSecretKeysBuffer.subarray( + i * GrumpkinScalar.SIZE_IN_BYTES, + (i + 1) * GrumpkinScalar.SIZE_IN_BYTES, + ), + ); + const publicKey = derivePublicKeyFromSecretKey(secretKey); + if (publicKey.hash().equals(npkMHash)) { + return Promise.resolve(computeAppNullifierSecretKey(secretKey, app)); + } + } + + throw new Error(`Could not find master nullifier secret key for npk_m_hash ${npkMHash.toString()}.`); } /** @@ -232,24 +285,60 @@ export class TestKeyStore implements KeyStore { * @dev Used when feeding the master nullifier secret key to the kernel circuit for nullifier keys verification. */ public getMasterNullifierSecretKeyForPublicKey(masterNullifierPublicKey: PublicKey): Promise { - // We iterate over the map keys to find the account address that corresponds to the provided public key - for (const [key, value] of [...this.#keys.entries(), ...this.#rotatedKeys.entries()]) { - if (value.equals(masterNullifierPublicKey.toBuffer())) { - const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); + // We get the account address associated with the master nullifier public key hash + const accountAddressBuffer = this.#keys.get(`${masterNullifierPublicKey.hash().toString()}-npk_m_hash`); + if (!accountAddressBuffer) { + throw new Error( + `Could not find account address for master nullifier public key ${masterNullifierPublicKey.toString()}`, + ); + } + const accountAddress = AztecAddress.fromBuffer(accountAddressBuffer); - const masterNullifierSecretKeyBuffer = - this.#keys.get(mapKeyForNullifierSecretKey) ?? this.#rotatedKeys.get(mapKeyForNullifierSecretKey); + // We fetch the public keys and find this specific public key's position in the buffer + const masterNullifierPublicKeysBuffer = this.#keys.get(`${accountAddress.toString()}-np_keys_m`); + if (!masterNullifierPublicKeysBuffer) { + throw new Error(`Could not find master nullifier public keys for account ${accountAddress.toString()}`); + } - if (!masterNullifierSecretKeyBuffer) { - throw new Error( - `Could not find master nullifier secret key for master nullifier public key ${masterNullifierPublicKey.toString()}`, - ); - } - return Promise.resolve(GrumpkinScalar.fromBuffer(masterNullifierSecretKeyBuffer)); + // We check that the buffer's length is a multiple of Point.SIZE_IN_BYTES + if (masterNullifierPublicKeysBuffer.byteLength % Point.SIZE_IN_BYTES !== 0) { + throw new Error("Master nullifier public key buffer's length is not a multiple of Point.SIZE_IN_BYTES."); + } + + // Now we iterate over the public keys in the buffer to find the one that matches the hash + const numKeys = masterNullifierPublicKeysBuffer.byteLength / Point.SIZE_IN_BYTES; + let keyIndex = -1; + for (let i = 0; i < numKeys; i++) { + const publicKey = Point.fromBuffer( + masterNullifierPublicKeysBuffer.subarray(i * Point.SIZE_IN_BYTES, (i + 1) * Point.SIZE_IN_BYTES), + ); + if (publicKey.equals(masterNullifierPublicKey)) { + keyIndex = i; + break; } } - throw new Error(`Could not find master nullifier secret key for public key ${masterNullifierPublicKey.toString()}`); + // Now we fetch the secret keys buffer and extract the secret key at the same index + const masterNullifierSecretKeysBuffer = this.#keys.get(`${accountAddress.toString()}-ns_keys_m`); + if (!masterNullifierSecretKeysBuffer) { + throw new Error(`Could not find master nullifier secret keys for account ${accountAddress.toString()}`); + } + + // We extract the secret key from the buffer + const secretKeyBuffer = masterNullifierSecretKeysBuffer.subarray( + keyIndex * GrumpkinScalar.SIZE_IN_BYTES, + (keyIndex + 1) * GrumpkinScalar.SIZE_IN_BYTES, + ); + const secretKey = GrumpkinScalar.fromBuffer(secretKeyBuffer); + + // We sanity check that it's possible to derive the public key from the secret key + if (!derivePublicKeyFromSecretKey(secretKey).equals(masterNullifierPublicKey)) { + throw new Error( + `Could not find master nullifier secret key for public key ${masterNullifierPublicKey.toString()}`, + ); + } + + return Promise.resolve(secretKey); } /** @@ -298,98 +387,41 @@ export class TestKeyStore implements KeyStore { return Promise.resolve(Fr.fromBuffer(publicKeysHashBuffer)); } - #getPublicKey(npkMHash: Fr): PublicKey | undefined { - for (const [key, value] of this.#keys.entries()) { - if (key.includes('-npk_m')) { - const masterNullifierPublicKey = Point.fromBuffer(value); - const computedMasterNullifierPublicKeyHash = masterNullifierPublicKey.hash(); - if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { - return masterNullifierPublicKey; - } - } - } - for (const [key, value] of this.#rotatedKeys.entries()) { - if (key.includes('-npk_m')) { - const numKeys = value.byteLength / Point.SIZE_IN_BYTES; - for (let i = 0; i < numKeys; i++) { - const masterNullifierPublicKey = Point.fromBuffer( - value.subarray(i * Point.SIZE_IN_BYTES, (i + 1) * Point.SIZE_IN_BYTES), - ); - const computedMasterNullifierPublicKeyHash = masterNullifierPublicKey.hash(); - if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { - return masterNullifierPublicKey; - } - } - } - } - - return undefined; - } - - #getSecretKey(npkMHash: Fr): Fq | undefined { - for (const [key, value] of this.#keys.entries()) { - if (key.includes('-npk_m')) { - const masterNullifierPublicKey = Point.fromBuffer(value); - const computedMasterNullifierPublicKeyHash = masterNullifierPublicKey.hash(); - if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { - const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); - - return GrumpkinScalar.fromBuffer(this.#keys.get(mapKeyForNullifierSecretKey)!); - } - } - } - for (const [key, value] of this.#rotatedKeys.entries()) { - if (key.includes('-npk_m')) { - const numKeys = value.byteLength / Point.SIZE_IN_BYTES; - for (let i = 0; i < numKeys; i++) { - const masterNullifierPublicKey = Point.fromBuffer( - value.subarray(i * Point.SIZE_IN_BYTES, (i + 1) * Point.SIZE_IN_BYTES), - ); - const computedMasterNullifierPublicKeyHash = masterNullifierPublicKey.hash(); - if (computedMasterNullifierPublicKeyHash.equals(npkMHash)) { - const mapKeyForNullifierSecretKey = key.replace('npk_m', 'nsk_m'); - const nullifierSecretKeyBuffer = this.#rotatedKeys.get(mapKeyForNullifierSecretKey); - - return GrumpkinScalar.fromBuffer( - nullifierSecretKeyBuffer!.subarray(i * Fq.SIZE_IN_BYTES, (i + 1) * Fq.SIZE_IN_BYTES), - ); - } - } - } - } - - return undefined; - } - + /** + * Rotates the master nullifier key for the specified account. + * + * @dev This function updates the secret and public keys associated with the account. + * It appends a new secret key to the existing secret keys, derives the + * corresponding public key, and updates the stored keys accordingly. + * + * @param account - The account address for which the master nullifier key is being rotated. + * @param newSecretKey - (Optional) A new secret key of type Fq. If not provided, a random key is generated. + * @throws If the account does not have existing nullifier secret keys or public keys. + * @returns A Promise that resolves when the key rotation is complete. + */ public async rotateMasterNullifierKey(account: AztecAddress, newSecretKey: Fq = Fq.random()) { - const storedAccounts = await this.getAccounts(); - - if (!storedAccounts.some(storedAccount => storedAccount.equals(account))) { - throw new Error('Account does not exist'); + // We append the secret key to the original secret key + const secretKeysBuffer = this.#keys.get(`${account.toString()}-ns_keys_m`); + if (!secretKeysBuffer) { + throw new Error(`Could not find nullifier secret keys for account ${account.toString()}`); } - const newPublicKey = derivePublicKeyFromSecretKey(newSecretKey); + // We append the new secret key to the buffer of secret keys + const newSecretKeysBuffer = Buffer.concat([secretKeysBuffer, newSecretKey.toBuffer()]); + await this.#keys.set(`${account.toString()}-ns_keys_m`, newSecretKeysBuffer); - const [previousRotatedNskM, previousRotatedNpkM] = [ - this.#rotatedKeys.get(`${account.toString()}-nsk_m-r`), - this.#rotatedKeys.get(`${account.toString()}-npk_m-r`), - ]; - if (!previousRotatedNskM != !previousRotatedNpkM) { - throw new Error('The nullifier public key is defined, but the secret key is undefined, or vice versa'); + // Now we derive the public key from the new secret key and append it to the buffer of original public keys + const newPublicKey = derivePublicKeyFromSecretKey(newSecretKey); + const publicKeysBuffer = this.#keys.get(`${account.toString()}-np_keys_m`); + if (!publicKeysBuffer) { + throw new Error(`Could not find nullifier public keys for account ${account.toString()}`); } - if (previousRotatedNskM === undefined || previousRotatedNpkM === undefined) { - await this.#rotatedKeys.set(`${account.toString()}-nsk_m-r`, newSecretKey.toBuffer()); - await this.#rotatedKeys.set(`${account.toString()}-npk_m-r`, newPublicKey.toBuffer()); - } else { - await this.#rotatedKeys.set( - `${account.toString()}-nsk_m-r`, - Buffer.concat([previousRotatedNskM, newSecretKey.toBuffer()]), - ); - await this.#rotatedKeys.set( - `${account.toString()}-npk_m-r`, - Buffer.concat([previousRotatedNpkM, newPublicKey.toBuffer()]), - ); - } + // We append the new public key to the buffer of public keys + const newPublicKeysBuffer = Buffer.concat([publicKeysBuffer, newPublicKey.toBuffer()]); + await this.#keys.set(`${account.toString()}-np_keys_m`, newPublicKeysBuffer); + + // We store a npk_m_hash-account_address map to make address easy to obtain with the hash later on + await this.#keys.set(`${newPublicKey.hash().toString()}-npk_m_hash`, account.toBuffer()); } } From 968085851a7b24561726329b7310238d9e4c2fc9 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 16 May 2024 09:12:56 +0000 Subject: [PATCH 125/125] reworked key rotation test --- .../end-to-end/src/e2e_key_rotation.test.ts | 168 +++++++++++------- 1 file changed, 102 insertions(+), 66 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts index 6c9cf81a2e6..3f2a3dc22e7 100644 --- a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts @@ -8,11 +8,12 @@ import { Fr, Note, type PXE, + type TxHash, type Wallet, computeSecretHash, retryUntil, } from '@aztec/aztec.js'; -import { derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; +import { type PublicKey, derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; import { KeyRegistryContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; @@ -22,10 +23,12 @@ import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup, setupPXEService } f const TIMEOUT = 120_000; +const SHARED_MUTABLE_DELAY = 5; + describe('e2e_key_rotation', () => { jest.setTimeout(TIMEOUT); - let aztecNode: AztecNode | undefined; + let aztecNode: AztecNode; let pxeA: PXE; let pxeB: PXE; let walletA: Wallet; @@ -35,12 +38,15 @@ describe('e2e_key_rotation', () => { let teardownB: () => Promise; let keyRegistryWithB: KeyRegistryContract; - let testContract: TestContract; + let contractWithWalletA: TokenContract; + let contractWithWalletB: TokenContract; + + let tokenAddress: AztecAddress; - const SHARED_MUTABLE_DELAY = 5 + 3; + const initialBalance = 987n; - beforeEach(async () => { + beforeAll(async () => { ({ aztecNode, pxe: pxeA, @@ -49,12 +55,29 @@ describe('e2e_key_rotation', () => { teardown: teardownA, } = await setup(1)); - ({ pxe: pxeB, teardown: teardownB } = await setupPXEService(aztecNode!, {}, undefined, true)); + ({ pxe: pxeB, teardown: teardownB } = await setupPXEService(aztecNode, {}, undefined, true)); [walletB] = await createAccounts(pxeB, 1); keyRegistryWithB = await KeyRegistryContract.at(getCanonicalKeyRegistryAddress(), walletB); + // We deploy test and token contracts testContract = await TestContract.deploy(walletA).send().deployed(); + const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); + tokenAddress = tokenInstance.address; + + // Add account B to wallet A + await pxeA.registerRecipient(walletB.getCompleteAddress()); + // Add account A to wallet B + await pxeB.registerRecipient(walletA.getCompleteAddress()); + + // Add token to PXE B (PXE A already has it because it was deployed through it) + await pxeB.registerContract({ + artifact: TokenContract.artifact, + instance: tokenInstance, + }); + + contractWithWalletA = await TokenContract.at(tokenAddress, walletA); + contractWithWalletB = await TokenContract.at(tokenAddress, walletB); }); afterEach(async () => { @@ -128,70 +151,83 @@ describe('e2e_key_rotation', () => { await contract.methods.redeem_shield(recipient, balance, secret).send().wait(); }; - it(`We test key rotation in four steps. - 1. We transfer funds from A to B. - 2. We rotate B's keys by calling rotateMasterNullifierKey on our wallet and by calling rotate_npk_m on the Key Registry. - 3. After the key rotation has been applied, we then transfer more funds from A to B. - 4. We finally send all of the funds back from B to A, proving that all the funds sent before and after key rotation are spendable, - and that we are able to spend notes associated with different nullifying keys`, async () => { - const initialBalance = 987n; - const transferAmount1 = 654n; - // const transferAmount2 = 323n; + it(`Rotates keys and uses them`, async () => { + // 1. We check that setup set initial balances as expected + await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); + await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); - const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); - const tokenAddress = tokenInstance.address; + // 2. Transfer funds from A to B via PXE A + let txHashTransfer1: TxHash; + const transfer1Amount = 654n; + { + ({ txHash: txHashTransfer1 } = await contractWithWalletA.methods + .transfer(walletA.getAddress(), walletB.getAddress(), transfer1Amount, 0) + .send() + .wait()); + + // Check balances and logs are as expected + await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transfer1Amount); + await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transfer1Amount); + await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); + } - // Add account B to wallet A - await pxeA.registerRecipient(walletB.getCompleteAddress()); - // Add account A to wallet B - await pxeB.registerRecipient(walletA.getCompleteAddress()); + // 3. Rotates B key + let newNpkM: PublicKey; + { + const newNskM = Fq.random(); + newNpkM = derivePublicKeyFromSecretKey(newNskM); + await pxeB.rotateMasterNullifierKey(walletB.getAddress(), newNskM); - // Add token to PXE B (PXE A already has it because it was deployed through it) - await pxeB.registerContract({ - artifact: TokenContract.artifact, - instance: tokenInstance, - }); + await keyRegistryWithB.methods.rotate_npk_m(walletB.getAddress(), newNpkM, 0).send().wait(); + await crossDelay(); + } - // Check initial balances and logs are as expected - await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); - await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); - await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1); - - // Transfer funds from A to B via PXE A - const contractWithWalletA = await TokenContract.at(tokenAddress, walletA); - await contractWithWalletA.methods - .transfer(walletA.getAddress(), walletB.getAddress(), transferAmount1, 0) - .send() - .wait(); - - // Check balances and logs are as expected - await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transferAmount1); - await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1); - await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); - - // Rotates B key - const newNskM = Fq.random(); - const newNpkM = derivePublicKeyFromSecretKey(newNskM); - await pxeB.rotateMasterNullifierKey(walletB.getAddress(), newNskM); - - await keyRegistryWithB.methods.rotate_npk_m(walletB.getAddress(), newNpkM, 0).send().wait(); - await crossDelay(); - - // Transfer funds from A to B via PXE A - await contractWithWalletA.methods.transfer(walletA.getAddress(), walletB.getAddress(), 123, 0).send().wait(); - - await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance - transferAmount1 - 123n); - await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transferAmount1 + 123n); - // await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); - - // Transfer funds from B to A via PXE B - const contractWithWalletB = await TokenContract.at(tokenAddress, walletB); - await contractWithWalletB.methods - .transfer(walletB.getAddress(), walletA.getAddress(), transferAmount1 + 123n, 0) - .send() - .wait({ interval: 0.1 }); + // 4. Transfer funds from A to B via PXE A + let txHashTransfer2: TxHash; + const transfer2Amount = 321n; + { + ({ txHash: txHashTransfer2 } = await contractWithWalletA.methods + .transfer(walletA.getAddress(), walletB.getAddress(), transfer2Amount, 0) + .send() + .wait()); + + await expectTokenBalance( + walletA, + tokenAddress, + walletA.getAddress(), + initialBalance - transfer1Amount - transfer2Amount, + ); + await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), transfer1Amount + transfer2Amount); + } - await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); - await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); + // 5. Now we check that a correct nullifier keys were used in both transfers + { + await awaitUserSynchronized(walletB, walletB.getAddress()); + const transfer1Notes = await walletB.getNotes({ txHash: txHashTransfer1 }); + const transfer2Notes = await walletB.getNotes({ txHash: txHashTransfer2 }); + expect(transfer1Notes.length).toBe(1); + expect(transfer2Notes.length).toBe(1); + // Second field in the token note is the npk_m_hash + const noteNpkMHashTransfer1 = transfer1Notes[0].note.items[1]; + const noteNpkMHashTransfer2 = transfer2Notes[0].note.items[1]; + + // Now we check the note created in transfer 2 used the new npk_m_hash + expect(noteNpkMHashTransfer2.equals(newNpkM.hash())).toBe(true); + // We sanity check that the note created in transfer 1 had old npk_m_hash by checking it's different from the new + // one + expect(noteNpkMHashTransfer2.equals(noteNpkMHashTransfer1)).toBe(false); + } + + // 6. Finally we check that all the B notes are spendable by transferring full B balance to A + // --> this way we verify that it's possible to obtain both keys via oracles + { + await contractWithWalletB.methods + .transfer(walletB.getAddress(), walletA.getAddress(), transfer1Amount + transfer2Amount, 0) + .send() + .wait(); + + await expectTokenBalance(walletA, tokenAddress, walletA.getAddress(), initialBalance); + await expectTokenBalance(walletB, tokenAddress, walletB.getAddress(), 0n); + } }, 600_000); });