diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index b6fc2759fb7..0e531da1028 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}; +use dep::protocol_types::{ + address::{AztecAddress, PublicKeysHash}, constants::CANONICAL_KEY_REGISTRY_ADDRESS, + grumpkin_point::GrumpkinPoint +}; use crate::{ context::PrivateContext, oracle::keys::get_public_keys_and_partial_address, state_vars::{ @@ -80,20 +83,15 @@ fn fetch_key_from_registry( fn fetch_and_constrain_keys(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 npk_m = public_keys[0]; + let ivpk_m = public_keys[1]; + let ovpk_m = public_keys[2]; + let tpk_m = 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 - ); + let public_keys_hash = PublicKeysHash::compute(npk_m, ivpk_m, ovpk_m, tpk_m); + let computed_address = AztecAddress::compute(public_keys_hash, partial_address); assert(computed_address.eq(address)); - [nullifier_pub_key, incoming_pub_key, outgoing_pub_key, tagging_pub_key] + [npk_m, ivpk_m, ovpk_m, tpk_m] } 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..49e97cf5a28 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,20 +1,8 @@ -use dep::protocol_types::{address::{AztecAddress, PartialAddress, PublicKeysHash}, grumpkin_point::GrumpkinPoint}; - -#[oracle(getPublicKeyAndPartialAddress)] -fn get_public_key_and_partial_address_oracle(_address: AztecAddress) -> [Field; 3] {} - -unconstrained fn get_public_key_and_partial_address_internal(address: AztecAddress) -> [Field; 3] { - get_public_key_and_partial_address_oracle(address) -} +use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}; +use crate::oracle::keys::get_public_keys_and_partial_address; +// To be nuked in my next PR: https://github.com/AztecProtocol/aztec-packages/pull/6219 pub fn get_public_key(address: AztecAddress) -> GrumpkinPoint { - let result = get_public_key_and_partial_address_internal(address); - 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 + let result = get_public_keys_and_partial_address(address); + result.0[1] } 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 b985c829d26..ca63a68aba3 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 @@ -3,7 +3,7 @@ contract KeyRegistry { use dep::aztec::{ state_vars::{SharedMutable, Map}, - protocol_types::{grumpkin_point::GrumpkinPoint, address::{AztecAddress, PartialAddress}} + protocol_types::{grumpkin_point::GrumpkinPoint, address::{AztecAddress, PartialAddress, PublicKeysHash}} }; global KEY_ROTATION_DELAY = 5; @@ -27,11 +27,7 @@ contract KeyRegistry { } #[aztec(public)] - fn rotate_nullifier_public_key( - address: AztecAddress, - new_nullifier_public_key: GrumpkinPoint, - nonce: Field - ) { + fn rotate_npk_m(address: AztecAddress, new_npk_m: GrumpkinPoint, nonce: Field) { // TODO: (#6137) if (!address.eq(context.msg_sender())) { assert_current_call_valid_authwit_public(&mut context, address); @@ -41,26 +37,21 @@ contract KeyRegistry { let npk_m_x_registry = storage.npk_m_x_registry.at(address); let npk_m_y_registry = storage.npk_m_y_registry.at(address); - npk_m_x_registry.schedule_value_change(new_nullifier_public_key.x); - npk_m_y_registry.schedule_value_change(new_nullifier_public_key.y); + npk_m_x_registry.schedule_value_change(new_npk_m.x); + npk_m_y_registry.schedule_value_change(new_npk_m.y); } #[aztec(public)] fn register( address: AztecAddress, partial_address: PartialAddress, - nullifier_public_key: GrumpkinPoint, - incoming_public_key: GrumpkinPoint, - outgoing_public_key: GrumpkinPoint, - tagging_public_key: GrumpkinPoint + npk_m: GrumpkinPoint, + ivpk_m: GrumpkinPoint, + ovpk_m: GrumpkinPoint, + tpk_m: GrumpkinPoint ) { - 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 - ); + let public_keys_hash = PublicKeysHash::compute(npk_m, ivpk_m, ovpk_m, tpk_m); + let computed_address = AztecAddress::compute(public_keys_hash, partial_address); assert(computed_address.eq(address), "Computed address does not match supplied address"); @@ -73,14 +64,14 @@ contract KeyRegistry { // let tpk_m_x_registry = storage.tpk_m_x_registry.at(address); // let tpk_m_y_registry = storage.tpk_m_y_registry.at(address); - npk_m_x_registry.schedule_value_change(nullifier_public_key.x); - npk_m_y_registry.schedule_value_change(nullifier_public_key.y); - ivpk_m_x_registry.schedule_value_change(incoming_public_key.x); - ivpk_m_y_registry.schedule_value_change(incoming_public_key.y); + npk_m_x_registry.schedule_value_change(npk_m.x); + npk_m_y_registry.schedule_value_change(npk_m.y); + ivpk_m_x_registry.schedule_value_change(ivpk_m.x); + ivpk_m_y_registry.schedule_value_change(ivpk_m.y); // Commented out as we hit the max enqueued public calls limit when not done so - // ovpk_m_x_registry.schedule_value_change(outgoing_public_key.x); - // ovpk_m_y_registry.schedule_value_change(outgoing_public_key.y); - // tpk_m_x_registry.schedule_value_change(tagging_public_key.x); - // tpk_m_y_registry.schedule_value_change(tagging_public_key.y); + // ovpk_m_x_registry.schedule_value_change(ovpk_m.x); + // ovpk_m_y_registry.schedule_value_change(ovpk_m.y); + // tpk_m_x_registry.schedule_value_change(tpk_m.x); + // tpk_m_y_registry.schedule_value_change(tpk_m.y); } } diff --git a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr index bb6aad4b787..5c75c095d2f 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr @@ -6,7 +6,8 @@ contract SchnorrSingleKeyAccount { use dep::authwit::{entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions}; - use crate::{util::recover_address, auth_oracle::get_auth_witness}; + // use crate::{util::recover_address, auth_oracle::get_auth_witness}; + use crate::auth_oracle::get_auth_witness; global ACCOUNT_ACTIONS_STORAGE_SLOT = 1; diff --git a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr index f337d688bbd..89f7e2e9b4d 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr @@ -3,18 +3,19 @@ use dep::aztec::protocol_types::address::PublicKeysHash; use dep::std::{schnorr::verify_signature_slice}; use crate::auth_oracle::AuthWitness; -pub fn recover_address(message_hash: Field, witness: AuthWitness) -> AztecAddress { - let message_bytes = message_hash.to_be_bytes(32); - let verification = verify_signature_slice( - witness.owner.x, - witness.owner.y, - witness.signature, - message_bytes - ); - assert(verification == true); +// TODO(#5830): the following is currently broken because we are no longer able to compute public keys hash +// pub fn recover_address(message_hash: Field, witness: AuthWitness) -> AztecAddress { +// let message_bytes = message_hash.to_be_bytes(32); +// let verification = verify_signature_slice( +// witness.owner.x, +// witness.owner.y, +// witness.signature, +// message_bytes +// ); +// assert(verification == true); - AztecAddress::compute( - PublicKeysHash::compute(witness.owner), - witness.partial_address - ) -} +// AztecAddress::compute( +// PublicKeysHash::compute(witness.owner), +// witness.partial_address +// ) +// } 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 6413bedf15e..6c91a609990 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 @@ -59,25 +59,6 @@ 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 } @@ -93,7 +74,7 @@ impl AztecAddress { } #[test] -fn compute_address_from_partial_and_pubkey() { +fn compute_address_from_partial_and_pub_keys_hash() { let pub_keys_hash = PublicKeysHash::from_field(1); let partial_address = PartialAddress::from_field(2); 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 f91d1383a19..09ad9ba1a15 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,37 +38,18 @@ impl PublicKeysHash { Self { inner: field } } - // TODO(#5830): When we do this refactor, rename compute_new -> compute - pub fn compute(public_key: GrumpkinPoint) -> Self { - PublicKeysHash::from_field( - pedersen_hash( - [ - public_key.x, - public_key.y - ], - GENERATOR_INDEX__PARTIAL_ADDRESS - ) - ) - } - - // TODO(#5830): When we do this refactor, rename compute_new -> compute - pub fn compute_new( - nullifier_public_key: GrumpkinPoint, - incoming_public_key: GrumpkinPoint, - outgoing_public_key: GrumpkinPoint, - tagging_public_key: GrumpkinPoint - ) -> Self { + pub fn compute(npk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint, ovpk_m: GrumpkinPoint, tpk_m: 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, + npk_m.x, + npk_m.y, + ivpk_m.x, + ivpk_m.y, + ovpk_m.x, + ovpk_m.y, + tpk_m.x, + tpk_m.y, GENERATOR_INDEX__PUBLIC_KEYS_HASH ] ) @@ -84,11 +65,14 @@ impl PublicKeysHash { } } -// TODO(#5830): re-enable this test once the compute function is updated -// #[test] -// fn compute_public_keys_hash() { -// let point = GrumpkinPoint { x: 1, y: 2 }; -// let actual = PublicKeysHash::compute(point); -// let expected_public_keys_hash = 0x22d83a089d7650514c2de24cd30185a414d943eaa19817c67bffe2c3183006a3; -// assert(actual.to_field() == expected_public_keys_hash); -// } +#[test] +fn compute_public_keys_hash() { + let npk_m = GrumpkinPoint { x: 1, y: 2 }; + let ivpk_m = GrumpkinPoint { x: 3, y: 4 }; + let ovpk_m = GrumpkinPoint { x: 5, y: 6 }; + let tpk_m = GrumpkinPoint { x: 7, y: 8 }; + + let actual = PublicKeysHash::compute(npk_m, ivpk_m, ovpk_m, tpk_m); + let expected_public_keys_hash = 0x1936abe4f6a920d16a9f6917f10a679507687e2cd935dd1f1cdcb1e908c027f3; + assert(actual.to_field() == expected_public_keys_hash); +} diff --git a/yarn-project/accounts/src/defaults/account_contract.ts b/yarn-project/accounts/src/defaults/account_contract.ts index dc3b2330059..f2842c9ac0f 100644 --- a/yarn-project/accounts/src/defaults/account_contract.ts +++ b/yarn-project/accounts/src/defaults/account_contract.ts @@ -1,6 +1,5 @@ import { type AccountContract, type AccountInterface, type AuthWitnessProvider } from '@aztec/aztec.js/account'; import { type CompleteAddress } from '@aztec/circuit-types'; -import { type Fr } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -20,7 +19,7 @@ export abstract class DefaultAccountContract implements AccountContract { return this.artifact; } - getInterface(address: CompleteAddress, publicKeysHash: Fr, nodeInfo: NodeInfo): AccountInterface { - return new DefaultAccountInterface(this.getAuthWitnessProvider(address), address, publicKeysHash, nodeInfo); + getInterface(address: CompleteAddress, nodeInfo: NodeInfo): AccountInterface { + return new DefaultAccountInterface(this.getAuthWitnessProvider(address), address, nodeInfo); } } diff --git a/yarn-project/accounts/src/defaults/account_interface.ts b/yarn-project/accounts/src/defaults/account_interface.ts index f32e96aa208..5d7fa311c6e 100644 --- a/yarn-project/accounts/src/defaults/account_interface.ts +++ b/yarn-project/accounts/src/defaults/account_interface.ts @@ -17,7 +17,6 @@ export class DefaultAccountInterface implements AccountInterface { constructor( private authWitnessProvider: AuthWitnessProvider, private address: CompleteAddress, - private publicKeysHash: Fr, nodeInfo: Pick, ) { this.entrypoint = new DefaultAccountEntrypoint( @@ -38,10 +37,6 @@ export class DefaultAccountInterface implements AccountInterface { return this.authWitnessProvider.createAuthWit(messageHash); } - getPublicKeysHash(): Fr { - return this.publicKeysHash; - } - getCompleteAddress(): CompleteAddress { return this.address; } diff --git a/yarn-project/accounts/src/testing/configuration.ts b/yarn-project/accounts/src/testing/configuration.ts index 7fc376ddd70..cc37380d93f 100644 --- a/yarn-project/accounts/src/testing/configuration.ts +++ b/yarn-project/accounts/src/testing/configuration.ts @@ -45,7 +45,9 @@ export async function getDeployedTestAccountsWallets(pxe: PXE): Promise { const initialEncryptionKey = sha512ToGrumpkinScalar([initialSecretKey, GeneratorIndex.IVSK_M]); const publicKey = generatePublicKey(initialEncryptionKey); - return registeredAccounts.find(registered => registered.publicKey.equals(publicKey)) != undefined; + return ( + registeredAccounts.find(registered => registered.masterIncomingViewingPublicKey.equals(publicKey)) != undefined + ); }).map(secretKey => { const signingKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); // TODO(#5726): use actual salt here instead of hardcoding Fr.ZERO diff --git a/yarn-project/aztec.js/src/account/contract.ts b/yarn-project/aztec.js/src/account/contract.ts index 6ae607d386b..6c49a3b5cf0 100644 --- a/yarn-project/aztec.js/src/account/contract.ts +++ b/yarn-project/aztec.js/src/account/contract.ts @@ -1,5 +1,4 @@ import { type CompleteAddress } from '@aztec/circuit-types'; -import { type Fr } from '@aztec/circuits.js'; import { type ContractArtifact } from '@aztec/foundation/abi'; import { type NodeInfo } from '@aztec/types/interfaces'; @@ -26,11 +25,10 @@ export interface AccountContract { * The account interface is responsible for assembling tx requests given requested function calls, and * for creating signed auth witnesses given action identifiers (message hashes). * @param address - Address where this account contract is deployed. - * @param publicKeysHash - Hash of the public keys used to authorize actions. * @param nodeInfo - Info on the chain where it is deployed. * @returns An account interface instance for creating tx requests and authorizing actions. */ - getInterface(address: CompleteAddress, publicKeysHash: Fr, nodeInfo: NodeInfo): AccountInterface; + getInterface(address: CompleteAddress, nodeInfo: NodeInfo): AccountInterface; /** * Returns the auth witness provider for the given address. diff --git a/yarn-project/aztec.js/src/account/interface.ts b/yarn-project/aztec.js/src/account/interface.ts index 555fce8cbbc..5a5ab2cf28e 100644 --- a/yarn-project/aztec.js/src/account/interface.ts +++ b/yarn-project/aztec.js/src/account/interface.ts @@ -42,9 +42,6 @@ export interface AccountInterface extends AuthWitnessProvider, EntrypointInterfa /** Returns the complete address for this account. */ getCompleteAddress(): CompleteAddress; - /** Returns the public keys hash for this account. */ - getPublicKeysHash(): Fr; - /** Returns the address for this account. */ getAddress(): AztecAddress; diff --git a/yarn-project/aztec.js/src/account_manager/index.ts b/yarn-project/aztec.js/src/account_manager/index.ts index 549855a4d97..842236286a1 100644 --- a/yarn-project/aztec.js/src/account_manager/index.ts +++ b/yarn-project/aztec.js/src/account_manager/index.ts @@ -51,7 +51,7 @@ export class AccountManager { public async getAccount(): Promise { const nodeInfo = await this.pxe.getNodeInfo(); const completeAddress = this.getCompleteAddress(); - return this.accountContract.getInterface(completeAddress, this.getPublicKeysHash(), nodeInfo); + return this.accountContract.getInterface(completeAddress, nodeInfo); } /** diff --git a/yarn-project/aztec.js/src/utils/account.ts b/yarn-project/aztec.js/src/utils/account.ts index c128d8e227e..b9cc606b9b6 100644 --- a/yarn-project/aztec.js/src/utils/account.ts +++ b/yarn-project/aztec.js/src/utils/account.ts @@ -14,7 +14,7 @@ export async function waitForAccountSynch( address: CompleteAddress, { interval, timeout }: WaitOpts = DefaultWaitOpts, ): Promise { - const publicKey = address.publicKey.toString(); + const publicKey = address.masterIncomingViewingPublicKey.toString(); await retryUntil( async () => { const status = await pxe.getSyncStatus(); diff --git a/yarn-project/aztec.js/src/wallet/account_wallet.ts b/yarn-project/aztec.js/src/wallet/account_wallet.ts index a1f7cea1848..803d07010eb 100644 --- a/yarn-project/aztec.js/src/wallet/account_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/account_wallet.ts @@ -16,10 +16,6 @@ export class AccountWallet extends BaseWallet { super(pxe); } - getPublicKeysHash(): Fr { - return this.account.getPublicKeysHash(); - } - createTxExecutionRequest(exec: ExecutionRequestInit): Promise { return this.account.createTxExecutionRequest(exec); } diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index eeacdb4f23a..200ad930dee 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -32,8 +32,6 @@ export abstract class BaseWallet implements Wallet { abstract getCompleteAddress(): CompleteAddress; - abstract getPublicKeysHash(): Fr; - abstract getChainId(): Fr; abstract getVersion(): Fr; @@ -80,9 +78,6 @@ export abstract class BaseWallet implements Wallet { getRegisteredAccount(address: AztecAddress): Promise { return this.pxe.getRegisteredAccount(address); } - getRegisteredAccountPublicKeysHash(address: AztecAddress): Promise { - return this.pxe.getRegisteredAccountPublicKeysHash(address); - } getRecipients(): Promise { return this.pxe.getRecipients(); } diff --git a/yarn-project/aztec.js/src/wallet/index.ts b/yarn-project/aztec.js/src/wallet/index.ts index ad92b67fdd0..08e8cb27c41 100644 --- a/yarn-project/aztec.js/src/wallet/index.ts +++ b/yarn-project/aztec.js/src/wallet/index.ts @@ -25,11 +25,7 @@ export async function getWallet( if (!completeAddress) { throw new Error(`Account ${address} not found`); } - const publicKeysHash = await pxe.getRegisteredAccountPublicKeysHash(address); - if (!publicKeysHash) { - throw new Error(`Public keys hash for account ${address} not found`); - } const nodeInfo = await pxe.getNodeInfo(); - const entrypoint = accountContract.getInterface(completeAddress, publicKeysHash, nodeInfo); + const entrypoint = accountContract.getInterface(completeAddress, nodeInfo); return new AccountWallet(pxe, entrypoint); } diff --git a/yarn-project/aztec/src/cli/util.ts b/yarn-project/aztec/src/cli/util.ts index 769e3b1aba1..610aa727288 100644 --- a/yarn-project/aztec/src/cli/util.ts +++ b/yarn-project/aztec/src/cli/util.ts @@ -126,7 +126,14 @@ export async function createAccountLogs( accountLogStrings.push(` Address: ${completeAddress.address.toString()}\n`); accountLogStrings.push(` Partial Address: ${completeAddress.partialAddress.toString()}\n`); accountLogStrings.push(` Secret Key: ${account.secretKey.toString()}\n`); - accountLogStrings.push(` Public Key: ${completeAddress.publicKey.toString()}\n\n`); + accountLogStrings.push(` Master nullifier public key: ${completeAddress.masterNullifierPublicKey.toString()}\n`); + accountLogStrings.push( + ` Master incoming viewing public key: ${completeAddress.masterIncomingViewingPublicKey.toString()}\n\n`, + ); + accountLogStrings.push( + ` Master outgoing viewing public key: ${completeAddress.masterOutgoingViewingPublicKey.toString()}\n\n`, + ); + accountLogStrings.push(` Master tagging public key: ${completeAddress.masterTaggingPublicKey.toString()}\n\n`); } } return accountLogStrings; diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 0e95d024727..9e01820e4f7 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 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,8 +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: Nuke publicKeys optional parameter after `CompleteAddress` refactor. - registerRecipient(recipient: CompleteAddress, publicKeys?: Point[]): Promise; + registerRecipient(recipient: CompleteAddress): Promise; /** * Retrieves the user accounts registered on this PXE Service. @@ -91,15 +90,6 @@ export interface PXE { */ getRegisteredAccount(address: AztecAddress): Promise; - /** - * Retrieves the public keys hash of the account corresponding to the provided aztec address. - * - * @param address - The address of account. - * @returns The public keys hash of the requested account if found. - * TODO(#5834): refactor complete address and merge with getRegisteredAccount? - */ - getRegisteredAccountPublicKeysHash(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 168ec8d5f04..b4a0d7ce300 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 { type AztecAddress, + type CompleteAddress, type Fr, type GrumpkinPrivateKey, type PartialAddress, - type Point, type PublicKey, } from '@aztec/circuits.js'; @@ -13,17 +13,17 @@ import { export interface KeyStore { /** * Creates a new account from a randomly generated secret key. - * @returns A promise that resolves to the newly created account's AztecAddress. + * @returns A promise that resolves to the newly created account's CompleteAddress. */ - createAccount(): Promise; + createAccount(): Promise; /** * Adds an account to the key store from the provided secret key. * @param sk - The secret key of the account. * @param partialAddress - The partial address of the account. - * @returns The account's address. + * @returns The account's complete address. */ - addAccount(sk: Fr, partialAddress: PartialAddress): Promise; + addAccount(sk: Fr, partialAddress: PartialAddress): Promise; /** * Retrieves addresses of accounts stored in the key store. @@ -117,21 +117,4 @@ export interface KeyStore { * @returns A Promise that resolves to the public keys hash. */ 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 - */ - // TODO(#5834): Move this function out of here. Key store should only be used for accounts, not recipients - addPublicKeysForAccount( - accountAddress: AztecAddress, - masterNullifierPublicKey: Point, - masterIncomingViewingPublicKey: Point, - masterOutgoingViewingPublicKey: Point, - masterTaggingPublicKey: Point, - ): Promise; } diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap index dc6ef757820..37d75fc64af 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap @@ -1,7 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ContractAddress Address from partial matches Noir 1`] = `"0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa"`; - exports[`ContractAddress Public key hash matches Noir 1`] = `"0x22d83a089d7650514c2de24cd30185a414d943eaa19817c67bffe2c3183006a3"`; exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x0bed63221d281713007bfb0c063e1f61d0646404fb3701b99bb92f41b6390604"`; diff --git a/yarn-project/circuits.js/src/contract/contract_address.test.ts b/yarn-project/circuits.js/src/contract/contract_address.test.ts index 6199e69a25d..a2c84f657a1 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.test.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.test.ts @@ -5,7 +5,6 @@ import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/fou import { AztecAddress, deriveKeys } from '../index.js'; import { computeContractAddressFromInstance, - computeContractAddressFromPartial, computeInitializationHash, computePartialAddress, computeSaltedInitializationHash, @@ -69,14 +68,6 @@ describe('ContractAddress', () => { }).toString(); expect(address).toMatchSnapshot(); - - // TODO(#5834): the following was removed from aztec_address.nr, should it be re-introduced? - // // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data - // updateInlineTestData( - // 'noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr', - // 'expected_computed_address_from_preimage', - // address.toString(), - // ); }); it('Public key hash matches Noir', () => { @@ -91,18 +82,4 @@ describe('ContractAddress', () => { hash.toString(), ); }); - - it('Address from partial matches Noir', () => { - const publicKeysHash = new Fr(1n); - const partialAddress = new Fr(2n); - const address = computeContractAddressFromPartial({ publicKeysHash, partialAddress }).toString(); - expect(address).toMatchSnapshot(); - - // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data - updateInlineTestData( - 'noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr', - 'expected_computed_address_from_partial_and_pubkey', - address.toString(), - ); - }); }); diff --git a/yarn-project/circuits.js/src/contract/contract_address.ts b/yarn-project/circuits.js/src/contract/contract_address.ts index 11c4dade226..353e3737d90 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.ts @@ -1,12 +1,12 @@ import { type FunctionAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { pedersenHash, poseidon2Hash } from '@aztec/foundation/crypto'; +import { type AztecAddress } from '@aztec/foundation/aztec-address'; +import { pedersenHash } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; import { GeneratorIndex } from '../constants.gen.js'; import { computeVarArgsHash } from '../hash/hash.js'; -import { deriveKeys } from '../keys/index.js'; +import { computeAddress } from '../keys/index.js'; // TODO(@spalladino): Review all generator indices in this file @@ -26,7 +26,7 @@ export function computeContractAddressFromInstance( ): AztecAddress { const partialAddress = computePartialAddress(instance); const publicKeysHash = instance.publicKeysHash; - return computeContractAddressFromPartial({ partialAddress, publicKeysHash }); + return computeAddress(publicKeysHash, partialAddress); } /** @@ -56,19 +56,6 @@ export function computeSaltedInitializationHash( return pedersenHash([instance.salt, instance.initializationHash, instance.deployer], GeneratorIndex.PARTIAL_ADDRESS); } -/** - * Computes a contract address from its partial address and public keys hash. - * @param args - The hash of the public keys or the plain public key to be hashed, along with the partial address. - * @returns The contract address. - */ -export function computeContractAddressFromPartial( - args: ({ publicKeysHash: Fr } | { secretKey: Fr }) & { partialAddress: Fr }, -): AztecAddress { - const publicKeysHash = 'secretKey' in args ? deriveKeys(args.secretKey).publicKeysHash : args.publicKeysHash; - const result = poseidon2Hash([publicKeysHash, args.partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]); - return AztecAddress.fromField(result); -} - /** * Computes the initialization hash for an instance given its constructor function and arguments. * @param initFn - Constructor function or empty if no initialization is expected. diff --git a/yarn-project/circuits.js/src/keys/__snapshots__/index.test.ts.snap b/yarn-project/circuits.js/src/keys/__snapshots__/index.test.ts.snap new file mode 100644 index 00000000000..1ec1734aed8 --- /dev/null +++ b/yarn-project/circuits.js/src/keys/__snapshots__/index.test.ts.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`🔑 Address from partial matches Noir 1`] = `"0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa"`; diff --git a/yarn-project/circuits.js/src/keys/index.test.ts b/yarn-project/circuits.js/src/keys/index.test.ts new file mode 100644 index 00000000000..13d54bbbab1 --- /dev/null +++ b/yarn-project/circuits.js/src/keys/index.test.ts @@ -0,0 +1,44 @@ +import { Fr, Point } from '@aztec/foundation/fields'; +import { updateInlineTestData } from '@aztec/foundation/testing'; + +import { computeAddress, computePublicKeysHash } from './index.js'; + +describe('🔑', () => { + it('computing public keys hash matches Noir', () => { + const masterNullifierPublicKey = new Point(new Fr(1), new Fr(2)); + const masterIncomingViewingPublicKey = new Point(new Fr(3), new Fr(4)); + const masterOutgoingViewingPublicKey = new Point(new Fr(5), new Fr(6)); + const masterTaggingPublicKey = new Point(new Fr(7), new Fr(8)); + + const expected = Fr.fromString('0x1936abe4f6a920d16a9f6917f10a679507687e2cd935dd1f1cdcb1e908c027f3'); + expect( + computePublicKeysHash( + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ), + ).toEqual(expected); + + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr', + 'expected_public_keys_hash', + expected.toString(), + ); + }); + + it('Address from partial matches Noir', () => { + const publicKeysHash = new Fr(1n); + const partialAddress = new Fr(2n); + const address = computeAddress(publicKeysHash, partialAddress).toString(); + expect(address).toMatchSnapshot(); + + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr', + 'expected_computed_address_from_partial_and_pubkey', + address.toString(), + ); + }); +}); diff --git a/yarn-project/circuits.js/src/keys/index.ts b/yarn-project/circuits.js/src/keys/index.ts index f8da77fcba5..11fd962e75e 100644 --- a/yarn-project/circuits.js/src/keys/index.ts +++ b/yarn-project/circuits.js/src/keys/index.ts @@ -1,4 +1,4 @@ -import { type AztecAddress } from '@aztec/foundation/aztec-address'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; import { poseidon2Hash, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; import { type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; @@ -39,6 +39,11 @@ export function computePublicKeysHash( ]); } +export function computeAddress(publicKeysHash: Fr, partialAddress: Fr) { + const addressFr = poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]); + return AztecAddress.fromField(addressFr); +} + /** * 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/circuits.js/src/structs/complete_address.test.ts b/yarn-project/circuits.js/src/structs/complete_address.test.ts index e8ce620e5e4..70c006ed2b2 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.test.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.test.ts @@ -4,16 +4,29 @@ import { Fr, Point } from '@aztec/foundation/fields'; import { CompleteAddress } from './complete_address.js'; describe('CompleteAddress', () => { - // TODO(#5834): re-enable or remove this test - it.skip('refuses to add an account with incorrect address for given partial address and pubkey', () => { - expect(() => CompleteAddress.create(AztecAddress.random(), Point.random(), Fr.random())).toThrow( - /cannot be derived/, - ); + it('refuses to add an account with incorrect address for given partial address and pubkey', () => { + expect(() => + CompleteAddress.create( + AztecAddress.random(), + Point.random(), + Point.random(), + Point.random(), + Point.random(), + Fr.random(), + ), + ).toThrow(/cannot be derived/); }); it('equals returns true when 2 instances are equal', () => { const address1 = CompleteAddress.random(); - const address2 = CompleteAddress.create(address1.address, address1.publicKey, address1.partialAddress); + const address2 = CompleteAddress.create( + address1.address, + address1.masterNullifierPublicKey, + address1.masterIncomingViewingPublicKey, + address1.masterOutgoingViewingPublicKey, + address1.masterTaggingPublicKey, + address1.partialAddress, + ); expect(address1.equals(address2)).toBe(true); }); diff --git a/yarn-project/circuits.js/src/structs/complete_address.ts b/yarn-project/circuits.js/src/structs/complete_address.ts index f4465685ca0..2e57265516a 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.ts @@ -2,8 +2,8 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, Point } from '@aztec/foundation/fields'; import { BufferReader } from '@aztec/foundation/serialize'; -import { computeContractAddressFromPartial, computePartialAddress } from '../contract/contract_address.js'; -import { deriveKeys } from '../keys/index.js'; +import { computePartialAddress } from '../contract/contract_address.js'; +import { computeAddress, computePublicKeysHash, deriveKeys } from '../keys/index.js'; import { type PartialAddress } from '../types/partial_address.js'; import { type PublicKey } from '../types/public_key.js'; @@ -22,8 +22,14 @@ export class CompleteAddress { public constructor( /** Contract address (typically of an account contract) */ public address: AztecAddress, - /** Public key corresponding to the address (used during note encryption). */ - public publicKey: PublicKey, + /** Master nullifier public key */ + public masterNullifierPublicKey: PublicKey, + /** Master incoming viewing public key */ + public masterIncomingViewingPublicKey: PublicKey, + /** Master outgoing viewing public key */ + public masterOutgoingViewingPublicKey: PublicKey, + /** Master tagging viewing public key */ + public masterTaggingPublicKey: PublicKey, /** Partial key corresponding to the public key to the address. */ public partialAddress: PartialAddress, ) {} @@ -31,32 +37,47 @@ export class CompleteAddress { /** Size in bytes of an instance */ static readonly SIZE_IN_BYTES = 32 * 4; - static create(address: AztecAddress, publicKey: PublicKey, partialAddress: PartialAddress) { - const completeAddress = new CompleteAddress(address, publicKey, partialAddress); - // TODO(#5834): re-enable validation - // completeAddress.validate(); + static create( + address: AztecAddress, + masterNullifierPublicKey: PublicKey, + masterIncomingViewingPublicKey: PublicKey, + masterOutgoingViewingPublicKey: PublicKey, + masterTaggingPublicKey: PublicKey, + partialAddress: PartialAddress, + ): CompleteAddress { + const completeAddress = new CompleteAddress( + address, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + partialAddress, + ); + completeAddress.validate(); return completeAddress; } - static random() { - // TODO(#5834): the following should be cleaned up - const secretKey = Fr.random(); - const partialAddress = Fr.random(); - const address = computeContractAddressFromPartial({ secretKey, partialAddress }); - const publicKey = deriveKeys(secretKey).masterIncomingViewingPublicKey; - return new CompleteAddress(address, publicKey, partialAddress); - } - - static fromRandomSecretKey() { - const secretKey = Fr.random(); - const partialAddress = Fr.random(); - return { secretKey, completeAddress: CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, partialAddress) }; + static random(): CompleteAddress { + return this.fromSecretKeyAndPartialAddress(Fr.random(), Fr.random()); } static fromSecretKeyAndPartialAddress(secretKey: Fr, partialAddress: Fr): CompleteAddress { - const address = computeContractAddressFromPartial({ secretKey, partialAddress }); - const publicKey = deriveKeys(secretKey).masterIncomingViewingPublicKey; - return new CompleteAddress(address, publicKey, partialAddress); + const { + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + publicKeysHash, + } = deriveKeys(secretKey); + const address = computeAddress(publicKeysHash, partialAddress); + return new CompleteAddress( + address, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + partialAddress, + ); } static fromSecretKeyAndInstance( @@ -64,29 +85,31 @@ export class CompleteAddress { instance: Parameters[0], ): CompleteAddress { const partialAddress = computePartialAddress(instance); - const address = computeContractAddressFromPartial({ secretKey, partialAddress }); - const publicKey = deriveKeys(secretKey).masterIncomingViewingPublicKey; - return new CompleteAddress(address, publicKey, partialAddress); + return CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, partialAddress); } - // TODO(#5834): re-enable validation - // /** Throws if the address is not correctly derived from the public key and partial address.*/ - // public validate() { - // const expectedAddress = computeContractAddressFromPartial(this); - // const address = this.address; - // if (!expectedAddress.equals(address)) { - // throw new Error( - // `Address cannot be derived from pubkey and partial address (received ${address.toString()}, derived ${expectedAddress.toString()})`, - // ); - // } - // } + /** Throws if the address is not correctly derived from the public key and partial address.*/ + public validate() { + const publicKeysHash = computePublicKeysHash( + this.masterNullifierPublicKey, + this.masterIncomingViewingPublicKey, + this.masterOutgoingViewingPublicKey, + this.masterTaggingPublicKey, + ); + const expectedAddress = computeAddress(publicKeysHash, this.partialAddress); + if (!expectedAddress.equals(this.address)) { + throw new Error( + `Address cannot be derived from public keys and partial address (received ${this.address.toString()}, derived ${expectedAddress.toString()})`, + ); + } + } /** - * Gets a readable string representation of a the complete address. + * Gets a readable string representation of the complete address. * @returns A readable string representation of the complete address. */ public toReadableString(): string { - return ` Address: ${this.address.toString()}\n Public Key: ${this.publicKey.toString()}\n Partial Address: ${this.partialAddress.toString()}\n`; + return `Address: ${this.address.toString()}\nMaster Nullifier Public Key: ${this.masterNullifierPublicKey.toString()}\nMaster Incoming Viewing Public Key: ${this.masterIncomingViewingPublicKey.toString()}\nMaster Outgoing Viewing Public Key: ${this.masterOutgoingViewingPublicKey.toString()}\nMaster Tagging Public Key: ${this.masterTaggingPublicKey.toString()}\nPartial Address: ${this.partialAddress.toString()}\n`; } /** @@ -96,10 +119,13 @@ export class CompleteAddress { * @param other - The CompleteAddress instance to compare against. * @returns True if the buffers of both instances are equal, false otherwise. */ - equals(other: CompleteAddress) { + equals(other: CompleteAddress): boolean { return ( this.address.equals(other.address) && - this.publicKey.equals(other.publicKey) && + this.masterNullifierPublicKey.equals(other.masterNullifierPublicKey) && + this.masterIncomingViewingPublicKey.equals(other.masterIncomingViewingPublicKey) && + this.masterOutgoingViewingPublicKey.equals(other.masterOutgoingViewingPublicKey) && + this.masterTaggingPublicKey.equals(other.masterTaggingPublicKey) && this.partialAddress.equals(other.partialAddress) ); } @@ -110,8 +136,15 @@ export class CompleteAddress { * * @returns A Buffer representation of the CompleteAddress instance. */ - toBuffer() { - return Buffer.concat([this.address.toBuffer(), this.publicKey.toBuffer(), this.partialAddress.toBuffer()]); + toBuffer(): Buffer { + return Buffer.concat([ + this.address.toBuffer(), + this.masterNullifierPublicKey.toBuffer(), + this.masterIncomingViewingPublicKey.toBuffer(), + this.masterOutgoingViewingPublicKey.toBuffer(), + this.masterTaggingPublicKey.toBuffer(), + this.partialAddress.toBuffer(), + ]); } /** @@ -122,12 +155,22 @@ export class CompleteAddress { * @param buffer - The input buffer or BufferReader containing the address data. * @returns - A new CompleteAddress instance with the extracted address data. */ - static fromBuffer(buffer: Buffer | BufferReader) { + static fromBuffer(buffer: Buffer | BufferReader): CompleteAddress { const reader = BufferReader.asReader(buffer); const address = reader.readObject(AztecAddress); - const publicKey = reader.readObject(Point); + const masterNullifierPublicKey = reader.readObject(Point); + const masterIncomingViewingPublicKey = reader.readObject(Point); + const masterOutgoingViewingPublicKey = reader.readObject(Point); + const masterTaggingPublicKey = reader.readObject(Point); const partialAddress = reader.readObject(Fr); - return new this(address, publicKey, partialAddress); + return new CompleteAddress( + address, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + partialAddress, + ); } /** @@ -151,4 +194,13 @@ export class CompleteAddress { toString(): string { return `0x${this.toBuffer().toString('hex')}`; } + + get publicKeysHash(): Fr { + return computePublicKeysHash( + this.masterNullifierPublicKey, + this.masterIncomingViewingPublicKey, + this.masterOutgoingViewingPublicKey, + this.masterTaggingPublicKey, + ); + } } diff --git a/yarn-project/end-to-end/src/benchmarks/utils.ts b/yarn-project/end-to-end/src/benchmarks/utils.ts index 0dbbe2d6162..1072040b1ce 100644 --- a/yarn-project/end-to-end/src/benchmarks/utils.ts +++ b/yarn-project/end-to-end/src/benchmarks/utils.ts @@ -127,7 +127,8 @@ export async function waitNewPXESynced( */ export async function waitRegisteredAccountSynced(pxe: PXE, secretKey: Fr, partialAddress: PartialAddress) { const l2Block = await pxe.getBlockNumber(); - const { publicKey } = await pxe.registerAccount(secretKey, partialAddress); - const isAccountSynced = async () => (await pxe.getSyncStatus()).notes[publicKey.toString()] === l2Block; + const { masterIncomingViewingPublicKey } = await pxe.registerAccount(secretKey, partialAddress); + const isAccountSynced = async () => + (await pxe.getSyncStatus()).notes[masterIncomingViewingPublicKey.toString()] === l2Block; await retryUntil(isAccountSynced, 'pxe-notes-sync'); } diff --git a/yarn-project/end-to-end/src/e2e_account_contracts.test.ts b/yarn-project/end-to-end/src/e2e_account_contracts.test.ts index e5f8f0743a5..68ac9c89e28 100644 --- a/yarn-project/end-to-end/src/e2e_account_contracts.test.ts +++ b/yarn-project/end-to-end/src/e2e_account_contracts.test.ts @@ -74,11 +74,7 @@ describe('e2e_account_contracts', () => { const walletAt = async (pxe: PXE, accountContract: AccountContract, address: CompleteAddress) => { const nodeInfo = await pxe.getNodeInfo(); - const publicKeysHash = await pxe.getRegisteredAccountPublicKeysHash(address.address); - if (!publicKeysHash) { - throw new Error(`Public keys hash for account ${address.address} not found`); - } - const entrypoint = accountContract.getInterface(address, publicKeysHash, nodeInfo); + const entrypoint = accountContract.getInterface(address, nodeInfo); return new AccountWallet(pxe, entrypoint); }; diff --git a/yarn-project/end-to-end/src/e2e_card_game.test.ts b/yarn-project/end-to-end/src/e2e_card_game.test.ts index f0949b16663..743ff3a38b3 100644 --- a/yarn-project/end-to-end/src/e2e_card_game.test.ts +++ b/yarn-project/end-to-end/src/e2e_card_game.test.ts @@ -105,7 +105,7 @@ describe('e2e_card_game', () => { const publicKey = deriveKeys(key).masterIncomingViewingPublicKey; return ( preRegisteredAccounts.find(preRegisteredAccount => { - return preRegisteredAccount.publicKey.equals(publicKey); + return preRegisteredAccount.masterIncomingViewingPublicKey.equals(publicKey); }) == undefined ); }); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts index 05b31422828..ffafbb038e7 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts @@ -3,11 +3,10 @@ import { type AccountWallet, type AztecAddress, type AztecNode, - CompleteAddress, type ContractArtifact, type ContractBase, type DebugLogger, - type Fr, + Fr, type PXE, type Wallet, createDebugLogger, @@ -81,10 +80,8 @@ export class DeployTest { } async registerRandomAccount(): Promise { - const pxe = this.pxe; - const { completeAddress: owner, secretKey } = CompleteAddress.fromRandomSecretKey(); - await pxe.registerAccount(secretKey, owner.partialAddress); - return owner.address; + const completeAddress = await this.pxe.registerAccount(Fr.random(), Fr.random()); + return completeAddress.address; } } diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts index 403da38154c..8d50e4e91a1 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts @@ -33,7 +33,7 @@ describe('e2e_deploy_contract legacy', () => { */ it('should deploy a test contract', async () => { const salt = Fr.random(); - const publicKeysHash = wallet.getPublicKeysHash(); + const publicKeysHash = wallet.getCompleteAddress().publicKeysHash; const deploymentData = getContractInstanceFromDeployParams(TestContractArtifact, { salt, publicKeysHash, 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 c770ceaf9dd..88d65a5037a 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,6 +1,5 @@ import { type AccountWallet, AztecAddress, Fr, type PXE } from '@aztec/aztec.js'; -import { CompleteAddress, GeneratorIndex, type PartialAddress, Point, deriveKeys } from '@aztec/circuits.js'; -import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { CompleteAddress, Point } from '@aztec/circuits.js'; import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; @@ -23,16 +22,7 @@ describe('Key Registry', () => { let teardown: () => Promise; - // TODO(#5834): use AztecAddress.compute or smt - const { - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - publicKeysHash, - } = deriveKeys(Fr.random()); - const partialAddress: PartialAddress = Fr.random(); - let account: AztecAddress; + const account = CompleteAddress.random(); beforeAll(async () => { ({ teardown, pxe, wallets } = await setup(3)); @@ -41,11 +31,6 @@ describe('Key Registry', () => { testContract = await TestContract.deploy(wallets[0]).send().deployed(); await publicDeployAccounts(wallets[0], wallets.slice(0, 2)); - - // TODO(#5834): use AztecAddress.compute or smt - account = AztecAddress.fromField( - poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]), - ); }); const crossDelay = async () => { @@ -60,10 +45,10 @@ describe('Key Registry', () => { describe('failure cases', () => { it('throws when address preimage check fails', async () => { const keys = [ - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, + account.masterNullifierPublicKey, + account.masterIncomingViewingPublicKey, + account.masterOutgoingViewingPublicKey, + account.masterTaggingPublicKey, ]; // We randomly invalidate some of the keys @@ -72,7 +57,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.register(AztecAddress.fromField(account), partialAddress, keys[0], keys[1], keys[2], keys[3]) + .methods.register(account, account.partialAddress, keys[0], keys[1], keys[2], keys[3]) .send() .wait(), ).rejects.toThrow('Computed address does not match supplied address'); @@ -82,7 +67,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[1].getAddress(), Point.random(), Fr.ZERO) + .methods.rotate_npk_m(wallets[1].getAddress(), Point.random(), Fr.ZERO) .send() .wait(), ).rejects.toThrow('Assertion failed: Message not authorized by account'); @@ -96,33 +81,20 @@ describe('Key Registry', () => { await expect( testContract.methods.test_nullifier_key_freshness(randomAddress, randomMasterNullifierPublicKey).send().wait(), - ).rejects.toThrow(`Cannot satisfy constraint 'computed_address.eq(address)'`); + ).rejects.toThrow(/No public key registered for address/); }); }); it('fresh key lib succeeds for non-registered account available in PXE', async () => { - // TODO(#5834): Make this not disgusting - const newAccountKeys = deriveKeys(Fr.random()); - const newAccountPartialAddress = Fr.random(); - const newAccount = AztecAddress.fromField( - poseidon2Hash([newAccountKeys.publicKeysHash, newAccountPartialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]), - ); - const newAccountCompleteAddress = CompleteAddress.create( - newAccount, - newAccountKeys.masterIncomingViewingPublicKey, - newAccountPartialAddress, - ); - - await pxe.registerRecipient(newAccountCompleteAddress, [ - newAccountKeys.masterNullifierPublicKey, - newAccountKeys.masterIncomingViewingPublicKey, - newAccountKeys.masterOutgoingViewingPublicKey, - newAccountKeys.masterTaggingPublicKey, - ]); + const newAccountCompleteAddress = CompleteAddress.random(); + await pxe.registerRecipient(newAccountCompleteAddress); // Should succeed as the account is now registered as a recipient in PXE await testContract.methods - .test_nullifier_key_freshness(newAccount, newAccountKeys.masterNullifierPublicKey) + .test_nullifier_key_freshness( + newAccountCompleteAddress.address, + newAccountCompleteAddress.masterNullifierPublicKey, + ) .send() .wait(); }); @@ -133,11 +105,11 @@ describe('Key Registry', () => { .withWallet(wallets[0]) .methods.register( account, - partialAddress, - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, + account.partialAddress, + account.masterNullifierPublicKey, + account.masterIncomingViewingPublicKey, + account.masterOutgoingViewingPublicKey, + account.masterTaggingPublicKey, ) .send() .wait(); @@ -157,13 +129,13 @@ describe('Key Registry', () => { .test_shared_mutable_private_getter_for_registry_contract(1, account) .simulate(); - expect(new Fr(nullifierPublicKeyX)).toEqual(masterNullifierPublicKey.x); + expect(new Fr(nullifierPublicKeyX)).toEqual(account.masterNullifierPublicKey.x); }); // Note: This test case is dependent on state from the previous one it('key lib succeeds for registered account', async () => { // Should succeed as the account is registered in key registry from tests before - await testContract.methods.test_nullifier_key_freshness(account, masterNullifierPublicKey).send().wait(); + await testContract.methods.test_nullifier_key_freshness(account, account.masterNullifierPublicKey).send().wait(); }); }); @@ -174,7 +146,7 @@ describe('Key Registry', () => { it('rotates npk_m', async () => { await keyRegistry .withWallet(wallets[0]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), firstNewMasterNullifierPublicKey, Fr.ZERO) + .methods.rotate_npk_m(wallets[0].getAddress(), firstNewMasterNullifierPublicKey, Fr.ZERO) .send() .wait(); @@ -199,7 +171,7 @@ describe('Key Registry', () => { it(`rotates npk_m with authwit`, async () => { const action = keyRegistry .withWallet(wallets[1]) - .methods.rotate_nullifier_public_key(wallets[0].getAddress(), secondNewMasterNullifierPublicKey, Fr.ZERO); + .methods.rotate_npk_m(wallets[0].getAddress(), secondNewMasterNullifierPublicKey, Fr.ZERO); await wallets[0] .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) diff --git a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts index a8b0ed53439..6aaae7545f7 100644 --- a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts +++ b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts @@ -50,7 +50,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { const encryptionPublicKey = deriveKeys(encryptionPrivateKey).masterIncomingViewingPublicKey; for (const account of accounts) { - expect(account.publicKey).toEqual(encryptionPublicKey); + expect(account.masterIncomingViewingPublicKey).toEqual(encryptionPublicKey); } logger.info(`Deploying Token...`); 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 61647e0097c..2395dbf1472 100644 --- a/yarn-project/key-store/src/test_key_store.test.ts +++ b/yarn-project/key-store/src/test_key_store.test.ts @@ -11,7 +11,7 @@ describe('TestKeyStore', () => { const sk = new Fr(8923n); const partialAddress = new Fr(243523n); - const accountAddress = await keyStore.addAccount(sk, partialAddress); + const { address: accountAddress } = await keyStore.addAccount(sk, partialAddress); expect(accountAddress.toString()).toMatchInlineSnapshot( `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, ); diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index a3c0d4b239b..a21763ebf83 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -1,12 +1,14 @@ import { type KeyStore, type PublicKey } from '@aztec/circuit-types'; import { AztecAddress, + CompleteAddress, Fr, GeneratorIndex, type GrumpkinPrivateKey, GrumpkinScalar, type PartialAddress, Point, + computeAddress, computeAppNullifierSecretKey, deriveKeys, } from '@aztec/circuits.js'; @@ -26,9 +28,9 @@ export class TestKeyStore implements KeyStore { /** * Creates a new account from a randomly generated secret key. - * @returns A promise that resolves to the newly created account's AztecAddress. + * @returns A promise that resolves to the newly created account's CompleteAddress. */ - public createAccount(): Promise { + public createAccount(): Promise { const sk = Fr.random(); const partialAddress = Fr.random(); return this.addAccount(sk, partialAddress); @@ -38,9 +40,9 @@ export class TestKeyStore implements KeyStore { * Adds an account to the key store from the provided secret key. * @param sk - The secret key of the account. * @param partialAddress - The partial address of the account. - * @returns The account's address. + * @returns The account's complete address. */ - public async addAccount(sk: Fr, partialAddress: PartialAddress): Promise { + public async addAccount(sk: Fr, partialAddress: PartialAddress): Promise { const { publicKeysHash, masterNullifierSecretKey, @@ -53,10 +55,7 @@ export class TestKeyStore implements KeyStore { masterTaggingPublicKey, } = deriveKeys(sk); - // 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 accountAddressFr = poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]); - const accountAddress = AztecAddress.fromField(accountAddressFr); + const accountAddress = computeAddress(publicKeysHash, partialAddress); // We save the keys to db await this.#keys.set(`${accountAddress.toString()}-public_keys_hash`, publicKeysHash.toBuffer()); @@ -72,7 +71,16 @@ export class TestKeyStore implements KeyStore { await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); // At last, we return the newly derived account address - return Promise.resolve(accountAddress); + return Promise.resolve( + CompleteAddress.create( + accountAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + partialAddress, + ), + ); } /** @@ -292,18 +300,4 @@ 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, - 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/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index c07a29219de..7452f98f5b9 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -209,7 +209,7 @@ export class KVPxeDatabase implements PxeDatabase { #getNotes(filter: NoteFilter): NoteDao[] { const publicKey: PublicKey | undefined = filter.owner - ? this.#getCompleteAddress(filter.owner)?.publicKey + ? this.#getCompleteAddress(filter.owner)?.masterIncomingViewingPublicKey : undefined; filter.status = filter.status ?? NoteStatus.ACTIVE; 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 9a1fbbe46f8..440df3db400 100644 --- a/yarn-project/pxe/src/database/pxe_database_test_suite.ts +++ b/yarn-project/pxe/src/database/pxe_database_test_suite.ts @@ -92,7 +92,10 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { [() => ({ txHash: notes[0].txHash }), () => [notes[0]]], [() => ({ txHash: randomTxHash() }), () => []], - [() => ({ owner: owners[0].address }), () => notes.filter(note => note.publicKey.equals(owners[0].publicKey))], + [ + () => ({ owner: owners[0].address }), + () => notes.filter(note => note.publicKey.equals(owners[0].masterIncomingViewingPublicKey)), + ], [ () => ({ contractAddress: contractAddresses[0], storageSlot: storageSlots[0] }), @@ -113,7 +116,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { randomNoteDao({ contractAddress: contractAddresses[i % contractAddresses.length], storageSlot: storageSlots[i % storageSlots.length], - publicKey: owners[i % owners.length].publicKey, + publicKey: owners[i % owners.length].masterIncomingViewingPublicKey, index: BigInt(i), }), ); @@ -142,9 +145,11 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { // Nullify all notes and use the same filter as other test cases for (const owner of owners) { - const notesToNullify = notes.filter(note => note.publicKey.equals(owner.publicKey)); + const notesToNullify = notes.filter(note => note.publicKey.equals(owner.masterIncomingViewingPublicKey)); const nullifiers = notesToNullify.map(note => note.siloedNullifier); - await expect(database.removeNullifiedNotes(nullifiers, owner.publicKey)).resolves.toEqual(notesToNullify); + await expect( + database.removeNullifiedNotes(nullifiers, owner.masterIncomingViewingPublicKey), + ).resolves.toEqual(notesToNullify); } await expect(database.getNotes({ ...getFilter(), status: NoteStatus.ACTIVE_OR_NULLIFIED })).resolves.toEqual( @@ -155,7 +160,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { it('skips nullified notes by default or when requesting active', async () => { await database.addNotes(notes); - const notesToNullify = notes.filter(note => note.publicKey.equals(owners[0].publicKey)); + const notesToNullify = notes.filter(note => note.publicKey.equals(owners[0].masterIncomingViewingPublicKey)); const nullifiers = notesToNullify.map(note => note.siloedNullifier); await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].publicKey)).resolves.toEqual( notesToNullify, @@ -171,7 +176,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { it('returns active and nullified notes when requesting either', async () => { await database.addNotes(notes); - const notesToNullify = notes.filter(note => note.publicKey.equals(owners[0].publicKey)); + const notesToNullify = notes.filter(note => note.publicKey.equals(owners[0].masterIncomingViewingPublicKey)); const nullifiers = notesToNullify.map(note => note.siloedNullifier); await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].publicKey)).resolves.toEqual( notesToNullify, @@ -215,7 +220,14 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { it.skip('refuses to overwrite an address with a different public key', async () => { const address = CompleteAddress.random(); - const otherAddress = new CompleteAddress(address.address, Point.random(), address.partialAddress); + const otherAddress = new CompleteAddress( + address.address, + Point.random(), + Point.random(), + Point.random(), + Point.random(), + address.partialAddress, + ); await database.addCompleteAddress(address); await expect(database.addCompleteAddress(otherAddress)).rejects.toThrow(); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 3ed4fa30cf4..c918ffaafa9 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -25,7 +25,7 @@ import { type TxPXEProcessingStats } from '@aztec/circuit-types/stats'; import { AztecAddress, CallRequest, - CompleteAddress, + type CompleteAddress, FunctionData, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, type PartialAddress, @@ -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, 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'; @@ -115,12 +115,12 @@ export class PXEService implements PXE { let count = 0; for (const address of registeredAddresses) { - if (!publicKeysSet.has(address.publicKey.toString())) { + if (!publicKeysSet.has(address.masterIncomingViewingPublicKey.toString())) { continue; } count++; - this.synchronizer.addAccount(address.publicKey, this.keyStore, this.config.l2StartingBlock); + this.synchronizer.addAccount(address.masterIncomingViewingPublicKey, this.keyStore, this.config.l2StartingBlock); } if (count > 0) { @@ -170,24 +170,21 @@ export class PXEService implements PXE { public async registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise { const accounts = await this.keyStore.getAccounts(); - const account = await this.keyStore.addAccount(secretKey, partialAddress); - const completeAddress = new CompleteAddress( - account, - await this.keyStore.getMasterIncomingViewingPublicKey(account), - partialAddress, - ); - if (accounts.includes(account)) { - this.log.info(`Account:\n "${completeAddress.address.toString()}"\n already registered.`); - return completeAddress; + const accountCompleteAddress = await this.keyStore.addAccount(secretKey, partialAddress); + if (accounts.includes(accountCompleteAddress.address)) { + this.log.info(`Account:\n "${accountCompleteAddress.address.toString()}"\n already registered.`); + return accountCompleteAddress; } else { - const masterIncomingViewingPublicKey = await this.keyStore.getMasterIncomingViewingPublicKey(account); + const masterIncomingViewingPublicKey = await this.keyStore.getMasterIncomingViewingPublicKey( + accountCompleteAddress.address, + ); this.synchronizer.addAccount(masterIncomingViewingPublicKey, this.keyStore, this.config.l2StartingBlock); - this.log.info(`Registered account ${completeAddress.address.toString()}`); - this.log.debug(`Registered account\n ${completeAddress.toReadableString()}`); + this.log.info(`Registered account ${accountCompleteAddress.address.toString()}`); + this.log.debug(`Registered account\n ${accountCompleteAddress.toReadableString()}`); } - await this.db.addCompleteAddress(completeAddress); - return completeAddress; + await this.db.addCompleteAddress(accountCompleteAddress); + return accountCompleteAddress; } public async getRegisteredAccounts(): Promise { @@ -214,20 +211,9 @@ export class PXEService implements PXE { return this.keyStore.getPublicKeysHash(address); } - public async registerRecipient(recipient: CompleteAddress, publicKeys: Point[] = []): Promise { + public async registerRecipient(recipient: CompleteAddress): 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) { - 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 { @@ -306,7 +292,7 @@ export class PXEService implements PXE { let owner = filter.owner; if (owner === undefined) { const completeAddresses = (await this.db.getCompleteAddresses()).find(address => - address.publicKey.equals(dao.publicKey), + address.masterIncomingViewingPublicKey.equals(dao.publicKey), ); if (completeAddresses === undefined) { throw new Error(`Cannot find complete address for public key ${dao.publicKey.toString()}`); @@ -319,8 +305,8 @@ export class PXEService implements PXE { } public async addNote(note: ExtendedNote) { - const { publicKey } = (await this.db.getCompleteAddress(note.owner)) ?? {}; - if (!publicKey) { + const { masterIncomingViewingPublicKey } = (await this.db.getCompleteAddress(note.owner)) ?? {}; + if (!masterIncomingViewingPublicKey) { throw new Error('Unknown account.'); } @@ -360,7 +346,7 @@ export class PXEService implements PXE { innerNoteHash, siloedNullifier, index, - publicKey, + masterIncomingViewingPublicKey, ), ); } diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index 75d2f11b142..cf9e7d6c4c4 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -70,7 +70,14 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => it('cannot register a recipient with the same aztec address but different pub key or partial address', async () => { const recipient1 = CompleteAddress.random(); - const recipient2 = new CompleteAddress(recipient1.address, Point.random(), Fr.random()); + const recipient2 = new CompleteAddress( + recipient1.address, + Point.random(), + Point.random(), + Point.random(), + Point.random(), + Fr.random(), + ); await pxe.registerRecipient(recipient1); await expect(() => pxe.registerRecipient(recipient2)).rejects.toThrow( diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 12e540148b7..ac9ee3566ef 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -15,7 +15,6 @@ import { 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 FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/abi'; @@ -44,7 +43,6 @@ export class SimulatorOracle implements DBOracle { return { masterNullifierPublicKey, appNullifierSecretKey }; } - // TODO: #5834 async getCompleteAddress(address: AztecAddress): Promise { const completeAddress = await this.db.getCompleteAddress(address); if (!completeAddress) { @@ -79,16 +77,6 @@ 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); - 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/pxe/src/synchronizer/synchronizer.test.ts b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts index f8deb8b8ca3..1c145eb3302 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.test.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts @@ -1,5 +1,5 @@ import { type AztecNode, L2Block } from '@aztec/circuit-types'; -import { CompleteAddress, Fr, type Header, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js'; +import { Fr, type Header, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js'; import { makeHeader } from '@aztec/circuits.js/testing'; import { randomInt } from '@aztec/foundation/crypto'; import { SerialQueue } from '@aztec/foundation/fifo'; @@ -130,12 +130,9 @@ describe('Synchronizer', () => { const addAddress = async (startingBlockNum: number) => { const secretKey = Fr.random(); const partialAddress = Fr.random(); - const accountAddress = await keyStore.addAccount(secretKey, partialAddress); - const masterIncomingViewingPublicKey = await keyStore.getMasterIncomingViewingPublicKey(accountAddress); - - const completeAddress = new CompleteAddress(accountAddress, masterIncomingViewingPublicKey, partialAddress); + const completeAddress = await keyStore.addAccount(secretKey, partialAddress); await database.addCompleteAddress(completeAddress); - synchronizer.addAccount(completeAddress.publicKey, keyStore, startingBlockNum); + synchronizer.addAccount(completeAddress.masterIncomingViewingPublicKey, keyStore, startingBlockNum); return completeAddress; }; diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.ts b/yarn-project/pxe/src/synchronizer/synchronizer.ts index dc7f1890877..d7da26c991e 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.ts @@ -285,7 +285,8 @@ export class Synchronizer { if (!completeAddress) { throw new Error(`Checking if account is synched is not possible for ${account} because it is not registered.`); } - const findByPublicKey = (x: NoteProcessor) => x.masterIncomingViewingPublicKey.equals(completeAddress.publicKey); + const findByPublicKey = (x: NoteProcessor) => + x.masterIncomingViewingPublicKey.equals(completeAddress.masterIncomingViewingPublicKey); const processor = this.noteProcessors.find(findByPublicKey) ?? this.noteProcessorsToCatchUp.find(findByPublicKey); if (!processor) { throw new Error( diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 415f8c3e84e..7df1704f427 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 { 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'; @@ -53,14 +53,6 @@ export class Oracle { ]; } - // TODO: #5834 Nuke this - async getPublicKeyAndPartialAddress([address]: ACVMField[]) { - const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddress( - AztecAddress.fromField(fromACVMField(address)), - ); - return [publicKey.x, publicKey.y, partialAddress].map(toACVMField); - } - async getContractInstance([address]: ACVMField[]) { const instance = await this.typedOracle.getContractInstance(AztecAddress.fromField(fromACVMField(address))); @@ -173,25 +165,22 @@ export class Oracle { } async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { - 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)))); - } catch (err) { - partialAddress = Fr.ZERO; - } + const parsedAddress = AztecAddress.fromField(fromACVMField(address)); + const { + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + partialAddress, + } = await this.typedOracle.getCompleteAddress(parsedAddress); - try { - publicKeys = await this.typedOracle.getPublicKeysForAddress(AztecAddress.fromField(fromACVMField(address))); - } catch (err) { - publicKeys = Array(4).fill(Point.ZERO); - } - - const acvmPublicKeys = publicKeys.flatMap(key => key.toFields()); - - return [...acvmPublicKeys, partialAddress].map(toACVMField); + return [ + ...masterNullifierPublicKey.toFields(), + ...masterIncomingViewingPublicKey.toFields(), + ...masterOutgoingViewingPublicKey.toFields(), + ...masterTaggingPublicKey.toFields(), + partialAddress, + ].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 171ccb4d757..231d8cd99d1 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, 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. */ @@ -93,10 +93,6 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getNullifierKeys'); } - getPublicKeyAndPartialAddress(_address: AztecAddress): Promise { - throw new OracleMethodNotAvailableError('getPublicKeyAndPartialAddress'); - } - getContractInstance(_address: AztecAddress): Promise { throw new OracleMethodNotAvailableError('getContractInstance'); } @@ -140,10 +136,6 @@ 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 a7e78619eb1..0fbdbd64364 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -8,7 +8,7 @@ import { 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, 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'; @@ -64,14 +64,6 @@ export interface DBOracle extends CommitmentsDB { */ popCapsule(): Promise; - /** - * Gets public keys for an address. - * @param The address to look up - * @returns The public keys for a specific address - * TODO(#5834): Replace with `getCompleteAddress`. - */ - getPublicKeysForAddress(address: AztecAddress): Promise; - /** * Retrieve nullifier keys associated with a specific account and app/contract address. * diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 1037f15109e..8bfb5019bc9 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -1053,7 +1053,7 @@ describe('Private Execution test suite', () => { // Generate a partial address, pubkey, and resulting address const completeAddress = CompleteAddress.random(); const args = [completeAddress.address]; - const pubKey = completeAddress.publicKey; + const pubKey = completeAddress.masterIncomingViewingPublicKey; oracle.getCompleteAddress.mockResolvedValue(completeAddress); const result = await runSimulator({ artifact, args }); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index 50dc2552c25..b4c02039175 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -166,16 +166,6 @@ export class ViewDataOracle extends TypedOracle { return this.db.popCapsule(); } - /** - * Gets public keys for an address. - * @param The address to look up - * @returns The public keys for a specific address - * TODO(#5834): Replace with `getCompleteAddress`. - */ - 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.