From 7068d055d91a6e81e6fbb670e17c77ee209a1a80 Mon Sep 17 00:00:00 2001 From: Gregorio Juliana Date: Thu, 23 Jan 2025 13:00:32 +0100 Subject: [PATCH] feat: Lazy wasm pt3 (#11435) Moved all grumpkin math to be async, which mostly affected address derivation --- .../barretenberg_wasm_main/heap_allocator.ts | 24 ++++--- .../barretenberg_wasm_main/index.ts | 4 +- .../accounts/src/ecdsa/ecdsa_k/index.ts | 1 + .../accounts/src/ecdsa/ssh_ecdsa_r/index.ts | 1 + yarn-project/accounts/src/schnorr/index.ts | 1 + yarn-project/accounts/src/single_key/index.ts | 1 + .../accounts/src/testing/configuration.ts | 32 +++++---- yarn-project/archiver/src/factory.ts | 2 +- .../account_manager/deploy_account_method.ts | 2 +- .../aztec.js/src/account_manager/index.ts | 18 ++--- .../aztec.js/src/contract/contract.test.ts | 2 +- .../aztec.js/src/contract/deploy_method.ts | 31 +++++---- .../aztec.js/src/contract/deploy_proven_tx.ts | 4 +- .../aztec.js/src/contract/deploy_sent_tx.ts | 12 ++-- .../src/deployment/broadcast_function.ts | 4 +- .../src/deployment/deploy_instance.ts | 7 +- .../src/deployment/protocol_contracts.ts | 8 +-- .../aztec.js/src/deployment/register_class.ts | 2 +- .../fee_juice_payment_method_with_claim.ts | 5 +- yarn-project/aztec.js/src/utils/pub_key.ts | 2 +- yarn-project/aztec/src/cli/util.ts | 8 +-- yarn-project/bot/src/factory.ts | 2 +- .../circuit-types/src/interfaces/pxe.test.ts | 4 +- .../l1_payload/encrypted_log_payload.test.ts | 8 +-- .../logs/l1_payload/encrypted_log_payload.ts | 2 +- .../src/logs/l1_payload/encryption_util.ts | 12 ++-- .../l1_payload/shared_secret_derivation.ts | 4 +- yarn-project/circuit-types/src/mocks.ts | 2 +- .../crypto/grumpkin/index.test.ts | 12 ++-- .../src/barretenberg/crypto/grumpkin/index.ts | 66 ++++++++++--------- .../src/contract/contract_address.test.ts | 22 ++++--- .../src/contract/contract_address.ts | 2 +- .../src/contract/contract_instance.ts | 6 +- .../circuits.js/src/keys/derivation.test.ts | 4 +- .../circuits.js/src/keys/derivation.ts | 22 +++---- .../src/structs/complete_address.test.ts | 26 ++++---- .../src/structs/complete_address.ts | 30 +++++---- .../circuits.js/src/tests/factories.ts | 2 +- .../cli-wallet/src/cmds/create_account.ts | 2 +- yarn-project/cli-wallet/src/cmds/deploy.ts | 2 +- .../cli-wallet/src/cmds/deploy_account.ts | 2 +- yarn-project/cli/src/cmds/pxe/add_contract.ts | 2 +- .../end-to-end/src/e2e_2_pxes.test.ts | 2 +- .../end-to-end/src/e2e_block_building.test.ts | 13 ++-- .../end-to-end/src/e2e_card_game.test.ts | 13 ++-- .../src/e2e_crowdfunding_and_claim.test.ts | 4 +- .../contract_class_registration.test.ts | 9 +-- .../e2e_deploy_contract/deploy_method.test.ts | 3 +- .../src/e2e_deploy_contract/deploy_test.ts | 2 +- .../src/e2e_deploy_contract/legacy.test.ts | 5 +- .../src/e2e_escrow_contract.test.ts | 4 +- .../end-to-end/src/e2e_event_logs.test.ts | 4 +- .../src/e2e_fees/account_init.test.ts | 4 +- .../end-to-end/src/e2e_fees/fees_test.ts | 4 +- yarn-project/end-to-end/src/e2e_keys.test.ts | 2 +- .../e2e_multiple_accounts_1_enc_key.test.ts | 4 +- yarn-project/end-to-end/src/e2e_p2p/shared.ts | 2 +- .../end-to-end/src/e2e_synching.test.ts | 2 +- .../src/e2e_token_contract/transfer.test.ts | 2 +- .../src/fixtures/snapshot_manager.ts | 5 +- yarn-project/end-to-end/src/fixtures/utils.ts | 5 +- ...akey_e2e_inclusion_proofs_contract.test.ts | 10 ++- yarn-project/end-to-end/src/shared/browser.ts | 2 +- .../src/spartan/setup_test_wallets.ts | 6 +- .../json-rpc/client/safe_json_rpc_client.ts | 1 - yarn-project/key-store/src/key_store.test.ts | 4 +- yarn-project/key-store/src/key_store.ts | 10 +-- yarn-project/noir-contracts.js/package.json | 2 +- .../src/noir_test_gen.test.ts | 4 +- .../src/auth-registry/index.ts | 4 +- .../protocol-contracts/src/bundle/index.ts | 4 +- .../src/class-registerer/index.ts | 4 +- .../protocol-contracts/src/fee-juice/index.ts | 4 +- .../src/instance-deployer/index.ts | 4 +- .../src/make_protocol_contract.ts | 7 +- .../src/multi-call-entrypoint/index.ts | 4 +- .../protocol-contracts/src/router/index.ts | 4 +- .../src/scripts/generate_data.ts | 7 +- .../pxe/src/database/kv_pxe_database.ts | 4 +- .../src/database/pxe_database_test_suite.ts | 17 ++--- .../pxe/src/pxe_service/pxe_service.ts | 7 +- .../pxe/src/simulator_oracle/index.ts | 2 +- .../simulator_oracle/simulator_oracle.test.ts | 22 +++---- .../simulator/src/avm/avm_simulator.test.ts | 8 +-- .../simulator/src/avm/opcodes/ec_add.test.ts | 6 +- .../simulator/src/avm/opcodes/ec_add.ts | 2 +- .../src/avm/opcodes/multi_scalar_mul.test.ts | 19 +++--- .../src/avm/opcodes/multi_scalar_mul.ts | 14 ++-- .../src/client/private_execution.test.ts | 17 +++-- .../simulator/src/client/simulator.test.ts | 2 +- .../client/unconstrained_execution.test.ts | 4 +- .../txe/src/txe_service/txe_service.ts | 12 ++-- 92 files changed, 392 insertions(+), 319 deletions(-) diff --git a/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/heap_allocator.ts b/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/heap_allocator.ts index 390b32ed0d8..14f7cfbdcb6 100644 --- a/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/heap_allocator.ts +++ b/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/heap_allocator.ts @@ -15,17 +15,21 @@ export class HeapAllocator { constructor(private wasm: BarretenbergWasmMain) {} - copyToMemory(buffers: Uint8Array[]) { - return buffers.map(buf => { - if (buf.length <= this.inScratchRemaining) { - const ptr = (this.inScratchRemaining -= buf.length); - this.wasm.writeMemory(ptr, buf); - return ptr; + getInputs(buffers: (Uint8Array | number)[]) { + return buffers.map(bufOrNum => { + if (typeof bufOrNum === 'object') { + if (bufOrNum.length <= this.inScratchRemaining) { + const ptr = (this.inScratchRemaining -= bufOrNum.length); + this.wasm.writeMemory(ptr, bufOrNum); + return ptr; + } else { + const ptr = this.wasm.call('bbmalloc', bufOrNum.length); + this.wasm.writeMemory(ptr, bufOrNum); + this.allocs.push(ptr); + return ptr; + } } else { - const ptr = this.wasm.call('bbmalloc', buf.length); - this.wasm.writeMemory(ptr, buf); - this.allocs.push(ptr); - return ptr; + return bufOrNum; } }); } diff --git a/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/index.ts b/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/index.ts index 06a57aa5a80..569b4b1e974 100644 --- a/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/index.ts +++ b/barretenberg/ts/src/barretenberg_wasm/barretenberg_wasm_main/index.ts @@ -102,9 +102,9 @@ export class BarretenbergWasmMain extends BarretenbergWasmBase { /* eslint-enable camelcase */ } - callWasmExport(funcName: string, inArgs: Uint8Array[], outLens: (number | undefined)[]) { + callWasmExport(funcName: string, inArgs: (Uint8Array | number)[], outLens: (number | undefined)[]) { const alloc = new HeapAllocator(this); - const inPtrs = alloc.copyToMemory(inArgs); + const inPtrs = alloc.getInputs(inArgs); const outPtrs = alloc.getOutputPtrs(outLens); this.call(funcName, ...inPtrs, ...outPtrs); const outArgs = this.getOutputArgs(outLens, outPtrs, alloc); diff --git a/yarn-project/accounts/src/ecdsa/ecdsa_k/index.ts b/yarn-project/accounts/src/ecdsa/ecdsa_k/index.ts index 2e2e1ad3ab5..ab35d9cb8b0 100644 --- a/yarn-project/accounts/src/ecdsa/ecdsa_k/index.ts +++ b/yarn-project/accounts/src/ecdsa/ecdsa_k/index.ts @@ -20,6 +20,7 @@ export { EcdsaKAccountContract }; * @param secretKey - Secret key used to derive all the keystore keys. * @param signingPrivateKey - Secp256k1 key used for signing transactions. * @param salt - Deployment salt. + * @returns An account manager initialized with the account contract and its deployment params */ export function getEcdsaKAccount( pxe: PXE, diff --git a/yarn-project/accounts/src/ecdsa/ssh_ecdsa_r/index.ts b/yarn-project/accounts/src/ecdsa/ssh_ecdsa_r/index.ts index af953cb953d..98d5fce02b9 100644 --- a/yarn-project/accounts/src/ecdsa/ssh_ecdsa_r/index.ts +++ b/yarn-project/accounts/src/ecdsa/ssh_ecdsa_r/index.ts @@ -20,6 +20,7 @@ export { EcdsaRSSHAccountContract }; * @param secretKey - Secret key used to derive all the keystore keys. * @param signingPublicKey - Secp2561 key used to identify its corresponding private key in the SSH Agent. * @param salt - Deployment salt. + * @returns An account manager initialized with the account contract and its deployment params */ export function getEcdsaRSSHAccount( pxe: PXE, diff --git a/yarn-project/accounts/src/schnorr/index.ts b/yarn-project/accounts/src/schnorr/index.ts index b210c789c49..48f78feaa0f 100644 --- a/yarn-project/accounts/src/schnorr/index.ts +++ b/yarn-project/accounts/src/schnorr/index.ts @@ -21,6 +21,7 @@ export { SchnorrAccountContractArtifact } from './artifact.js'; * @param secretKey - Secret key used to derive all the keystore keys. * @param signingPrivateKey - Grumpkin key used for signing transactions. * @param salt - Deployment salt. + * @returns An account manager initialized with the account contract and its deployment params */ export function getSchnorrAccount( pxe: PXE, diff --git a/yarn-project/accounts/src/single_key/index.ts b/yarn-project/accounts/src/single_key/index.ts index 732f44f0059..3908156d75f 100644 --- a/yarn-project/accounts/src/single_key/index.ts +++ b/yarn-project/accounts/src/single_key/index.ts @@ -20,6 +20,7 @@ export { SchnorrSingleKeyAccountContractArtifact as SingleKeyAccountContractArti * @param pxe - An PXE server instance. * @param secretKey - Secret key used to derive all the keystore keys (in this case also used to get signing key). * @param salt - Deployment salt. + * @returns An account manager initialized with the account contract and its deployment params */ export function getSingleKeyAccount(pxe: PXE, secretKey: Fr, salt?: Salt) { const encryptionPrivateKey = deriveMasterIncomingViewingSecretKey(secretKey); diff --git a/yarn-project/accounts/src/testing/configuration.ts b/yarn-project/accounts/src/testing/configuration.ts index 70f45c402e6..ea5a825b709 100644 --- a/yarn-project/accounts/src/testing/configuration.ts +++ b/yarn-project/accounts/src/testing/configuration.ts @@ -48,21 +48,29 @@ export function getInitialTestAccountsWallets(pxe: PXE): Promise { const registeredAccounts = await pxe.getRegisteredAccounts(); - return Promise.all( - INITIAL_TEST_SECRET_KEYS.filter(initialSecretKey => { + const publicKeys = await Promise.all( + INITIAL_TEST_SECRET_KEYS.map(async initialSecretKey => { const initialEncryptionKey = deriveMasterIncomingViewingSecretKey(initialSecretKey); - const publicKey = generatePublicKey(initialEncryptionKey); - return ( - registeredAccounts.find(registered => registered.publicKeys.masterIncomingViewingPublicKey.equals(publicKey)) != - undefined - ); - }).map(async secretKey => { - const signingKey = deriveSigningKey(secretKey); - // TODO(#5726): use actual salt here instead of hardcoding Fr.ZERO - const account = await getSchnorrAccount(pxe, secretKey, signingKey, Fr.ZERO); - return account.getWallet(); + const publicKey = await generatePublicKey(initialEncryptionKey); + return { sk: initialSecretKey, pk: publicKey }; }), ); + return Promise.all( + publicKeys + .filter(keyPairs => { + return ( + registeredAccounts.find(registered => + registered.publicKeys.masterIncomingViewingPublicKey.equals(keyPairs.pk), + ) != undefined + ); + }) + .map(async keyPairs => { + const signingKey = deriveSigningKey(keyPairs.sk); + // TODO(#5726): use actual salt here instead of hardcoding Fr.ZERO + const account = await getSchnorrAccount(pxe, keyPairs.sk, signingKey, Fr.ZERO); + return account.getWallet(); + }), + ); } /** diff --git a/yarn-project/archiver/src/factory.ts b/yarn-project/archiver/src/factory.ts index 96556003117..9863b4a57ca 100644 --- a/yarn-project/archiver/src/factory.ts +++ b/yarn-project/archiver/src/factory.ts @@ -41,7 +41,7 @@ export async function createArchiver( async function registerProtocolContracts(store: KVArchiverDataStore) { const blockNumber = 0; for (const name of protocolContractNames) { - const contract = getCanonicalProtocolContract(name); + const contract = await getCanonicalProtocolContract(name); const contractClassPublic: ContractClassPublic = { ...contract.contractClass, privateFunctions: [], diff --git a/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts b/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts index 0407f1b43a6..6a1b1db1f42 100644 --- a/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts +++ b/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts @@ -52,7 +52,7 @@ export class DeployAccountMethod extends DeployMethod { const exec = await super.getInitializeFunctionCalls(options); if (options.fee && this.#feePaymentArtifact) { - const { address } = this.getInstance(); + const { address } = await this.getInstance(); const emptyAppPayload = EntrypointPayload.fromAppExecution([]); const fee = await this.getDefaultFeeOptions(options.fee); const feePayload = await EntrypointPayload.fromFeeOptions(address, fee); diff --git a/yarn-project/aztec.js/src/account_manager/index.ts b/yarn-project/aztec.js/src/account_manager/index.ts index 873d88e2333..6b2114cf405 100644 --- a/yarn-project/aztec.js/src/account_manager/index.ts +++ b/yarn-project/aztec.js/src/account_manager/index.ts @@ -37,10 +37,10 @@ export class AccountManager { ) {} static async create(pxe: PXE, secretKey: Fr, accountContract: AccountContract, salt?: Salt) { - const { publicKeys } = deriveKeys(secretKey); + const { publicKeys } = await deriveKeys(secretKey); salt = salt !== undefined ? new Fr(salt) : Fr.random(); - const instance = getContractInstanceFromDeployParams(accountContract.getContractArtifact(), { + const instance = await getContractInstanceFromDeployParams(accountContract.getContractArtifact(), { constructorArgs: await accountContract.getDeploymentArgs(), salt: salt, publicKeys, @@ -63,7 +63,7 @@ export class AccountManager { */ public async getAccount(): Promise { const nodeInfo = await this.pxe.getNodeInfo(); - const completeAddress = this.getCompleteAddress(); + const completeAddress = await this.getCompleteAddress(); return this.accountContract.getInterface(completeAddress, nodeInfo); } @@ -72,7 +72,7 @@ export class AccountManager { * Does not require the account to be deployed or registered. * @returns The address, partial address, and encryption public key. */ - public getCompleteAddress(): CompleteAddress { + public getCompleteAddress(): Promise { return CompleteAddress.fromSecretKeyAndInstance(this.secretKey, this.instance); } @@ -82,7 +82,7 @@ export class AccountManager { * @returns The address. */ public getAddress() { - return this.getCompleteAddress().address; + return this.instance.address; } /** @@ -117,7 +117,7 @@ export class AccountManager { instance: this.getInstance(), }); - await this.pxe.registerAccount(this.secretKey, this.getCompleteAddress().partialAddress); + await this.pxe.registerAccount(this.secretKey, (await this.getCompleteAddress()).partialAddress); return this.getWallet(); } @@ -135,7 +135,9 @@ export class AccountManager { ); } - await this.pxe.registerAccount(this.secretKey, this.getCompleteAddress().partialAddress); + const completeAddress = await this.getCompleteAddress(); + + await this.pxe.registerAccount(this.secretKey, completeAddress.partialAddress); const { l1ChainId: chainId, protocolVersion } = await this.pxe.getNodeInfo(); const deployWallet = new SignerlessWallet(this.pxe, new DefaultMultiCallEntrypoint(chainId, protocolVersion)); @@ -145,7 +147,7 @@ export class AccountManager { // and it can't be used unless the contract is initialized const args = (await this.accountContract.getDeploymentArgs()) ?? []; return new DeployAccountMethod( - this.accountContract.getAuthWitnessProvider(this.getCompleteAddress()), + this.accountContract.getAuthWitnessProvider(completeAddress), this.getPublicKeys(), deployWallet, this.accountContract.getContractArtifact(), diff --git a/yarn-project/aztec.js/src/contract/contract.test.ts b/yarn-project/aztec.js/src/contract/contract.test.ts index 7b52deaf799..24f85feb2ef 100644 --- a/yarn-project/aztec.js/src/contract/contract.test.ts +++ b/yarn-project/aztec.js/src/contract/contract.test.ts @@ -130,7 +130,7 @@ describe('Contract Class', () => { beforeEach(async () => { contractAddress = await AztecAddress.random(); - account = CompleteAddress.random(); + account = await CompleteAddress.random(); contractInstance = { address: contractAddress } as ContractInstanceWithAddress; const mockNodeInfo: NodeInfo = { diff --git a/yarn-project/aztec.js/src/contract/deploy_method.ts b/yarn-project/aztec.js/src/contract/deploy_method.ts index 91fa60e78c0..136be11473c 100644 --- a/yarn-project/aztec.js/src/contract/deploy_method.ts +++ b/yarn-project/aztec.js/src/contract/deploy_method.ts @@ -100,7 +100,7 @@ export class DeployMethod extends Bas // in case the initializer is public. This hints at the need of having "transient" contracts scoped to a // simulation, so we can run the simulation with a set of contracts, but only "commit" them to the wallet // once this tx has gone through. - await this.wallet.registerContract({ artifact: this.artifact, instance: this.getInstance(options) }); + await this.wallet.registerContract({ artifact: this.artifact, instance: await this.getInstance(options) }); const bootstrap = await this.getInitializeFunctionCalls(options); @@ -124,7 +124,7 @@ export class DeployMethod extends Bas * @param options - Deployment options. */ public async register(options: DeployOptions = {}): Promise { - const instance = this.getInstance(options); + const instance = await this.getInstance(options); await this.wallet.registerContract({ artifact: this.artifact, instance }); return this.postDeployCtor(instance.address, this.wallet); } @@ -140,7 +140,7 @@ export class DeployMethod extends Bas const calls: FunctionCall[] = []; // Set contract instance object so it's available for populating the DeploySendTx object - const instance = this.getInstance(options); + const instance = await this.getInstance(options); // Obtain contract class from artifact and check it matches the reported one by the instance. // TODO(@spalladino): We're unnecessarily calculating the contract class multiple times here. @@ -167,7 +167,8 @@ export class DeployMethod extends Bas // Deploy the contract via the instance deployer. if (!options.skipPublicDeployment) { - calls.push(deployInstance(this.wallet, instance).request()); + const deploymentInteraction = await deployInstance(this.wallet, instance); + calls.push(deploymentInteraction.request()); } return { calls }; @@ -178,10 +179,10 @@ export class DeployMethod extends Bas * @param options - Deployment options. * @returns - An array of function calls. */ - protected getInitializeFunctionCalls( + protected async getInitializeFunctionCalls( options: DeployOptions, ): Promise> { - const { address } = this.getInstance(options); + const { address } = await this.getInstance(options); const calls: FunctionCall[] = []; if (this.constructorArtifact && !options.skipInitialization) { const constructorCall = new ContractFunctionInteraction( @@ -192,7 +193,7 @@ export class DeployMethod extends Bas ); calls.push(constructorCall.request()); } - return Promise.resolve({ calls }); + return { calls }; } /** @@ -205,11 +206,8 @@ export class DeployMethod extends Bas */ public override send(options: DeployOptions = {}): DeploySentTx { const txHashPromise = super.send(options).getTxHash(); - const instance = this.getInstance(options); - this.log.debug( - `Sent deployment tx of ${this.artifact.name} contract with deployment address ${instance.address.toString()}`, - ); - return new DeploySentTx(this.wallet, txHashPromise, this.postDeployCtor, instance); + this.log.debug(`Sent deployment tx of ${this.artifact.name} contract`); + return new DeploySentTx(this.wallet, txHashPromise, this.postDeployCtor, () => this.getInstance(options)); } /** @@ -218,9 +216,9 @@ export class DeployMethod extends Bas * @param options - An object containing various deployment options. * @returns An instance object. */ - public getInstance(options: DeployOptions = {}): ContractInstanceWithAddress { + public async getInstance(options: DeployOptions = {}): Promise { if (!this.instance) { - this.instance = getContractInstanceFromDeployParams(this.artifact, { + this.instance = await getContractInstanceFromDeployParams(this.artifact, { constructorArgs: this.args, salt: options.contractAddressSalt, publicKeys: this.publicKeys, @@ -238,8 +236,9 @@ export class DeployMethod extends Bas */ public override async prove(options: DeployOptions): Promise> { const txProvingResult = await this.proveInternal(options); - const instance = this.getInstance(options); - return new DeployProvenTx(this.wallet, txProvingResult.toTx(), this.postDeployCtor, instance); + return new DeployProvenTx(this.wallet, txProvingResult.toTx(), this.postDeployCtor, () => + this.getInstance(options), + ); } /** diff --git a/yarn-project/aztec.js/src/contract/deploy_proven_tx.ts b/yarn-project/aztec.js/src/contract/deploy_proven_tx.ts index e364c03b20d..e07f7c1e0f3 100644 --- a/yarn-project/aztec.js/src/contract/deploy_proven_tx.ts +++ b/yarn-project/aztec.js/src/contract/deploy_proven_tx.ts @@ -14,7 +14,7 @@ export class DeployProvenTx extends Prove wallet: PXE | Wallet, tx: Tx, private postDeployCtor: (address: AztecAddress, wallet: Wallet) => Promise, - private instance: ContractInstanceWithAddress, + private instanceGetter: () => Promise, ) { super(wallet, tx); } @@ -27,6 +27,6 @@ export class DeployProvenTx extends Prove return this.wallet.sendTx(this.getPlainDataTx()); })(); - return new DeploySentTx(this.wallet, promise, this.postDeployCtor, this.instance); + return new DeploySentTx(this.wallet, promise, this.postDeployCtor, this.instanceGetter); } } diff --git a/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts b/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts index 6f294db1f03..fb87f00f2c4 100644 --- a/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/deploy_sent_tx.ts @@ -30,8 +30,8 @@ export class DeploySentTx extends SentTx wallet: PXE | Wallet, txHashPromise: Promise, private postDeployCtor: (address: AztecAddress, wallet: Wallet) => Promise, - /** The deployed contract instance */ - public instance: ContractInstanceWithAddress, + /** A getter for the deployed contract instance */ + public instanceGetter: () => Promise, ) { super(wallet, txHashPromise); } @@ -43,7 +43,8 @@ export class DeploySentTx extends SentTx */ public async deployed(opts?: DeployedWaitOpts): Promise { const receipt = await this.wait(opts); - this.log.info(`Contract ${this.instance.address.toString()} successfully deployed.`); + const instance = await this.instanceGetter(); + this.log.info(`Contract ${instance.address.toString()} successfully deployed.`); return receipt.contract; } @@ -58,12 +59,13 @@ export class DeploySentTx extends SentTx return { ...receipt, contract }; } - protected getContractObject(wallet?: Wallet): Promise { + protected async getContractObject(wallet?: Wallet): Promise { const isWallet = (pxe: PXE | Wallet): pxe is Wallet => !!(pxe as Wallet).createTxExecutionRequest; const contractWallet = wallet ?? (isWallet(this.pxe) && this.pxe); if (!contractWallet) { throw new Error(`A wallet is required for creating a contract instance`); } - return this.postDeployCtor(this.instance.address, contractWallet) as Promise; + const instance = await this.instanceGetter(); + return this.postDeployCtor(instance.address, contractWallet) as Promise; } } diff --git a/yarn-project/aztec.js/src/deployment/broadcast_function.ts b/yarn-project/aztec.js/src/deployment/broadcast_function.ts index 599d2d4b63c..a0367788a4a 100644 --- a/yarn-project/aztec.js/src/deployment/broadcast_function.ts +++ b/yarn-project/aztec.js/src/deployment/broadcast_function.ts @@ -52,7 +52,7 @@ export async function broadcastPrivateFunction( await wallet.addCapsule(bytecode); - const registerer = getRegistererContract(wallet); + const registerer = await getRegistererContract(wallet); return Promise.resolve( registerer.methods.broadcast_private_function( contractClass.id, @@ -103,7 +103,7 @@ export async function broadcastUnconstrainedFunction( await wallet.addCapsule(bytecode); - const registerer = getRegistererContract(wallet); + const registerer = await getRegistererContract(wallet); return registerer.methods.broadcast_unconstrained_function( contractClass.id, artifactMetadataHash, diff --git a/yarn-project/aztec.js/src/deployment/deploy_instance.ts b/yarn-project/aztec.js/src/deployment/deploy_instance.ts index 24b5fa65d82..bf0d501d28d 100644 --- a/yarn-project/aztec.js/src/deployment/deploy_instance.ts +++ b/yarn-project/aztec.js/src/deployment/deploy_instance.ts @@ -9,8 +9,11 @@ import { getDeployerContract } from './protocol_contracts.js'; * @param wallet - The wallet to use for the deployment. * @param instance - The instance to deploy. */ -export function deployInstance(wallet: Wallet, instance: ContractInstanceWithAddress): ContractFunctionInteraction { - const deployerContract = getDeployerContract(wallet); +export async function deployInstance( + wallet: Wallet, + instance: ContractInstanceWithAddress, +): Promise { + const deployerContract = await getDeployerContract(wallet); const { salt, contractClassId, publicKeys, deployer } = instance; const isUniversalDeploy = deployer.isZero(); if (!isUniversalDeploy && !wallet.getAddress().equals(deployer)) { diff --git a/yarn-project/aztec.js/src/deployment/protocol_contracts.ts b/yarn-project/aztec.js/src/deployment/protocol_contracts.ts index 9fc681f8a55..5cbf059c1cd 100644 --- a/yarn-project/aztec.js/src/deployment/protocol_contracts.ts +++ b/yarn-project/aztec.js/src/deployment/protocol_contracts.ts @@ -5,13 +5,13 @@ import { UnsafeContract } from '../contract/unsafe_contract.js'; import { type Wallet } from '../wallet/index.js'; /** Returns a Contract wrapper for the class registerer. */ -export function getRegistererContract(wallet: Wallet) { - const { artifact, instance } = getCanonicalClassRegisterer(); +export async function getRegistererContract(wallet: Wallet) { + const { artifact, instance } = await getCanonicalClassRegisterer(); return new UnsafeContract(instance, artifact, wallet); } /** Returns a Contract wrapper for the instance deployer. */ -export function getDeployerContract(wallet: Wallet) { - const { artifact, instance } = getCanonicalInstanceDeployer(); +export async function getDeployerContract(wallet: Wallet) { + const { artifact, instance } = await getCanonicalInstanceDeployer(); return new UnsafeContract(instance, artifact, wallet); } diff --git a/yarn-project/aztec.js/src/deployment/register_class.ts b/yarn-project/aztec.js/src/deployment/register_class.ts index eaaba5e8b95..2a708cf6589 100644 --- a/yarn-project/aztec.js/src/deployment/register_class.ts +++ b/yarn-project/aztec.js/src/deployment/register_class.ts @@ -20,7 +20,7 @@ export async function registerContractClass( const { artifactHash, privateFunctionsRoot, publicBytecodeCommitment, packedBytecode } = getContractClassFromArtifact(artifact); const encodedBytecode = bufferAsFields(packedBytecode, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS); - const registerer = getRegistererContract(wallet); + const registerer = await getRegistererContract(wallet); await wallet.addCapsule(encodedBytecode); return registerer.methods.register(artifactHash, privateFunctionsRoot, publicBytecodeCommitment, emitPublicBytecode); } diff --git a/yarn-project/aztec.js/src/fee/fee_juice_payment_method_with_claim.ts b/yarn-project/aztec.js/src/fee/fee_juice_payment_method_with_claim.ts index 565825c66ef..a63aafd7e0e 100644 --- a/yarn-project/aztec.js/src/fee/fee_juice_payment_method_with_claim.ts +++ b/yarn-project/aztec.js/src/fee/fee_juice_payment_method_with_claim.ts @@ -22,9 +22,10 @@ export class FeeJuicePaymentMethodWithClaim extends FeeJuicePaymentMethod { * Creates a function call to pay the fee in Fee Juice. * @returns A function call */ - override getFunctionCalls(): Promise { + override async getFunctionCalls(): Promise { + const canonicalFeeJuice = await getCanonicalFeeJuice(); const selector = FunctionSelector.fromNameAndParameters( - getCanonicalFeeJuice().artifact.functions.find(f => f.name === 'claim')!, + canonicalFeeJuice.artifact.functions.find(f => f.name === 'claim')!, ); return Promise.resolve([ diff --git a/yarn-project/aztec.js/src/utils/pub_key.ts b/yarn-project/aztec.js/src/utils/pub_key.ts index ab7388a5c16..f61df0b154b 100644 --- a/yarn-project/aztec.js/src/utils/pub_key.ts +++ b/yarn-project/aztec.js/src/utils/pub_key.ts @@ -6,7 +6,7 @@ import { Grumpkin } from '@aztec/circuits.js/barretenberg'; * @param privateKey - The private key. * @returns The generated public key. */ -export function generatePublicKey(privateKey: GrumpkinScalar): PublicKey { +export function generatePublicKey(privateKey: GrumpkinScalar): Promise { const grumpkin = new Grumpkin(); return grumpkin.mul(grumpkin.generator(), privateKey); } diff --git a/yarn-project/aztec/src/cli/util.ts b/yarn-project/aztec/src/cli/util.ts index cb5ab65fcda..118044ebd10 100644 --- a/yarn-project/aztec/src/cli/util.ts +++ b/yarn-project/aztec/src/cli/util.ts @@ -29,7 +29,7 @@ export const installSignalHandlers = (logFn: LogFn, cb?: Array<() => Promise a.equals(completeAddress))) { 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(` Secret Key: ${accountWithSecretKey.secretKey.toString()}\n`); accountLogStrings.push( ` Master nullifier public key: ${completeAddress.publicKeys.masterNullifierPublicKey.toString()}\n`, ); diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index 261dc870daa..69495fbefcf 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -111,7 +111,7 @@ export class BotFactory { throw new Error(`Unsupported token contract type: ${this.config.contract}`); } - const address = deploy.getInstance(deployOpts).address; + const address = (await deploy.getInstance(deployOpts)).address; if (await this.pxe.isContractPubliclyDeployed(address)) { this.log.info(`Token at ${address.toString()} already deployed`); return deploy.register(); diff --git a/yarn-project/circuit-types/src/interfaces/pxe.test.ts b/yarn-project/circuit-types/src/interfaces/pxe.test.ts index 7d9813b8d28..9745659762c 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.test.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.test.ts @@ -354,8 +354,8 @@ class MockPXE implements PXE { expect(partialAddress).toBeInstanceOf(Fr); return Promise.resolve(CompleteAddress.random()); } - getRegisteredAccounts(): Promise { - return Promise.resolve([CompleteAddress.random()]); + async getRegisteredAccounts(): Promise { + return [await CompleteAddress.random()]; } getRegisteredAccount(address: AztecAddress): Promise { expect(address).toBeInstanceOf(AztecAddress); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.test.ts index 303452d53df..013ef2d2bad 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.test.ts @@ -30,9 +30,9 @@ describe('EncryptedLogPayload', () => { const secretKey = Fr.random(); const partialAddress = Fr.random(); - ({ masterIncomingViewingSecretKey: ivskM } = deriveKeys(secretKey)); + ({ masterIncomingViewingSecretKey: ivskM } = await deriveKeys(secretKey)); - completeAddress = CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, partialAddress); + completeAddress = await CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, partialAddress); const ephSk = GrumpkinScalar.random(); @@ -40,7 +40,7 @@ describe('EncryptedLogPayload', () => { }); it('decrypt a log as incoming', async () => { - const addressSecret = computeAddressSecret(completeAddress.getPreaddress(), ivskM); + const addressSecret = await computeAddressSecret(completeAddress.getPreaddress(), ivskM); const recreated = await EncryptedLogPayload.decryptAsIncoming(payload.fields, addressSecret); @@ -89,7 +89,7 @@ describe('EncryptedLogPayload', () => { const ivskM = new GrumpkinScalar(0x0d6e27b21c89a7632f7766e35cc280d43f75bea3898d7328400a5fefc804d462n); - const addressSecret = computeAddressSecret(recipientCompleteAddress.getPreaddress(), ivskM); + const addressSecret = await computeAddressSecret(recipientCompleteAddress.getPreaddress(), ivskM); const recreated = await EncryptedLogPayload.decryptAsIncoming(payload.fields, addressSecret); expect(recreated?.toBuffer()).toEqual(log.toBuffer()); }); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.ts index e210d8b5639..61ce6e692f4 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_payload.ts @@ -99,7 +99,7 @@ export class EncryptedLogPayload { ): Promise { const addressPoint = await recipient.toAddressPoint(); - const ephPk = derivePublicKeyFromSecretKey(ephSk); + const ephPk = await derivePublicKeyFromSecretKey(ephSk); const incomingHeaderCiphertext = await encrypt(this.contractAddress.toBuffer(), ephSk, addressPoint); if (incomingHeaderCiphertext.length !== HEADER_SIZE) { diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encryption_util.ts b/yarn-project/circuit-types/src/logs/l1_payload/encryption_util.ts index 3881ba76853..787277ff7ce 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encryption_util.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encryption_util.ts @@ -12,13 +12,13 @@ import { deriveAESSecret } from './shared_secret_derivation.js'; * @param deriveSecret - Function to derive the AES secret from the ephemeral secret key and public key * @returns The ciphertext */ -export function encrypt( +export async function encrypt( plaintext: Buffer, secret: GrumpkinScalar, publicKey: PublicKey, - deriveSecret: (secret: GrumpkinScalar, publicKey: PublicKey) => Buffer = deriveAESSecret, + deriveSecret: (secret: GrumpkinScalar, publicKey: PublicKey) => Promise = deriveAESSecret, ): Promise { - const aesSecret = deriveSecret(secret, publicKey); + const aesSecret = await deriveSecret(secret, publicKey); const key = aesSecret.subarray(0, 16); const iv = aesSecret.subarray(16, 32); @@ -34,13 +34,13 @@ export function encrypt( * @param deriveSecret - Function to derive the AES secret from the ephemeral secret key and public key * @returns */ -export function decrypt( +export async function decrypt( ciphertext: Buffer, secret: GrumpkinScalar, publicKey: PublicKey, - deriveSecret: (secret: GrumpkinScalar, publicKey: PublicKey) => Buffer = deriveAESSecret, + deriveSecret: (secret: GrumpkinScalar, publicKey: PublicKey) => Promise = deriveAESSecret, ): Promise { - const aesSecret = deriveSecret(secret, publicKey); + const aesSecret = await deriveSecret(secret, publicKey); const key = aesSecret.subarray(0, 16); const iv = aesSecret.subarray(16, 32); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/shared_secret_derivation.ts b/yarn-project/circuit-types/src/logs/l1_payload/shared_secret_derivation.ts index 00903bf43ba..80a616ad7b6 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/shared_secret_derivation.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/shared_secret_derivation.ts @@ -14,14 +14,14 @@ import { numToUInt8 } from '@aztec/foundation/serialize'; * @returns A derived AES secret key. * @throws If the public key is zero. */ -export function deriveAESSecret(secretKey: GrumpkinScalar, publicKey: PublicKey): Buffer { +export async function deriveAESSecret(secretKey: GrumpkinScalar, publicKey: PublicKey): Promise { if (publicKey.isZero()) { throw new Error( `Attempting to derive AES secret with a zero public key. You have probably passed a zero public key in your Noir code somewhere thinking that the note won't broadcasted... but it was.`, ); } const curve = new Grumpkin(); - const sharedSecret = curve.mul(publicKey, secretKey); + const sharedSecret = await curve.mul(publicKey, secretKey); const secretBuffer = Buffer.concat([sharedSecret.toCompressedBuffer(), numToUInt8(GeneratorIndex.SYMMETRIC_KEY)]); const hash = sha256(secretBuffer); return hash; diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index b67df5e0c93..03cdda0fb79 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -214,7 +214,7 @@ export const randomContractInstanceWithAddress = async ( address?: AztecAddress, ): Promise => { const instance = await SerializableContractInstance.random(opts); - return instance.withAddress(address ?? computeContractAddressFromInstance(instance)); + return instance.withAddress(address ?? (await computeContractAddressFromInstance(instance))); }; export const randomDeployedContract = async () => { diff --git a/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.test.ts b/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.test.ts index db0b31c6fcf..efd59168da2 100644 --- a/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.test.ts +++ b/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.test.ts @@ -12,29 +12,29 @@ describe('grumpkin', () => { grumpkin = new Grumpkin(); }); - it('should correctly perform scalar muls', () => { + it('should correctly perform scalar muls', async () => { const exponent = GrumpkinScalar.random(); - const numPoints = 2048; + const numPoints = 3; const inputPoints: Point[] = []; for (let i = 0; i < numPoints; ++i) { - inputPoints.push(grumpkin.mul(Grumpkin.generator, GrumpkinScalar.random())); + inputPoints.push(await grumpkin.mul(Grumpkin.generator, GrumpkinScalar.random())); } const start = new Date().getTime(); - const outputPoints = grumpkin.batchMul(inputPoints, exponent); + const outputPoints = await grumpkin.batchMul(inputPoints, exponent); log.debug(`batch mul in: ${new Date().getTime() - start}ms`); const start2 = new Date().getTime(); for (let i = 0; i < numPoints; ++i) { - grumpkin.mul(inputPoints[i], exponent); + await grumpkin.mul(inputPoints[i], exponent); } log.debug(`regular mul in: ${new Date().getTime() - start2}ms`); for (let i = 0; i < numPoints; ++i) { const lhs = outputPoints[i]; - const rhs = grumpkin.mul(inputPoints[i], exponent); + const rhs = await grumpkin.mul(inputPoints[i], exponent); expect(lhs).toEqual(rhs); } }); diff --git a/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.ts b/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.ts index c146417f140..ecda999647b 100644 --- a/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.ts +++ b/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.ts @@ -1,12 +1,10 @@ -import { BarretenbergSync } from '@aztec/bb.js'; +import { BarretenbergLazy } from '@aztec/bb.js'; import { Fr, type GrumpkinScalar, Point } from '@aztec/foundation/fields'; /** * Grumpkin elliptic curve operations. */ export class Grumpkin { - private wasm = BarretenbergSync.getSingleton().getWasm(); - // prettier-ignore static generator = Point.fromBuffer(Buffer.from([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -29,11 +27,12 @@ export class Grumpkin { * @param scalar - Scalar to multiply by. * @returns Result of the multiplication. */ - public mul(point: Point, scalar: GrumpkinScalar): Point { - this.wasm.writeMemory(0, point.toBuffer()); - this.wasm.writeMemory(64, scalar.toBuffer()); - this.wasm.call('ecc_grumpkin__mul', 0, 64, 96); - return Point.fromBuffer(Buffer.from(this.wasm.getMemorySlice(96, 160))); + public async mul(point: Point, scalar: GrumpkinScalar): Promise { + const api = await BarretenbergLazy.getSingleton(); + const [result] = await api + .getWasm() + .callWasmExport('ecc_grumpkin__mul', [point.toBuffer(), scalar.toBuffer()], [64]); + return Point.fromBuffer(Buffer.from(result)); } /** @@ -42,11 +41,10 @@ export class Grumpkin { * @param b - Point b to add to a * @returns Result of the addition. */ - public add(a: Point, b: Point): Point { - this.wasm.writeMemory(0, a.toBuffer()); - this.wasm.writeMemory(64, b.toBuffer()); - this.wasm.call('ecc_grumpkin__add', 0, 64, 128); - return Point.fromBuffer(Buffer.from(this.wasm.getMemorySlice(128, 192))); + public async add(a: Point, b: Point): Promise { + const api = await BarretenbergLazy.getSingleton(); + const [result] = await api.getWasm().callWasmExport('ecc_grumpkin__add', [a.toBuffer(), b.toBuffer()], [64]); + return Point.fromBuffer(Buffer.from(result)); } /** @@ -55,24 +53,23 @@ export class Grumpkin { * @param scalar - Scalar to multiply by. * @returns Points multiplied by the scalar. */ - public batchMul(points: Point[], scalar: GrumpkinScalar) { + public async batchMul(points: Point[], scalar: GrumpkinScalar) { const concatenatedPoints: Buffer = Buffer.concat(points.map(point => point.toBuffer())); - const pointsByteLength = points.length * Point.SIZE_IN_BYTES; - const mem = this.wasm.call('bbmalloc', pointsByteLength * 2); - - this.wasm.writeMemory(mem, concatenatedPoints); - this.wasm.writeMemory(0, scalar.toBuffer()); - this.wasm.call('ecc_grumpkin__batch_mul', mem, 0, points.length, mem + pointsByteLength); + const pointsByteLength = points.length * Point.SIZE_IN_BYTES; - const result: Buffer = Buffer.from( - this.wasm.getMemorySlice(mem + pointsByteLength, mem + pointsByteLength + pointsByteLength), - ); - this.wasm.call('bbfree', mem); + const api = await BarretenbergLazy.getSingleton(); + const [result] = await api + .getWasm() + .callWasmExport( + 'ecc_grumpkin__batch_mul', + [concatenatedPoints, scalar.toBuffer(), points.length], + [pointsByteLength], + ); const parsedResult: Point[] = []; for (let i = 0; i < pointsByteLength; i += 64) { - parsedResult.push(Point.fromBuffer(result.subarray(i, i + 64))); + parsedResult.push(Point.fromBuffer(Buffer.from(result.subarray(i, i + 64)))); } return parsedResult; } @@ -81,9 +78,12 @@ export class Grumpkin { * Gets a random field element. * @returns Random field element. */ - public getRandomFr(): Fr { - this.wasm.call('ecc_grumpkin__get_random_scalar_mod_circuit_modulus', 0); - return Fr.fromBuffer(Buffer.from(this.wasm.getMemorySlice(0, 32))); + public async getRandomFr(): Promise { + const api = await BarretenbergLazy.getSingleton(); + const [result] = await api + .getWasm() + .callWasmExport('ecc_grumpkin__get_random_scalar_mod_circuit_modulus', [], [32]); + return Fr.fromBuffer(Buffer.from(result)); } /** @@ -91,9 +91,11 @@ export class Grumpkin { * @param uint512Buf - The buffer to convert. * @returns Buffer representation of the field element. */ - public reduce512BufferToFr(uint512Buf: Buffer): Fr { - this.wasm.writeMemory(0, uint512Buf); - this.wasm.call('ecc_grumpkin__reduce512_buffer_mod_circuit_modulus', 0, 64); - return Fr.fromBuffer(Buffer.from(this.wasm.getMemorySlice(64, 96))); + public async reduce512BufferToFr(uint512Buf: Buffer): Promise { + const api = await BarretenbergLazy.getSingleton(); + const [result] = await api + .getWasm() + .callWasmExport('ecc_grumpkin__reduce512_buffer_mod_circuit_modulus', [uint512Buf], [32]); + return Fr.fromBuffer(Buffer.from(result)); } } 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 c8918ea0d3e..d33427746d9 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.test.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.test.ts @@ -52,22 +52,24 @@ describe('ContractAddress', () => { expect(result).toEqual(Fr.ZERO); }); - it('computeContractAddressFromInstance', () => { + it('computeContractAddressFromInstance', async () => { const secretKey = new Fr(2n); const salt = new Fr(3n); const contractClassId = new Fr(4n); const initializationHash = new Fr(5n); const deployer = AztecAddress.fromField(new Fr(7)); - const publicKeys = deriveKeys(secretKey).publicKeys; + const publicKeys = (await deriveKeys(secretKey)).publicKeys; - const address = computeContractAddressFromInstance({ - publicKeys, - salt, - contractClassId, - initializationHash, - deployer, - version: 1, - }).toString(); + const address = ( + await computeContractAddressFromInstance({ + publicKeys, + salt, + contractClassId, + initializationHash, + deployer, + version: 1, + }) + ).toString(); expect(address).toMatchSnapshot(); }); diff --git a/yarn-project/circuits.js/src/contract/contract_address.ts b/yarn-project/circuits.js/src/contract/contract_address.ts index 25238a1d381..bf931d52ba7 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.ts @@ -23,7 +23,7 @@ export function computeContractAddressFromInstance( instance: | ContractInstance | ({ contractClassId: Fr; saltedInitializationHash: Fr } & Pick), -): AztecAddress { +): Promise { const partialAddress = computePartialAddress(instance); return computeAddress(instance.publicKeys, partialAddress); } diff --git a/yarn-project/circuits.js/src/contract/contract_instance.ts b/yarn-project/circuits.js/src/contract/contract_instance.ts index b84ff10253a..96cf400315a 100644 --- a/yarn-project/circuits.js/src/contract/contract_instance.ts +++ b/yarn-project/circuits.js/src/contract/contract_instance.ts @@ -98,7 +98,7 @@ export class SerializableContractInstance { * @param opts - Options for the deployment. * @returns - The contract instance */ -export function getContractInstanceFromDeployParams( +export async function getContractInstanceFromDeployParams( artifact: ContractArtifact, opts: { constructorArtifact?: FunctionArtifact | string; @@ -108,7 +108,7 @@ export function getContractInstanceFromDeployParams( publicKeys?: PublicKeys; deployer?: AztecAddress; }, -): ContractInstanceWithAddress { +): Promise { const args = opts.constructorArgs ?? []; const salt = opts.salt ?? Fr.random(); const constructorArtifact = getConstructorArtifact(artifact, opts.constructorArtifact); @@ -133,7 +133,7 @@ export function getContractInstanceFromDeployParams( version: 1, }; - return { ...instance, address: computeContractAddressFromInstance(instance) }; + return { ...instance, address: await computeContractAddressFromInstance(instance) }; } function getConstructorArtifact( diff --git a/yarn-project/circuits.js/src/keys/derivation.test.ts b/yarn-project/circuits.js/src/keys/derivation.test.ts index e2fec80baf5..dab2a79891b 100644 --- a/yarn-project/circuits.js/src/keys/derivation.test.ts +++ b/yarn-project/circuits.js/src/keys/derivation.test.ts @@ -43,7 +43,7 @@ describe('🔑', () => { ); }); - it('Address matches Noir', () => { + it('Address matches Noir', async () => { const npkM = Point.fromString( '0x22f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7', ); @@ -61,7 +61,7 @@ describe('🔑', () => { const partialAddress = Fr.fromHexString('0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de'); - const address = computeAddress(publicKeys, partialAddress).toString(); + const address = (await computeAddress(publicKeys, partialAddress)).toString(); expect(address).toMatchSnapshot(); // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data diff --git a/yarn-project/circuits.js/src/keys/derivation.ts b/yarn-project/circuits.js/src/keys/derivation.ts index 39568d1fce6..681a028c5ee 100644 --- a/yarn-project/circuits.js/src/keys/derivation.ts +++ b/yarn-project/circuits.js/src/keys/derivation.ts @@ -46,21 +46,21 @@ export function computePreaddress(publicKeysHash: Fr, partialAddress: Fr) { return poseidon2HashWithSeparator([publicKeysHash, partialAddress], GeneratorIndex.CONTRACT_ADDRESS_V1); } -export function computeAddress(publicKeys: PublicKeys, partialAddress: Fr): AztecAddress { +export async function computeAddress(publicKeys: PublicKeys, partialAddress: Fr): Promise { // Given public keys and a partial address, we can compute our address in the following steps. // 1. preaddress = poseidon2([publicKeysHash, partialAddress], GeneratorIndex.CONTRACT_ADDRESS_V1); // 2. addressPoint = (preaddress * G) + ivpk_m // 3. address = addressPoint.x const preaddress = computePreaddress(publicKeys.hash(), partialAddress); - const address = new Grumpkin().add( - derivePublicKeyFromSecretKey(new Fq(preaddress.toBigInt())), + const address = await new Grumpkin().add( + await derivePublicKeyFromSecretKey(new Fq(preaddress.toBigInt())), publicKeys.masterIncomingViewingPublicKey, ); return new AztecAddress(address.x); } -export function computeAddressSecret(preaddress: Fr, ivsk: Fq) { +export async function computeAddressSecret(preaddress: Fr, ivsk: Fq) { // TLDR; P1 = (h + ivsk) * G // if P1.y is pos // S = (h + ivsk) @@ -71,7 +71,7 @@ export function computeAddressSecret(preaddress: Fr, ivsk: Fq) { // and the other encodes to a point with a negative y-coordinate. We take the addressSecret candidate that is a simple addition of the two Scalars. const addressSecretCandidate = ivsk.add(new Fq(preaddress.toBigInt())); // We then multiply this secretCandidate by the generator G to create an addressPoint candidate. - const addressPointCandidate = derivePublicKeyFromSecretKey(addressSecretCandidate); + const addressPointCandidate = await derivePublicKeyFromSecretKey(addressSecretCandidate); // Because all encryption to addresses is done using a point with the positive y-coordinate, if our addressSecret candidate derives a point with a // negative y-coordinate, we use the other candidate by negating the secret. This transformation of the secret simply flips the y-coordinate of the derived point while keeping the x-coordinate the same. @@ -92,7 +92,7 @@ export function derivePublicKeyFromSecretKey(secretKey: Fq) { * @param secretKey - The secret key to derive keys from. * @returns The derived keys. */ -export function deriveKeys(secretKey: Fr) { +export async function deriveKeys(secretKey: Fr) { // First we derive master secret keys - we use sha512 here because this derivation will never take place // in a circuit const masterNullifierSecretKey = deriveMasterNullifierSecretKey(secretKey); @@ -101,10 +101,10 @@ export function deriveKeys(secretKey: Fr) { const masterTaggingSecretKey = sha512ToGrumpkinScalar([secretKey, GeneratorIndex.TSK_M]); // Then we derive master public keys - const masterNullifierPublicKey = derivePublicKeyFromSecretKey(masterNullifierSecretKey); - const masterIncomingViewingPublicKey = derivePublicKeyFromSecretKey(masterIncomingViewingSecretKey); - const masterOutgoingViewingPublicKey = derivePublicKeyFromSecretKey(masterOutgoingViewingSecretKey); - const masterTaggingPublicKey = derivePublicKeyFromSecretKey(masterTaggingSecretKey); + const masterNullifierPublicKey = await derivePublicKeyFromSecretKey(masterNullifierSecretKey); + const masterIncomingViewingPublicKey = await derivePublicKeyFromSecretKey(masterIncomingViewingSecretKey); + const masterOutgoingViewingPublicKey = await derivePublicKeyFromSecretKey(masterOutgoingViewingSecretKey); + const masterTaggingPublicKey = await derivePublicKeyFromSecretKey(masterTaggingSecretKey); // We hash the public keys to get the public keys hash const publicKeys = new PublicKeys( @@ -138,5 +138,5 @@ export async function computeTaggingSecretPoint( // Beware! h_a + ivsk_a (also known as the address secret) can lead to an address point with a negative y-coordinate, since there's two possible candidates // computeAddressSecret takes care of selecting the one that leads to a positive y-coordinate, which is the only valid address point - return curve.mul(externalAddressPoint, computeAddressSecret(knownPreaddress, ivsk)); + return curve.mul(externalAddressPoint, await computeAddressSecret(knownPreaddress, ivsk)); } 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 4fda53c496f..481e52f4ae5 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.test.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.test.ts @@ -7,29 +7,29 @@ import { CompleteAddress } from './complete_address.js'; describe('CompleteAddress', () => { it('refuses to add an account with incorrect address for given partial address and pubkey', async () => { await expect( - async () => new CompleteAddress(await AztecAddress.random(), await PublicKeys.random(), Fr.random()), + CompleteAddress.create(await AztecAddress.random(), await PublicKeys.random(), Fr.random()), ).rejects.toThrow(/cannot be derived/); }); - it('equals returns true when 2 instances are equal', () => { - const address1 = CompleteAddress.random(); - const address2 = new CompleteAddress(address1.address, address1.publicKeys, address1.partialAddress); + it('equals returns true when 2 instances are equal', async () => { + const address1 = await CompleteAddress.random(); + const address2 = await CompleteAddress.create(address1.address, address1.publicKeys, address1.partialAddress); expect(address1.equals(address2)).toBe(true); }); - it('equals returns true when 2 instances are not equal', () => { - const address1 = CompleteAddress.random(); - const address2 = CompleteAddress.random(); + it('equals returns true when 2 instances are not equal', async () => { + const address1 = await CompleteAddress.random(); + const address2 = await CompleteAddress.random(); expect(address1.equals(address2)).toBe(false); }); - it('serializes / deserializes correctly', () => { - const expectedAddress = CompleteAddress.random(); + it('serializes / deserializes correctly', async () => { + const expectedAddress = await CompleteAddress.random(); const address = CompleteAddress.fromBuffer(expectedAddress.toBuffer()); expect(address.equals(expectedAddress)).toBe(true); }); - it('instantiates from string and individual components', () => { + it('instantiates from string and individual components', async () => { const completeAddressFromString = CompleteAddress.fromString( '0x24e4646f58b9fbe7d38e317db8d5636c423fbbdfbe119fc190fe9c64747e0c6222f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be9509115c96e962322ffed6522f57194627136b8d03ac7469109707f5e44190c4840c49773308a13d740a7f0d4f0e6163b02c5a408b6f965856b6a491002d073d5b00d3d81beb009873eb7116327cf47c612d5758ef083d4fda78e9b63980b2a7622f567d22d2b02fe1f4ad42db9d58a36afd1983e7e2909d1cab61cafedad6193a0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de', ); @@ -52,7 +52,7 @@ describe('CompleteAddress', () => { const partialAddress = Fr.fromHexString('0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de'); - const completeAddressFromComponents = new CompleteAddress( + const completeAddressFromComponents = await CompleteAddress.create( address, new PublicKeys(npkM, ivpkM, ovpkM, tpkM), partialAddress, @@ -61,8 +61,8 @@ describe('CompleteAddress', () => { expect(completeAddressFromComponents.equals(completeAddressFromString)).toBe(true); }); - it('has correct size in bytes', () => { - const completeAddress = CompleteAddress.random(); + it('has correct size in bytes', async () => { + const completeAddress = await CompleteAddress.random(); expect(completeAddress.toBuffer().length).toBe(CompleteAddress.SIZE_IN_BYTES); }); }); diff --git a/yarn-project/circuits.js/src/structs/complete_address.ts b/yarn-project/circuits.js/src/structs/complete_address.ts index a58014ea60c..2c1e1ba23e8 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.ts @@ -18,15 +18,23 @@ import { PublicKeys } from '../types/public_keys.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 { - public constructor( + private constructor( /** Contract address (typically of an account contract) */ public address: AztecAddress, /** User public keys */ public publicKeys: PublicKeys, /** Partial key corresponding to the public key to the address. */ public partialAddress: PartialAddress, - ) { - this.validate(); + ) {} + + static async create( + address: AztecAddress, + publicKeys: PublicKeys, + partialAddress: PartialAddress, + ): Promise { + const completeAddress = new CompleteAddress(address, publicKeys, partialAddress); + await completeAddress.validate(); + return completeAddress; } /** Size in bytes of an instance */ @@ -40,13 +48,13 @@ export class CompleteAddress { return this.toString(); } - static random(): CompleteAddress { - return this.fromSecretKeyAndPartialAddress(Fr.random(), Fr.random()); + static async random(): Promise { + return await this.fromSecretKeyAndPartialAddress(Fr.random(), Fr.random()); } - static fromSecretKeyAndPartialAddress(secretKey: Fr, partialAddress: Fr): CompleteAddress { - const { publicKeys } = deriveKeys(secretKey); - const address = computeAddress(publicKeys, partialAddress); + static async fromSecretKeyAndPartialAddress(secretKey: Fr, partialAddress: Fr): Promise { + const { publicKeys } = await deriveKeys(secretKey); + const address = await computeAddress(publicKeys, partialAddress); return new CompleteAddress(address, publicKeys, partialAddress); } @@ -58,14 +66,14 @@ export class CompleteAddress { static fromSecretKeyAndInstance( secretKey: Fr, instance: Parameters[0], - ): CompleteAddress { + ): Promise { const partialAddress = computePartialAddress(instance); return CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, partialAddress); } /** Throws if the address is not correctly derived from the public key and partial address.*/ - public validate() { - const expectedAddress = computeAddress(this.publicKeys, this.partialAddress); + public async validate() { + const expectedAddress = await computeAddress(this.publicKeys, this.partialAddress); if (!expectedAddress.equals(this.address)) { throw new Error( diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 1919089f85d..e4297628120 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -1338,7 +1338,7 @@ export async function makeContractInstanceFromClassId(classId: Fr, seed = 0): Pr [classId, saltedInitializationHash], GeneratorIndex.PARTIAL_ADDRESS, ); - const address = computeAddress(publicKeys, partialAddress); + const address = await computeAddress(publicKeys, partialAddress); return new SerializableContractInstance({ version: 1, salt, diff --git a/yarn-project/cli-wallet/src/cmds/create_account.ts b/yarn-project/cli-wallet/src/cmds/create_account.ts index ace2e3f4f31..42fef035d78 100644 --- a/yarn-project/cli-wallet/src/cmds/create_account.ts +++ b/yarn-project/cli-wallet/src/cmds/create_account.ts @@ -33,7 +33,7 @@ export async function createAccount( publicKey, ); const salt = account.getInstance().salt; - const { address, publicKeys, partialAddress } = account.getCompleteAddress(); + const { address, publicKeys, partialAddress } = await account.getCompleteAddress(); const out: Record = {}; if (json) { diff --git a/yarn-project/cli-wallet/src/cmds/deploy.ts b/yarn-project/cli-wallet/src/cmds/deploy.ts index df49a1a678a..7b53e5831a3 100644 --- a/yarn-project/cli-wallet/src/cmds/deploy.ts +++ b/yarn-project/cli-wallet/src/cmds/deploy.ts @@ -90,7 +90,7 @@ export async function deploy( } } else { const { address, partialAddress } = deploy; - const instance = deploy.getInstance(); + const instance = await deploy.getInstance(); if (json) { logJson({ address: address?.toString() ?? 'N/A', diff --git a/yarn-project/cli-wallet/src/cmds/deploy_account.ts b/yarn-project/cli-wallet/src/cmds/deploy_account.ts index d6b76f482da..3ecbd48bd3e 100644 --- a/yarn-project/cli-wallet/src/cmds/deploy_account.ts +++ b/yarn-project/cli-wallet/src/cmds/deploy_account.ts @@ -13,7 +13,7 @@ export async function deployAccount( log: LogFn, ) { const out: Record = {}; - const { address, partialAddress, publicKeys } = account.getCompleteAddress(); + const { address, partialAddress, publicKeys } = await account.getCompleteAddress(); const { initializationHash, deployer, salt } = account.getInstance(); const wallet = await account.getWallet(); const secretKey = wallet.getSecretKey(); diff --git a/yarn-project/cli/src/cmds/pxe/add_contract.ts b/yarn-project/cli/src/cmds/pxe/add_contract.ts index 0638c50239f..62ee9176a40 100644 --- a/yarn-project/cli/src/cmds/pxe/add_contract.ts +++ b/yarn-project/cli/src/cmds/pxe/add_contract.ts @@ -27,7 +27,7 @@ export async function addContract( address, deployer: deployer ?? AztecAddress.ZERO, }; - const computed = computeContractAddressFromInstance(instance); + const computed = await computeContractAddressFromInstance(instance); if (!computed.equals(address)) { throw new Error(`Contract address ${address.toString()} does not match computed address ${computed.toString()}`); } diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index 342fb690ac3..782ed9971fe 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -179,7 +179,7 @@ describe('e2e_2_pxes', () => { // setup an account that is shared across PXEs const sharedSecretKey = Fr.random(); const sharedAccountOnA = await getUnsafeSchnorrAccount(pxeA, sharedSecretKey, Fr.random()); - const sharedAccountAddress = sharedAccountOnA.getCompleteAddress(); + const sharedAccountAddress = await sharedAccountOnA.getCompleteAddress(); const sharedWalletOnA = await sharedAccountOnA.waitSetup(); await sharedWalletOnA.registerSender(walletA.getAddress()); diff --git a/yarn-project/end-to-end/src/e2e_block_building.test.ts b/yarn-project/end-to-end/src/e2e_block_building.test.ts index 2236261d002..484b056b079 100644 --- a/yarn-project/end-to-end/src/e2e_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_block_building.test.ts @@ -253,9 +253,10 @@ describe('e2e_block_building', () => { // We can't use `TokenContract.at` to call a function because it checks the contract is deployed // but we are in the same block as the deployment transaction + const deployerInstance = await deployer.getInstance(); const callInteraction = new ContractFunctionInteraction( owner, - deployer.getInstance().address, + deployerInstance.address, TokenContract.artifact.functions.find(x => x.name === 'set_minter')!, [minter.getCompleteAddress(), true], ); @@ -407,7 +408,7 @@ describe('e2e_block_building', () => { it('calls a method with nested note encrypted logs', async () => { // account setup const privateKey = new Fr(7n); - const keys = deriveKeys(privateKey); + const keys = await deriveKeys(privateKey); const account = await getSchnorrAccount(pxe, privateKey, keys.masterIncomingViewingSecretKey); await account.deploy().wait(); const thisWallet = await account.getWallet(); @@ -422,7 +423,7 @@ describe('e2e_block_building', () => { expect(rct.status).toEqual('success'); const noteValues = await Promise.all( tx.data.getNonEmptyPrivateLogs().map(async log => { - const notePayload = await L1NotePayload.decryptAsIncoming(log, thisWallet.getEncryptionSecret()); + const notePayload = await L1NotePayload.decryptAsIncoming(log, await thisWallet.getEncryptionSecret()); // In this test we care only about the privately delivered values return notePayload?.privateNoteValues[0]; }), @@ -435,7 +436,7 @@ describe('e2e_block_building', () => { it('calls a method with nested encrypted logs', async () => { // account setup const privateKey = new Fr(7n); - const keys = deriveKeys(privateKey); + const keys = await deriveKeys(privateKey); const account = await getSchnorrAccount(pxe, privateKey, keys.masterIncomingViewingSecretKey); await account.deploy().wait(); const thisWallet = await account.getWallet(); @@ -454,10 +455,10 @@ describe('e2e_block_building', () => { expect(privateLogs.length).toBe(3); // The first two logs are encrypted. - const event0 = (await L1EventPayload.decryptAsIncoming(privateLogs[0], thisWallet.getEncryptionSecret()))!; + const event0 = (await L1EventPayload.decryptAsIncoming(privateLogs[0], await thisWallet.getEncryptionSecret()))!; expect(event0.event.items).toEqual(values); - const event1 = (await L1EventPayload.decryptAsIncoming(privateLogs[1], thisWallet.getEncryptionSecret()))!; + const event1 = (await L1EventPayload.decryptAsIncoming(privateLogs[1], await thisWallet.getEncryptionSecret()))!; expect(event1.event.items).toEqual(nestedValues); // The last log is not encrypted. 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 d8e1e4aa8ce..72ee46c0c0f 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 @@ -107,18 +107,23 @@ describe('e2e_card_game', () => { const preRegisteredAccounts = await pxe.getRegisteredAccounts(); - const secretKeysToRegister = INITIAL_TEST_SECRET_KEYS.filter(key => { - const publicKey = deriveKeys(key).publicKeys.masterIncomingViewingPublicKey; + const keyPairs = await Promise.all( + INITIAL_TEST_SECRET_KEYS.map(async sk => ({ + sk, + pk: (await deriveKeys(sk)).publicKeys.masterIncomingViewingPublicKey, + })), + ); + const secretKeysToRegister = keyPairs.filter(keyPair => { return ( preRegisteredAccounts.find(preRegisteredAccount => { - return preRegisteredAccount.publicKeys.masterIncomingViewingPublicKey.equals(publicKey); + return preRegisteredAccount.publicKeys.masterIncomingViewingPublicKey.equals(keyPair.pk); }) == undefined ); }); for (let i = 0; i < secretKeysToRegister.length; i++) { logger.info(`Deploying account contract ${i}/${secretKeysToRegister.length}...`); - const encryptionPrivateKey = secretKeysToRegister[i]; + const encryptionPrivateKey = secretKeysToRegister[i].sk; const account = await getSchnorrAccount(pxe, encryptionPrivateKey, GrumpkinScalar.random()); const wallet = await account.waitSetup({ interval: 0.1 }); wallets.push(wallet); 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 b6098f5c11f..e3027690bb1 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 @@ -92,7 +92,7 @@ describe('e2e_crowdfunding_and_claim', () => { logger.info(`Reward Token deployed to ${rewardToken.address}`); crowdfundingSecretKey = Fr.random(); - crowdfundingPublicKeys = deriveKeys(crowdfundingSecretKey).publicKeys; + crowdfundingPublicKeys = (await deriveKeys(crowdfundingSecretKey)).publicKeys; const crowdfundingDeployment = CrowdfundingContract.deployWithPublicKeys( crowdfundingPublicKeys, @@ -101,7 +101,7 @@ describe('e2e_crowdfunding_and_claim', () => { operatorWallet.getAddress(), deadline, ); - const crowdfundingInstance = crowdfundingDeployment.getInstance(); + const crowdfundingInstance = await crowdfundingDeployment.getInstance(); await pxe.registerAccount(crowdfundingSecretKey, computePartialAddress(crowdfundingInstance)); crowdfundingContract = await crowdfundingDeployment.send().deployed(); logger.info(`Crowdfunding contract deployed at ${crowdfundingContract.address}`); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts index 828a8ad4d55..e1518bf45b8 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts @@ -145,7 +145,7 @@ describe('e2e_deploy_contract contract class registration', () => { const initArgs = [wallet.getAddress(), wallet.getAddress(), 42] as StatefulContractCtorArgs; const salt = Fr.random(); const publicKeys = await PublicKeys.random(); - const instance = getContractInstanceFromDeployParams(artifact, { + const instance = await getContractInstanceFromDeployParams(artifact, { constructorArgs: initArgs, salt, publicKeys, @@ -296,7 +296,8 @@ describe('e2e_deploy_contract contract class registration', () => { testDeployingAnInstance('from a wallet', async instance => { // Calls the deployer contract directly from a wallet - await deployInstance(wallet, instance).send().wait(); + const deployMethod = await deployInstance(wallet, instance); + await deployMethod.send().wait(); }); testDeployingAnInstance('from a contract', async instance => { @@ -326,11 +327,11 @@ describe('e2e_deploy_contract contract class registration', () => { }); it('refuses to deploy an instance from a different deployer', async () => { - const instance = getContractInstanceFromDeployParams(artifact, { + const instance = await getContractInstanceFromDeployParams(artifact, { constructorArgs: [await AztecAddress.random(), await AztecAddress.random(), 42], deployer: await AztecAddress.random(), }); - expect(() => deployInstance(wallet, instance)).toThrow(/does not match/i); + await expect(deployInstance(wallet, instance)).rejects.toThrow(/does not match/i); }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts index 638244ca40a..ba73c129e80 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts @@ -127,7 +127,8 @@ describe('e2e_deploy_contract deploy method', () => { logger.debug(`Creating request/calls to register and deploy contract`); const deploy = await deployMethod.request(); logger.debug(`Getting an instance of the not-yet-deployed contract to batch calls to`); - const contract = await StatefulTestContract.at(deployMethod.getInstance().address, wallet); + const instance = await deployMethod.getInstance(); + const contract = await StatefulTestContract.at(instance.address, wallet); // Batch registration, deployment, and public call into same TX logger.debug(`Creating public calls to run in same batch as deployment`); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts index 6b2e8513436..f1ffeba41ac 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_test.ts @@ -73,7 +73,7 @@ export class DeployTest { } = {}, ): Promise { const { salt, publicKeys, initArgs, constructorName, deployer } = opts; - const instance = getContractInstanceFromDeployParams(contractArtifact.artifact, { + const instance = await getContractInstanceFromDeployParams(contractArtifact.artifact, { constructorArgs: initArgs ?? [], constructorArtifact: constructorName, salt, 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 81603e318ea..cb4c0292485 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 @@ -34,7 +34,7 @@ describe('e2e_deploy_contract legacy', () => { it('should deploy a test contract', async () => { const salt = Fr.random(); const publicKeys = wallet.getCompleteAddress().publicKeys; - const deploymentData = getContractInstanceFromDeployParams(TestContractArtifact, { + const deploymentData = await getContractInstanceFromDeployParams(TestContractArtifact, { salt, publicKeys, deployer: wallet.getAddress(), @@ -114,6 +114,7 @@ describe('e2e_deploy_contract legacy', () => { expect(badTxReceipt.status).toEqual(TxStatus.APP_LOGIC_REVERTED); // But the bad tx did not deploy - await expect(pxe.isContractClassPubliclyRegistered(badDeploy.getInstance().contractClassId)).resolves.toBeFalsy(); + const badInstance = await badDeploy.getInstance(); + await expect(pxe.isContractClassPubliclyRegistered(badInstance.contractClassId)).resolves.toBeFalsy(); }); }); 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 588cc2262cb..cb0550efe53 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 @@ -44,9 +44,9 @@ 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(); - escrowPublicKeys = deriveKeys(escrowSecretKey).publicKeys; + escrowPublicKeys = (await deriveKeys(escrowSecretKey)).publicKeys; const escrowDeployment = EscrowContract.deployWithPublicKeys(escrowPublicKeys, wallet, owner); - const escrowInstance = escrowDeployment.getInstance(); + const escrowInstance = await escrowDeployment.getInstance(); await pxe.registerAccount(escrowSecretKey, computePartialAddress(escrowInstance)); escrowContract = await escrowDeployment.send().deployed(); logger.info(`Escrow contract deployed at ${escrowContract.address}`); diff --git a/yarn-project/end-to-end/src/e2e_event_logs.test.ts b/yarn-project/end-to-end/src/e2e_event_logs.test.ts index b5229455c80..b106afa689f 100644 --- a/yarn-project/end-to-end/src/e2e_event_logs.test.ts +++ b/yarn-project/end-to-end/src/e2e_event_logs.test.ts @@ -50,7 +50,7 @@ describe('Logs', () => { const decryptedEvent0 = (await L1EventPayload.decryptAsIncoming( privateLogs[0], - wallets[0].getEncryptionSecret(), + await wallets[0].getEncryptionSecret(), ))!; expect(decryptedEvent0.contractAddress).toStrictEqual(testLogContract.address); @@ -66,7 +66,7 @@ describe('Logs', () => { const decryptedEvent1 = (await L1EventPayload.decryptAsIncoming( privateLogs[2], - wallets[0].getEncryptionSecret(), + await wallets[0].getEncryptionSecret(), ))!; const event1Metadata = new EventMetadata(TestLogContract.events.ExampleEvent1); diff --git a/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts b/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts index 1348b5001da..3df618ee98e 100644 --- a/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/account_init.test.ts @@ -78,7 +78,7 @@ describe('e2e_fees account_init', () => { bobsSecretKey = Fr.random(); bobsPrivateSigningKey = Fq.random(); bobsAccountManager = await getSchnorrAccount(pxe, bobsSecretKey, bobsPrivateSigningKey, Fr.random()); - bobsCompleteAddress = bobsAccountManager.getCompleteAddress(); + bobsCompleteAddress = await bobsAccountManager.getCompleteAddress(); bobsAddress = bobsCompleteAddress.address; bobsWallet = await bobsAccountManager.getWallet(); @@ -166,7 +166,7 @@ describe('e2e_fees account_init', () => { const [alicesInitialGas] = await t.getGasBalanceFn(aliceAddress); // bob generates the private keys for his account on his own - const bobsPublicKeys = deriveKeys(bobsSecretKey).publicKeys; + const bobsPublicKeys = (await deriveKeys(bobsSecretKey)).publicKeys; const bobsSigningPubKey = await new Schnorr().computePublicKey(bobsPrivateSigningKey); const bobsInstance = bobsAccountManager.getInstance(); diff --git a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts index 18af1e1914d..aa544329bda 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts @@ -145,8 +145,8 @@ export class FeesTest { // We set Alice as the FPC admin to avoid the need for deployment of another account. this.fpcAdmin = this.aliceAddress; - - this.feeJuiceContract = await FeeJuiceContract.at(getCanonicalFeeJuice().address, this.aliceWallet); + const canonicalFeeJuice = await getCanonicalFeeJuice(); + this.feeJuiceContract = await FeeJuiceContract.at(canonicalFeeJuice.address, this.aliceWallet); const bobInstance = await this.bobWallet.getContractInstance(this.bobAddress); if (!bobInstance) { throw new Error('Bob instance not found'); diff --git a/yarn-project/end-to-end/src/e2e_keys.test.ts b/yarn-project/end-to-end/src/e2e_keys.test.ts index c114ec46a7c..8d854a07271 100644 --- a/yarn-project/end-to-end/src/e2e_keys.test.ts +++ b/yarn-project/end-to-end/src/e2e_keys.test.ts @@ -112,7 +112,7 @@ describe('Keys', () => { it('gets ovsk_app', async () => { // Derive the ovpk_m_hash from the account secret const ovskM = deriveMasterOutgoingViewingSecretKey(secret); - const ovpkMHash = derivePublicKeyFromSecretKey(ovskM).hash(); + const ovpkMHash = (await derivePublicKeyFromSecretKey(ovskM)).hash(); // Compute the expected ovsk_app const expectedOvskApp = computeAppSecretKey(ovskM, testContract.address, 'ov'); 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 0ec6529038a..5749a83bfcf 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 @@ -35,14 +35,14 @@ describe('e2e_multiple_accounts_1_enc_key', () => { const signingPrivateKey = GrumpkinScalar.random(); const account = await getSchnorrAccount(pxe, encryptionPrivateKey, signingPrivateKey); const wallet = await account.waitSetup({ interval: 0.1 }); - const completeAddress = account.getCompleteAddress(); + const completeAddress = await account.getCompleteAddress(); wallets.push(wallet); accounts.push(completeAddress); } logger.info('Account contracts deployed'); // Verify that all accounts use the same encryption key - const encryptionPublicKey = deriveKeys(encryptionPrivateKey).publicKeys.masterIncomingViewingPublicKey; + const encryptionPublicKey = (await deriveKeys(encryptionPrivateKey)).publicKeys.masterIncomingViewingPublicKey; for (const account of accounts) { expect(account.publicKeys.masterIncomingViewingPublicKey).toEqual(encryptionPublicKey); diff --git a/yarn-project/end-to-end/src/e2e_p2p/shared.ts b/yarn-project/end-to-end/src/e2e_p2p/shared.ts index f98d4f4d622..4829070d1f5 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/shared.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/shared.ts @@ -49,7 +49,7 @@ export const createPXEServiceAndSubmitTransactions = async ( const pxeService = await createPXEService(node, rpcConfig, true); const secretKey = Fr.random(); - const completeAddress = CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, Fr.random()); + const completeAddress = await CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, Fr.random()); await pxeService.registerAccount(secretKey, completeAddress.partialAddress); const txs = await submitTxsTo(logger, pxeService, numTxs); diff --git a/yarn-project/end-to-end/src/e2e_synching.test.ts b/yarn-project/end-to-end/src/e2e_synching.test.ts index 40dc9a1a8b9..2283214ce27 100644 --- a/yarn-project/end-to-end/src/e2e_synching.test.ts +++ b/yarn-project/end-to-end/src/e2e_synching.test.ts @@ -150,7 +150,7 @@ class TestVariant { return await Promise.all( accountKeys.map(async (ak, i) => { const account = await getSchnorrAccount(this.pxe, ak[0], ak[1], 1); - const partialAddress = account.getCompleteAddress().partialAddress; + const partialAddress = (await account.getCompleteAddress()).partialAddress; await this.pxe.registerAccount(accountKeys[i][0], partialAddress); const wallet = await account.getWallet(); this.logger.verbose(`Wallet ${i} address: ${wallet.getAddress()} registered`); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts index a5eead3ae09..073ba3014c5 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer.test.ts @@ -47,7 +47,7 @@ describe('e2e_token_contract transfer private', () => { const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - const nonDeployed = CompleteAddress.random(); + const nonDeployed = await CompleteAddress.random(); await asset.methods.transfer(nonDeployed.address, amount).send().wait(); diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index 65f92922c27..d6fc0635f03 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -608,7 +608,10 @@ export async function publicDeployAccounts( if (!alreadyRegistered) { calls.push((await registerContractClass(sender, SchnorrAccountContractArtifact)).request()); } - calls.push(...instances.map(instance => deployInstance(sender, instance!).request())); + const requests = await Promise.all( + instances.map(async instance => (await deployInstance(sender, instance!)).request()), + ); + calls.push(...requests); const batch = new BatchCall(sender, calls); await batch.send().wait({ proven: waitUntilProven }); diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index f0f8523b3e6..c2c43a22af5 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -590,7 +590,10 @@ export async function ensureAccountsPubliclyDeployed(sender: Wallet, accountsToD if (!(await sender.isContractClassPubliclyRegistered(contractClass.id))) { await (await registerContractClass(sender, SchnorrAccountContractArtifact)).send().wait(); } - const batch = new BatchCall(sender, [...instances.map(instance => deployInstance(sender, instance!).request())]); + const requests = await Promise.all( + instances.map(async instance => (await deployInstance(sender, instance!)).request()), + ); + const batch = new BatchCall(sender, [...requests]); await batch.send().wait(); } // docs:end:public_deploy_accounts diff --git a/yarn-project/end-to-end/src/flakey_e2e_inclusion_proofs_contract.test.ts b/yarn-project/end-to-end/src/flakey_e2e_inclusion_proofs_contract.test.ts index b93218fbd60..678d2f548f7 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_inclusion_proofs_contract.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_inclusion_proofs_contract.test.ts @@ -272,9 +272,13 @@ describe('e2e_inclusion_proofs_contract', () => { it('proves public deployment of a contract', async () => { // Publicly deploy another contract (so we don't test on the same contract) const initArgs = [wallets[0].getAddress(), 42n]; - const instance = getContractInstanceFromDeployParams(StatefulTestContractArtifact, { constructorArgs: initArgs }); - await (await registerContractClass(wallets[0], StatefulTestContractArtifact)).send().wait(); - const receipt = await deployInstance(wallets[0], instance).send().wait(); + const instance = await getContractInstanceFromDeployParams(StatefulTestContractArtifact, { + constructorArgs: initArgs, + }); + const registerMethod = await registerContractClass(wallets[0], StatefulTestContractArtifact); + await registerMethod.send().wait(); + const deployMethod = await deployInstance(wallets[0], instance); + const receipt = await deployMethod.send().wait(); await assertInclusion(instance.address, receipt.blockNumber!, { testDeploy: true, testInit: false }); }); diff --git a/yarn-project/end-to-end/src/shared/browser.ts b/yarn-project/end-to-end/src/shared/browser.ts index fff8c7a874a..3f3be722344 100644 --- a/yarn-project/end-to-end/src/shared/browser.ts +++ b/yarn-project/end-to-end/src/shared/browser.ts @@ -128,7 +128,7 @@ export const browserTestSuite = ( const secretKey = Fr.fromHexString(secretKeyString); const account = await getUnsafeSchnorrAccount(pxe, secretKey); await account.waitSetup(); - const completeAddress = account.getCompleteAddress(); + const completeAddress = await account.getCompleteAddress(); const addressString = completeAddress.address.toString(); console.log(`Created Account: ${addressString}`); return addressString; diff --git a/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts b/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts index b78f8ec3a75..edd73ac528f 100644 --- a/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts +++ b/yarn-project/end-to-end/src/spartan/setup_test_wallets.ts @@ -33,7 +33,8 @@ export async function setupTestWalletsWithTokens( const { accountKeys } = await addAccounts(1, logger, false)({ pxe }); const accountManagers = await Promise.all(accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], 1))); - const partialAddress = accountManagers[0].getCompleteAddress().partialAddress; + const completeAddress = await accountManagers[0].getCompleteAddress(); + const partialAddress = completeAddress.partialAddress; await pxe.registerAccount(accountKeys[0][0], partialAddress); recipientWallet = await accountManagers[0].getWallet(); logger.verbose(`Recipient Wallet address: ${recipientWallet.getAddress()} registered`); @@ -44,7 +45,8 @@ export async function setupTestWalletsWithTokens( const wallets = await Promise.all( accountManagers.map(async (a, i) => { - const partialAddress = a.getCompleteAddress().partialAddress; + const completeAddress = await a.getCompleteAddress(); + const partialAddress = completeAddress.partialAddress; await pxe.registerAccount(accountKeys[i][0], partialAddress); const wallet = await a.getWallet(); logger.verbose(`Wallet ${i} address: ${wallet.getAddress()} registered`); diff --git a/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts b/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts index 10604259299..93c195a2ebd 100644 --- a/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts +++ b/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts @@ -40,7 +40,6 @@ export function createSafeJsonRpcClient( if ([null, undefined, 'null', 'undefined'].includes(res.result)) { return; } - return (schema as ApiSchema)[methodName].returnType().parse(res.result); }; diff --git a/yarn-project/key-store/src/key_store.test.ts b/yarn-project/key-store/src/key_store.test.ts index 67f161eb3e7..6ff7b8bea41 100644 --- a/yarn-project/key-store/src/key_store.test.ts +++ b/yarn-project/key-store/src/key_store.test.ts @@ -9,8 +9,8 @@ describe('KeyStore', () => { // Arbitrary fixed values const sk = new Fr(8923n); - const keys = deriveKeys(sk); - const derivedMasterNullifierPublicKey = derivePublicKeyFromSecretKey(keys.masterNullifierSecretKey); + const keys = await deriveKeys(sk); + const derivedMasterNullifierPublicKey = await derivePublicKeyFromSecretKey(keys.masterNullifierSecretKey); const computedMasterNullifierPublicKeyHash = derivedMasterNullifierPublicKey.hash(); const partialAddress = new Fr(243523n); diff --git a/yarn-project/key-store/src/key_store.ts b/yarn-project/key-store/src/key_store.ts index 10d539c40c3..a9adfd151a1 100644 --- a/yarn-project/key-store/src/key_store.ts +++ b/yarn-project/key-store/src/key_store.ts @@ -52,9 +52,9 @@ export class KeyStore { masterOutgoingViewingSecretKey, masterTaggingSecretKey, publicKeys, - } = deriveKeys(sk); + } = await deriveKeys(sk); - const completeAddress = CompleteAddress.fromSecretKeyAndPartialAddress(sk, partialAddress); + const completeAddress = await CompleteAddress.fromSecretKeyAndPartialAddress(sk, partialAddress); const { address: account } = completeAddress; // Naming of keys is as follows ${account}-${n/iv/ov/t}${sk/pk}_m @@ -131,7 +131,8 @@ export class KeyStore { const skM = GrumpkinScalar.fromBuffer(skMBuffer); // We sanity check that it's possible to derive the public key from the secret key - if (!derivePublicKeyFromSecretKey(skM).equals(pkM)) { + const derivedPkM = await derivePublicKeyFromSecretKey(skM); + if (!derivedPkM.equals(pkM)) { throw new Error(`Could not derive ${keyPrefix}pkM from ${keyPrefix}skM.`); } @@ -261,7 +262,8 @@ export class KeyStore { } const skM = GrumpkinScalar.fromBuffer(secretKeyBuffer); - if (!derivePublicKeyFromSecretKey(skM).equals(pkM)) { + const derivedpkM = await derivePublicKeyFromSecretKey(skM); + if (!derivedpkM.equals(pkM)) { throw new Error(`Could not find ${keyPrefix}skM for ${keyPrefix}pkM ${pkM.toString()} in secret keys buffer.`); } diff --git a/yarn-project/noir-contracts.js/package.json b/yarn-project/noir-contracts.js/package.json index ee504495238..b1cea9b52bf 100644 --- a/yarn-project/noir-contracts.js/package.json +++ b/yarn-project/noir-contracts.js/package.json @@ -76,4 +76,4 @@ "engines": { "node": ">=18" } -} \ No newline at end of file +} diff --git a/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts b/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts index dd191ced744..33c5cf551f3 100644 --- a/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts +++ b/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts @@ -49,7 +49,7 @@ describe('Data generation for noir tests', () => { const format = (obj: object) => JSON.stringify(obj, null, 2).replaceAll('"', ''); - test.each(contracts)('Computes contract info for %s', contract => { + test.each(contracts)('Computes contract info for %s', async contract => { const contractClass: ContractClass = { ...contract, publicFunctions: [], version: 1 }; const contractClassId = computeContractClassId(contractClass); const initializationHash = computeInitializationHashFromEncodedArgs(constructorSelector, []); @@ -57,7 +57,7 @@ describe('Data generation for noir tests', () => { computeContractClassIdPreimage(contractClass); const deployer = AztecAddress.ZERO; const instance: ContractInstance = { ...contract, version: 1, initializationHash, contractClassId, deployer }; - const address = computeContractAddressFromInstance(instance); + const address = await computeContractAddressFromInstance(instance); const saltedInitializationHash = computeSaltedInitializationHash(instance); const partialAddress = computePartialAddress(instance); diff --git a/yarn-project/protocol-contracts/src/auth-registry/index.ts b/yarn-project/protocol-contracts/src/auth-registry/index.ts index 60438443618..fd0ca2f05db 100644 --- a/yarn-project/protocol-contracts/src/auth-registry/index.ts +++ b/yarn-project/protocol-contracts/src/auth-registry/index.ts @@ -10,9 +10,9 @@ let protocolContract: ProtocolContract; export const AuthRegistryArtifact = loadContractArtifact(AuthRegistryJson as NoirCompiledContract); /** Returns the canonical deployment of the auth registry. */ -export function getCanonicalAuthRegistry(): ProtocolContract { +export async function getCanonicalAuthRegistry(): Promise { if (!protocolContract) { - protocolContract = makeProtocolContract('AuthRegistry', AuthRegistryArtifact); + protocolContract = await makeProtocolContract('AuthRegistry', AuthRegistryArtifact); } return protocolContract; } diff --git a/yarn-project/protocol-contracts/src/bundle/index.ts b/yarn-project/protocol-contracts/src/bundle/index.ts index a8203e7dc33..c6afe731ece 100644 --- a/yarn-project/protocol-contracts/src/bundle/index.ts +++ b/yarn-project/protocol-contracts/src/bundle/index.ts @@ -11,13 +11,13 @@ import { ProtocolContractAddress, type ProtocolContractName, ProtocolContractSal import { RouterArtifact } from '../router/index.js'; /** Returns the canonical deployment a given artifact. */ -export function getCanonicalProtocolContract(name: ProtocolContractName): ProtocolContract { +export async function getCanonicalProtocolContract(name: ProtocolContractName): Promise { const artifact = ProtocolContractArtifact[name]; const address = ProtocolContractAddress[name]; const salt = ProtocolContractSalt[name]; // TODO(@spalladino): This computes the contract class from the artifact twice. const contractClass = getContractClassFromArtifact(artifact); - const instance = getContractInstanceFromDeployParams(artifact, { salt }); + const instance = await getContractInstanceFromDeployParams(artifact, { salt }); return { instance: { ...instance, address }, contractClass, diff --git a/yarn-project/protocol-contracts/src/class-registerer/index.ts b/yarn-project/protocol-contracts/src/class-registerer/index.ts index 9967cc1a225..17dc8e3891f 100644 --- a/yarn-project/protocol-contracts/src/class-registerer/index.ts +++ b/yarn-project/protocol-contracts/src/class-registerer/index.ts @@ -16,10 +16,10 @@ export const ContractClassRegistererArtifact = loadContractArtifact( let protocolContract: ProtocolContract; /** Returns the canonical deployment of the contract. */ -export function getCanonicalClassRegisterer(): ProtocolContract { +export async function getCanonicalClassRegisterer(): Promise { if (!protocolContract) { const artifact = ContractClassRegistererArtifact; - protocolContract = makeProtocolContract('ContractClassRegisterer', artifact); + protocolContract = await makeProtocolContract('ContractClassRegisterer', artifact); } return protocolContract; } diff --git a/yarn-project/protocol-contracts/src/fee-juice/index.ts b/yarn-project/protocol-contracts/src/fee-juice/index.ts index 3c2baabf873..e20a54a7404 100644 --- a/yarn-project/protocol-contracts/src/fee-juice/index.ts +++ b/yarn-project/protocol-contracts/src/fee-juice/index.ts @@ -10,9 +10,9 @@ export const FeeJuiceArtifact = loadContractArtifact(FeeJuiceJson as NoirCompile let protocolContract: ProtocolContract; /** Returns the canonical deployment of the contract. */ -export function getCanonicalFeeJuice(): ProtocolContract { +export async function getCanonicalFeeJuice(): Promise { if (!protocolContract) { - protocolContract = makeProtocolContract('FeeJuice', FeeJuiceArtifact); + protocolContract = await makeProtocolContract('FeeJuice', FeeJuiceArtifact); } return protocolContract; } diff --git a/yarn-project/protocol-contracts/src/instance-deployer/index.ts b/yarn-project/protocol-contracts/src/instance-deployer/index.ts index 7af519ff744..dff020eb191 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/index.ts +++ b/yarn-project/protocol-contracts/src/instance-deployer/index.ts @@ -14,9 +14,9 @@ export const ContractInstanceDeployerArtifact = loadContractArtifact( let protocolContract: ProtocolContract; /** Returns the canonical deployment of the contract. */ -export function getCanonicalInstanceDeployer(): ProtocolContract { +export async function getCanonicalInstanceDeployer(): Promise { if (!protocolContract) { - protocolContract = makeProtocolContract('ContractInstanceDeployer', ContractInstanceDeployerArtifact); + protocolContract = await makeProtocolContract('ContractInstanceDeployer', ContractInstanceDeployerArtifact); } return protocolContract; } diff --git a/yarn-project/protocol-contracts/src/make_protocol_contract.ts b/yarn-project/protocol-contracts/src/make_protocol_contract.ts index fdd05e4e4c5..62e0a3b4b64 100644 --- a/yarn-project/protocol-contracts/src/make_protocol_contract.ts +++ b/yarn-project/protocol-contracts/src/make_protocol_contract.ts @@ -8,12 +8,15 @@ import { ProtocolContractAddress, type ProtocolContractName, ProtocolContractSal * Returns the canonical deployment given its name and artifact. * To be used internally within the protocol-contracts package. */ -export function makeProtocolContract(name: ProtocolContractName, artifact: ContractArtifact): ProtocolContract { +export async function makeProtocolContract( + name: ProtocolContractName, + artifact: ContractArtifact, +): Promise { const address = ProtocolContractAddress[name]; const salt = ProtocolContractSalt[name]; // TODO(@spalladino): This computes the contract class from the artifact twice. const contractClass = getContractClassFromArtifact(artifact); - const instance = getContractInstanceFromDeployParams(artifact, { salt }); + const instance = await getContractInstanceFromDeployParams(artifact, { salt }); return { instance: { ...instance, address }, contractClass, diff --git a/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts b/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts index 862a32b76a2..edfc9b71234 100644 --- a/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts +++ b/yarn-project/protocol-contracts/src/multi-call-entrypoint/index.ts @@ -10,9 +10,9 @@ export const MultiCallEntrypointArtifact = loadContractArtifact(MultiCallEntrypo let protocolContract: ProtocolContract; /** Returns the canonical deployment of the contract. */ -export function getCanonicalMultiCallEntrypoint(): ProtocolContract { +export async function getCanonicalMultiCallEntrypoint(): Promise { if (!protocolContract) { - protocolContract = makeProtocolContract('MultiCallEntrypoint', MultiCallEntrypointArtifact); + protocolContract = await makeProtocolContract('MultiCallEntrypoint', MultiCallEntrypointArtifact); } return protocolContract; } diff --git a/yarn-project/protocol-contracts/src/router/index.ts b/yarn-project/protocol-contracts/src/router/index.ts index a8bf704aa68..a90209e8faf 100644 --- a/yarn-project/protocol-contracts/src/router/index.ts +++ b/yarn-project/protocol-contracts/src/router/index.ts @@ -10,9 +10,9 @@ export const RouterArtifact = loadContractArtifact(RouterJson as NoirCompiledCon let protocolContract: ProtocolContract; /** Returns the canonical deployment of the contract. */ -export function getCanonicalRouter(): ProtocolContract { +export async function getCanonicalRouter(): Promise { if (!protocolContract) { - protocolContract = makeProtocolContract('Router', RouterArtifact); + protocolContract = await makeProtocolContract('Router', RouterArtifact); } return protocolContract; } diff --git a/yarn-project/protocol-contracts/src/scripts/generate_data.ts b/yarn-project/protocol-contracts/src/scripts/generate_data.ts index b803b63f8f0..8aff92bc9a0 100644 --- a/yarn-project/protocol-contracts/src/scripts/generate_data.ts +++ b/yarn-project/protocol-contracts/src/scripts/generate_data.ts @@ -64,8 +64,8 @@ async function copyArtifact(srcName: string, destName: string) { return artifact; } -function computeContractLeaf(artifact: NoirCompiledContract) { - const instance = getContractInstanceFromDeployParams(loadContractArtifact(artifact), { salt }); +async function computeContractLeaf(artifact: NoirCompiledContract) { + const instance = await getContractInstanceFromDeployParams(loadContractArtifact(artifact), { salt }); return instance.address; } @@ -175,7 +175,8 @@ async function main() { const destName = destNames[i]; const artifact = await copyArtifact(srcName, destName); await generateDeclarationFile(destName); - leaves.push(computeContractLeaf(artifact).toField()); + const contractLeaf = await computeContractLeaf(artifact); + leaves.push(contractLeaf.toField()); } await generateOutputFile(destNames, leaves); diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index e8872d4f128..269b673ad77 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -545,7 +545,9 @@ export class KVPxeDatabase implements PxeDatabase { } async getCompleteAddresses(): Promise { - return (await toArray(this.#completeAddresses.valuesAsync())).map(v => CompleteAddress.fromBuffer(v)); + return await Promise.all( + (await toArray(this.#completeAddresses.valuesAsync())).map(v => CompleteAddress.fromBuffer(v)), + ); } async addSenderAddress(address: AztecAddress): Promise { diff --git a/yarn-project/pxe/src/database/pxe_database_test_suite.ts b/yarn-project/pxe/src/database/pxe_database_test_suite.ts index ed315a9c376..202c2f6848e 100644 --- a/yarn-project/pxe/src/database/pxe_database_test_suite.ts +++ b/yarn-project/pxe/src/database/pxe_database_test_suite.ts @@ -125,7 +125,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { ]; beforeEach(async () => { - owners = times(2, () => CompleteAddress.random()); + owners = await timesParallel(2, () => CompleteAddress.random()); contractAddresses = await timesParallel(2, () => AztecAddress.random()); storageSlots = times(2, () => Fr.random()); @@ -339,20 +339,20 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { describe('addresses', () => { it('stores and retrieves addresses', async () => { - const address = CompleteAddress.random(); + const address = await CompleteAddress.random(); await expect(database.addCompleteAddress(address)).resolves.toBe(true); await expect(database.getCompleteAddress(address.address)).resolves.toEqual(address); }); it('silently ignores an address it already knows about', async () => { - const address = CompleteAddress.random(); + const address = await CompleteAddress.random(); await expect(database.addCompleteAddress(address)).resolves.toBe(true); await expect(database.addCompleteAddress(address)).resolves.toBe(false); }); it.skip('refuses to overwrite an address with a different public key', async () => { - const address = CompleteAddress.random(); - const otherAddress = new CompleteAddress( + const address = await CompleteAddress.random(); + const otherAddress = await CompleteAddress.create( address.address, new PublicKeys(await Point.random(), await Point.random(), await Point.random(), await Point.random()), address.partialAddress, @@ -363,7 +363,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { }); it('returns all addresses', async () => { - const addresses = Array.from({ length: 10 }).map(() => CompleteAddress.random()); + const addresses = await timesParallel(10, () => CompleteAddress.random()); for (const address of addresses) { await database.addCompleteAddress(address); } @@ -373,7 +373,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { }); it('returns a single address', async () => { - const addresses = Array.from({ length: 10 }).map(() => CompleteAddress.random()); + const addresses = await timesParallel(10, () => CompleteAddress.random()); for (const address of addresses) { await database.addCompleteAddress(address); } @@ -387,7 +387,8 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { }); it("returns undefined if it doesn't have an address", async () => { - expect(await database.getCompleteAddress(CompleteAddress.random().address)).toBeUndefined(); + const completeAddress = await CompleteAddress.random(); + expect(await database.getCompleteAddress(completeAddress.address)).toBeUndefined(); }); }); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 21ed85c1b4e..7be423a1fc4 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -235,7 +235,8 @@ export class PXEService implements PXE { `Artifact does not match expected class id (computed ${contractClassId} but instance refers to ${instance.contractClassId})`, ); } - if (!computeContractAddressFromInstance(instance).equals(instance.address)) { + const computedAddress = await computeContractAddressFromInstance(instance); + if (!computedAddress.equals(instance.address)) { throw new Error('Added a contract in which the address does not match the contract instance.'); } @@ -690,7 +691,7 @@ export class PXEService implements PXE { async #registerProtocolContracts() { const registered: Record = {}; for (const name of protocolContractNames) { - const { address, contractClass, instance, artifact } = getCanonicalProtocolContract(name); + const { address, contractClass, instance, artifact } = await getCanonicalProtocolContract(name); await this.db.addContractArtifact(contractClass.id, artifact); await this.db.addContractInstance(instance); registered[name] = address.toString(); @@ -867,7 +868,7 @@ export class PXEService implements PXE { const preaddress = registeredAccount.getPreaddress(); - secretKey = computeAddressSecret(preaddress, secretKey); + secretKey = await computeAddressSecret(preaddress, secretKey); } return secretKey; diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 0a5e9618d09..1317c88eddf 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -607,7 +607,7 @@ export class SimulatorOracle implements DBOracle { const ivskM = await this.keyStore.getMasterSecretKey( recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey, ); - const addressSecret = computeAddressSecret(recipientCompleteAddress.getPreaddress(), ivskM); + const addressSecret = await computeAddressSecret(recipientCompleteAddress.getPreaddress(), ivskM); // Since we could have notes with the same index for different txs, we need // to keep track of them scoping by txHash diff --git a/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts b/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts index c7de0ca3906..0c7786f205e 100644 --- a/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts +++ b/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts @@ -28,6 +28,7 @@ import { deriveKeys, } from '@aztec/circuits.js'; import { type FunctionArtifact, FunctionType } from '@aztec/foundation/abi'; +import { timesParallel } from '@aztec/foundation/collection'; import { pedersenHash, poseidon2Hash } from '@aztec/foundation/crypto'; import { KeyStore } from '@aztec/key-store'; import { openTmpStore } from '@aztec/kv-store/lmdb'; @@ -35,7 +36,6 @@ import { type AcirSimulator, type SimulationProvider, WASMSimulator } from '@azt import { jest } from '@jest/globals'; import { type MockProxy, mock } from 'jest-mock-extended'; -import times from 'lodash.times'; import { type PxeDatabase } from '../database/index.js'; import { KVPxeDatabase } from '../database/kv_pxe_database.js'; @@ -202,9 +202,9 @@ describe('Simulator oracle', () => { // Add a random note from every address in the address book for a random recipient with index tagIndex // Compute the tag as sender (knowledge of preaddress and ivsk) for (const sender of senders) { - const keys = deriveKeys(Fr.random()); + const keys = await deriveKeys(Fr.random()); const partialAddress = Fr.random(); - const randomRecipient = computeAddress(keys.publicKeys, partialAddress); + const randomRecipient = await computeAddress(keys.publicKeys, partialAddress); const tag = await computeSiloedTagForIndex(sender, randomRecipient, contractAddress, tagIndex); const blockNumber = 3; const randomNote = new MockNoteRequest( @@ -227,11 +227,11 @@ describe('Simulator oracle', () => { beforeEach(async () => { // Set up the address book - senders = times(NUM_SENDERS).map((_, index) => { - const keys = deriveKeys(new Fr(index)); + senders = await timesParallel(NUM_SENDERS, async index => { + const keys = await deriveKeys(new Fr(index)); const partialAddress = Fr.random(); - const address = computeAddress(keys.publicKeys, partialAddress); - const completeAddress = new CompleteAddress(address, keys.publicKeys, partialAddress); + const address = await computeAddress(keys.publicKeys, partialAddress); + const completeAddress = await CompleteAddress.create(address, keys.publicKeys, partialAddress); return { completeAddress, ivsk: keys.masterIncomingViewingSecretKey, secretKey: new Fr(index) }; }); for (const sender of senders) { @@ -636,7 +636,7 @@ describe('Simulator oracle', () => { 2, 3, 0, - CompleteAddress.random().address, + await AztecAddress.random(), ), new MockNoteRequest(await getRandomNoteLogPayload(Fr.random(), contractAddress), 6, 3, 2, recipient.address), new MockNoteRequest( @@ -644,7 +644,7 @@ describe('Simulator oracle', () => { 9, 3, 2, - CompleteAddress.random().address, + await AztecAddress.random(), ), new MockNoteRequest(await getRandomNoteLogPayload(Fr.random(), contractAddress), 12, 3, 2, recipient.address), ]; @@ -661,8 +661,8 @@ describe('Simulator oracle', () => { it('should not store notes that do not belong to us', async () => { // Both notes should be ignored because the encryption keys do not belong to owner (they are random). const requests = [ - new MockNoteRequest(await getRandomNoteLogPayload(), 2, 1, 1, CompleteAddress.random().address), - new MockNoteRequest(await getRandomNoteLogPayload(), 2, 3, 0, CompleteAddress.random().address), + new MockNoteRequest(await getRandomNoteLogPayload(), 2, 1, 1, await AztecAddress.random()), + new MockNoteRequest(await getRandomNoteLogPayload(), 2, 3, 0, await AztecAddress.random()), ]; const taggedLogs = await mockTaggedLogs(requests); diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 5a4c0f88d20..81c4f4ffa23 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -307,7 +307,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(results.reverted).toBe(false); const grumpkin = new Grumpkin(); - const g3 = grumpkin.mul(grumpkin.generator(), new Fq(3)); + const g3 = await grumpkin.mul(grumpkin.generator(), new Fq(3)); expect(results.output).toEqual([g3.x, g3.y, Fr.ZERO]); }); @@ -319,9 +319,9 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(results.reverted).toBe(false); const grumpkin = new Grumpkin(); - const g3 = grumpkin.mul(grumpkin.generator(), new Fq(3)); - const g20 = grumpkin.mul(grumpkin.generator(), new Fq(20)); - const expectedResult = grumpkin.add(g3, g20); + const g3 = await grumpkin.mul(grumpkin.generator(), new Fq(3)); + const g20 = await grumpkin.mul(grumpkin.generator(), new Fq(20)); + const expectedResult = await grumpkin.add(g3, g20); expect(results.output).toEqual([expectedResult.x, expectedResult.y, Fr.ZERO]); }); diff --git a/yarn-project/simulator/src/avm/opcodes/ec_add.test.ts b/yarn-project/simulator/src/avm/opcodes/ec_add.test.ts index 7fe9e7ac199..0a39a349b20 100644 --- a/yarn-project/simulator/src/avm/opcodes/ec_add.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/ec_add.test.ts @@ -74,13 +74,13 @@ describe('EC Instructions', () => { context.machineState.memory.get(7).toFr(), pIsInfinite, ); - const expected = grumpkin.add(grumpkin.generator(), grumpkin.generator()); + const expected = await grumpkin.add(grumpkin.generator(), grumpkin.generator()); expect(actual).toEqual(expected); expect(context.machineState.memory.get(8).toFr().equals(Fr.ZERO)).toBe(true); }); it('Should add correctly', async () => { - const G2 = grumpkin.add(grumpkin.generator(), grumpkin.generator()); + const G2 = await grumpkin.add(grumpkin.generator(), grumpkin.generator()); const zero = new Uint1(0); const x1 = new Field(grumpkin.generator().x); @@ -112,7 +112,7 @@ describe('EC Instructions', () => { context.machineState.memory.get(7).toFr(), false, ); - const G3 = grumpkin.add(grumpkin.generator(), G2); + const G3 = await grumpkin.add(grumpkin.generator(), G2); expect(actual).toEqual(G3); expect(context.machineState.memory.get(8).toFr().equals(Fr.ZERO)).toBe(true); }); diff --git a/yarn-project/simulator/src/avm/opcodes/ec_add.ts b/yarn-project/simulator/src/avm/opcodes/ec_add.ts index c4d3dd33e6a..e358342c063 100644 --- a/yarn-project/simulator/src/avm/opcodes/ec_add.ts +++ b/yarn-project/simulator/src/avm/opcodes/ec_add.ts @@ -81,7 +81,7 @@ export class EcAdd extends Instruction { } else if (p2IsInfinite) { dest = p1; } else { - dest = grumpkin.add(p1, p2); + dest = await grumpkin.add(p1, p2); } // Important to use setSlice() and not set() in the two following statements as diff --git a/yarn-project/simulator/src/avm/opcodes/multi_scalar_mul.test.ts b/yarn-project/simulator/src/avm/opcodes/multi_scalar_mul.test.ts index 8b963fe8670..d9ddc3677e0 100644 --- a/yarn-project/simulator/src/avm/opcodes/multi_scalar_mul.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/multi_scalar_mul.test.ts @@ -1,5 +1,6 @@ import { Fq, Fr, Point } from '@aztec/circuits.js'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; +import { timesParallel } from '@aztec/foundation/collection'; import { type AvmContext } from '../avm_context.js'; import { Field, type MemoryValue, Uint1, Uint32 } from '../avm_memory_types.js'; @@ -39,7 +40,7 @@ describe('MultiScalarMul Opcode', () => { const grumpkin = new Grumpkin(); // We need to ensure points are actually on curve, so we just use the generator // In future we could use a random point, for now we create an array of [G, 2G, 3G] - const points = Array.from({ length: 3 }, (_, i) => grumpkin.mul(grumpkin.generator(), new Fq(i + 1))); + const points = await timesParallel(3, i => grumpkin.mul(grumpkin.generator(), new Fq(i + 1))); // Pick some big scalars to test the edge cases const scalars = [new Fq(Fq.MODULUS - 1n), new Fq(Fq.MODULUS - 2n), new Fq(1n)]; @@ -67,9 +68,9 @@ describe('MultiScalarMul Opcode', () => { const result = context.machineState.memory.getSlice(outputOffset, 3).map(r => r.toFr()); // We write it out explicitly here - let expectedResult = grumpkin.mul(points[0], scalars[0]); - expectedResult = grumpkin.add(expectedResult, grumpkin.mul(points[1], scalars[1])); - expectedResult = grumpkin.add(expectedResult, grumpkin.mul(points[2], scalars[2])); + let expectedResult = await grumpkin.mul(points[0], scalars[0]); + expectedResult = await grumpkin.add(expectedResult, await grumpkin.mul(points[1], scalars[1])); + expectedResult = await grumpkin.add(expectedResult, await grumpkin.mul(points[2], scalars[2])); expect(result).toEqual([expectedResult.x, expectedResult.y, new Fr(0n)]); }); @@ -79,7 +80,7 @@ describe('MultiScalarMul Opcode', () => { const grumpkin = new Grumpkin(); // We need to ensure points are actually on curve, so we just use the generator // In future we could use a random point, for now we create an array of [G, 2G, 3G] - const points = Array.from({ length: 3 }, (_, i) => grumpkin.mul(grumpkin.generator(), new Fq(i + 1))); + const points = await timesParallel(3, i => grumpkin.mul(grumpkin.generator(), new Fq(i + 1))); // Pick some big scalars to test the edge cases const scalars = [new Fq(Fq.MODULUS - 1n), new Fq(Fq.MODULUS - 2n), new Fq(1n)]; @@ -122,9 +123,9 @@ describe('MultiScalarMul Opcode', () => { const result = context.machineState.memory.getSlice(outputOffset, 3).map(r => r.toFr()); // We write it out explicitly here - let expectedResult = grumpkin.mul(points[0], scalars[0]); - expectedResult = grumpkin.add(expectedResult, grumpkin.mul(points[1], scalars[1])); - expectedResult = grumpkin.add(expectedResult, grumpkin.mul(points[2], scalars[2])); + let expectedResult = await grumpkin.mul(points[0], scalars[0]); + expectedResult = await grumpkin.add(expectedResult, await grumpkin.mul(points[1], scalars[1])); + expectedResult = await grumpkin.add(expectedResult, await grumpkin.mul(points[2], scalars[2])); expect(result).toEqual([expectedResult.x, expectedResult.y, new Fr(0n)]); }); @@ -151,7 +152,7 @@ describe('MultiScalarMul Opcode', () => { const grumpkin = new Grumpkin(); // We need to ensure points are actually on curve, so we just use the generator // In future we could use a random point, for now we create an array of [G, 2G, NOT_ON_CURVE] - const points = Array.from({ length: 2 }, (_, i) => grumpkin.mul(grumpkin.generator(), new Fq(i + 1))); + const points = await timesParallel(2, i => grumpkin.mul(grumpkin.generator(), new Fq(i + 1))); points.push(new Point(new Fr(13), new Fr(14), false)); const scalars = [new Fq(5n), new Fq(3n), new Fq(1n)]; diff --git a/yarn-project/simulator/src/avm/opcodes/multi_scalar_mul.ts b/yarn-project/simulator/src/avm/opcodes/multi_scalar_mul.ts index ecd64876235..4b73beba502 100644 --- a/yarn-project/simulator/src/avm/opcodes/multi_scalar_mul.ts +++ b/yarn-project/simulator/src/avm/opcodes/multi_scalar_mul.ts @@ -95,20 +95,22 @@ export class MultiScalarMul extends Instruction { const [firstBaseScalarPair, ...rest]: Array<[Point, Fq]> = grumpkinPoints.map((p, idx) => [p, scalarFqVector[idx]]); // Fold the points and scalars into a single point // We have to ensure get the first point, since the identity element (point at infinity) isn't quite working in ts - const outputPoint = rest.reduce((acc, curr) => { + let acc = await grumpkin.mul(firstBaseScalarPair[0], firstBaseScalarPair[1]); + for (const curr of rest) { if (curr[1] === Fq.ZERO) { // If we multiply by 0, the result will the point at infinity - so we ignore it - return acc; + continue; } else if (curr[0].inf) { // If we multiply the point at infinity by a scalar, it's still the point at infinity - return acc; + continue; } else if (acc.inf) { // If we accumulator is the point at infinity, we can just return the current point - return curr[0]; + acc = curr[0]; } else { - return grumpkin.add(acc, grumpkin.mul(curr[0], curr[1])); + acc = await grumpkin.add(acc, await grumpkin.mul(curr[0], curr[1])); } - }, grumpkin.mul(firstBaseScalarPair[0], firstBaseScalarPair[1])); + } + const outputPoint = acc; // Important to use setSlice() and not set() in the two following statements as // this checks that the offsets lie within memory range. diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 90bec2d8b72..e02c4e1124b 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -186,12 +186,15 @@ describe('Private Execution test suite', () => { logger = createLogger('simulator:test:private_execution'); const ownerPartialAddress = Fr.random(); - ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSk, ownerPartialAddress); - ({ masterNullifierSecretKey: ownerNskM } = deriveKeys(ownerSk)); + ownerCompleteAddress = await CompleteAddress.fromSecretKeyAndPartialAddress(ownerSk, ownerPartialAddress); + ({ masterNullifierSecretKey: ownerNskM } = await deriveKeys(ownerSk)); const recipientPartialAddress = Fr.random(); - recipientCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(recipientSk, recipientPartialAddress); - ({ masterNullifierSecretKey: recipientNskM } = deriveKeys(recipientSk)); + recipientCompleteAddress = await CompleteAddress.fromSecretKeyAndPartialAddress( + recipientSk, + recipientPartialAddress, + ); + ({ masterNullifierSecretKey: recipientNskM } = await deriveKeys(recipientSk)); owner = ownerCompleteAddress.address; recipient = recipientCompleteAddress.address; @@ -313,7 +316,9 @@ describe('Private Execution test suite', () => { it('should have a constructor with arguments that inserts notes', async () => { const initArgs = [owner, owner, 140]; - const instance = getContractInstanceFromDeployParams(StatefulTestContractArtifact, { constructorArgs: initArgs }); + const instance = await getContractInstanceFromDeployParams(StatefulTestContractArtifact, { + constructorArgs: initArgs, + }); oracle.getContractInstance.mockResolvedValue(instance); const artifact = getFunctionArtifact(StatefulTestContractArtifact, 'constructor'); const executionResult = await runSimulator({ args: initArgs, artifact, contractAddress: instance.address }); @@ -1024,7 +1029,7 @@ describe('Private Execution test suite', () => { const artifact = getFunctionArtifact(TestContractArtifact, 'get_master_incoming_viewing_public_key'); // Generate a partial address, pubkey, and resulting address - const completeAddress = CompleteAddress.random(); + const completeAddress = await CompleteAddress.random(); const args = [completeAddress.address]; const pubKey = completeAddress.publicKeys.masterIncomingViewingPublicKey; diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 18cf8df8085..c6adcf3d85f 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -24,7 +24,7 @@ describe('Simulator', () => { beforeEach(async () => { const ownerSk = Fr.fromHexString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); - const allOwnerKeys = deriveKeys(ownerSk); + const allOwnerKeys = await deriveKeys(ownerSk); ownerMasterNullifierPublicKey = allOwnerKeys.publicKeys.masterNullifierPublicKey; const ownerMasterNullifierSecretKey = allOwnerKeys.masterNullifierSecretKey; diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index b9ed1df73a8..11163cef275 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -38,8 +38,8 @@ describe('Unconstrained Execution test suite', () => { return new Note([new Fr(amount), owner.toField(), Fr.random()]); }; - beforeEach(() => { - const ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSecretKey, Fr.random()); + beforeEach(async () => { + const ownerCompleteAddress = await CompleteAddress.fromSecretKeyAndPartialAddress(ownerSecretKey, Fr.random()); owner = ownerCompleteAddress.address; oracle.getCompleteAddress.mockImplementation((account: AztecAddress) => { diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 2fa308e766f..a881a0d12e1 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -48,7 +48,7 @@ export class TXEService { const txeDatabase = new TXEDatabase(store); // Register protocol contracts. for (const name of protocolContractNames) { - const { contractClass, instance, artifact } = getCanonicalProtocolContract(name); + const { contractClass, instance, artifact } = await getCanonicalProtocolContract(name); await txeDatabase.addContractArtifact(contractClass.id, artifact); await txeDatabase.addContractInstance(instance); } @@ -95,8 +95,8 @@ export class TXEService { return toForeignCallResult([]); } - deriveKeys(secret: ForeignCallSingle) { - const keys = (this.typedOracle as TXE).deriveKeys(fromSingle(secret)); + async deriveKeys(secret: ForeignCallSingle) { + const keys = await (this.typedOracle as TXE).deriveKeys(fromSingle(secret)); return toForeignCallResult(keys.publicKeys.toFields().map(toSingle)); } @@ -116,7 +116,7 @@ export class TXEService { `Deploy ${artifact.name} with initializer ${initializerStr}(${decodedArgs}) and public keys hash ${publicKeysHashFr}`, ); - const instance = getContractInstanceFromDeployParams(artifact, { + const instance = await getContractInstanceFromDeployParams(artifact, { constructorArgs: decodedArgs, skipArgsDecoding: true, salt: Fr.ONE, @@ -177,10 +177,10 @@ export class TXEService { } async addAccount(secret: ForeignCallSingle) { - const keys = (this.typedOracle as TXE).deriveKeys(fromSingle(secret)); + const keys = await (this.typedOracle as TXE).deriveKeys(fromSingle(secret)); const args = [keys.publicKeys.masterIncomingViewingPublicKey.x, keys.publicKeys.masterIncomingViewingPublicKey.y]; const artifact = SchnorrAccountContractArtifact; - const instance = getContractInstanceFromDeployParams(artifact, { + const instance = await getContractInstanceFromDeployParams(artifact, { constructorArgs: args, skipArgsDecoding: true, salt: Fr.ONE,