From e57a82f7ed0da6c93718aa9b1e922ccdafa4eabf Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 13 May 2024 11:49:16 +0000 Subject: [PATCH 1/7] feat: demonstrating use of nsk_app to check nullification --- .../accounts/src/testing/create_account.ts | 17 ++++--- .../end-to-end/src/e2e_key_registry.test.ts | 48 +++++++++++++++++-- .../pxe/src/pxe_service/pxe_service.ts | 4 -- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/yarn-project/accounts/src/testing/create_account.ts b/yarn-project/accounts/src/testing/create_account.ts index 262fb29e07be..e9f16e4ba545 100644 --- a/yarn-project/accounts/src/testing/create_account.ts +++ b/yarn-project/accounts/src/testing/create_account.ts @@ -1,6 +1,6 @@ import { type AccountWalletWithSecretKey } from '@aztec/aztec.js/wallet'; import { type PXE } from '@aztec/circuit-types'; -import { Fr, GeneratorIndex } from '@aztec/circuits.js'; +import { Fr, GeneratorIndex, deriveSigningKey } from '@aztec/circuits.js'; import { sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; import { getSchnorrAccount } from '../schnorr/index.js'; @@ -22,14 +22,19 @@ export function createAccount(pxe: PXE): Promise { * @param numberOfAccounts - How many accounts to create. * @returns The created account wallets. */ -export async function createAccounts(pxe: PXE, numberOfAccounts = 1): Promise { +export async function createAccounts(pxe: PXE, numberOfAccounts = 1, secrets: Fr[] = []): Promise { const accounts = []; + if (secrets.length == 0) { + secrets = Array(numberOfAccounts).fill(Fr.random()); + } else if (secrets.length > 0 && secrets.length !== numberOfAccounts) { + throw new Error('Secrets array must be empty or have the same length as the number of accounts'); + } + // Prepare deployments - for (let i = 0; i < numberOfAccounts; ++i) { - const secretKey = Fr.random(); - const signingKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); - const account = getSchnorrAccount(pxe, secretKey, signingKey); + for (const secret of secrets) { + const signingKey = deriveSigningKey(secret); + const account = getSchnorrAccount(pxe, secret, signingKey); // Unfortunately the function below is not stateless and we call it here because it takes a long time to run and // the results get stored within the account object. By calling it here we increase the probability of all the // accounts being deployed in the same block because it makes the deploy() method basically instant. 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 d0c47faa1876..203f8112ccba 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,11 +1,12 @@ -import { type AccountWallet, AztecAddress, Fr, type PXE } from '@aztec/aztec.js'; -import { CompleteAddress, Point, PublicKeys } from '@aztec/circuits.js'; +import { type AccountWallet, AztecAddress, Fr, type PXE, AztecNode, L2Block } from '@aztec/aztec.js'; +import { CompleteAddress, GeneratorIndex, INITIAL_L2_BLOCK_NUM, Point } from '@aztec/circuits.js'; import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; import { jest } from '@jest/globals'; import { publicDeployAccounts, setup } from './fixtures/utils.js'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; const TIMEOUT = 120_000; @@ -15,6 +16,7 @@ describe('Key Registry', () => { let keyRegistry: KeyRegistryContract; let pxe: PXE; + let aztecNode: AztecNode; let testContract: TestContract; jest.setTimeout(TIMEOUT); @@ -25,7 +27,7 @@ describe('Key Registry', () => { const account = CompleteAddress.random(); beforeAll(async () => { - ({ teardown, pxe, wallets } = await setup(3)); + ({ aztecNode, teardown, pxe, wallets } = await setup(2)); keyRegistry = await KeyRegistryContract.at(getCanonicalKeyRegistryAddress(), wallets[0]); testContract = await TestContract.deploy(wallets[0]).send().deployed(); @@ -208,4 +210,44 @@ describe('Key Registry', () => { .wait(); }); }); + + it.only('nsk_app is enough to detect note nullification', async () => { + const nskApp = computeAppNullifierSecretKey(wallets[0].getPrivateKey(), testContract.address); + + const noteValue = 5; + const noteOwner = wallets[0].getAddress(); + const noteStorageSlot = 12; + + await testContract.methods + .call_create_note( + noteValue, + noteOwner, + noteStorageSlot, + ) + .send() + .wait(); + + await testContract.methods + .call_destroy_note( + noteStorageSlot, + ) + .send() + .wait(); + }); + + const getNumNullifiedNotes = async (nskApp: Fr) => { + // 1. Get all note hashes + const blocks = await aztecNode.getBlocks(INITIAL_L2_BLOCK_NUM, 1000); + const noteHashes = blocks.flatMap((block: L2Block) => block.body.txEffects.flatMap((txEffect) => txEffect.noteHashes)); + // 2. Get all seen nullifiers + const nullifiers = blocks.flatMap((block: L2Block) => block.body.txEffects.flatMap((txEffect) => txEffect.nullifiers)); + // 3. Derive all the possible nullifiers using nskApp + const derivedNullifiers = noteHashes.map((noteHash) => poseidon2Hash([ + noteHash, + nskApp, + GeneratorIndex.NOTE_NULLIFIER, + ])); + // 4. Count the number of nullifiers that are in the nullifiers list + return derivedNullifiers.filter((nullifier) => nullifiers.includes(nullifier)).length; + } }); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index c4b4aa1cd985..55dbfa158857 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -804,10 +804,6 @@ export class PXEService implements PXE { return Promise.resolve(this.synchronizer.getSyncStatus()); } - public getKeyStore() { - return this.keyStore; - } - public async isContractClassPubliclyRegistered(id: Fr): Promise { return !!(await this.node.getContractClass(id)); } From f20e5ba31a4fb3b0ec1f2b58bcdccfe273bb308d Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 13 May 2024 13:00:36 +0000 Subject: [PATCH 2/7] WIP --- .../accounts/src/testing/create_account.ts | 6 +++++- .../end-to-end/src/e2e_key_registry.test.ts | 19 ++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/yarn-project/accounts/src/testing/create_account.ts b/yarn-project/accounts/src/testing/create_account.ts index e9f16e4ba545..970964f7d146 100644 --- a/yarn-project/accounts/src/testing/create_account.ts +++ b/yarn-project/accounts/src/testing/create_account.ts @@ -22,7 +22,11 @@ export function createAccount(pxe: PXE): Promise { * @param numberOfAccounts - How many accounts to create. * @returns The created account wallets. */ -export async function createAccounts(pxe: PXE, numberOfAccounts = 1, secrets: Fr[] = []): Promise { +export async function createAccounts( + pxe: PXE, + numberOfAccounts = 1, + secrets: Fr[] = [], +): Promise { const accounts = []; if (secrets.length == 0) { 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 203f8112ccba..80dc7690ac01 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, AztecNode, L2Block } from '@aztec/aztec.js'; -import { CompleteAddress, GeneratorIndex, INITIAL_L2_BLOCK_NUM, Point } from '@aztec/circuits.js'; +import { type AccountWallet, AztecAddress, Fr, type PXE, type AztecNode, type L2Block } from '@aztec/aztec.js'; +import { CompleteAddress, GeneratorIndex, INITIAL_L2_BLOCK_NUM, Point, computeAppNullifierSecretKey, deriveMasterNullifierSecretKey } from '@aztec/circuits.js'; import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; @@ -7,6 +7,7 @@ import { jest } from '@jest/globals'; import { publicDeployAccounts, setup } from './fixtures/utils.js'; import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { createAccounts } from '@aztec/accounts/testing'; const TIMEOUT = 120_000; @@ -211,11 +212,15 @@ describe('Key Registry', () => { }); }); - it.only('nsk_app is enough to detect note nullification', async () => { - const nskApp = computeAppNullifierSecretKey(wallets[0].getPrivateKey(), testContract.address); + it('nsk_app is enough to detect note nullification', async () => { + const secret = Fr.random(); + const [account] = await createAccounts(pxe, 1, [secret]); + + const masterNullifierSecretKey = deriveMasterNullifierSecretKey(secret); + const nskApp = computeAppNullifierSecretKey(masterNullifierSecretKey, testContract.address); const noteValue = 5; - const noteOwner = wallets[0].getAddress(); + const noteOwner = account.getAddress(); const noteStorageSlot = 12; await testContract.methods @@ -227,12 +232,16 @@ describe('Key Registry', () => { .send() .wait(); + expect(await getNumNullifiedNotes(nskApp)).toEqual(0); + await testContract.methods .call_destroy_note( noteStorageSlot, ) .send() .wait(); + + expect(await getNumNullifiedNotes(nskApp)).toEqual(1); }); const getNumNullifiedNotes = async (nskApp: Fr) => { From 7ff91a3f3c9d387f69fc2cc37e44fdaae3530dd4 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 13 May 2024 15:37:44 +0000 Subject: [PATCH 3/7] fix --- .../end-to-end/src/e2e_key_registry.test.ts | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 80dc7690ac01..0e43b77f1bd1 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,13 +1,21 @@ -import { type AccountWallet, AztecAddress, Fr, type PXE, type AztecNode, type L2Block } from '@aztec/aztec.js'; -import { CompleteAddress, GeneratorIndex, INITIAL_L2_BLOCK_NUM, Point, computeAppNullifierSecretKey, deriveMasterNullifierSecretKey } from '@aztec/circuits.js'; +import { createAccounts } from '@aztec/accounts/testing'; +import { type AccountWallet, AztecAddress, type AztecNode, Fr, type L2Block, type PXE } from '@aztec/aztec.js'; +import { + CompleteAddress, + GeneratorIndex, + INITIAL_L2_BLOCK_NUM, + Point, + PublicKeys, + computeAppNullifierSecretKey, + deriveMasterNullifierSecretKey, +} from '@aztec/circuits.js'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; import { jest } from '@jest/globals'; import { publicDeployAccounts, setup } from './fixtures/utils.js'; -import { poseidon2Hash } from '@aztec/foundation/crypto'; -import { createAccounts } from '@aztec/accounts/testing'; const TIMEOUT = 120_000; @@ -223,23 +231,11 @@ describe('Key Registry', () => { const noteOwner = account.getAddress(); const noteStorageSlot = 12; - await testContract.methods - .call_create_note( - noteValue, - noteOwner, - noteStorageSlot, - ) - .send() - .wait(); + await testContract.methods.call_create_note(noteValue, noteOwner, noteStorageSlot).send().wait(); expect(await getNumNullifiedNotes(nskApp)).toEqual(0); - await testContract.methods - .call_destroy_note( - noteStorageSlot, - ) - .send() - .wait(); + await testContract.methods.call_destroy_note(noteStorageSlot).send().wait(); expect(await getNumNullifiedNotes(nskApp)).toEqual(1); }); @@ -247,16 +243,18 @@ describe('Key Registry', () => { const getNumNullifiedNotes = async (nskApp: Fr) => { // 1. Get all note hashes const blocks = await aztecNode.getBlocks(INITIAL_L2_BLOCK_NUM, 1000); - const noteHashes = blocks.flatMap((block: L2Block) => block.body.txEffects.flatMap((txEffect) => txEffect.noteHashes)); + const noteHashes = blocks.flatMap((block: L2Block) => + block.body.txEffects.flatMap(txEffect => txEffect.noteHashes), + ); // 2. Get all seen nullifiers - const nullifiers = blocks.flatMap((block: L2Block) => block.body.txEffects.flatMap((txEffect) => txEffect.nullifiers)); + const nullifiers = blocks.flatMap((block: L2Block) => + block.body.txEffects.flatMap(txEffect => txEffect.nullifiers), + ); // 3. Derive all the possible nullifiers using nskApp - const derivedNullifiers = noteHashes.map((noteHash) => poseidon2Hash([ - noteHash, - nskApp, - GeneratorIndex.NOTE_NULLIFIER, - ])); + const derivedNullifiers = noteHashes.map(noteHash => + poseidon2Hash([noteHash, nskApp, GeneratorIndex.NOTE_NULLIFIER]), + ); // 4. Count the number of nullifiers that are in the nullifiers list - return derivedNullifiers.filter((nullifier) => nullifiers.includes(nullifier)).length; - } + return derivedNullifiers.filter(nullifier => nullifiers.includes(nullifier)).length; + }; }); From 960f7d003f1e7fb08670682d32eb368a7bf6925c Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 14 May 2024 08:17:00 +0000 Subject: [PATCH 4/7] it works --- .../end-to-end/src/e2e_key_registry.test.ts | 72 +++++++++++-------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 0e43b77f1bd1..2d347a553fdc 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 @@ -9,6 +9,7 @@ import { computeAppNullifierSecretKey, deriveMasterNullifierSecretKey, } from '@aztec/circuits.js'; +import { siloNullifier } from '@aztec/circuits.js/hash'; import { poseidon2Hash } from '@aztec/foundation/crypto'; import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; @@ -220,41 +221,52 @@ describe('Key Registry', () => { }); }); - it('nsk_app is enough to detect note nullification', async () => { - const secret = Fr.random(); - const [account] = await createAccounts(pxe, 1, [secret]); + describe('using nsk_app to detect nullification', () => { + // This test checks that it possible to detect that a note has been nullified just by using nsk_app. Note that this + // only works for non-transient note as transient notes never emit a note hash which makes it impossible to brute + // force their nullifier. This makes this scheme a bit useless in practice. + it('nsk_app and contract address are enough to detect note nullification', async () => { + const secret = Fr.random(); + const [account] = await createAccounts(pxe, 1, [secret]); - const masterNullifierSecretKey = deriveMasterNullifierSecretKey(secret); - const nskApp = computeAppNullifierSecretKey(masterNullifierSecretKey, testContract.address); + const masterNullifierSecretKey = deriveMasterNullifierSecretKey(secret); + const nskApp = computeAppNullifierSecretKey(masterNullifierSecretKey, testContract.address); - const noteValue = 5; - const noteOwner = account.getAddress(); - const noteStorageSlot = 12; + const noteValue = 5; + const noteOwner = account.getAddress(); + const noteStorageSlot = 12; - await testContract.methods.call_create_note(noteValue, noteOwner, noteStorageSlot).send().wait(); + await testContract.methods.call_create_note(noteValue, noteOwner, noteStorageSlot).send().wait(); - expect(await getNumNullifiedNotes(nskApp)).toEqual(0); + expect(await getNumNullifiedNotes(nskApp, testContract.address)).toEqual(0); - await testContract.methods.call_destroy_note(noteStorageSlot).send().wait(); + await testContract.methods.call_destroy_note(noteStorageSlot).send().wait(); - expect(await getNumNullifiedNotes(nskApp)).toEqual(1); - }); + expect(await getNumNullifiedNotes(nskApp, testContract.address)).toEqual(1); + }); - const getNumNullifiedNotes = async (nskApp: Fr) => { - // 1. Get all note hashes - const blocks = await aztecNode.getBlocks(INITIAL_L2_BLOCK_NUM, 1000); - const noteHashes = blocks.flatMap((block: L2Block) => - block.body.txEffects.flatMap(txEffect => txEffect.noteHashes), - ); - // 2. Get all seen nullifiers - const nullifiers = blocks.flatMap((block: L2Block) => - block.body.txEffects.flatMap(txEffect => txEffect.nullifiers), - ); - // 3. Derive all the possible nullifiers using nskApp - const derivedNullifiers = noteHashes.map(noteHash => - poseidon2Hash([noteHash, nskApp, GeneratorIndex.NOTE_NULLIFIER]), - ); - // 4. Count the number of nullifiers that are in the nullifiers list - return derivedNullifiers.filter(nullifier => nullifiers.includes(nullifier)).length; - }; + const getNumNullifiedNotes = async (nskApp: Fr, contractAddress: AztecAddress) => { + // 1. Get all the note hashes + const blocks = await aztecNode.getBlocks(INITIAL_L2_BLOCK_NUM, 1000); + const noteHashes = blocks.flatMap((block: L2Block) => + block.body.txEffects.flatMap(txEffect => txEffect.noteHashes), + ); + // 2. Get all the seen nullifiers + const nullifiers = blocks.flatMap((block: L2Block) => + block.body.txEffects.flatMap(txEffect => txEffect.nullifiers), + ); + // 3. Derive all the possible nullifiers using nskApp + const derivedNullifiers = noteHashes.map(noteHash => { + const innerNullifier = poseidon2Hash([noteHash, nskApp, GeneratorIndex.NOTE_NULLIFIER]); + return siloNullifier(contractAddress, innerNullifier); + }); + // 4. Count the number of derived nullifiers that are in the nullifiers array + return derivedNullifiers.reduce((count, derived) => { + if (nullifiers.some(nullifier => nullifier.equals(derived))) { + count++; + } + return count; + }, 0); + }; + }); }); From a852e8047365cb531a7d11c5b8cb07a7546918b7 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 14 May 2024 08:23:47 +0000 Subject: [PATCH 5/7] cleanup + docs --- yarn-project/accounts/src/single_key/index.ts | 5 ++--- yarn-project/accounts/src/testing/configuration.ts | 9 ++++----- yarn-project/accounts/src/testing/create_account.ts | 7 ++++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/yarn-project/accounts/src/single_key/index.ts b/yarn-project/accounts/src/single_key/index.ts index f29ed18a7e68..72bb8d7c1de2 100644 --- a/yarn-project/accounts/src/single_key/index.ts +++ b/yarn-project/accounts/src/single_key/index.ts @@ -7,8 +7,7 @@ import { AccountManager, type Salt } from '@aztec/aztec.js/account'; import { type AccountWallet, getWallet } from '@aztec/aztec.js/wallet'; import { type GrumpkinPrivateKey, type PXE } from '@aztec/circuit-types'; -import { type AztecAddress, type Fr, GeneratorIndex } from '@aztec/circuits.js'; -import { sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; +import { type AztecAddress, type Fr, deriveMasterIncomingViewingSecretKey } from '@aztec/circuits.js'; import { SingleKeyAccountContract } from './account_contract.js'; @@ -23,7 +22,7 @@ export { SchnorrSingleKeyAccountContractArtifact as SingleKeyAccountContractArti * @param salt - Deployment salt. */ export function getSingleKeyAccount(pxe: PXE, secretKey: Fr, salt?: Salt): AccountManager { - const encryptionPrivateKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); + const encryptionPrivateKey = deriveMasterIncomingViewingSecretKey(secretKey); return new AccountManager(pxe, secretKey, new SingleKeyAccountContract(encryptionPrivateKey), salt); } diff --git a/yarn-project/accounts/src/testing/configuration.ts b/yarn-project/accounts/src/testing/configuration.ts index b5a1d7586fc3..bb58e05c3cf9 100644 --- a/yarn-project/accounts/src/testing/configuration.ts +++ b/yarn-project/accounts/src/testing/configuration.ts @@ -1,8 +1,7 @@ import { generatePublicKey } from '@aztec/aztec.js'; import { type AccountWalletWithSecretKey } from '@aztec/aztec.js/wallet'; import { type PXE } from '@aztec/circuit-types'; -import { GeneratorIndex } from '@aztec/circuits.js/constants'; -import { sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; +import { deriveMasterIncomingViewingSecretKey, deriveSigningKey } from '@aztec/circuits.js/keys'; import { Fr } from '@aztec/foundation/fields'; import { getSchnorrAccount } from '../schnorr/index.js'; @@ -14,7 +13,7 @@ export const INITIAL_TEST_SECRET_KEYS = [ ]; export const INITIAL_TEST_ENCRYPTION_KEYS = INITIAL_TEST_SECRET_KEYS.map(secretKey => - sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]), + deriveMasterIncomingViewingSecretKey(secretKey), ); // TODO(#5837): come up with a standard signing key derivation scheme instead of using ivsk_m as signing keys here export const INITIAL_TEST_SIGNING_KEYS = INITIAL_TEST_ENCRYPTION_KEYS; @@ -43,14 +42,14 @@ export async function getDeployedTestAccountsWallets(pxe: PXE): Promise { - const initialEncryptionKey = sha512ToGrumpkinScalar([initialSecretKey, GeneratorIndex.IVSK_M]); + const initialEncryptionKey = deriveMasterIncomingViewingSecretKey(initialSecretKey); const publicKey = generatePublicKey(initialEncryptionKey); return ( registeredAccounts.find(registered => registered.publicKeys.masterIncomingViewingPublicKey.equals(publicKey)) != undefined ); }).map(secretKey => { - const signingKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); + const signingKey = deriveSigningKey(secretKey); // TODO(#5726): use actual salt here instead of hardcoding Fr.ZERO return getSchnorrAccount(pxe, secretKey, signingKey, Fr.ZERO).getWallet(); }), diff --git a/yarn-project/accounts/src/testing/create_account.ts b/yarn-project/accounts/src/testing/create_account.ts index 970964f7d146..1ecf3a87c885 100644 --- a/yarn-project/accounts/src/testing/create_account.ts +++ b/yarn-project/accounts/src/testing/create_account.ts @@ -1,7 +1,6 @@ import { type AccountWalletWithSecretKey } from '@aztec/aztec.js/wallet'; import { type PXE } from '@aztec/circuit-types'; -import { Fr, GeneratorIndex, deriveSigningKey } from '@aztec/circuits.js'; -import { sha512ToGrumpkinScalar } from '@aztec/foundation/crypto'; +import { Fr, deriveSigningKey } from '@aztec/circuits.js'; import { getSchnorrAccount } from '../schnorr/index.js'; @@ -12,7 +11,7 @@ import { getSchnorrAccount } from '../schnorr/index.js'; */ export function createAccount(pxe: PXE): Promise { const secretKey = Fr.random(); - const signingKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.IVSK_M]); + const signingKey = deriveSigningKey(secretKey); return getSchnorrAccount(pxe, secretKey, signingKey).waitSetup(); } @@ -20,6 +19,8 @@ export function createAccount(pxe: PXE): Promise { * Creates a given number of random accounts using the Schnorr account wallet. * @param pxe - PXE. * @param numberOfAccounts - How many accounts to create. + * @param secrets - Optional array of secrets to use for the accounts. If empty, random secrets will be generated. + * @throws If the secrets array is not empty and does not have the same length as the number of accounts. * @returns The created account wallets. */ export async function createAccounts( From fa883a6b222e32c38f0a9198dfe9d454e83e63b3 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 14 May 2024 08:33:22 +0000 Subject: [PATCH 6/7] WIP --- yarn-project/end-to-end/src/shared/browser.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/yarn-project/end-to-end/src/shared/browser.ts b/yarn-project/end-to-end/src/shared/browser.ts index 0aec2e8b7b9d..d9af14773288 100644 --- a/yarn-project/end-to-end/src/shared/browser.ts +++ b/yarn-project/end-to-end/src/shared/browser.ts @@ -218,7 +218,6 @@ export const browserTestSuite = ( createPXEClient, getSchnorrAccount, Contract, - deriveKeys, Fr, ExtendedNote, Note, @@ -248,11 +247,9 @@ export const browserTestSuite = ( knownAccounts.push(newAccount); } const owner = knownAccounts[0]; - // TODO(#5726): this is messy, maybe we should expose publicKeysHash on account - const publicKeysHash = deriveKeys(INITIAL_TEST_SECRET_KEYS[0]).publicKeys.hash(); const ownerAddress = owner.getAddress(); const tx = new DeployMethod( - publicKeysHash, + owner.getCompleteAddress().publicKeys.hash(), owner, TokenContractArtifact, (a: AztecJs.AztecAddress) => Contract.at(a, TokenContractArtifact, owner), From 20e7b2b3545d5511617f87b73f0d780132261728 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 14 May 2024 11:10:22 +0000 Subject: [PATCH 7/7] same secrets fix --- yarn-project/accounts/src/testing/create_account.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/accounts/src/testing/create_account.ts b/yarn-project/accounts/src/testing/create_account.ts index 1ecf3a87c885..5f9903165dae 100644 --- a/yarn-project/accounts/src/testing/create_account.ts +++ b/yarn-project/accounts/src/testing/create_account.ts @@ -31,7 +31,7 @@ export async function createAccounts( const accounts = []; if (secrets.length == 0) { - secrets = Array(numberOfAccounts).fill(Fr.random()); + secrets = Array.from({ length: numberOfAccounts }, () => Fr.random()); } else if (secrets.length > 0 && secrets.length !== numberOfAccounts) { throw new Error('Secrets array must be empty or have the same length as the number of accounts'); }