From 864bc6f34431dee17e76c476716821996d2ff9e5 Mon Sep 17 00:00:00 2001 From: Gregorio Juliana Date: Tue, 21 Jan 2025 15:37:52 +0100 Subject: [PATCH] feat: Lazy wasm pt.1 (#11371) Starts the transition towards no top level await when importing wasm in any client bundle, so that browsers don't have to load +8MB right away. This PR introduces a `BarretembergLazy` class that behaves as `Barretenberg` (in the sense that methods are async), but it's intended to be initialized with a single thread to perform common operations, such as Field math or hashes. Since it's a big change, this PR focuses on a single thing: making `Fr.sqrt()` async. This of course had terrible ramifications, since that operation is used to assert validity of Grumpkin points that ultimately is what our `AztecAddresses` are. This leaked into the `AztecAddress.random()` method, so most tests in the repo are affected. However and even though this PR seems gigantic, that's the only thing that has changed, and as stated affects mostly tests. After this, more asynchronification on the client will happen, but hopefully will result in smaller diffs. `BarretenbergSync` will probably be kept around for server stuff, but `bb.js` will be split so that it's not imported all the time. --- barretenberg/ts/src/barretenberg/index.ts | 28 ++- barretenberg/ts/src/barretenberg_api/index.ts | 3 +- barretenberg/ts/src/index.ts | 1 + .../archiver/src/archiver/archiver.test.ts | 4 +- .../src/archiver/archiver_store_test_suite.ts | 35 ++-- .../memory_archiver_store.test.ts | 6 +- .../archiver/src/test/mock_archiver.ts | 1 + .../archiver/src/test/mock_l2_block_source.ts | 4 +- .../aztec.js/src/contract/contract.test.ts | 31 +-- .../src/contract/get_gas_limits.test.ts | 4 +- .../bb-prover/src/avm_proving.test.ts | 14 +- yarn-project/circuit-types/src/body.test.ts | 12 +- yarn-project/circuit-types/src/body.ts | 7 +- .../src/interfaces/archiver.test.ts | 42 ++-- .../src/interfaces/aztec-node.test.ts | 73 +++---- .../circuit-types/src/interfaces/p2p.test.ts | 4 +- .../circuit-types/src/interfaces/pxe.test.ts | 78 ++++--- .../circuit-types/src/l2_block.test.ts | 4 +- yarn-project/circuit-types/src/l2_block.ts | 6 +- .../src/logs/extended_public_log.ts | 4 +- .../src/logs/extended_unencrypted_l2_log.ts | 4 +- .../src/logs/function_l2_logs.test.ts | 16 +- .../src/logs/function_l2_logs.ts | 4 +- .../l1_payload/encrypted_log_payload.test.ts | 16 +- .../logs/l1_payload/encrypted_log_payload.ts | 16 +- .../src/logs/l1_payload/l1_event_payload.ts | 8 +- .../src/logs/l1_payload/l1_note_payload.ts | 18 +- .../src/logs/l2_block_l2_logs.test.ts | 12 +- .../src/logs/l2_block_l2_logs.ts | 8 +- .../circuit-types/src/logs/tx_l2_logs.test.ts | 16 +- .../circuit-types/src/logs/tx_l2_logs.ts | 4 +- .../src/logs/unencrypted_l2_log.test.ts | 8 +- .../src/logs/unencrypted_l2_log.ts | 4 +- .../src/messaging/l1_to_l2_message.test.ts | 4 +- .../src/messaging/l1_to_l2_message.ts | 4 +- .../circuit-types/src/messaging/l2_actor.ts | 4 +- yarn-project/circuit-types/src/mocks.ts | 45 ++-- .../src/notes/extended_note.test.ts | 8 +- .../circuit-types/src/notes/extended_note.ts | 12 +- .../src/private_execution_result.test.ts | 4 +- .../src/private_execution_result.ts | 20 +- .../src/public_execution_request.ts | 4 +- .../circuit-types/src/simulation_error.ts | 4 +- .../src/tx/public_simulation_output.test.ts | 4 +- .../src/tx/public_simulation_output.ts | 4 +- .../circuit-types/src/tx/simulated_tx.test.ts | 8 +- .../circuit-types/src/tx/simulated_tx.ts | 10 +- yarn-project/circuit-types/src/tx/tx.ts | 8 +- .../circuit-types/src/tx_effect.test.ts | 16 +- yarn-project/circuit-types/src/tx_effect.ts | 8 +- .../src/tx_execution_request.test.ts | 4 +- .../circuit-types/src/tx_execution_request.ts | 4 +- .../src/contract/contract_instance.test.ts | 4 +- .../src/contract/contract_instance.ts | 6 +- ...build_note_hash_read_request_hints.test.ts | 5 +- ...build_nullifier_read_request_hints.test.ts | 5 +- .../circuits.js/src/keys/derivation.ts | 8 +- .../circuits.js/src/structs/avm/avm.test.ts | 4 +- .../circuits.js/src/structs/call_context.ts | 6 +- .../src/structs/complete_address.test.ts | 13 +- .../src/structs/key_validation_request.ts | 4 +- .../src/structs/public_log.test.ts | 4 +- .../circuits.js/src/structs/public_log.ts | 4 +- .../circuits.js/src/tests/factories.ts | 45 +++- .../circuits.js/src/types/public_keys.test.ts | 4 +- .../circuits.js/src/types/public_keys.ts | 4 +- .../composed/integration_l1_publisher.test.ts | 2 +- .../access_control.test.ts | 5 +- .../end-to-end/src/e2e_block_building.test.ts | 16 +- .../contract_class_registration.test.ts | 24 ++- .../e2e_deploy_contract/deploy_method.test.ts | 3 +- .../end-to-end/src/e2e_event_logs.test.ts | 15 +- .../end-to-end/src/shared/uniswap_l1_l2.ts | 2 +- .../ethereum/src/deploy_l1_contracts.test.ts | 2 +- .../foundation/src/abi/encoder.test.ts | 6 +- yarn-project/foundation/src/array/array.ts | 15 ++ .../src/aztec-address/aztec-address.test.ts | 28 +-- .../foundation/src/aztec-address/index.ts | 10 +- .../foundation/src/collection/array.ts | 15 ++ .../foundation/src/fields/fields.test.ts | 8 +- yarn-project/foundation/src/fields/fields.ts | 17 +- .../foundation/src/fields/point.test.ts | 26 +-- yarn-project/foundation/src/fields/point.ts | 12 +- .../src/serialize/type_registry.test.ts | 8 +- yarn-project/key-store/src/key_store.test.ts | 2 +- .../src/conversion/type_conversion.test.ts | 4 +- .../p2p/src/client/p2p_client.test.ts | 6 +- yarn-project/p2p/src/mocks/index.ts | 5 +- .../tx_validator/data_validator.test.ts | 11 +- .../reqresp/reqresp.integration.test.ts | 2 +- .../p2p/src/services/reqresp/reqresp.test.ts | 2 +- .../agent-queue-rpc-integration.test.ts | 26 +-- .../src/job/epoch-proving-job.test.ts | 6 +- .../prover-node/src/prover-node.test.ts | 6 +- .../src/quote-provider/http.test.ts | 6 +- .../pxe/src/database/kv_pxe_database.ts | 6 +- .../pxe/src/database/note_dao.test.ts | 4 +- yarn-project/pxe/src/database/note_dao.ts | 10 +- .../pxe/src/database/outgoing_note_dao.ts | 10 +- .../src/database/pxe_database_test_suite.ts | 112 +++++----- .../src/kernel_prover/kernel_prover.test.ts | 4 +- .../pxe/src/pxe_service/pxe_service.ts | 42 ++-- .../src/pxe_service/test/pxe_service.test.ts | 2 +- .../src/pxe_service/test/pxe_test_suite.ts | 14 +- .../pxe/src/simulator_oracle/index.ts | 20 +- .../simulator_oracle/simulator_oracle.test.ts | 196 +++++++++++------- .../pxe/src/synchronizer/synchronizer.test.ts | 13 +- .../sequencer-client/src/config.test.ts | 6 +- .../src/publisher/l1-publisher.test.ts | 4 +- .../src/sequencer/sequencer.test.ts | 5 +- .../src/slasher/slasher_client.test.ts | 6 +- .../src/tx_validator/gas_validator.test.ts | 4 +- .../simulator/src/avm/avm_context.test.ts | 8 +- .../simulator/src/avm/avm_simulator.test.ts | 77 ++++--- .../simulator/src/avm/journal/journal.test.ts | 5 +- .../src/avm/opcodes/contract.test.ts | 26 ++- .../avm/opcodes/environment_getters.test.ts | 21 +- .../src/avm/opcodes/external_calls.test.ts | 6 +- .../simulator/src/avm/opcodes/storage.test.ts | 3 +- .../src/client/private_execution.test.ts | 53 +++-- .../simulator/src/client/simulator.test.ts | 4 +- .../client/unconstrained_execution.test.ts | 4 +- .../enqueued_call_side_effect_trace.test.ts | 23 +- .../simulator/src/public/fixtures/index.ts | 88 ++++---- .../src/public/public_db_sources.test.ts | 4 +- .../src/public/public_tx_simulator.test.ts | 6 +- yarn-project/txe/src/oracle/txe_oracle.ts | 17 +- .../txe/src/txe_service/txe_service.ts | 2 +- .../server_world_state_synchronizer.test.ts | 4 +- .../world-state/src/test/integration.test.ts | 42 ++-- yarn-project/world-state/src/test/utils.ts | 2 +- 131 files changed, 1092 insertions(+), 837 deletions(-) diff --git a/barretenberg/ts/src/barretenberg/index.ts b/barretenberg/ts/src/barretenberg/index.ts index 22a0f3bbcda..ea78d4f64c8 100644 --- a/barretenberg/ts/src/barretenberg/index.ts +++ b/barretenberg/ts/src/barretenberg/index.ts @@ -3,7 +3,7 @@ import { BarretenbergApi, BarretenbergApiSync } from '../barretenberg_api/index. import { createMainWorker } from '../barretenberg_wasm/barretenberg_wasm_main/factory/node/index.js'; import { BarretenbergWasmMain, BarretenbergWasmMainWorker } from '../barretenberg_wasm/barretenberg_wasm_main/index.js'; import { getRemoteBarretenbergWasm } from '../barretenberg_wasm/helpers/index.js'; -import { BarretenbergWasmWorker, fetchModuleAndThreads } from '../barretenberg_wasm/index.js'; +import { BarretenbergWasm, BarretenbergWasmWorker, fetchModuleAndThreads } from '../barretenberg_wasm/index.js'; import createDebug from 'debug'; import { Crs, GrumpkinCrs } from '../crs/index.js'; import { RawBuffer } from '../types/raw_buffer.js'; @@ -123,6 +123,32 @@ export class BarretenbergSync extends BarretenbergApiSync { } } +let barrentenbergLazySingleton: BarretenbergLazy; + +export class BarretenbergLazy extends BarretenbergApi { + private constructor(wasm: BarretenbergWasmMain) { + super(wasm); + } + + private static async new() { + const wasm = new BarretenbergWasmMain(); + const { module, threads } = await fetchModuleAndThreads(1); + await wasm.init(module, threads); + return new BarretenbergLazy(wasm); + } + + static async getSingleton() { + if (!barrentenbergLazySingleton) { + barrentenbergLazySingleton = await BarretenbergLazy.new(); + } + return barrentenbergLazySingleton; + } + + getWasm() { + return this.wasm; + } +} + // If we're in ESM environment, use top level await. CJS users need to call it manually. // Need to ignore for cjs build. // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index 4bd05354276..c0f4e50050a 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -1,5 +1,6 @@ // WARNING: FILE CODE GENERATED BY BINDGEN UTILITY. DO NOT EDIT! /* eslint-disable @typescript-eslint/no-unused-vars */ +import { BarretenbergWasmMain } from '../barretenberg_wasm/barretenberg_wasm_main/index.js'; import { BarretenbergWasmWorker, BarretenbergWasm } from '../barretenberg_wasm/index.js'; import { BufferDeserializer, @@ -13,7 +14,7 @@ import { import { Fr, Fq, Point, Buffer32, Buffer128, Ptr } from '../types/index.js'; export class BarretenbergApi { - constructor(protected wasm: BarretenbergWasmWorker) {} + constructor(protected wasm: BarretenbergWasmWorker | BarretenbergWasmMain) {} async pedersenCommit(inputsBuffer: Fr[], ctxIndex: number): Promise { const inArgs = [inputsBuffer, ctxIndex].map(serializeBufferable); diff --git a/barretenberg/ts/src/index.ts b/barretenberg/ts/src/index.ts index e9ca030a196..0129d2799fe 100644 --- a/barretenberg/ts/src/index.ts +++ b/barretenberg/ts/src/index.ts @@ -3,6 +3,7 @@ export { BackendOptions, Barretenberg, BarretenbergSync, + BarretenbergLazy, BarretenbergVerifier, UltraPlonkBackend, UltraHonkBackend, diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 00d1813d86f..7915f5ca265 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -71,7 +71,7 @@ describe('Archiver', () => { const GENESIS_ROOT = new Fr(GENESIS_ARCHIVE_ROOT).toString(); - beforeEach(() => { + beforeEach(async () => { logger = createLogger('archiver:test'); now = +new Date(); publicClient = mock>({ @@ -117,7 +117,7 @@ describe('Archiver', () => { l1Constants, ); - blocks = blockNumbers.map(x => L2Block.random(x, txsPerBlock, x + 1, 2)); + blocks = await Promise.all(blockNumbers.map(x => L2Block.random(x, txsPerBlock, x + 1, 2))); blocks.forEach(block => { block.body.txEffects.forEach((txEffect, i) => { txEffect.privateLogs = Array(getNumPrivateLogsForTx(block.number, i)) diff --git a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts index 1892ecb4bcb..aeaa4e61d7f 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -20,7 +20,7 @@ import { makeExecutablePrivateFunctionWithMembershipProof, makeUnconstrainedFunctionWithMembershipProof, } from '@aztec/circuits.js/testing'; -import { times } from '@aztec/foundation/collection'; +import { times, timesParallel } from '@aztec/foundation/collection'; import { randomInt } from '@aztec/foundation/crypto'; import { type ArchiverDataStore, type ArchiverL1SynchPoint } from './archiver_store.js'; @@ -51,9 +51,9 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }, }); - beforeEach(() => { + beforeEach(async () => { store = getStore(); - blocks = times(10, i => makeL1Published(L2Block.random(i + 1), i + 10)); + blocks = await timesParallel(10, async i => makeL1Published(await L2Block.random(i + 1), i + 10)); }); describe('addBlocks', () => { @@ -81,7 +81,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); it('can unwind multiple empty blocks', async () => { - const emptyBlocks = times(10, i => makeL1Published(L2Block.random(i + 1, 0), i + 10)); + const emptyBlocks = await timesParallel(10, async i => makeL1Published(await L2Block.random(i + 1, 0), i + 10)); await store.addBlocks(emptyBlocks); expect(await store.getSynchedL2BlockNumber()).toBe(10); @@ -276,7 +276,8 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const blockNum = 10; beforeEach(async () => { - contractInstance = { ...SerializableContractInstance.random(), address: AztecAddress.random() }; + const randomInstance = await SerializableContractInstance.random(); + contractInstance = { ...randomInstance, address: await AztecAddress.random() }; await store.addContractInstances([contractInstance], blockNum); }); @@ -285,7 +286,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); it('returns undefined if contract instance is not found', async () => { - await expect(store.getContractInstance(AztecAddress.random())).resolves.toBeUndefined(); + await expect(store.getContractInstance(await AztecAddress.random())).resolves.toBeUndefined(); }); it('returns undefined if previously stored contract instances was deleted', async () => { @@ -408,12 +409,12 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); }; - const mockBlockWithLogs = (blockNumber: number): L1Published => { - const block = L2Block.random(blockNumber); + const mockBlockWithLogs = async (blockNumber: number): Promise> => { + const block = await L2Block.random(blockNumber); block.header.globalVariables.blockNumber = new Fr(blockNumber); - block.body.txEffects = times(numTxsPerBlock, (txIndex: number) => { - const txEffect = TxEffect.random(); + block.body.txEffects = await timesParallel(numTxsPerBlock, async (txIndex: number) => { + const txEffect = await TxEffect.random(); txEffect.privateLogs = mockPrivateLogs(blockNumber, txIndex); txEffect.publicLogs = mockPublicLogs(blockNumber, txIndex); return txEffect; @@ -426,7 +427,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }; beforeEach(async () => { - blocks = times(numBlocks, (index: number) => mockBlockWithLogs(index)); + blocks = await timesParallel(numBlocks, (index: number) => mockBlockWithLogs(index)); await store.addBlocks(blocks); await store.addLogs(blocks.map(b => b.data)); @@ -482,7 +483,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch // Create a block containing logs that have the same tag as the blocks before. const newBlockNumber = numBlocks; - const newBlock = mockBlockWithLogs(newBlockNumber); + const newBlock = await mockBlockWithLogs(newBlockNumber); const newLog = newBlock.data.body.txEffects[1].privateLogs[1]; newLog.fields[0] = tags[0]; newBlock.data.body.txEffects[1].privateLogs[1] = newLog; @@ -545,7 +546,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch // Create a block containing these invalid logs const newBlockNumber = numBlocks; - const newBlock = mockBlockWithLogs(newBlockNumber); + const newBlock = await mockBlockWithLogs(newBlockNumber); newBlock.data.body.txEffects[0].publicLogs = invalidLogs; await store.addBlocks([newBlock]); await store.addLogs([newBlock.data]); @@ -565,8 +566,8 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch let blocks: L1Published[]; beforeEach(async () => { - blocks = times(numBlocks, (index: number) => ({ - data: L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs), + blocks = await timesParallel(numBlocks, async (index: number) => ({ + data: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs), l1: { blockNumber: BigInt(index), blockHash: `0x${index}`, timestamp: BigInt(index) }, })); @@ -748,8 +749,8 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const numBlocks = 10; const nullifiersPerBlock = new Map(); - beforeEach(() => { - blocks = times(numBlocks, (index: number) => L2Block.random(index + 1, 1)); + beforeEach(async () => { + blocks = await timesParallel(numBlocks, (index: number) => L2Block.random(index + 1, 1)); blocks.forEach((block, blockIndex) => { nullifiersPerBlock.set( diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.test.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.test.ts index 125a6132bc9..b0e78fc1fd9 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.test.ts @@ -1,5 +1,5 @@ import { L2Block } from '@aztec/circuit-types'; -import { times } from '@aztec/foundation/collection'; +import { timesParallel } from '@aztec/foundation/collection'; import { type ArchiverDataStore } from '../archiver_store.js'; import { describeArchiverDataStore } from '../archiver_store_test_suite.js'; @@ -18,8 +18,8 @@ describe('MemoryArchiverStore', () => { it('does not return more than "maxLogs" logs', async () => { const maxLogs = 5; archiverStore = new MemoryArchiverStore(maxLogs); - const blocks = times(10, (index: number) => ({ - data: L2Block.random(index + 1, 4, 3, 2), + const blocks = await timesParallel(10, async (index: number) => ({ + data: await L2Block.random(index + 1, 4, 3, 2), l1: { blockNumber: BigInt(index), blockHash: `0x${index}`, timestamp: BigInt(index) }, })); diff --git a/yarn-project/archiver/src/test/mock_archiver.ts b/yarn-project/archiver/src/test/mock_archiver.ts index a31e7bbd872..bdc1092969a 100644 --- a/yarn-project/archiver/src/test/mock_archiver.ts +++ b/yarn-project/archiver/src/test/mock_archiver.ts @@ -51,5 +51,6 @@ export class MockPrefilledArchiver extends MockArchiver { const fromBlock = this.l2Blocks.length; this.addBlocks(this.precomputed.slice(fromBlock, fromBlock + numBlocks)); + return Promise.resolve(); } } diff --git a/yarn-project/archiver/src/test/mock_l2_block_source.ts b/yarn-project/archiver/src/test/mock_l2_block_source.ts index 4f1ea8f15bb..96f89f959d4 100644 --- a/yarn-project/archiver/src/test/mock_l2_block_source.ts +++ b/yarn-project/archiver/src/test/mock_l2_block_source.ts @@ -24,10 +24,10 @@ export class MockL2BlockSource implements L2BlockSource { private log = createLogger('archiver:mock_l2_block_source'); - public createBlocks(numBlocks: number) { + public async createBlocks(numBlocks: number) { for (let i = 0; i < numBlocks; i++) { const blockNum = this.l2Blocks.length + 1; - const block = L2Block.random(blockNum); + const block = await L2Block.random(blockNum); this.l2Blocks.push(block); } diff --git a/yarn-project/aztec.js/src/contract/contract.test.ts b/yarn-project/aztec.js/src/contract/contract.test.ts index f45eb0203d1..7b52deaf799 100644 --- a/yarn-project/aztec.js/src/contract/contract.test.ts +++ b/yarn-project/aztec.js/src/contract/contract.test.ts @@ -49,19 +49,6 @@ describe('Contract Class', () => { governanceProposerAddress: EthAddress.random(), slashFactoryAddress: EthAddress.random(), }; - const mockNodeInfo: NodeInfo = { - nodeVersion: 'vx.x.x', - l1ChainId: 1, - protocolVersion: 2, - l1ContractAddresses: l1Addresses, - enr: undefined, - protocolContractAddresses: { - classRegisterer: AztecAddress.random(), - feeJuice: AztecAddress.random(), - instanceDeployer: AztecAddress.random(), - multiCallEntrypoint: AztecAddress.random(), - }, - }; const defaultArtifact: ContractArtifact = { name: 'FooContract', @@ -141,11 +128,25 @@ describe('Contract Class', () => { notes: {}, }; - beforeEach(() => { - contractAddress = AztecAddress.random(); + beforeEach(async () => { + contractAddress = await AztecAddress.random(); account = CompleteAddress.random(); contractInstance = { address: contractAddress } as ContractInstanceWithAddress; + const mockNodeInfo: NodeInfo = { + nodeVersion: 'vx.x.x', + l1ChainId: 1, + protocolVersion: 2, + l1ContractAddresses: l1Addresses, + enr: undefined, + protocolContractAddresses: { + classRegisterer: await AztecAddress.random(), + feeJuice: await AztecAddress.random(), + instanceDeployer: await AztecAddress.random(), + multiCallEntrypoint: await AztecAddress.random(), + }, + }; + wallet = mock(); wallet.simulateTx.mockResolvedValue(mockTxSimulationResult); wallet.createTxExecutionRequest.mockResolvedValue(mockTxRequest); diff --git a/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts b/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts index a4f64ba896d..a49c639fb59 100644 --- a/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts +++ b/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts @@ -6,8 +6,8 @@ import { getGasLimits } from './get_gas_limits.js'; describe('getGasLimits', () => { let txSimulationResult: TxSimulationResult; - beforeEach(() => { - txSimulationResult = mockSimulatedTx(); + beforeEach(async () => { + txSimulationResult = await mockSimulatedTx(); const tx = mockTxForRollup(); tx.data.gasUsed = Gas.from({ daGas: 100, l2Gas: 200 }); diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index b2532672786..def9b2f1c58 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -107,7 +107,7 @@ describe('AVM WitGen, "check circuit" tests', () => { it( 'call the max number of unique contract classes', async () => { - const contractDataSource = new MockedAvmTestContractDataSource(); + const contractDataSource = await MockedAvmTestContractDataSource.create(); // args is initialized to MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS contract addresses with unique class IDs const args = Array.from(contractDataSource.contractInstances.values()) .map(instance => instance.address.toField()) @@ -130,7 +130,7 @@ describe('AVM WitGen, "check circuit" tests', () => { it( 'attempt too many calls to unique contract class ids', async () => { - const contractDataSource = new MockedAvmTestContractDataSource(); + const contractDataSource = await MockedAvmTestContractDataSource.create(); // args is initialized to MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS+1 contract addresses with unique class IDs // should fail because we are trying to call MAX+1 unique class IDs const args = Array.from(contractDataSource.contractInstances.values()).map(instance => @@ -301,8 +301,11 @@ async function proveAndVerifyAvmTestContractSimple( args: Fr[] = [], expectRevert = false, skipContractDeployments = false, - contractDataSource = new MockedAvmTestContractDataSource(skipContractDeployments), + contractDataSource?: MockedAvmTestContractDataSource, ) { + if (!contractDataSource) { + contractDataSource = await MockedAvmTestContractDataSource.create(skipContractDeployments); + } await proveAndVerifyAvmTestContract( checkCircuitOnly, /*setupFunctionNames=*/ [], @@ -330,8 +333,11 @@ async function proveAndVerifyAvmTestContract( teardownArgs: Fr[] = [], expectRevert = false, skipContractDeployments = false, - contractDataSource = new MockedAvmTestContractDataSource(skipContractDeployments), + contractDataSource?: MockedAvmTestContractDataSource, ) { + if (!contractDataSource) { + contractDataSource = await MockedAvmTestContractDataSource.create(skipContractDeployments); + } const avmCircuitInputs = await simulateAvmTestContractGenerateCircuitInputs( setupFunctionNames, setupArgs, diff --git a/yarn-project/circuit-types/src/body.test.ts b/yarn-project/circuit-types/src/body.test.ts index d28ae42c478..d6cfbbccf94 100644 --- a/yarn-project/circuit-types/src/body.test.ts +++ b/yarn-project/circuit-types/src/body.test.ts @@ -3,14 +3,14 @@ import { Fr } from '@aztec/circuits.js'; import { Body } from './body.js'; describe('Body', () => { - it('converts to and from buffer', () => { - const body = Body.random(); + it('converts to and from buffer', async () => { + const body = await Body.random(); const buf = body.toBuffer(); expect(Body.fromBuffer(buf)).toEqual(body); }); - it('converts to and from fields', () => { - const body = Body.random(); + it('converts to and from fields', async () => { + const body = await Body.random(); const fields = body.toBlobFields(); // TODO(#8954): When logs are refactored into fields, we won't need to inject them here expect(Body.fromBlobFields(fields, body.contractClassLogs)).toEqual(body); @@ -22,8 +22,8 @@ describe('Body', () => { expect(Body.fromBlobFields(fields)).toEqual(body); }); - it('fails with invalid fields', () => { - const body = Body.random(); + it('fails with invalid fields', async () => { + const body = await Body.random(); const fields = body.toBlobFields(); // Replace the initial field with an invalid encoding fields[0] = new Fr(12); diff --git a/yarn-project/circuit-types/src/body.ts b/yarn-project/circuit-types/src/body.ts index 5722e1405e9..b5fe1577e7d 100644 --- a/yarn-project/circuit-types/src/body.ts +++ b/yarn-project/circuit-types/src/body.ts @@ -1,4 +1,5 @@ import { type Fr } from '@aztec/circuits.js'; +import { timesParallel } from '@aztec/foundation/collection'; import { type ZodFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -88,8 +89,10 @@ export class Body { return new ContractClass2BlockL2Logs(logs); } - static random(txsPerBlock = 4, numPublicCallsPerTx = 3, numPublicLogsPerCall = 1) { - const txEffects = [...new Array(txsPerBlock)].map(_ => TxEffect.random(numPublicCallsPerTx, numPublicLogsPerCall)); + static async random(txsPerBlock = 4, numPublicCallsPerTx = 3, numPublicLogsPerCall = 1) { + const txEffects = await timesParallel(txsPerBlock, () => + TxEffect.random(numPublicCallsPerTx, numPublicLogsPerCall), + ); return new Body(txEffects); } diff --git a/yarn-project/circuit-types/src/interfaces/archiver.test.ts b/yarn-project/circuit-types/src/interfaces/archiver.test.ts index 8f522fe4cfd..aac93f40cde 100644 --- a/yarn-project/circuit-types/src/interfaces/archiver.test.ts +++ b/yarn-project/circuit-types/src/interfaces/archiver.test.ts @@ -169,7 +169,7 @@ describe('ArchiverApiSchema', () => { it('getPublicLogs', async () => { const result = await context.client.getPublicLogs({ txHash: TxHash.random(), - contractAddress: AztecAddress.random(), + contractAddress: await AztecAddress.random(), }); expect(result).toEqual({ logs: [expect.any(ExtendedPublicLog)], maxLogsHit: true }); }); @@ -177,14 +177,14 @@ describe('ArchiverApiSchema', () => { it('getContractClassLogs', async () => { const result = await context.client.getContractClassLogs({ txHash: TxHash.random(), - contractAddress: AztecAddress.random(), + contractAddress: await AztecAddress.random(), }); expect(result).toEqual({ logs: [expect.any(ExtendedUnencryptedL2Log)], maxLogsHit: true }); }); it('getPublicFunction', async () => { const selector = FunctionSelector.random(); - const result = await context.client.getPublicFunction(AztecAddress.random(), selector); + const result = await context.client.getPublicFunction(await AztecAddress.random(), selector); expect(result).toEqual({ selector, bytecode: Buffer.alloc(10, 10) }); }); @@ -203,7 +203,7 @@ describe('ArchiverApiSchema', () => { artifact.functions[0].name, artifact.functions[0].parameters, ); - const result = await context.client.getContractFunctionName(AztecAddress.random(), selector); + const result = await context.client.getContractFunctionName(await AztecAddress.random(), selector); expect(result).toEqual(artifact.functions[0].name); }); @@ -229,11 +229,11 @@ describe('ArchiverApiSchema', () => { }); it('registerContractFunctionSignatures', async () => { - await context.client.registerContractFunctionSignatures(AztecAddress.random(), ['test()']); + await context.client.registerContractFunctionSignatures(await AztecAddress.random(), ['test()']); }); it('getContract', async () => { - const address = AztecAddress.random(); + const address = await AztecAddress.random(); const result = await context.client.getContract(address); expect(result).toEqual({ address, @@ -285,12 +285,12 @@ class MockArchiver implements ArchiverApi { getBlockHeader(_number: number | 'latest'): Promise { return Promise.resolve(BlockHeader.empty()); } - getBlocks(from: number, _limit: number, _proven?: boolean | undefined): Promise { - return Promise.resolve([L2Block.random(from)]); + async getBlocks(from: number, _limit: number, _proven?: boolean | undefined): Promise { + return [await L2Block.random(from)]; } - getTxEffect(_txHash: TxHash): Promise | undefined> { + async getTxEffect(_txHash: TxHash): Promise | undefined> { expect(_txHash).toBeInstanceOf(TxHash); - return Promise.resolve({ l2BlockNumber: 1, l2BlockHash: '0x12', data: TxEffect.random() }); + return { l2BlockNumber: 1, l2BlockHash: '0x12', data: await TxEffect.random() }; } getSettledTxReceipt(txHash: TxHash): Promise { expect(txHash).toBeInstanceOf(TxHash); @@ -302,9 +302,9 @@ class MockArchiver implements ArchiverApi { getL2EpochNumber(): Promise { return Promise.resolve(1n); } - getBlocksForEpoch(epochNumber: bigint): Promise { + async getBlocksForEpoch(epochNumber: bigint): Promise { expect(epochNumber).toEqual(1n); - return Promise.resolve([L2Block.random(Number(epochNumber))]); + return [await L2Block.random(Number(epochNumber))]; } isEpochComplete(epochNumber: bigint): Promise { expect(epochNumber).toEqual(1n); @@ -331,15 +331,15 @@ class MockArchiver implements ArchiverApi { expect(tags[0]).toBeInstanceOf(Fr); return Promise.resolve([Array.from({ length: tags.length }, () => TxScopedL2Log.random())]); } - getPublicLogs(filter: LogFilter): Promise { + async getPublicLogs(filter: LogFilter): Promise { expect(filter.txHash).toBeInstanceOf(TxHash); expect(filter.contractAddress).toBeInstanceOf(AztecAddress); - return Promise.resolve({ logs: [ExtendedPublicLog.random()], maxLogsHit: true }); + return { logs: [await ExtendedPublicLog.random()], maxLogsHit: true }; } - getContractClassLogs(filter: LogFilter): Promise { + async getContractClassLogs(filter: LogFilter): Promise { expect(filter.txHash).toBeInstanceOf(TxHash); expect(filter.contractAddress).toBeInstanceOf(AztecAddress); - return Promise.resolve({ logs: [ExtendedUnencryptedL2Log.random()], maxLogsHit: true }); + return { logs: [await ExtendedUnencryptedL2Log.random()], maxLogsHit: true }; } getPublicFunction(address: AztecAddress, selector: FunctionSelector): Promise { expect(address).toBeInstanceOf(AztecAddress); @@ -365,16 +365,16 @@ class MockArchiver implements ArchiverApi { )?.name, ); } - getContract(address: AztecAddress): Promise { - return Promise.resolve({ + async getContract(address: AztecAddress): Promise { + return { address, contractClassId: Fr.random(), - deployer: AztecAddress.random(), + deployer: await AztecAddress.random(), initializationHash: Fr.random(), - publicKeys: PublicKeys.random(), + publicKeys: await PublicKeys.random(), salt: Fr.random(), version: 1, - }); + }; } getContractClassIds(): Promise { return Promise.resolve([Fr.random()]); diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts index c7276545234..c3d98c74ead 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts @@ -27,7 +27,6 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { readFileSync } from 'fs'; import omit from 'lodash.omit'; -import times from 'lodash.times'; import { resolve } from 'path'; import { type InBlock, randomInBlock } from '../in_block.js'; @@ -230,7 +229,7 @@ describe('AztecNodeApiSchema', () => { }); it('registerContractFunctionSignatures', async () => { - await context.client.registerContractFunctionSignatures(AztecAddress.random(), ['test()']); + await context.client.registerContractFunctionSignatures(await AztecAddress.random(), ['test()']); }); it('getPrivateLogs', async () => { @@ -239,12 +238,12 @@ describe('AztecNodeApiSchema', () => { }); it('getPublicLogs', async () => { - const response = await context.client.getPublicLogs({ contractAddress: AztecAddress.random() }); + const response = await context.client.getPublicLogs({ contractAddress: await AztecAddress.random() }); expect(response).toEqual({ logs: [expect.any(ExtendedPublicLog)], maxLogsHit: true }); }); it('getContractClassLogs', async () => { - const response = await context.client.getContractClassLogs({ contractAddress: AztecAddress.random() }); + const response = await context.client.getContractClassLogs({ contractAddress: await AztecAddress.random() }); expect(response).toEqual({ logs: [expect.any(ExtendedUnencryptedL2Log)], maxLogsHit: true }); }); @@ -254,7 +253,7 @@ describe('AztecNodeApiSchema', () => { }); it('sendTx', async () => { - await context.client.sendTx(Tx.random()); + await context.client.sendTx(await Tx.random()); }); it('getTxReceipt', async () => { @@ -283,7 +282,7 @@ describe('AztecNodeApiSchema', () => { }); it('getPublicStorageAt', async () => { - const response = await context.client.getPublicStorageAt(AztecAddress.random(), Fr.random(), 1); + const response = await context.client.getPublicStorageAt(await AztecAddress.random(), Fr.random(), 1); expect(response).toBeInstanceOf(Fr); }); @@ -293,17 +292,17 @@ describe('AztecNodeApiSchema', () => { }); it('simulatePublicCalls', async () => { - const response = await context.client.simulatePublicCalls(Tx.random()); + const response = await context.client.simulatePublicCalls(await Tx.random()); expect(response).toBeInstanceOf(PublicSimulationOutput); }); it('isValidTx(valid)', async () => { - const response = await context.client.isValidTx(Tx.random(), true); + const response = await context.client.isValidTx(await Tx.random(), true); expect(response).toEqual({ result: 'valid' }); }); it('isValidTx(invalid)', async () => { - const response = await context.client.isValidTx(Tx.random()); + const response = await context.client.isValidTx(await Tx.random()); expect(response).toEqual({ result: 'invalid', reason: ['Invalid'] }); }); @@ -322,7 +321,7 @@ describe('AztecNodeApiSchema', () => { }); it('getContract', async () => { - const response = await context.client.getContract(AztecAddress.random()); + const response = await context.client.getContract(await AztecAddress.random()); expect(response).toEqual({ address: expect.any(AztecAddress), contractClassId: expect.any(Fr), @@ -475,8 +474,11 @@ class MockAztecNode implements AztecNode { isReady(): Promise { return Promise.resolve(true); } - getNodeInfo(): Promise { - return Promise.resolve({ + async getNodeInfo(): Promise { + const protocolContracts = await Promise.all( + ProtocolContractsNames.map(async name => [name, await AztecAddress.random()]), + ); + return { nodeVersion: '1.0', l1ChainId: 1, protocolVersion: 1, @@ -484,13 +486,15 @@ class MockAztecNode implements AztecNode { l1ContractAddresses: Object.fromEntries( L1ContractsNames.map(name => [name, EthAddress.random()]), ) as L1ContractAddresses, - protocolContractAddresses: Object.fromEntries( - ProtocolContractsNames.map(name => [name, AztecAddress.random()]), - ) as ProtocolContractAddresses, - }); + protocolContractAddresses: Object.fromEntries(protocolContracts) as ProtocolContractAddresses, + }; } getBlocks(from: number, limit: number): Promise { - return Promise.resolve(times(limit, i => L2Block.random(from + i))); + return Promise.all( + Array(limit) + .fill(0) + .map(i => L2Block.random(from + i)), + ); } getNodeVersion(): Promise { return Promise.resolve('1.0.0'); @@ -508,12 +512,11 @@ class MockAztecNode implements AztecNode { ); } @memoize - getProtocolContractAddresses(): Promise { - return Promise.resolve( - Object.fromEntries( - ProtocolContractsNames.map(name => [name, AztecAddress.random()]), - ) as ProtocolContractAddresses, + async getProtocolContractAddresses(): Promise { + const protocolContracts = await Promise.all( + ProtocolContractsNames.map(async name => [name, await AztecAddress.random()]), ); + return Object.fromEntries(protocolContracts) as ProtocolContractAddresses; } registerContractFunctionSignatures(_address: AztecAddress, _signatures: string[]): Promise { return Promise.resolve(); @@ -521,13 +524,13 @@ class MockAztecNode implements AztecNode { getPrivateLogs(_from: number, _limit: number): Promise { return Promise.resolve([PrivateLog.random()]); } - getPublicLogs(filter: LogFilter): Promise { + async getPublicLogs(filter: LogFilter): Promise { expect(filter.contractAddress).toBeInstanceOf(AztecAddress); - return Promise.resolve({ logs: [ExtendedPublicLog.random()], maxLogsHit: true }); + return { logs: [await ExtendedPublicLog.random()], maxLogsHit: true }; } - getContractClassLogs(filter: LogFilter): Promise { + async getContractClassLogs(filter: LogFilter): Promise { expect(filter.contractAddress).toBeInstanceOf(AztecAddress); - return Promise.resolve({ logs: [ExtendedUnencryptedL2Log.random()], maxLogsHit: true }); + return { logs: [await ExtendedUnencryptedL2Log.random()], maxLogsHit: true }; } getLogsByTags(tags: Fr[]): Promise { expect(tags).toHaveLength(1); @@ -542,12 +545,12 @@ class MockAztecNode implements AztecNode { expect(txHash).toBeInstanceOf(TxHash); return Promise.resolve(TxReceipt.empty()); } - getTxEffect(txHash: TxHash): Promise | undefined> { + async getTxEffect(txHash: TxHash): Promise | undefined> { expect(txHash).toBeInstanceOf(TxHash); - return Promise.resolve({ l2BlockNumber: 1, l2BlockHash: '0x12', data: TxEffect.random() }); + return { l2BlockNumber: 1, l2BlockHash: '0x12', data: await TxEffect.random() }; } - getPendingTxs(): Promise { - return Promise.resolve([Tx.random()]); + async getPendingTxs(): Promise { + return [await Tx.random()]; } getPendingTxCount(): Promise { return Promise.resolve(1); @@ -581,18 +584,18 @@ class MockAztecNode implements AztecNode { const contractClass = getContractClassFromArtifact(this.artifact); return Promise.resolve({ ...contractClass, unconstrainedFunctions: [], privateFunctions: [] }); } - getContract(address: AztecAddress): Promise { + async getContract(address: AztecAddress): Promise { expect(address).toBeInstanceOf(AztecAddress); const instance = { version: 1 as const, contractClassId: Fr.random(), - deployer: AztecAddress.random(), + deployer: await AztecAddress.random(), initializationHash: Fr.random(), - publicKeys: PublicKeys.random(), + publicKeys: await PublicKeys.random(), salt: Fr.random(), - address: AztecAddress.random(), + address: await AztecAddress.random(), }; - return Promise.resolve(instance); + return instance; } flushTxs(): Promise { return Promise.resolve(); diff --git a/yarn-project/circuit-types/src/interfaces/p2p.test.ts b/yarn-project/circuit-types/src/interfaces/p2p.test.ts index d9eb0cc654a..10af0c9d12f 100644 --- a/yarn-project/circuit-types/src/interfaces/p2p.test.ts +++ b/yarn-project/circuit-types/src/interfaces/p2p.test.ts @@ -75,8 +75,8 @@ class MockP2P implements P2PApi { expect(epoch).toEqual(1n); return Promise.resolve([EpochProofQuote.empty()]); } - getPendingTxs(): Promise { - return Promise.resolve([Tx.random()]); + async getPendingTxs(): Promise { + return [await Tx.random()]; } getEncodedEnr(): Promise { return Promise.resolve('enr'); diff --git a/yarn-project/circuit-types/src/interfaces/pxe.test.ts b/yarn-project/circuit-types/src/interfaces/pxe.test.ts index af272a58f0b..7d9813b8d28 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.test.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.test.ts @@ -68,13 +68,13 @@ describe('PXESchema', () => { }); beforeEach(async () => { - address = AztecAddress.random(); + address = await AztecAddress.random(); instance = { version: 1, contractClassId: Fr.random(), - deployer: AztecAddress.random(), + deployer: await AztecAddress.random(), initializationHash: Fr.random(), - publicKeys: PublicKeys.random(), + publicKeys: await PublicKeys.random(), salt: Fr.random(), address, }; @@ -147,23 +147,34 @@ describe('PXESchema', () => { }); it('proveTx', async () => { - const result = await context.client.proveTx(TxExecutionRequest.random(), PrivateExecutionResult.random()); + const result = await context.client.proveTx( + await TxExecutionRequest.random(), + await PrivateExecutionResult.random(), + ); expect(result).toBeInstanceOf(TxProvingResult); }); it('simulateTx(all)', async () => { - const result = await context.client.simulateTx(TxExecutionRequest.random(), true, address, false, true, false, []); + const result = await context.client.simulateTx( + await TxExecutionRequest.random(), + true, + address, + false, + true, + false, + [], + ); expect(result).toBeInstanceOf(TxSimulationResult); }); it('simulateTx(required)', async () => { - const result = await context.client.simulateTx(TxExecutionRequest.random(), true); + const result = await context.client.simulateTx(await TxExecutionRequest.random(), true); expect(result).toBeInstanceOf(TxSimulationResult); }); it('simulateTx(undefined)', async () => { const result = await context.client.simulateTx( - TxExecutionRequest.random(), + await TxExecutionRequest.random(), true, undefined, undefined, @@ -175,7 +186,7 @@ describe('PXESchema', () => { }); it('sendTx', async () => { - const result = await context.client.sendTx(Tx.random()); + const result = await context.client.sendTx(await Tx.random()); expect(result).toBeInstanceOf(TxHash); }); @@ -212,11 +223,11 @@ describe('PXESchema', () => { }); it('addNote', async () => { - await context.client.addNote(ExtendedNote.random(), address); + await context.client.addNote(await ExtendedNote.random(), address); }); it('addNullifiedNote', async () => { - await context.client.addNullifiedNote(ExtendedNote.random()); + await context.client.addNullifiedNote(await ExtendedNote.random()); }); it('getBlock', async () => { @@ -300,7 +311,7 @@ describe('PXESchema', () => { { abiType: { kind: 'boolean' }, eventSelector: EventSelector.random(), fieldNames: ['name'] }, 1, 1, - [Point.random()], + [await Point.random()], ); expect(result).toEqual([{ value: 1n }]); }); @@ -383,7 +394,7 @@ class MockPXE implements PXE { new TxProvingResult(privateExecutionResult, PrivateKernelTailCircuitPublicInputs.empty(), ClientIvcProof.empty()), ); } - simulateTx( + async simulateTx( txRequest: TxExecutionRequest, _simulatePublic: boolean, msgSender?: AztecAddress | undefined, @@ -399,9 +410,7 @@ class MockPXE implements PXE { if (scopes) { expect(scopes).toEqual([]); } - return Promise.resolve( - new TxSimulationResult(PrivateExecutionResult.random(), PrivateKernelTailCircuitPublicInputs.empty()), - ); + return new TxSimulationResult(await PrivateExecutionResult.random(), PrivateKernelTailCircuitPublicInputs.empty()); } sendTx(tx: Tx): Promise { expect(tx).toBeInstanceOf(Tx); @@ -411,18 +420,19 @@ class MockPXE implements PXE { expect(txHash).toBeInstanceOf(TxHash); return Promise.resolve(TxReceipt.empty()); } - getTxEffect(txHash: TxHash): Promise | undefined> { + async getTxEffect(txHash: TxHash): Promise | undefined> { expect(txHash).toBeInstanceOf(TxHash); - return Promise.resolve({ data: TxEffect.random(), l2BlockHash: Fr.random().toString(), l2BlockNumber: 1 }); + return { data: await TxEffect.random(), l2BlockHash: Fr.random().toString(), l2BlockNumber: 1 }; } getPublicStorageAt(contract: AztecAddress, slot: Fr): Promise { expect(contract).toBeInstanceOf(AztecAddress); expect(slot).toBeInstanceOf(Fr); return Promise.resolve(Fr.random()); } - getNotes(filter: NotesFilter): Promise { + async getNotes(filter: NotesFilter): Promise { expect(filter.contractAddress).toEqual(this.address); - return Promise.resolve([UniqueNote.random()]); + const uniqueNote = await UniqueNote.random(); + return [uniqueNote]; } getL1ToL2MembershipWitness( contractAddress: AztecAddress, @@ -466,13 +476,13 @@ class MockPXE implements PXE { expect(scopes).toEqual([this.address]); return Promise.resolve(10n); } - getPublicLogs(filter: LogFilter): Promise { + async getPublicLogs(filter: LogFilter): Promise { expect(filter.contractAddress).toEqual(this.address); - return Promise.resolve({ logs: [ExtendedPublicLog.random()], maxLogsHit: true }); + return { logs: [await ExtendedPublicLog.random()], maxLogsHit: true }; } - getContractClassLogs(filter: LogFilter): Promise { + async getContractClassLogs(filter: LogFilter): Promise { expect(filter.contractAddress).toEqual(this.address); - return Promise.resolve({ logs: [ExtendedUnencryptedL2Log.random()], maxLogsHit: true }); + return { logs: [await ExtendedUnencryptedL2Log.random()], maxLogsHit: true }; } getBlockNumber(): Promise { return Promise.resolve(1); @@ -481,8 +491,11 @@ class MockPXE implements PXE { return Promise.resolve(1); } @memoize - getNodeInfo(): Promise { - return Promise.resolve({ + async getNodeInfo(): Promise { + const protocolContracts = await Promise.all( + ProtocolContractsNames.map(async name => [name, await AztecAddress.random()]), + ); + return { nodeVersion: '1.0', l1ChainId: 1, protocolVersion: 1, @@ -490,17 +503,16 @@ class MockPXE implements PXE { l1ContractAddresses: Object.fromEntries( L1ContractsNames.map(name => [name, EthAddress.random()]), ) as L1ContractAddresses, - protocolContractAddresses: Object.fromEntries( - ProtocolContractsNames.map(name => [name, AztecAddress.random()]), - ) as ProtocolContractAddresses, - }); + protocolContractAddresses: Object.fromEntries(protocolContracts) as ProtocolContractAddresses, + }; } @memoize - getPXEInfo(): Promise { + async getPXEInfo(): Promise { + const protocolContracts = await Promise.all( + ProtocolContractsNames.map(async name => [name, await AztecAddress.random()]), + ); return Promise.resolve({ - protocolContractAddresses: Object.fromEntries( - ProtocolContractsNames.map(name => [name, AztecAddress.random()]), - ) as ProtocolContractAddresses, + protocolContractAddresses: Object.fromEntries(protocolContracts) as ProtocolContractAddresses, pxeVersion: '1.0', }); } diff --git a/yarn-project/circuit-types/src/l2_block.test.ts b/yarn-project/circuit-types/src/l2_block.test.ts index 848bed33fd7..f9fd1039570 100644 --- a/yarn-project/circuit-types/src/l2_block.test.ts +++ b/yarn-project/circuit-types/src/l2_block.test.ts @@ -1,8 +1,8 @@ import { L2Block } from './l2_block.js'; describe('L2Block', () => { - it('can serialize an L2 block with logs to a buffer and back', () => { - const block = L2Block.random(42); + it('can serialize an L2 block with logs to a buffer and back', async () => { + const block = await L2Block.random(42); const buffer = block.toBuffer(); const recovered = L2Block.fromBuffer(buffer); diff --git a/yarn-project/circuit-types/src/l2_block.ts b/yarn-project/circuit-types/src/l2_block.ts index 5ae6db38f4f..037bc95027b 100644 --- a/yarn-project/circuit-types/src/l2_block.ts +++ b/yarn-project/circuit-types/src/l2_block.ts @@ -79,15 +79,15 @@ export class L2Block { * @param inHash - The hash of the L1 to L2 messages subtree which got inserted in this block. * @returns The L2 block. */ - static random( + static async random( l2BlockNum: number, txsPerBlock = 4, numPublicCallsPerTx = 3, numPublicLogsPerCall = 1, inHash: Buffer | undefined = undefined, slotNumber: number | undefined = undefined, - ): L2Block { - const body = Body.random(txsPerBlock, numPublicCallsPerTx, numPublicLogsPerCall); + ): Promise { + const body = await Body.random(txsPerBlock, numPublicCallsPerTx, numPublicLogsPerCall); return new L2Block( makeAppendOnlyTreeSnapshot(l2BlockNum + 1), diff --git a/yarn-project/circuit-types/src/logs/extended_public_log.ts b/yarn-project/circuit-types/src/logs/extended_public_log.ts index 30230aaa48d..5ac5c572852 100644 --- a/yarn-project/circuit-types/src/logs/extended_public_log.ts +++ b/yarn-project/circuit-types/src/logs/extended_public_log.ts @@ -19,8 +19,8 @@ export class ExtendedPublicLog { public readonly log: PublicLog, ) {} - static random() { - return new ExtendedPublicLog(LogId.random(), PublicLog.random()); + static async random() { + return new ExtendedPublicLog(LogId.random(), await PublicLog.random()); } static get schema() { diff --git a/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts index e218b50b43f..68646314612 100644 --- a/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts @@ -20,8 +20,8 @@ export class ExtendedUnencryptedL2Log { public readonly log: UnencryptedL2Log, ) {} - static random() { - return new ExtendedUnencryptedL2Log(LogId.random(), UnencryptedL2Log.random()); + static async random() { + return new ExtendedUnencryptedL2Log(LogId.random(), await UnencryptedL2Log.random()); } static get schema() { diff --git a/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts index 7826499292c..61e976890e1 100644 --- a/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts @@ -4,8 +4,8 @@ import { UnencryptedFunctionL2Logs } from './function_l2_logs.js'; function shouldBehaveLikeFunctionL2Logs(FunctionL2Logs: typeof UnencryptedFunctionL2Logs) { describe(FunctionL2Logs.name, () => { - it('can encode L2Logs to buffer and back', () => { - const l2Logs = FunctionL2Logs.random(1); + it('can encode L2Logs to buffer and back', async () => { + const l2Logs = await FunctionL2Logs.random(1); const buffer = l2Logs.toBuffer(); const recovered = FunctionL2Logs.fromBuffer(buffer); @@ -13,8 +13,8 @@ function shouldBehaveLikeFunctionL2Logs(FunctionL2Logs: typeof UnencryptedFuncti expect(recovered).toEqual(l2Logs); }); - it('can encode L2Logs to JSON and back', () => { - const l2Logs = FunctionL2Logs.random(1); + it('can encode L2Logs to JSON and back', async () => { + const l2Logs = await FunctionL2Logs.random(1); const buffer = jsonStringify(l2Logs); const recovered = FunctionL2Logs.schema.parse(JSON.parse(buffer)); @@ -22,8 +22,8 @@ function shouldBehaveLikeFunctionL2Logs(FunctionL2Logs: typeof UnencryptedFuncti expect(recovered).toEqual(l2Logs); }); - it('getSerializedLength returns the correct length', () => { - const l2Logs = FunctionL2Logs.random(1); + it('getSerializedLength returns the correct length', async () => { + const l2Logs = await FunctionL2Logs.random(1); const buffer = l2Logs.toBuffer(); const recovered = FunctionL2Logs.fromBuffer(buffer); @@ -36,8 +36,8 @@ function shouldBehaveLikeFunctionL2Logs(FunctionL2Logs: typeof UnencryptedFuncti } }); - it('getKernelLength returns the correct length', () => { - const l2Logs = FunctionL2Logs.random(1); + it('getKernelLength returns the correct length', async () => { + const l2Logs = await FunctionL2Logs.random(1); const expectedLength = l2Logs.logs.map(l => l.length).reduce((a, b) => a + b + 4, 0); diff --git a/yarn-project/circuit-types/src/logs/function_l2_logs.ts b/yarn-project/circuit-types/src/logs/function_l2_logs.ts index 5e9b6bf64c1..ad406b7b9a3 100644 --- a/yarn-project/circuit-types/src/logs/function_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/function_l2_logs.ts @@ -91,13 +91,13 @@ export class UnencryptedFunctionL2Logs { * @param numLogs - The number of logs to create. * @returns A new UnencryptedFunctionL2Logs object. */ - public static random(numLogs: number): UnencryptedFunctionL2Logs { + public static async random(numLogs: number): Promise { if (numLogs > MAX_CONTRACT_CLASS_LOGS_PER_CALL) { throw new Error(`Trying to create ${numLogs} logs for one call (max: ${MAX_CONTRACT_CLASS_LOGS_PER_CALL})`); } const logs: UnencryptedL2Log[] = []; for (let i = 0; i < numLogs; i++) { - logs.push(UnencryptedL2Log.random()); + logs.push(await UnencryptedL2Log.random()); } return new UnencryptedFunctionL2Logs(logs); } 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 467db1d4ce4..303452d53df 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 @@ -23,9 +23,9 @@ describe('EncryptedLogPayload', () => { let original: EncryptedLogPayload; let payload: PrivateLog; - beforeAll(() => { + beforeAll(async () => { const incomingBodyPlaintext = randomBytes(128); - const contract = AztecAddress.random(); + const contract = await AztecAddress.random(); original = new EncryptedLogPayload(PLACEHOLDER_TAG, contract, incomingBodyPlaintext); const secretKey = Fr.random(); @@ -36,19 +36,19 @@ describe('EncryptedLogPayload', () => { const ephSk = GrumpkinScalar.random(); - payload = original.generatePayload(ephSk, completeAddress.address); + payload = await original.generatePayload(ephSk, completeAddress.address); }); - it('decrypt a log as incoming', () => { + it('decrypt a log as incoming', async () => { const addressSecret = computeAddressSecret(completeAddress.getPreaddress(), ivskM); - const recreated = EncryptedLogPayload.decryptAsIncoming(payload.fields, addressSecret); + const recreated = await EncryptedLogPayload.decryptAsIncoming(payload.fields, addressSecret); expect(recreated?.toBuffer()).toEqual(original.toBuffer()); }); }); - it('encrypted tagged log matches Noir', () => { + it('encrypted tagged log matches Noir', async () => { // All the values in this test were arbitrarily set and copied over to `payload.nr` const contract = AztecAddress.fromString('0x10f48cd9eff7ae5b209c557c70de2e657ee79166868676b787e9417e19260e04'); const plaintext = Buffer.from( @@ -73,7 +73,7 @@ describe('EncryptedLogPayload', () => { return Buffer.from(Array(len).fill(1)); }; - const payload = log.generatePayload(ephSk, recipientCompleteAddress.address, fixedRand); + const payload = await log.generatePayload(ephSk, recipientCompleteAddress.address, fixedRand); expect(payload.toBuffer().toString('hex')).toMatchInlineSnapshot( `"0e9cffc3ddd746affb02410d8f0a823e89939785bcc8e88ee4f3cae05e737c36008d460c0e434d846ec1ea286e4090eb56376ff27bddc1aacae1d856549f701f00a70577790aeabcc2d81ec8d0c99e7f5d2bf2f1452025dc777a178404f851d9003de818923f85187871d99bdf95d695eff0a900000000000000000000000000000000a600a61f7d59eeaf52eb51bc0592ff981d9ba3ea8e6ea8ba9dc0cec8c7000b81e84556a77ce6c3ca47a527f99ffe7b2524bb885a23020b7295748ad19c001083618ad96298b76ee07eb1a56d19cc798710e9f5de96501bd59b3781c9c0002a6c95c5912f8936b1500d362afbf0922c85b1ada18db8b95162a6e9d06765005cdf669eb387f8e0492a95fdcdb39429d5340b4bebc250ba9bf62c2f49f54900f37beed75a668aa51967e0e57547e5a655157bcf381e22f30e25881548ec960006a151b5fbfb2d14ee4b34bf4c1dbd71c7be15ad4c63474bb6f89970aeb3d900489c8edbdff80a1a3a5c28370e534abc870a85ea4318326ea19222fb10df35008c765edada497db4284ae30507a2e03e983d23cfa0bd831577e857bbef9cf70090c97cb5699cc8783a1b4276d929be2882e5b9b72829a4f8404f7e3c853d1100d6d5a000b80134891e95f81007ad35d3945eaeecbe137fff85d01d7eaf8f1900a15eb965c6a4bc97aa87fd3463c31c9d4e0d722a8ba870bcc50c9c7a8b48ad0063c861bdbe490d44c57382decbae663927909652f87ac18dcfd5b30649cce500820f14caa725efe1fa3485ceac88499eadf0565c5b20998c05931bbf478e68"`, @@ -90,7 +90,7 @@ describe('EncryptedLogPayload', () => { const ivskM = new GrumpkinScalar(0x0d6e27b21c89a7632f7766e35cc280d43f75bea3898d7328400a5fefc804d462n); const addressSecret = computeAddressSecret(recipientCompleteAddress.getPreaddress(), ivskM); - const recreated = EncryptedLogPayload.decryptAsIncoming(payload.fields, addressSecret); + 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 0906f368f58..cfecd5a9ec8 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 @@ -62,8 +62,8 @@ function trimCiphertext(buf: Buffer, ciphertextLength: number) { class Overhead { constructor(public ephPk: Point, public incomingHeader: Buffer) {} - static fromBuffer(reader: BufferReader) { - const ephPk = Point.fromCompressedBuffer(reader.readBytes(Point.COMPRESSED_SIZE_IN_BYTES)); + static async fromBuffer(reader: BufferReader) { + const ephPk = await Point.fromCompressedBuffer(reader.readBytes(Point.COMPRESSED_SIZE_IN_BYTES)); const incomingHeader = reader.readBytes(HEADER_SIZE); // Advance the index to skip the padding. @@ -92,12 +92,12 @@ export class EncryptedLogPayload { public readonly incomingBodyPlaintext: Buffer, ) {} - public generatePayload( + public async generatePayload( ephSk: GrumpkinScalar, recipient: AztecAddress, rand: (len: number) => Buffer = randomBytes, - ): PrivateLog { - const addressPoint = recipient.toAddressPoint(); + ): Promise { + const addressPoint = await recipient.toAddressPoint(); const ephPk = derivePublicKeyFromSecretKey(ephSk); const incomingHeaderCiphertext = encrypt(this.contractAddress.toBuffer(), ephSk, addressPoint); @@ -152,16 +152,16 @@ export class EncryptedLogPayload { * @param ciphertextLength - Optionally supply the ciphertext length (see trimCiphertext()) * @returns The decrypted log payload */ - public static decryptAsIncoming( + public static async decryptAsIncoming( payload: Fr[], addressSecret: GrumpkinScalar, ciphertextLength?: number, - ): EncryptedLogPayload | undefined { + ): Promise { try { const tag = payload[0]; const reader = BufferReader.asReader(fieldsToEncryptedBytes(payload.slice(1))); - const overhead = Overhead.fromBuffer(reader); + const overhead = await Overhead.fromBuffer(reader); const { contractAddress } = this.#decryptOverhead(overhead, { addressSecret }); let ciphertext = reader.readToEnd(); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts index 1d4b577726a..7ae013efa66 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts @@ -46,8 +46,8 @@ export class L1EventPayload { return payload; } - static decryptAsIncoming(log: PrivateLog, sk: Fq): L1EventPayload | undefined { - const decryptedLog = EncryptedLogPayload.decryptAsIncoming(log.fields, sk); + static async decryptAsIncoming(log: PrivateLog, sk: Fq): Promise { + const decryptedLog = await EncryptedLogPayload.decryptAsIncoming(log.fields, sk); if (!decryptedLog) { return undefined; } @@ -72,8 +72,8 @@ export class L1EventPayload { * @param contract - The address of a contract the event was emitted from. * @returns A random L1EventPayload object. */ - static random(contract = AztecAddress.random()) { - return new L1EventPayload(Event.random(), contract, EventSelector.random()); + static async random(contract?: AztecAddress) { + return new L1EventPayload(Event.random(), contract ?? (await AztecAddress.random()), EventSelector.random()); } public equals(other: L1EventPayload) { diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index 3f36fd4841a..3c51488ee77 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -59,8 +59,8 @@ export class L1NotePayload { } } - static decryptAsIncoming(log: PrivateLog, sk: Fq): L1NotePayload | undefined { - const decryptedLog = EncryptedLogPayload.decryptAsIncoming(log.fields, sk); + static async decryptAsIncoming(log: PrivateLog, sk: Fq): Promise { + const decryptedLog = await EncryptedLogPayload.decryptAsIncoming(log.fields, sk); if (!decryptedLog) { return undefined; } @@ -72,13 +72,13 @@ export class L1NotePayload { ); } - static decryptAsIncomingFromPublic(log: PublicLog, sk: Fq): L1NotePayload | undefined { + static async decryptAsIncomingFromPublic(log: PublicLog, sk: Fq): Promise { const { privateValues, publicValues, ciphertextLength } = parseLogFromPublic(log); if (!privateValues) { return undefined; } - const decryptedLog = EncryptedLogPayload.decryptAsIncoming(privateValues, sk, ciphertextLength); + const decryptedLog = await EncryptedLogPayload.decryptAsIncoming(privateValues, sk, ciphertextLength); if (!decryptedLog) { return undefined; } @@ -104,14 +104,20 @@ export class L1NotePayload { * @param contract - The address of a contract the note was emitted from. * @returns A random L1NotePayload object. */ - static random(contract = AztecAddress.random()) { + static async random(contract?: AztecAddress) { const numPrivateNoteValues = randomInt(2) + 1; const privateNoteValues = Array.from({ length: numPrivateNoteValues }, () => Fr.random()); const numPublicNoteValues = randomInt(2) + 1; const publicNoteValues = Array.from({ length: numPublicNoteValues }, () => Fr.random()); - return new L1NotePayload(contract, Fr.random(), NoteSelector.random(), privateNoteValues, publicNoteValues); + return new L1NotePayload( + contract ?? (await AztecAddress.random()), + Fr.random(), + NoteSelector.random(), + privateNoteValues, + publicNoteValues, + ); } public equals(other: L1NotePayload) { diff --git a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts index 9d1a579ff53..5d8e30f3f32 100644 --- a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts @@ -4,23 +4,23 @@ import { ContractClass2BlockL2Logs } from './l2_block_l2_logs.js'; function shouldBehaveLikeL2BlockL2Logs(L2BlockL2Logs: typeof ContractClass2BlockL2Logs) { describe(L2BlockL2Logs.name, () => { - it('can encode L2Logs to buffer and back', () => { - const l2Logs = L2BlockL2Logs.random(3, 1, 1); + it('can encode L2Logs to buffer and back', async () => { + const l2Logs = await L2BlockL2Logs.random(3, 1, 1); const buffer = l2Logs.toBuffer(); const recovered = L2BlockL2Logs.fromBuffer(buffer); expect(recovered).toEqual(l2Logs); }); - it('getSerializedLength returns the correct length', () => { - const l2Logs = L2BlockL2Logs.random(3, 1, 1); + it('getSerializedLength returns the correct length', async () => { + const l2Logs = await L2BlockL2Logs.random(3, 1, 1); const buffer = l2Logs.toBuffer(); const recovered = L2BlockL2Logs.fromBuffer(buffer); expect(recovered.getSerializedLength()).toEqual(buffer.length); }); - it('serializes to and from JSON via schema', () => { - const l2Logs = L2BlockL2Logs.random(3, 1, 1); + it('serializes to and from JSON via schema', async () => { + const l2Logs = await L2BlockL2Logs.random(3, 1, 1); const json = jsonStringify(l2Logs); const recovered = L2BlockL2Logs.schema.parse(JSON.parse(json)); expect(recovered).toEqual(l2Logs); diff --git a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts index a0f5e275e06..f9f41f325ba 100644 --- a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts @@ -115,10 +115,14 @@ export class ContractClass2BlockL2Logs extends L2BlockL2Logs { * @param numLogsPerCall - The number of logs emitted in each function call. * @returns A new `L2BlockL2Logs` object. */ - public static random(numTxs: number, numCalls: number, numLogsPerCall: number): ContractClass2BlockL2Logs { + public static async random( + numTxs: number, + numCalls: number, + numLogsPerCall: number, + ): Promise { const txLogs: ContractClassTxL2Logs[] = []; for (let i = 0; i < numTxs; i++) { - txLogs.push(ContractClassTxL2Logs.random(numCalls, numLogsPerCall)); + txLogs.push(await ContractClassTxL2Logs.random(numCalls, numLogsPerCall)); } return new ContractClass2BlockL2Logs(txLogs); } diff --git a/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts index 767b0c93371..a81e5b3da8d 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts @@ -4,31 +4,31 @@ import { ContractClassTxL2Logs } from './tx_l2_logs.js'; function shouldBehaveLikeTxL2Logs(TxL2Logs: typeof ContractClassTxL2Logs) { describe(TxL2Logs.name, () => { - it('can encode TxL2Logs to buffer and back', () => { - const l2Logs = TxL2Logs.random(1, 1); + it('can encode TxL2Logs to buffer and back', async () => { + const l2Logs = await TxL2Logs.random(1, 1); const buffer = l2Logs.toBuffer(); const recovered = TxL2Logs.fromBuffer(buffer); expect(recovered).toEqual(l2Logs); }); - it('can encode TxL2Logs to JSON and back', () => { - const l2Logs = TxL2Logs.random(1, 1); + it('can encode TxL2Logs to JSON and back', async () => { + const l2Logs = await TxL2Logs.random(1, 1); const buffer = jsonStringify(l2Logs); const recovered = TxL2Logs.schema.parse(JSON.parse(buffer)); expect(recovered).toEqual(l2Logs); }); - it('getSerializedLength returns the correct length', () => { - const l2Logs = TxL2Logs.random(1, 1); + it('getSerializedLength returns the correct length', async () => { + const l2Logs = await TxL2Logs.random(1, 1); const buffer = l2Logs.toBuffer(); const recovered = TxL2Logs.fromBuffer(buffer); expect(recovered.getSerializedLength()).toEqual(buffer.length); }); - it('getKernelLength returns the correct length', () => { - const l2Logs = TxL2Logs.random(1, 1); + it('getKernelLength returns the correct length', async () => { + const l2Logs = await TxL2Logs.random(1, 1); const expectedLength = l2Logs.functionLogs.map(l => l.getKernelLength()).reduce((a, b) => a + b, 0); expect(l2Logs.getKernelLength()).toEqual(expectedLength); diff --git a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts index fab163a3ac9..e1becac450e 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts @@ -168,7 +168,7 @@ export class ContractClassTxL2Logs extends TxL2Logs { * @param numLogsPerCall - The number of logs emitted in each function call. * @returns A new `TxL2Logs` object. */ - public static random(numCalls: number, numLogsPerCall: number): ContractClassTxL2Logs { + public static async random(numCalls: number, numLogsPerCall: number): Promise { if (numCalls * numLogsPerCall > MAX_CONTRACT_CLASS_LOGS_PER_TX) { throw new Error( `Trying to create ${numCalls * numLogsPerCall} logs for one tx (max: ${MAX_CONTRACT_CLASS_LOGS_PER_TX})`, @@ -176,7 +176,7 @@ export class ContractClassTxL2Logs extends TxL2Logs { } const functionLogs: UnencryptedFunctionL2Logs[] = []; for (let i = 0; i < numCalls; i++) { - functionLogs.push(UnencryptedFunctionL2Logs.random(numLogsPerCall)); + functionLogs.push(await UnencryptedFunctionL2Logs.random(numLogsPerCall)); } return new ContractClassTxL2Logs(functionLogs); } diff --git a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.test.ts b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.test.ts index 7917be9f8a6..079202f1bce 100644 --- a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.test.ts +++ b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.test.ts @@ -3,8 +3,8 @@ import { jsonStringify } from '@aztec/foundation/json-rpc'; import { UnencryptedL2Log } from './unencrypted_l2_log.js'; describe('UnencryptedL2Log', () => { - it('can encode L2Logs to buffer and back', () => { - const l2Logs = UnencryptedL2Log.random(); + it('can encode L2Logs to buffer and back', async () => { + const l2Logs = await UnencryptedL2Log.random(); const buffer = l2Logs.toBuffer(); const recovered = UnencryptedL2Log.fromBuffer(buffer); @@ -12,8 +12,8 @@ describe('UnencryptedL2Log', () => { expect(recovered).toEqual(l2Logs); }); - it('can encode to JSON and back', () => { - const l2Logs = UnencryptedL2Log.random(); + it('can encode to JSON and back', async () => { + const l2Logs = await UnencryptedL2Log.random(); const buffer = jsonStringify(l2Logs); const recovered = UnencryptedL2Log.schema.parse(JSON.parse(buffer)); diff --git a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts index 472905de196..449befe8bf3 100644 --- a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts +++ b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts @@ -89,8 +89,8 @@ export class UnencryptedL2Log { * Crates a random log. * @returns A random log. */ - public static random(): UnencryptedL2Log { - const contractAddress = AztecAddress.random(); + public static async random(): Promise { + const contractAddress = await AztecAddress.random(); const dataLength = randomBytes(1)[0]; const data = randomBytes(dataLength); return new UnencryptedL2Log(contractAddress, data); diff --git a/yarn-project/circuit-types/src/messaging/l1_to_l2_message.test.ts b/yarn-project/circuit-types/src/messaging/l1_to_l2_message.test.ts index 842d0b5428f..d9955d4ca84 100644 --- a/yarn-project/circuit-types/src/messaging/l1_to_l2_message.test.ts +++ b/yarn-project/circuit-types/src/messaging/l1_to_l2_message.test.ts @@ -1,8 +1,8 @@ import { L1ToL2Message } from './l1_to_l2_message.js'; describe('L1 to L2 message', () => { - it('can encode an L1 to L2 message to buffer and back', () => { - const msg = L1ToL2Message.random(); + it('can encode an L1 to L2 message to buffer and back', async () => { + const msg = await L1ToL2Message.random(); const buffer = msg.toBuffer(); const recovered = L1ToL2Message.fromBuffer(buffer); expect(recovered).toEqual(msg); diff --git a/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts b/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts index 3dc438940e2..582a386feb4 100644 --- a/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts +++ b/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts @@ -68,8 +68,8 @@ export class L1ToL2Message { return new L1ToL2Message(L1Actor.empty(), L2Actor.empty(), Fr.ZERO, Fr.ZERO, Fr.ZERO); } - static random(): L1ToL2Message { - return new L1ToL2Message(L1Actor.random(), L2Actor.random(), Fr.random(), Fr.random(), Fr.random()); + static async random(): Promise { + return new L1ToL2Message(L1Actor.random(), await L2Actor.random(), Fr.random(), Fr.random(), Fr.random()); } } diff --git a/yarn-project/circuit-types/src/messaging/l2_actor.ts b/yarn-project/circuit-types/src/messaging/l2_actor.ts index 9581a454f1a..07d6af7cc82 100644 --- a/yarn-project/circuit-types/src/messaging/l2_actor.ts +++ b/yarn-project/circuit-types/src/messaging/l2_actor.ts @@ -37,7 +37,7 @@ export class L2Actor { return new L2Actor(aztecAddr, version); } - static random(): L2Actor { - return new L2Actor(AztecAddress.random(), randomInt(1000)); + static async random(): Promise { + return new L2Actor(await AztecAddress.random(), randomInt(1000)); } } diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 51797673d04..b67df5e0c93 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -162,13 +162,13 @@ export const mockTx = ( export const mockTxForRollup = (seed = 1) => mockTx(seed, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 0 }); -export const mockSimulatedTx = (seed = 1) => { +export const mockSimulatedTx = async (seed = 1) => { const privateExecutionResult = mockPrivateExecutionResult(seed); const tx = mockTx(seed); const output = new PublicSimulationOutput( undefined, makeCombinedConstantData(), - TxEffect.random(), + await TxEffect.random(), [accumulatePrivateReturnValues(privateExecutionResult)], { totalGas: makeGas(), @@ -209,39 +209,54 @@ export const randomContractArtifact = (): ContractArtifact => ({ notes: {}, }); -export const randomContractInstanceWithAddress = ( +export const randomContractInstanceWithAddress = async ( opts: { contractClassId?: Fr } = {}, address?: AztecAddress, -): ContractInstanceWithAddress => { - const instance = SerializableContractInstance.random(opts); +): Promise => { + const instance = await SerializableContractInstance.random(opts); return instance.withAddress(address ?? computeContractAddressFromInstance(instance)); }; -export const randomDeployedContract = () => { +export const randomDeployedContract = async () => { const artifact = randomContractArtifact(); const contractClassId = computeContractClassId(getContractClassFromArtifact(artifact)); - return { artifact, instance: randomContractInstanceWithAddress({ contractClassId }) }; + return { artifact, instance: await randomContractInstanceWithAddress({ contractClassId }) }; }; -export const randomExtendedNote = ({ +export const randomExtendedNote = async ({ note = Note.random(), - owner = AztecAddress.random(), - contractAddress = AztecAddress.random(), + owner = undefined, + contractAddress = undefined, txHash = randomTxHash(), storageSlot = Fr.random(), noteTypeId = NoteSelector.random(), }: Partial = {}) => { - return new ExtendedNote(note, owner, contractAddress, storageSlot, noteTypeId, txHash); + return new ExtendedNote( + note, + owner ?? (await AztecAddress.random()), + contractAddress ?? (await AztecAddress.random()), + storageSlot, + noteTypeId, + txHash, + ); }; -export const randomUniqueNote = ({ +export const randomUniqueNote = async ({ note = Note.random(), - owner = AztecAddress.random(), - contractAddress = AztecAddress.random(), + owner = undefined, + contractAddress = undefined, txHash = randomTxHash(), storageSlot = Fr.random(), noteTypeId = NoteSelector.random(), nonce = Fr.random(), }: Partial = {}) => { - return new UniqueNote(note, owner, contractAddress, storageSlot, noteTypeId, txHash, nonce); + return new UniqueNote( + note, + owner ?? (await AztecAddress.random()), + contractAddress ?? (await AztecAddress.random()), + storageSlot, + noteTypeId, + txHash, + nonce, + ); }; diff --git a/yarn-project/circuit-types/src/notes/extended_note.test.ts b/yarn-project/circuit-types/src/notes/extended_note.test.ts index a5035cc5406..968b2a544be 100644 --- a/yarn-project/circuit-types/src/notes/extended_note.test.ts +++ b/yarn-project/circuit-types/src/notes/extended_note.test.ts @@ -6,8 +6,8 @@ import { ExtendedNote, UniqueNote } from './extended_note.js'; describe('ExtendedNote', () => { let note: ExtendedNote; - beforeEach(() => { - note = randomExtendedNote(); + beforeEach(async () => { + note = await randomExtendedNote(); }); it('convert to and from buffer', () => { @@ -24,8 +24,8 @@ describe('ExtendedNote', () => { describe('UniqueNote', () => { let note: UniqueNote; - beforeEach(() => { - note = randomUniqueNote(); + beforeEach(async () => { + note = await randomUniqueNote(); }); it('convert to and from buffer', () => { diff --git a/yarn-project/circuit-types/src/notes/extended_note.ts b/yarn-project/circuit-types/src/notes/extended_note.ts index 85c8bda5ed2..4b1d8b65d3e 100644 --- a/yarn-project/circuit-types/src/notes/extended_note.ts +++ b/yarn-project/circuit-types/src/notes/extended_note.ts @@ -75,11 +75,11 @@ export class ExtendedNote { return ExtendedNote.fromBuffer(hexToBuffer(str)); } - static random() { + static async random() { return new ExtendedNote( Note.random(), - AztecAddress.random(), - AztecAddress.random(), + await AztecAddress.random(), + await AztecAddress.random(), Fr.random(), NoteSelector.random(), TxHash.random(), @@ -135,11 +135,11 @@ export class UniqueNote extends ExtendedNote { ]); } - static override random() { + static override async random() { return new UniqueNote( Note.random(), - AztecAddress.random(), - AztecAddress.random(), + await AztecAddress.random(), + await AztecAddress.random(), Fr.random(), NoteSelector.random(), TxHash.random(), diff --git a/yarn-project/circuit-types/src/private_execution_result.test.ts b/yarn-project/circuit-types/src/private_execution_result.test.ts index 32d3a6024d4..237b9c9086d 100644 --- a/yarn-project/circuit-types/src/private_execution_result.test.ts +++ b/yarn-project/circuit-types/src/private_execution_result.test.ts @@ -39,8 +39,8 @@ describe('execution_result', () => { }); describe('serialization', () => { - it('serializes and deserializes correctly', () => { - const instance = PrivateExecutionResult.random(); + it('serializes and deserializes correctly', async () => { + const instance = await PrivateExecutionResult.random(); jsonParseWithSchema; expect(jsonParseWithSchema(jsonStringify(instance), PrivateExecutionResult.schema)).toEqual(instance); }); diff --git a/yarn-project/circuit-types/src/private_execution_result.ts b/yarn-project/circuit-types/src/private_execution_result.ts index 5ac4a25b912..1f1a9b7e321 100644 --- a/yarn-project/circuit-types/src/private_execution_result.ts +++ b/yarn-project/circuit-types/src/private_execution_result.ts @@ -1,6 +1,6 @@ import { type IsEmpty, PrivateCircuitPublicInputs, sortByCounter } from '@aztec/circuits.js'; import { NoteSelector } from '@aztec/foundation/abi'; -import { times } from '@aztec/foundation/collection'; +import { timesParallel } from '@aztec/foundation/collection'; import { randomBytes, randomInt } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { type ZodFor, mapSchema, schemas } from '@aztec/foundation/schemas'; @@ -84,8 +84,8 @@ export class CountedPublicExecutionRequest { return this.request.isEmpty() && !this.counter; } - static random() { - return new CountedPublicExecutionRequest(PublicExecutionRequest.random(), 0); + static async random() { + return new CountedPublicExecutionRequest(await PublicExecutionRequest.random(), 0); } } @@ -109,8 +109,8 @@ export class PrivateExecutionResult { return new PrivateExecutionResult(fields.entrypoint, fields.firstNullifier); } - static random(nested = 1): PrivateExecutionResult { - return new PrivateExecutionResult(PrivateCallExecutionResult.random(nested), Fr.random()); + static async random(nested = 1): Promise { + return new PrivateExecutionResult(await PrivateCallExecutionResult.random(nested), Fr.random()); } } @@ -186,7 +186,7 @@ export class PrivateCallExecutionResult { ); } - static random(nested = 1): PrivateCallExecutionResult { + static async random(nested = 1): Promise { return new PrivateCallExecutionResult( randomBytes(4), randomBytes(4), @@ -196,10 +196,10 @@ export class PrivateCallExecutionResult { [NoteAndSlot.random()], new Map([[0, 0]]), [Fr.random()], - times(nested, () => PrivateCallExecutionResult.random(0)), - [CountedPublicExecutionRequest.random()], - PublicExecutionRequest.random(), - [new CountedContractClassLog(UnencryptedL2Log.random(), randomInt(10))], + await timesParallel(nested, () => PrivateCallExecutionResult.random(0)), + [await CountedPublicExecutionRequest.random()], + await PublicExecutionRequest.random(), + [new CountedContractClassLog(await UnencryptedL2Log.random(), randomInt(10))], ); } } diff --git a/yarn-project/circuit-types/src/public_execution_request.ts b/yarn-project/circuit-types/src/public_execution_request.ts index 6371bac3b09..6e386c3d888 100644 --- a/yarn-project/circuit-types/src/public_execution_request.ts +++ b/yarn-project/circuit-types/src/public_execution_request.ts @@ -57,8 +57,8 @@ export class PublicExecutionRequest { return new PublicExecutionRequest(CallContext.empty(), []); } - static random() { - return new PublicExecutionRequest(CallContext.random(), [Fr.random(), Fr.random()]); + static async random() { + return new PublicExecutionRequest(await CallContext.random(), [Fr.random(), Fr.random()]); } isEmpty(): boolean { diff --git a/yarn-project/circuit-types/src/simulation_error.ts b/yarn-project/circuit-types/src/simulation_error.ts index 735a7fd39d5..dc67b11d4d1 100644 --- a/yarn-project/circuit-types/src/simulation_error.ts +++ b/yarn-project/circuit-types/src/simulation_error.ts @@ -250,9 +250,9 @@ export class SimulationError extends Error { ); } - static random() { + static async random() { return new SimulationError('Random simulation error', [ - { contractAddress: AztecAddress.random(), functionSelector: FunctionSelector.random() }, + { contractAddress: await AztecAddress.random(), functionSelector: FunctionSelector.random() }, ]); } } diff --git a/yarn-project/circuit-types/src/tx/public_simulation_output.test.ts b/yarn-project/circuit-types/src/tx/public_simulation_output.test.ts index 8582164a408..84151682f58 100644 --- a/yarn-project/circuit-types/src/tx/public_simulation_output.test.ts +++ b/yarn-project/circuit-types/src/tx/public_simulation_output.test.ts @@ -3,8 +3,8 @@ import { jsonStringify } from '@aztec/foundation/json-rpc'; import { PublicSimulationOutput } from './public_simulation_output.js'; describe('PublicSimulationOutput', () => { - it('serializes to JSON', () => { - const output = PublicSimulationOutput.random(); + it('serializes to JSON', async () => { + const output = await PublicSimulationOutput.random(); const json = jsonStringify(output); expect(PublicSimulationOutput.schema.parse(JSON.parse(json))).toEqual(output); }); diff --git a/yarn-project/circuit-types/src/tx/public_simulation_output.ts b/yarn-project/circuit-types/src/tx/public_simulation_output.ts index 03b2fb9910d..0994cfcb92d 100644 --- a/yarn-project/circuit-types/src/tx/public_simulation_output.ts +++ b/yarn-project/circuit-types/src/tx/public_simulation_output.ts @@ -75,9 +75,9 @@ export class PublicSimulationOutput { ); } - static random() { + static async random() { return new PublicSimulationOutput( - SimulationError.random(), + await SimulationError.random(), CombinedConstantData.empty(), TxEffect.empty(), times(2, NestedProcessReturnValues.random), diff --git a/yarn-project/circuit-types/src/tx/simulated_tx.test.ts b/yarn-project/circuit-types/src/tx/simulated_tx.test.ts index a12a51e3452..a2d622b8b47 100644 --- a/yarn-project/circuit-types/src/tx/simulated_tx.test.ts +++ b/yarn-project/circuit-types/src/tx/simulated_tx.test.ts @@ -6,8 +6,8 @@ import { TxProvingResult, TxSimulationResult } from './simulated_tx.js'; describe('simulated_tx', () => { describe('TxSimulationResult', () => { let simulatedTx: TxSimulationResult; - beforeEach(() => { - simulatedTx = mockSimulatedTx(); + beforeEach(async () => { + simulatedTx = await mockSimulatedTx(); }); it('convert to and from json', () => { @@ -22,8 +22,8 @@ describe('simulated_tx', () => { describe('TxProvingResult', () => { let tx: TxProvingResult; - beforeEach(() => { - tx = TxProvingResult.random(); + beforeEach(async () => { + tx = await TxProvingResult.random(); }); it('convert to and from json', () => { diff --git a/yarn-project/circuit-types/src/tx/simulated_tx.ts b/yarn-project/circuit-types/src/tx/simulated_tx.ts index 737f3d45d2b..b68a90ab53b 100644 --- a/yarn-project/circuit-types/src/tx/simulated_tx.ts +++ b/yarn-project/circuit-types/src/tx/simulated_tx.ts @@ -102,11 +102,11 @@ export class TxSimulationResult extends PrivateSimulationResult { ); } - static random() { + static async random() { return new TxSimulationResult( - PrivateExecutionResult.random(), + await PrivateExecutionResult.random(), PrivateKernelTailCircuitPublicInputs.empty(), - PublicSimulationOutput.random(), + await PublicSimulationOutput.random(), ); } } @@ -147,9 +147,9 @@ export class TxProvingResult { return new TxProvingResult(fields.privateExecutionResult, fields.publicInputs, fields.clientIvcProof); } - static random() { + static async random() { return new TxProvingResult( - PrivateExecutionResult.random(), + await PrivateExecutionResult.random(), PrivateKernelTailCircuitPublicInputs.empty(), ClientIvcProof.empty(), ); diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index 0ed741bdf7a..53d7ee59da5 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -284,13 +284,13 @@ export class Tx extends Gossipable { return clonedTx; } - static random() { + static async random() { return new Tx( PrivateKernelTailCircuitPublicInputs.emptyWithNullifier(), ClientIvcProof.empty(), - ContractClassTxL2Logs.random(1, 1), - [PublicExecutionRequest.random()], - PublicExecutionRequest.random(), + await ContractClassTxL2Logs.random(1, 1), + [await PublicExecutionRequest.random()], + await PublicExecutionRequest.random(), ); } diff --git a/yarn-project/circuit-types/src/tx_effect.test.ts b/yarn-project/circuit-types/src/tx_effect.test.ts index c2c0b54d48d..d6bbcf9cd19 100644 --- a/yarn-project/circuit-types/src/tx_effect.test.ts +++ b/yarn-project/circuit-types/src/tx_effect.test.ts @@ -3,14 +3,14 @@ import { Fr } from '@aztec/circuits.js'; import { TxEffect } from './tx_effect.js'; describe('TxEffect', () => { - it('converts to and from buffer', () => { - const txEffect = TxEffect.random(); + it('converts to and from buffer', async () => { + const txEffect = await TxEffect.random(); const buf = txEffect.toBuffer(); expect(TxEffect.fromBuffer(buf)).toEqual(txEffect); }); - it('converts to and from fields', () => { - const txEffect = TxEffect.random(); + it('converts to and from fields', async () => { + const txEffect = await TxEffect.random(); const fields = txEffect.toBlobFields(); // TODO(#8954): When logs are refactored into fields, we won't need to inject them here expect(TxEffect.fromBlobFields(fields, txEffect.contractClassLogs)).toEqual(txEffect); @@ -22,21 +22,21 @@ describe('TxEffect', () => { expect(TxEffect.fromBlobFields(fields)).toEqual(txEffect); }); - it('fails with invalid fields', () => { - let txEffect = TxEffect.random(); + it('fails with invalid fields', async () => { + let txEffect = await TxEffect.random(); let fields = txEffect.toBlobFields(); // Replace the initial field with an invalid encoding fields[0] = new Fr(12); expect(() => TxEffect.fromBlobFields(fields)).toThrow('Invalid fields'); - txEffect = TxEffect.random(); + txEffect = await TxEffect.random(); fields = txEffect.toBlobFields(); // Add an extra field fields.push(new Fr(7)); // TODO(#8954): When logs are refactored into fields, we won't need to inject them here expect(() => TxEffect.fromBlobFields(fields, txEffect.contractClassLogs)).toThrow('Too many fields'); - txEffect = TxEffect.random(); + txEffect = await TxEffect.random(); fields = txEffect.toBlobFields(); const buf = Buffer.alloc(4); buf.writeUint8(6); diff --git a/yarn-project/circuit-types/src/tx_effect.ts b/yarn-project/circuit-types/src/tx_effect.ts index 1bd8f6713c2..59ce8624480 100644 --- a/yarn-project/circuit-types/src/tx_effect.ts +++ b/yarn-project/circuit-types/src/tx_effect.ts @@ -22,7 +22,7 @@ import { TX_FEE_PREFIX, TX_START_PREFIX, } from '@aztec/circuits.js'; -import { type FieldsOf, makeTuple } from '@aztec/foundation/array'; +import { type FieldsOf, makeTuple, makeTupleAsync } from '@aztec/foundation/array'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; import { padArrayEnd } from '@aztec/foundation/collection'; import { sha256Trunc } from '@aztec/foundation/crypto'; @@ -216,8 +216,8 @@ export class TxEffect { return thisLayer[0]; } - static random(numPublicCallsPerTx = 3, numPublicLogsPerCall = 1): TxEffect { - const contractClassLogs = ContractClassTxL2Logs.random(1, 1); + static async random(numPublicCallsPerTx = 3, numPublicLogsPerCall = 1): Promise { + const contractClassLogs = await ContractClassTxL2Logs.random(1, 1); return new TxEffect( RevertCode.random(), TxHash.random(), @@ -227,7 +227,7 @@ export class TxEffect { makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, Fr.random), makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, () => new PublicDataWrite(Fr.random(), Fr.random())), makeTuple(MAX_PRIVATE_LOGS_PER_TX, () => new PrivateLog(makeTuple(PRIVATE_LOG_SIZE_IN_FIELDS, Fr.random))), - makeTuple(numPublicCallsPerTx * numPublicLogsPerCall, PublicLog.random), + await makeTupleAsync(numPublicCallsPerTx * numPublicLogsPerCall, PublicLog.random), new Fr(contractClassLogs.getKernelLength()), contractClassLogs, ); diff --git a/yarn-project/circuit-types/src/tx_execution_request.test.ts b/yarn-project/circuit-types/src/tx_execution_request.test.ts index d1de9f1c4db..4fbe718f476 100644 --- a/yarn-project/circuit-types/src/tx_execution_request.test.ts +++ b/yarn-project/circuit-types/src/tx_execution_request.test.ts @@ -3,8 +3,8 @@ import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; import { TxExecutionRequest } from './tx_execution_request.js'; describe('TxExecutionRequest', () => { - it('serializes and deserializes', () => { - const request = TxExecutionRequest.random(); + it('serializes and deserializes', async () => { + const request = await TxExecutionRequest.random(); const json = jsonStringify(request); expect(jsonParseWithSchema(json, TxExecutionRequest.schema)).toEqual(request); }); diff --git a/yarn-project/circuit-types/src/tx_execution_request.ts b/yarn-project/circuit-types/src/tx_execution_request.ts index e554bc62bde..c40b0ddbde2 100644 --- a/yarn-project/circuit-types/src/tx_execution_request.ts +++ b/yarn-project/circuit-types/src/tx_execution_request.ts @@ -132,9 +132,9 @@ export class TxExecutionRequest { return TxExecutionRequest.fromBuffer(hexToBuffer(str)); } - static random() { + static async random() { return new TxExecutionRequest( - AztecAddress.random(), + await AztecAddress.random(), FunctionSelector.random(), Fr.random(), TxContext.empty(), diff --git a/yarn-project/circuits.js/src/contract/contract_instance.test.ts b/yarn-project/circuits.js/src/contract/contract_instance.test.ts index 86818076f93..2fbab0a8c70 100644 --- a/yarn-project/circuits.js/src/contract/contract_instance.test.ts +++ b/yarn-project/circuits.js/src/contract/contract_instance.test.ts @@ -1,8 +1,8 @@ import { SerializableContractInstance } from './contract_instance.js'; describe('ContractInstance', () => { - it('can serialize and deserialize an instance', () => { - const instance = SerializableContractInstance.random(); + it('can serialize and deserialize an instance', async () => { + const instance = await SerializableContractInstance.random(); expect(SerializableContractInstance.fromBuffer(instance.toBuffer())).toEqual(instance); }); }); diff --git a/yarn-project/circuits.js/src/contract/contract_instance.ts b/yarn-project/circuits.js/src/contract/contract_instance.ts index 9d60d1d7e4a..b84ff10253a 100644 --- a/yarn-project/circuits.js/src/contract/contract_instance.ts +++ b/yarn-project/circuits.js/src/contract/contract_instance.ts @@ -68,14 +68,14 @@ export class SerializableContractInstance { }); } - static random(opts: Partial> = {}) { + static async random(opts: Partial> = {}) { return new SerializableContractInstance({ version: VERSION, salt: Fr.random(), - deployer: AztecAddress.random(), + deployer: await AztecAddress.random(), contractClassId: Fr.random(), initializationHash: Fr.random(), - publicKeys: PublicKeys.random(), + publicKeys: await PublicKeys.random(), ...opts, }); } diff --git a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts index 3ede0df8bad..e04c5b725b9 100644 --- a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts @@ -18,7 +18,7 @@ import { import { buildNoteHashReadRequestHints } from './build_note_hash_read_request_hints.js'; describe('buildNoteHashReadRequestHints', () => { - const contractAddress = AztecAddress.random(); + let contractAddress: AztecAddress; const settledNoteHashes = [111, 222, 333]; const settledLeafIndexes = [1010n, 2020n, 3030n]; const oracle = { @@ -81,7 +81,8 @@ describe('buildNoteHashReadRequestHints', () => { futureNoteHashes, ); - beforeEach(() => { + beforeEach(async () => { + contractAddress = await AztecAddress.random(); noteHashReadRequests = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, i => makeNoteHash(getNoteHashValue(i))); noteHashLeafIndexMap = new Map(); diff --git a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts index a852769051e..5b1df7c425f 100644 --- a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts @@ -19,7 +19,7 @@ import { import { buildNullifierReadRequestHints } from './build_nullifier_read_request_hints.js'; describe('buildNullifierReadRequestHints', () => { - const contractAddress = AztecAddress.random(); + let contractAddress: AztecAddress; const settledNullifierInnerValue = 99999; const oracle = { getNullifierMembershipWitness: () => ({ membershipWitness: {}, leafPreimage: {} } as any), @@ -82,7 +82,8 @@ describe('buildNullifierReadRequestHints', () => { const buildHints = async () => await buildNullifierReadRequestHints(oracle, nullifierReadRequests, nullifiers, futureNullifiers); - beforeEach(() => { + beforeEach(async () => { + contractAddress = await AztecAddress.random(); nullifierReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, i => makeNullifier(innerNullifier(i))); expectedHints = NullifierReadRequestHintsBuilder.empty( diff --git a/yarn-project/circuits.js/src/keys/derivation.ts b/yarn-project/circuits.js/src/keys/derivation.ts index 032141f9842..39568d1fce6 100644 --- a/yarn-project/circuits.js/src/keys/derivation.ts +++ b/yarn-project/circuits.js/src/keys/derivation.ts @@ -124,10 +124,14 @@ export function deriveKeys(secretKey: Fr) { } // Returns shared tagging secret computed with Diffie-Hellman key exchange. -export function computeTaggingSecretPoint(knownAddress: CompleteAddress, ivsk: Fq, externalAddress: AztecAddress) { +export async function computeTaggingSecretPoint( + knownAddress: CompleteAddress, + ivsk: Fq, + externalAddress: AztecAddress, +) { const knownPreaddress = computePreaddress(knownAddress.publicKeys.hash(), knownAddress.partialAddress); // TODO: #8970 - Computation of address point from x coordinate might fail - const externalAddressPoint = externalAddress.toAddressPoint(); + const externalAddressPoint = await externalAddress.toAddressPoint(); const curve = new Grumpkin(); // Given A (known complete address) -> B (external address) and h == preaddress // Compute shared secret as S = (h_A + ivsk_A) * Addr_Point_B diff --git a/yarn-project/circuits.js/src/structs/avm/avm.test.ts b/yarn-project/circuits.js/src/structs/avm/avm.test.ts index 176aefb4c11..ced61219859 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.test.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.test.ts @@ -6,8 +6,8 @@ import { makeAvmCircuitInputs } from '../../tests/factories.js'; import { AvmCircuitInputs, serializeWithMessagePack } from './avm.js'; describe('Avm circuit inputs', () => { - it(`serializes to buffer and deserializes it back`, () => { - const avmCircuitInputs = makeAvmCircuitInputs(randomInt(2000)); + it(`serializes to buffer and deserializes it back`, async () => { + const avmCircuitInputs = await makeAvmCircuitInputs(randomInt(2000)); const buffer = avmCircuitInputs.toBuffer(); const res = AvmCircuitInputs.fromBuffer(buffer); expect(res).toEqual(avmCircuitInputs); diff --git a/yarn-project/circuits.js/src/structs/call_context.ts b/yarn-project/circuits.js/src/structs/call_context.ts index e16c6d1a96c..923b53d4934 100644 --- a/yarn-project/circuits.js/src/structs/call_context.ts +++ b/yarn-project/circuits.js/src/structs/call_context.ts @@ -41,10 +41,10 @@ export class CallContext { return new CallContext(AztecAddress.ZERO, AztecAddress.ZERO, FunctionSelector.empty(), false); } - static random() { + static async random() { return new CallContext( - AztecAddress.random(), - AztecAddress.random(), + await AztecAddress.random(), + await AztecAddress.random(), FunctionSelector.random(), Math.random() > 0.5, ); 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 a7f39f85bb9..4fda53c496f 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.test.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.test.ts @@ -5,15 +5,10 @@ import { PublicKeys } from '../types/public_keys.js'; import { CompleteAddress } from './complete_address.js'; describe('CompleteAddress', () => { - it('refuses to add an account with incorrect address for given partial address and pubkey', () => { - expect( - () => - new CompleteAddress( - AztecAddress.random(), - new PublicKeys(Point.random(), Point.random(), Point.random(), Point.random()), - Fr.random(), - ), - ).toThrow(/cannot be derived/); + 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()), + ).rejects.toThrow(/cannot be derived/); }); it('equals returns true when 2 instances are equal', () => { diff --git a/yarn-project/circuits.js/src/structs/key_validation_request.ts b/yarn-project/circuits.js/src/structs/key_validation_request.ts index 4fb96fabd0e..eb2e6ccf4d3 100644 --- a/yarn-project/circuits.js/src/structs/key_validation_request.ts +++ b/yarn-project/circuits.js/src/structs/key_validation_request.ts @@ -58,7 +58,7 @@ export class KeyValidationRequest { return new KeyValidationRequest(Point.ZERO, Fr.ZERO); } - static random() { - return new KeyValidationRequest(Point.random(), Fr.random()); + static async random() { + return new KeyValidationRequest(await Point.random(), Fr.random()); } } diff --git a/yarn-project/circuits.js/src/structs/public_log.test.ts b/yarn-project/circuits.js/src/structs/public_log.test.ts index 19ec895a97a..c15dd126d89 100644 --- a/yarn-project/circuits.js/src/structs/public_log.test.ts +++ b/yarn-project/circuits.js/src/structs/public_log.test.ts @@ -4,8 +4,8 @@ import { PublicLog } from './public_log.js'; describe('PublicLog', () => { let log: PublicLog; - beforeAll(() => { - log = PublicLog.random(); + beforeAll(async () => { + log = await PublicLog.random(); }); it('serializes to buffer and deserializes it back', () => { diff --git a/yarn-project/circuits.js/src/structs/public_log.ts b/yarn-project/circuits.js/src/structs/public_log.ts index 7eb63da7516..70fa4a34eff 100644 --- a/yarn-project/circuits.js/src/structs/public_log.ts +++ b/yarn-project/circuits.js/src/structs/public_log.ts @@ -50,8 +50,8 @@ export class PublicLog { return new PublicLog(reader.readObject(AztecAddress), reader.readArray(PUBLIC_LOG_DATA_SIZE_IN_FIELDS, Fr)); } - static random() { - return new PublicLog(AztecAddress.random(), makeTuple(PUBLIC_LOG_DATA_SIZE_IN_FIELDS, Fr.random)); + static async random() { + return new PublicLog(await AztecAddress.random(), makeTuple(PUBLIC_LOG_DATA_SIZE_IN_FIELDS, Fr.random)); } equals(other: this) { diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 908778ea909..1919089f85d 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -1296,19 +1296,39 @@ export function makeArray(length: number, fn: (i: number) return Array.from({ length }, (_: any, i: number) => fn(i + offset)); } +export function makeArrayAsync(length: number, fn: (i: number) => Promise, offset = 0) { + return Promise.all( + Array(length) + .fill(0) + .map((_: any, i: number) => fn(i + offset)), + ); +} + export function makeVector(length: number, fn: (i: number) => T, offset = 0) { return new Vector(makeArray(length, fn, offset)); } +export async function makeVectorAsync(length: number, fn: (i: number) => Promise, offset = 0) { + return new Vector(await makeArrayAsync(length, fn, offset)); +} + export function makeMap(size: number, fn: (i: number) => [string, T], offset = 0) { return new Map(makeArray(size, i => fn(i + offset))); } -export function makeContractInstanceFromClassId(classId: Fr, seed = 0): ContractInstanceWithAddress { +export async function makeMapAsync( + size: number, + fn: (i: number) => Promise<[string, T]>, + offset = 0, +) { + return new Map(await makeArrayAsync(size, i => fn(i + offset))); +} + +export async function makeContractInstanceFromClassId(classId: Fr, seed = 0): Promise { const salt = new Fr(seed); const initializationHash = new Fr(seed + 1); const deployer = new AztecAddress(new Fr(seed + 2)); - const publicKeys = PublicKeys.random(); + const publicKeys = await PublicKeys.random(); const saltedInitializationHash = poseidon2HashWithSeparator( [salt, initializationHash, deployer], @@ -1329,9 +1349,9 @@ export function makeContractInstanceFromClassId(classId: Fr, seed = 0): Contract }).withAddress(address); } -export function makeAvmBytecodeHints(seed = 0): AvmContractBytecodeHints { +export async function makeAvmBytecodeHints(seed = 0): Promise { const { artifactHash, privateFunctionsRoot, packedBytecode, id } = makeContractClassPublic(seed); - const instance = makeContractInstanceFromClassId(id, seed + 0x1000); + const instance = await makeContractInstanceFromClassId(id, seed + 0x1000); const avmHintInstance = new AvmContractInstanceHint( instance.address, @@ -1428,10 +1448,10 @@ export function makeAvmEnqueuedCallHint(seed = 0): AvmEnqueuedCallHint { * @param seed - The seed to use for generating the hints. * @returns the execution hints. */ -export function makeAvmExecutionHints( +export async function makeAvmExecutionHints( seed = 0, overrides: Partial> = {}, -): AvmExecutionHints { +): Promise { const lengthOffset = 10; const lengthSeedMod = 10; const baseLength = lengthOffset + (seed % lengthSeedMod); @@ -1439,10 +1459,10 @@ export function makeAvmExecutionHints( return AvmExecutionHints.from({ enqueuedCalls: makeVector(baseLength, makeAvmEnqueuedCallHint, seed + 0x4100), contractInstances: makeVector(baseLength + 5, makeAvmContractInstanceHint, seed + 0x4700), - contractBytecodeHints: makeMap( + contractBytecodeHints: await makeMapAsync( baseLength + 6, - i => { - const h = makeAvmBytecodeHints(i); + async i => { + const h = await makeAvmBytecodeHints(i); return [h.contractInstanceHint.address.toString(), h]; }, seed + 0x4900, @@ -1463,12 +1483,15 @@ export function makeAvmExecutionHints( * @param seed - The seed to use for generating the hints. * @returns the execution hints. */ -export function makeAvmCircuitInputs(seed = 0, overrides: Partial> = {}): AvmCircuitInputs { +export async function makeAvmCircuitInputs( + seed = 0, + overrides: Partial> = {}, +): Promise { return AvmCircuitInputs.from({ functionName: `function${seed}`, calldata: makeArray((seed % 100) + 10, i => new Fr(i), seed + 0x1000), publicInputs: PublicCircuitPublicInputs.empty(), - avmHints: makeAvmExecutionHints(seed + 0x3000), + avmHints: await makeAvmExecutionHints(seed + 0x3000), output: makeAvmCircuitPublicInputs(seed + 0x4000), ...overrides, }); diff --git a/yarn-project/circuits.js/src/types/public_keys.test.ts b/yarn-project/circuits.js/src/types/public_keys.test.ts index e8068ff6c31..0e0f2205ab4 100644 --- a/yarn-project/circuits.js/src/types/public_keys.test.ts +++ b/yarn-project/circuits.js/src/types/public_keys.test.ts @@ -4,8 +4,8 @@ import { updateInlineTestData } from '@aztec/foundation/testing/files'; import { PublicKeys } from './public_keys.js'; describe('PublicKeys', () => { - it('serialization and deserialization', () => { - const pk = PublicKeys.random(); + it('serialization and deserialization', async () => { + const pk = await PublicKeys.random(); const serialized = pk.toString(); const deserialized = PublicKeys.fromString(serialized); diff --git a/yarn-project/circuits.js/src/types/public_keys.ts b/yarn-project/circuits.js/src/types/public_keys.ts index 2faa0f7a488..70f4b26dcb2 100644 --- a/yarn-project/circuits.js/src/types/public_keys.ts +++ b/yarn-project/circuits.js/src/types/public_keys.ts @@ -84,8 +84,8 @@ export class PublicKeys { ); } - static random(): PublicKeys { - return new PublicKeys(Point.random(), Point.random(), Point.random(), Point.random()); + static async random(): Promise { + return new PublicKeys(await Point.random(), await Point.random(), await Point.random(), await Point.random()); } /** diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 1334d39aadf..2bd230a2399 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -183,7 +183,7 @@ describe('L1Publisher integration', () => { }); coinbase = config.coinbase || EthAddress.random(); - feeRecipient = config.feeRecipient || AztecAddress.random(); + feeRecipient = config.feeRecipient || (await AztecAddress.random()); const fork = await worldStateSynchronizer.fork(); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts index 5167717d5b3..569317987d8 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/access_control.test.ts @@ -72,7 +72,10 @@ describe('e2e_blacklist_token_contract access control', () => { it('set roles from non admin', async () => { const newRole = new Role().withAdmin().withAdmin(); await expect( - t.asset.withWallet(t.other).methods.update_roles(AztecAddress.random(), newRole.toNoirStruct()).prove(), + t.asset + .withWallet(t.other) + .methods.update_roles(await AztecAddress.random(), newRole.toNoirStruct()) + .prove(), ).rejects.toThrow(/Assertion failed: caller is not admin .*/); }); 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 e86a6f85af7..dc2afd3d7af 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 @@ -420,11 +420,13 @@ describe('e2e_block_building', () => { // compare logs expect(rct.status).toEqual('success'); - const noteValues = tx.data.getNonEmptyPrivateLogs().map(log => { - const notePayload = L1NotePayload.decryptAsIncoming(log, thisWallet.getEncryptionSecret()); - // In this test we care only about the privately delivered values - return notePayload?.privateNoteValues[0]; - }); + const noteValues = await Promise.all( + tx.data.getNonEmptyPrivateLogs().map(async log => { + const notePayload = await L1NotePayload.decryptAsIncoming(log, thisWallet.getEncryptionSecret()); + // In this test we care only about the privately delivered values + return notePayload?.privateNoteValues[0]; + }), + ); expect(noteValues[0]).toEqual(new Fr(10)); expect(noteValues[1]).toEqual(new Fr(11)); expect(noteValues[2]).toEqual(new Fr(12)); @@ -452,10 +454,10 @@ describe('e2e_block_building', () => { expect(privateLogs.length).toBe(3); // The first two logs are encrypted. - const event0 = L1EventPayload.decryptAsIncoming(privateLogs[0], thisWallet.getEncryptionSecret())!; + const event0 = (await L1EventPayload.decryptAsIncoming(privateLogs[0], thisWallet.getEncryptionSecret()))!; expect(event0.event.items).toEqual(values); - const event1 = L1EventPayload.decryptAsIncoming(privateLogs[1], thisWallet.getEncryptionSecret())!; + const event1 = (await L1EventPayload.decryptAsIncoming(privateLogs[1], thisWallet.getEncryptionSecret()))!; expect(event1.event.items).toEqual(nestedValues); // The last log is not encrypted. 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 2700daebfbd..828a8ad4d55 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 @@ -144,7 +144,7 @@ describe('e2e_deploy_contract contract class registration', () => { const deployInstance = async (opts: { constructorName?: string; deployer?: AztecAddress } = {}) => { const initArgs = [wallet.getAddress(), wallet.getAddress(), 42] as StatefulContractCtorArgs; const salt = Fr.random(); - const publicKeys = PublicKeys.random(); + const publicKeys = await PublicKeys.random(); const instance = getContractInstanceFromDeployParams(artifact, { constructorArgs: initArgs, salt, @@ -203,7 +203,7 @@ describe('e2e_deploy_contract contract class registration', () => { }); it('calls a public function with no init check on the deployed instance', async () => { - const whom = AztecAddress.random(); + const whom = await AztecAddress.random(); await contract.methods .increment_public_value_no_init_check(whom, 10) .send({ skipPublicSimulation: true }) @@ -213,7 +213,7 @@ describe('e2e_deploy_contract contract class registration', () => { }); it('refuses to call a public function with init check if the instance is not initialized', async () => { - const whom = AztecAddress.random(); + const whom = await AztecAddress.random(); const receipt = await contract.methods .increment_public_value(whom, 10) .send({ skipPublicSimulation: true }) @@ -226,7 +226,7 @@ describe('e2e_deploy_contract contract class registration', () => { it('refuses to initialize the instance with wrong args via a private function', async () => { await expect( - contract.methods.constructor(AztecAddress.random(), AztecAddress.random(), 43).prove(), + contract.methods.constructor(await AztecAddress.random(), await AztecAddress.random(), 43).prove(), ).rejects.toThrow(/initialization hash does not match/i); }); @@ -235,7 +235,7 @@ describe('e2e_deploy_contract contract class registration', () => { .constructor(...initArgs) .send() .wait(); - const whom = AztecAddress.random(); + const whom = await AztecAddress.random(); await contract.methods.increment_public_value(whom, 10).send({ skipPublicSimulation: true }).wait(); const stored = await contract.methods.get_public_value(whom).simulate(); expect(stored).toEqual(10n); @@ -253,15 +253,17 @@ describe('e2e_deploy_contract contract class registration', () => { }); describe('using a public constructor', () => { - const ignoredArg = AztecAddress.random(); + let ignoredArg: AztecAddress; beforeAll(async () => { + ignoredArg = await AztecAddress.random(); + ({ instance, initArgs, contract } = await deployInstance({ constructorName: 'public_constructor', })); }); it('refuses to initialize the instance with wrong args via a public function', async () => { - const whom = AztecAddress.random(); + const whom = await AztecAddress.random(); const receipt = await contract.methods .public_constructor(whom, ignoredArg, 43) .send({ skipPublicSimulation: true }) @@ -275,7 +277,7 @@ describe('e2e_deploy_contract contract class registration', () => { .public_constructor(...initArgs) .send() .wait(); - const whom = AztecAddress.random(); + const whom = await AztecAddress.random(); await contract.methods.increment_public_value(whom, 10).send({ skipPublicSimulation: true }).wait(); const stored = await contract.methods.get_public_value(whom).simulate(); expect(stored).toEqual(10n); @@ -323,10 +325,10 @@ describe('e2e_deploy_contract contract class registration', () => { expect(tx.status).toEqual(TxStatus.APP_LOGIC_REVERTED); }); - it('refuses to deploy an instance from a different deployer', () => { + it('refuses to deploy an instance from a different deployer', async () => { const instance = getContractInstanceFromDeployParams(artifact, { - constructorArgs: [AztecAddress.random(), AztecAddress.random(), 42], - deployer: AztecAddress.random(), + constructorArgs: [await AztecAddress.random(), await AztecAddress.random(), 42], + deployer: await AztecAddress.random(), }); expect(() => deployInstance(wallet, instance)).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 6250c19b8e2..8ef0f519ce3 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 @@ -24,9 +24,10 @@ describe('e2e_deploy_contract deploy method', () => { let logger: Logger; let wallet: Wallet; - const ignoredArg = AztecAddress.random(); + let ignoredArg: AztecAddress; beforeAll(async () => { + ignoredArg = await AztecAddress.random(); ({ pxe, logger, wallet } = await t.setup()); }); 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 fae4cab3509..b5229455c80 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 @@ -8,6 +8,7 @@ import { } from '@aztec/aztec.js'; import { EventSelector } from '@aztec/foundation/abi'; import { makeTuple } from '@aztec/foundation/array'; +import { timesParallel } from '@aztec/foundation/collection'; import { type Tuple } from '@aztec/foundation/serialize'; import { type ExampleEvent0, type ExampleEvent1, TestLogContract } from '@aztec/noir-contracts.js/TestLog'; @@ -47,7 +48,10 @@ describe('Logs', () => { const privateLogs = txEffect!.data.privateLogs; expect(privateLogs.length).toBe(3); - const decryptedEvent0 = L1EventPayload.decryptAsIncoming(privateLogs[0], wallets[0].getEncryptionSecret())!; + const decryptedEvent0 = (await L1EventPayload.decryptAsIncoming( + privateLogs[0], + wallets[0].getEncryptionSecret(), + ))!; expect(decryptedEvent0.contractAddress).toStrictEqual(testLogContract.address); expect(decryptedEvent0.eventTypeId).toStrictEqual(EventSelector.fromSignature('ExampleEvent0(Field,Field)')); @@ -60,7 +64,10 @@ describe('Logs', () => { expect(event0?.value0).toStrictEqual(preimage[0].toBigInt()); expect(event0?.value1).toStrictEqual(preimage[1].toBigInt()); - const decryptedEvent1 = L1EventPayload.decryptAsIncoming(privateLogs[2], wallets[0].getEncryptionSecret())!; + const decryptedEvent1 = (await L1EventPayload.decryptAsIncoming( + privateLogs[2], + wallets[0].getEncryptionSecret(), + ))!; const event1Metadata = new EventMetadata(TestLogContract.events.ExampleEvent1); @@ -156,9 +163,7 @@ describe('Logs', () => { let i = 0; const firstTx = await testLogContract.methods.emit_unencrypted_events(preimage[i]).send().wait(); - await Promise.all( - [...new Array(3)].map(() => testLogContract.methods.emit_unencrypted_events(preimage[++i]).send().wait()), - ); + await timesParallel(3, () => testLogContract.methods.emit_unencrypted_events(preimage[++i]).send().wait()); const lastTx = await testLogContract.methods.emit_unencrypted_events(preimage[++i]).send().wait(); const collectedEvent0s = await wallets[0].getPublicEvents( diff --git a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts index 4bf31cc1a78..64ba4f22e9a 100644 --- a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts +++ b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts @@ -728,7 +728,7 @@ export const uniswapL1L2TestSuite = ( it("someone can't call swap_public on my behalf without approval", async () => { // Owner approves a a user to swap_public: - const approvedUser = AztecAddress.random(); + const approvedUser = await AztecAddress.random(); const nonceForWETHTransferApproval = new Fr(3n); const nonceForSwap = new Fr(3n); diff --git a/yarn-project/ethereum/src/deploy_l1_contracts.test.ts b/yarn-project/ethereum/src/deploy_l1_contracts.test.ts index 78eb3156480..d4bf7dff374 100644 --- a/yarn-project/ethereum/src/deploy_l1_contracts.test.ts +++ b/yarn-project/ethereum/src/deploy_l1_contracts.test.ts @@ -31,7 +31,7 @@ describe('deploy_l1_contracts', () => { vkTreeRoot = Fr.random(); protocolContractTreeRoot = Fr.random(); initialValidators = times(3, EthAddress.random); - l2FeeJuiceAddress = AztecAddress.random(); + l2FeeJuiceAddress = await AztecAddress.random(); ({ anvil, rpcUrl } = await startAnvil()); }); diff --git a/yarn-project/foundation/src/abi/encoder.test.ts b/yarn-project/foundation/src/abi/encoder.test.ts index 0b901d030ef..65ca6e66eb6 100644 --- a/yarn-project/foundation/src/abi/encoder.test.ts +++ b/yarn-project/foundation/src/abi/encoder.test.ts @@ -87,7 +87,7 @@ describe('abi/encoder', () => { expect(encodeArguments(abi, [str])).toEqual(expected); }); - it.each(['AztecAddress', 'EthAddress'])('accepts address instance for %s structs', (structType: string) => { + it.each(['AztecAddress', 'EthAddress'])('accepts address instance for %s structs', async (structType: string) => { const abi: FunctionAbi = { name: 'constructor', isInitializer: true, @@ -114,12 +114,12 @@ describe('abi/encoder', () => { errorTypes: {}, }; - const address = AztecAddress.random(); + const address = await AztecAddress.random(); expect(encodeArguments(abi, [address])).toEqual([address.toField()]); expect(encodeArguments(abi, [{ address }])).toEqual([address.toField()]); expect(encodeArguments(abi, [{ address: address.toField() }])).toEqual([address.toField()]); - const completeAddressLike = { address, publicKey: Point.random(), partialAddress: Fr.random() }; + const completeAddressLike = { address, publicKey: await Point.random(), partialAddress: Fr.random() }; expect(encodeArguments(abi, [completeAddressLike])).toEqual([address.toField()]); const serializedAddress = jsonParseWithSchema(jsonStringify(address), schemas.AztecAddress); diff --git a/yarn-project/foundation/src/array/array.ts b/yarn-project/foundation/src/array/array.ts index 8b1d7b73f93..b75e3db4242 100644 --- a/yarn-project/foundation/src/array/array.ts +++ b/yarn-project/foundation/src/array/array.ts @@ -27,6 +27,21 @@ export function makeTuple(length: N, fn: (i: number) => T, return Array.from({ length }, (_: any, i: number) => fn(i + offset)) as Tuple; } +/** + * Create an array over an integer range, filled with a function 'fn'. + * This is used over e.g. lodash because it resolved to a tuple type, needed for our fixed array type safety. + * @param n - The number of integers. + * @param fn - The generator function. + * @returns The array of numbers. + */ +export async function makeTupleAsync(length: N, fn: (i: number) => Promise, offset = 0) { + return (await Promise.all( + Array(length) + .fill(0) + .map(async (_: any, i: number) => await fn(i + offset)), + )) as Tuple; +} + /** * Create an array over an integer range, filled with a function 'fn'. However, the latter half of the array are set to zeros. * see `makeTuple` above. diff --git a/yarn-project/foundation/src/aztec-address/aztec-address.test.ts b/yarn-project/foundation/src/aztec-address/aztec-address.test.ts index d7009692275..8c1b0b0f9d2 100644 --- a/yarn-project/foundation/src/aztec-address/aztec-address.test.ts +++ b/yarn-project/foundation/src/aztec-address/aztec-address.test.ts @@ -3,32 +3,32 @@ import { AztecAddress } from './index.js'; describe('aztec-address', () => { describe('isValid', () => { - it('returns true for a valid address', () => { + it('returns true for a valid address', async () => { // The point (5, 21888242871839275195798879923479812031525119486506890092185616889232283231735) is on the // Grumpkin curve. const address = new AztecAddress(new Fr(5)); - expect(address.isValid()).toEqual(true); + expect(await address.isValid()).toEqual(true); }); - it('returns false for an invalid address', () => { + it('returns false for an invalid address', async () => { // No point on the Grumpkin curve has an x coordinate equal to 6. const address = new AztecAddress(new Fr(6)); - expect(address.isValid()).toEqual(false); + expect(await address.isValid()).toEqual(false); }); }); describe('random', () => { - it('always returns a valid address', () => { + it('always returns a valid address', async () => { for (let i = 0; i < 100; ++i) { - const address = AztecAddress.random(); - expect(address.isValid()).toEqual(true); + const address = await AztecAddress.random(); + expect(await address.isValid()).toEqual(true); } }); - it('returns a different address on each call', () => { + it('returns a different address on each call', async () => { const set = new Set(); for (let i = 0; i < 100; ++i) { - set.add(AztecAddress.random()); + set.add(await AztecAddress.random()); } expect(set.size).toEqual(100); @@ -36,15 +36,15 @@ describe('aztec-address', () => { }); describe('toAddressPoint', () => { - it("reconstructs an address's point", () => { - const address = AztecAddress.random(); - const point = address.toAddressPoint(); + it("reconstructs an address's point", async () => { + const address = await AztecAddress.random(); + const point = await address.toAddressPoint(); expect(point.isOnGrumpkin()).toEqual(true); }); - it('throws for an invalid address', () => { + it('throws for an invalid address', async () => { const address = new AztecAddress(new Fr(6)); - expect(() => address.toAddressPoint()).toThrow('The given x-coordinate is not on the Grumpkin curve'); + await expect(address.toAddressPoint()).rejects.toThrow('The given x-coordinate is not on the Grumpkin curve'); }); }); }); diff --git a/yarn-project/foundation/src/aztec-address/index.ts b/yarn-project/foundation/src/aztec-address/index.ts index fe965da95e1..48024ba159e 100644 --- a/yarn-project/foundation/src/aztec-address/index.ts +++ b/yarn-project/foundation/src/aztec-address/index.ts @@ -75,11 +75,11 @@ export class AztecAddress { /** * @returns a random valid address (i.e. one that can be encrypted to). */ - static random() { + static async random() { // About half of random field elements result in invalid addresses, so we loop until we get a valid one. while (true) { const candidate = new AztecAddress(Fr.random()); - if (candidate.isValid()) { + if (await candidate.isValid()) { return candidate; } } @@ -100,20 +100,20 @@ export class AztecAddress { /** * @returns true if the address is valid. Invalid addresses cannot receive encrypted messages. */ - isValid() { + async isValid() { // An address is a field value (Fr), which for some purposes is assumed to be the x coordinate of a point in the // Grumpkin curve (notably in order to encrypt to it). An address that is not the x coordinate of such a point is // called an 'invalid' address. // // For Grumpkin, y^2 = x^3 − 17 . There exist values x ∈ Fr for which no y satisfies this equation. This means that // given such an x and t = x^3 − 17, then sqrt(t) does not exist in Fr. - return Point.YFromX(this.xCoord) !== null; + return (await Point.YFromX(this.xCoord)) !== null; } /** * @returns the Point from which the address is derived. Throws if the address is invalid. */ - toAddressPoint() { + toAddressPoint(): Promise { return Point.fromXAndSign(this.xCoord, true); } diff --git a/yarn-project/foundation/src/collection/array.ts b/yarn-project/foundation/src/collection/array.ts index b430ceefb36..c27e3540287 100644 --- a/yarn-project/foundation/src/collection/array.ts +++ b/yarn-project/foundation/src/collection/array.ts @@ -89,6 +89,21 @@ export async function timesAsync(n: number, fn: (i: number) => Promise): P return results; } +/** + * Executes the given async function n times in parallel and returns the results in an array. + * @param n - How many times to repeat. + * @param fn - Mapper from index to value. + * @returns The array with the result from all executions. + */ +export async function timesParallel(n: number, fn: (i: number) => Promise): Promise { + const results: T[] = await Promise.all( + Array(n) + .fill(0) + .map((_, i) => fn(i)), + ); + return results; +} + /** * Returns the serialized size of all non-empty items in an array. * @param arr - Array diff --git a/yarn-project/foundation/src/fields/fields.test.ts b/yarn-project/foundation/src/fields/fields.test.ts index 7b8b4cd80d4..fa64b0b2911 100644 --- a/yarn-project/foundation/src/fields/fields.test.ts +++ b/yarn-project/foundation/src/fields/fields.test.ts @@ -227,8 +227,8 @@ describe('Bn254 arithmetic', () => { [new Fr(4), 2n], [new Fr(9), 3n], [new Fr(16), 4n], - ])('Should return the correct square root for %p', (input, expected) => { - const actual = input.sqrt()!.toBigInt(); + ])('Should return the correct square root for %p', async (input, expected) => { + const actual = (await input.sqrt())!.toBigInt(); // The square root can be either the expected value or the modulus - expected value const isValid = actual == expected || actual == Fr.MODULUS - expected; @@ -236,11 +236,11 @@ describe('Bn254 arithmetic', () => { expect(isValid).toBeTruthy(); }); - it('Should return the correct square root for random value', () => { + it('Should return the correct square root for random value', async () => { const a = Fr.random(); const squared = a.mul(a); - const actual = squared.sqrt(); + const actual = await squared.sqrt(); expect(actual!.mul(actual!)).toEqual(squared); }); }); diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 1b2072769fb..cd1cc15ccaf 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -1,4 +1,4 @@ -import { BarretenbergSync } from '@aztec/bb.js'; +import { BarretenbergLazy } from '@aztec/bb.js'; import { inspect } from 'util'; @@ -318,19 +318,16 @@ export class Fr extends BaseField { * Computes a square root of the field element. * @returns A square root of the field element (null if it does not exist). */ - sqrt(): Fr | null { - const wasm = BarretenbergSync.getSingleton().getWasm(); - wasm.writeMemory(0, this.toBuffer()); - wasm.call('bn254_fr_sqrt', 0, Fr.SIZE_IN_BYTES); - const isSqrtBuf = Buffer.from(wasm.getMemorySlice(Fr.SIZE_IN_BYTES, Fr.SIZE_IN_BYTES + 1)); - const isSqrt = isSqrtBuf[0] === 1; + async sqrt(): Promise { + const wasm = (await BarretenbergLazy.getSingleton()).getWasm(); + const [buf] = await wasm.callWasmExport('bn254_fr_sqrt', [this.toBuffer()], [Fr.SIZE_IN_BYTES * 2 + 1]); + const isSqrt = buf[0] === 1; if (!isSqrt) { // Field element is not a quadratic residue mod p so it has no square root. return null; } - - const rootBuf = Buffer.from(wasm.getMemorySlice(Fr.SIZE_IN_BYTES + 1, Fr.SIZE_IN_BYTES * 2 + 1)); - return Fr.fromBuffer(rootBuf); + const reader = BufferReader.asReader(buf.slice(1)); + return new Fr(reader.readBytes(Fr.SIZE_IN_BYTES)); } toJSON() { diff --git a/yarn-project/foundation/src/fields/point.test.ts b/yarn-project/foundation/src/fields/point.test.ts index f7650b38da0..f969da13303 100644 --- a/yarn-project/foundation/src/fields/point.test.ts +++ b/yarn-project/foundation/src/fields/point.test.ts @@ -6,24 +6,24 @@ import { Point } from './point.js'; describe('Point', () => { describe('random', () => { - it('always returns a valid point', () => { + it('always returns a valid point', async () => { for (let i = 0; i < 100; ++i) { - const point = Point.random(); + const point = await Point.random(); expect(point.isOnGrumpkin()).toEqual(true); } }); - it('returns a different points on each call', () => { + it('returns a different points on each call', async () => { const set = new Set(); for (let i = 0; i < 100; ++i) { - set.add(Point.random()); + set.add(await Point.random()); } expect(set.size).toEqual(100); }); }); - it('converts to and from x and sign of y coordinate', () => { + it('converts to and from x and sign of y coordinate', async () => { const p = new Point( new Fr(0x30426e64aee30e998c13c8ceecda3a77807dbead52bc2f3bf0eae851b4b710c1n), new Fr(0x113156a068f603023240c96b4da5474667db3b8711c521c748212a15bc034ea6n), @@ -31,21 +31,21 @@ describe('Point', () => { ); const [x, sign] = p.toXAndSign(); - const p2 = Point.fromXAndSign(x, sign); + const p2 = await Point.fromXAndSign(x, sign); expect(p.equals(p2)).toBeTruthy(); }); - it('converts to and from buffer', () => { - const p = Point.random(); + it('converts to and from buffer', async () => { + const p = await Point.random(); const p2 = Point.fromBuffer(p.toBuffer()); expect(p.equals(p2)).toBeTruthy(); }); - it('converts to and from compressed buffer', () => { - const p = Point.random(); - const p2 = Point.fromCompressedBuffer(p.toCompressedBuffer()); + it('converts to and from compressed buffer', async () => { + const p = await Point.random(); + const p2 = await Point.fromCompressedBuffer(p.toCompressedBuffer()); expect(p.equals(p2)).toBeTruthy(); }); @@ -92,8 +92,8 @@ describe('Point', () => { ); }); - it('serializes from and to JSON', () => { - const p = Point.random(); + it('serializes from and to JSON', async () => { + const p = await Point.random(); const p2 = jsonParseWithSchema(jsonStringify(p), schemas.Point); expect(p).toEqual(p2); expect(p2).toBeInstanceOf(Point); diff --git a/yarn-project/foundation/src/fields/point.ts b/yarn-project/foundation/src/fields/point.ts index e950998350b..a0f8ca8cc2b 100644 --- a/yarn-project/foundation/src/fields/point.ts +++ b/yarn-project/foundation/src/fields/point.ts @@ -50,10 +50,10 @@ export class Point { * * @returns A randomly generated Point instance. */ - static random() { + static async random() { while (true) { try { - return Point.fromXAndSign(Fr.random(), randomBoolean()); + return await Point.fromXAndSign(Fr.random(), randomBoolean()); } catch (e: any) { if (!(e instanceof NotOnCurveError)) { throw e; @@ -83,7 +83,7 @@ export class Point { * @param buffer - The buffer containing the x coordinate and the sign of the y coordinate. * @returns A Point instance. */ - static fromCompressedBuffer(buffer: Buffer | BufferReader) { + static fromCompressedBuffer(buffer: Buffer | BufferReader): Promise { const reader = BufferReader.asReader(buffer); const value = toBigIntBE(reader.readBytes(Point.COMPRESSED_SIZE_IN_BYTES)); @@ -127,8 +127,8 @@ export class Point { * Instead it is a boolean flag that determines whether the y coordinate is <= (Fr.MODULUS - 1) / 2 * @returns The point as an array of 2 fields */ - static fromXAndSign(x: Fr, sign: boolean) { - const y = Point.YFromX(x); + static async fromXAndSign(x: Fr, sign: boolean) { + const y = await Point.YFromX(x); if (y == null) { throw new NotOnCurveError(x); } @@ -146,7 +146,7 @@ export class Point { /** * @returns */ - static YFromX(x: Fr): Fr | null { + static YFromX(x: Fr): Promise { // Calculate y^2 = x^3 - 17 (i.e. the Grumpkin curve equation) const ySquared = x.square().mul(x).sub(new Fr(17)); diff --git a/yarn-project/foundation/src/serialize/type_registry.test.ts b/yarn-project/foundation/src/serialize/type_registry.test.ts index b77e96a837f..440c44aa7bc 100644 --- a/yarn-project/foundation/src/serialize/type_registry.test.ts +++ b/yarn-project/foundation/src/serialize/type_registry.test.ts @@ -14,11 +14,11 @@ describe('TypeRegistry', () => { expect(parsed.fr).toEqual({ type: 'Fr', value: data.fr.toString() }); }); - it('deserializes registered types in objects', () => { + it('deserializes registered types in objects', async () => { const data = { fr: Fr.random(), fq: Fq.random(), - aztecAddress: AztecAddress.random(), + aztecAddress: await AztecAddress.random(), ethAddress: EthAddress.random(), functionSelector: FunctionSelector.random(), noteSelector: NoteSelector.random(), @@ -36,11 +36,11 @@ describe('TypeRegistry', () => { expect(parsed.noteSelector).toBeInstanceOf(NoteSelector); }); - it('deserializes registered types in arrays', () => { + it('deserializes registered types in arrays', async () => { const data = [ Fr.random(), Fq.random(), - AztecAddress.random(), + await AztecAddress.random(), EthAddress.random(), FunctionSelector.random(), NoteSelector.random(), diff --git a/yarn-project/key-store/src/key_store.test.ts b/yarn-project/key-store/src/key_store.test.ts index 1435225b6de..67f161eb3e7 100644 --- a/yarn-project/key-store/src/key_store.test.ts +++ b/yarn-project/key-store/src/key_store.test.ts @@ -22,7 +22,7 @@ describe('KeyStore', () => { const { pkM: masterNullifierPublicKey } = await keyStore.getKeyValidationRequest( computedMasterNullifierPublicKeyHash, - AztecAddress.random(), // Address is random because we are not interested in the app secret key here + await AztecAddress.random(), // Address is random because we are not interested in the app secret key here ); expect(masterNullifierPublicKey.toString()).toMatchInlineSnapshot( `"0x1c088f4e4a711f236a88b55da9ddf388de0bc00d56a5ceca96cea3a5cbe75bf32db0a333ba30c36b844d9fc6d2fb0de8d10e4371f0c5baebae452d90ff366798"`, diff --git a/yarn-project/noir-protocol-circuits-types/src/conversion/type_conversion.test.ts b/yarn-project/noir-protocol-circuits-types/src/conversion/type_conversion.test.ts index 02fadc4d347..7f7960f318b 100644 --- a/yarn-project/noir-protocol-circuits-types/src/conversion/type_conversion.test.ts +++ b/yarn-project/noir-protocol-circuits-types/src/conversion/type_conversion.test.ts @@ -30,8 +30,8 @@ describe('Noir<>Circuits.js type conversion test suite', () => { expect(mapPointFromNoir(mapPointToNoir(point))).toEqual(point); }); - it('should map aztec addresses', () => { - const aztecAddress = AztecAddress.random(); + it('should map aztec addresses', async () => { + const aztecAddress = await AztecAddress.random(); expect(mapAztecAddressFromNoir(mapAztecAddressToNoir(aztecAddress))).toEqual(aztecAddress); }); diff --git a/yarn-project/p2p/src/client/p2p_client.test.ts b/yarn-project/p2p/src/client/p2p_client.test.ts index c3fdc989974..4dc69f6d7cb 100644 --- a/yarn-project/p2p/src/client/p2p_client.test.ts +++ b/yarn-project/p2p/src/client/p2p_client.test.ts @@ -25,7 +25,7 @@ describe('In-Memory P2P Client', () => { let kvStore: AztecKVStore; let client: P2PClient; - beforeEach(() => { + beforeEach(async () => { txPool = mock(); txPool.getAllTxs.mockReturnValue([]); txPool.getPendingTxHashes.mockReturnValue([]); @@ -40,7 +40,7 @@ describe('In-Memory P2P Client', () => { epochProofQuotePool.getQuotes.mockReturnValue([]); blockSource = new MockL2BlockSource(); - blockSource.createBlocks(100); + await blockSource.createBlocks(100); mempools = { txPool, @@ -225,7 +225,7 @@ describe('In-Memory P2P Client', () => { finalized: { number: 90, hash: expect.any(String) }, }); - blockSource.addBlocks([L2Block.random(91), L2Block.random(92)]); + blockSource.addBlocks([await L2Block.random(91), await L2Block.random(92)]); // give the client a chance to react to the new blocks await sleep(100); diff --git a/yarn-project/p2p/src/mocks/index.ts b/yarn-project/p2p/src/mocks/index.ts index 179288c4f83..8bebe47f3be 100644 --- a/yarn-project/p2p/src/mocks/index.ts +++ b/yarn-project/p2p/src/mocks/index.ts @@ -6,6 +6,7 @@ import { type WorldStateSynchronizer, } from '@aztec/circuit-types'; import { type EpochCache } from '@aztec/epoch-cache'; +import { timesParallel } from '@aztec/foundation/collection'; import { type DataStoreConfig } from '@aztec/kv-store/config'; import { openTmpStore } from '@aztec/kv-store/lmdb'; import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client'; @@ -170,8 +171,8 @@ export const MOCK_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = { * @param numberOfNodes - the number of nodes to create * @returns An array of the created nodes */ -export const createNodes = async (peerScoring: PeerScoring, numberOfNodes: number): Promise => { - return await Promise.all(Array.from({ length: numberOfNodes }, () => createReqResp(peerScoring))); +export const createNodes = (peerScoring: PeerScoring, numberOfNodes: number): Promise => { + return timesParallel(numberOfNodes, () => createReqResp(peerScoring)); }; export const startNodes = async ( diff --git a/yarn-project/p2p/src/msg_validators/tx_validator/data_validator.test.ts b/yarn-project/p2p/src/msg_validators/tx_validator/data_validator.test.ts index 894d0e970c7..52b97bb83a0 100644 --- a/yarn-project/p2p/src/msg_validators/tx_validator/data_validator.test.ts +++ b/yarn-project/p2p/src/msg_validators/tx_validator/data_validator.test.ts @@ -41,7 +41,7 @@ describe('TxDataValidator', () => { const badTxs = mockTxs(2); badTxs[0].data.forPublic!.nonRevertibleAccumulatedData.publicCallRequests[0].argsHash = Fr.random(); badTxs[1].data.forPublic!.nonRevertibleAccumulatedData.publicCallRequests[1].contractAddress = - AztecAddress.random(); + await AztecAddress.random(); await expectValid(goodTxs); @@ -52,8 +52,9 @@ describe('TxDataValidator', () => { it('rejects txs with mismatch revertible execution requests', async () => { const goodTxs = mockTxs(3); const badTxs = mockTxs(4); - badTxs[0].data.forPublic!.revertibleAccumulatedData.publicCallRequests[0].msgSender = AztecAddress.random(); - badTxs[1].data.forPublic!.revertibleAccumulatedData.publicCallRequests[1].contractAddress = AztecAddress.random(); + badTxs[0].data.forPublic!.revertibleAccumulatedData.publicCallRequests[0].msgSender = await AztecAddress.random(); + badTxs[1].data.forPublic!.revertibleAccumulatedData.publicCallRequests[1].contractAddress = + await AztecAddress.random(); badTxs[2].data.forPublic!.revertibleAccumulatedData.publicCallRequests[0].functionSelector = FunctionSelector.random(); badTxs[3].data.forPublic!.revertibleAccumulatedData.publicCallRequests[0].isStaticCall = @@ -70,8 +71,8 @@ describe('TxDataValidator', () => { it('rejects txs with mismatch teardown execution requests', async () => { const goodTxs = mockTxs(3); const badTxs = mockTxs(2); - badTxs[0].data.forPublic!.publicTeardownCallRequest.contractAddress = AztecAddress.random(); - badTxs[1].data.forPublic!.publicTeardownCallRequest.msgSender = AztecAddress.random(); + badTxs[0].data.forPublic!.publicTeardownCallRequest.contractAddress = await AztecAddress.random(); + badTxs[1].data.forPublic!.publicTeardownCallRequest.msgSender = await AztecAddress.random(); await expectValid(goodTxs); diff --git a/yarn-project/p2p/src/services/reqresp/reqresp.integration.test.ts b/yarn-project/p2p/src/services/reqresp/reqresp.integration.test.ts index 70e6c6b51ba..d69c0b3efed 100644 --- a/yarn-project/p2p/src/services/reqresp/reqresp.integration.test.ts +++ b/yarn-project/p2p/src/services/reqresp/reqresp.integration.test.ts @@ -117,7 +117,7 @@ describe('Req Resp p2p client integration', () => { } as P2PConfig & DataStoreConfig; l2BlockSource = new MockL2BlockSource(); - l2BlockSource.createBlocks(100); + await l2BlockSource.createBlocks(100); proofVerifier = alwaysTrueVerifier ? new AlwaysTrueCircuitVerifier() : new AlwaysFalseCircuitVerifier(); kvStore = openTmpStore(); diff --git a/yarn-project/p2p/src/services/reqresp/reqresp.test.ts b/yarn-project/p2p/src/services/reqresp/reqresp.test.ts index 220c682c83e..1090d2169c5 100644 --- a/yarn-project/p2p/src/services/reqresp/reqresp.test.ts +++ b/yarn-project/p2p/src/services/reqresp/reqresp.test.ts @@ -347,7 +347,7 @@ describe('ReqResp', () => { it('should handle block requests', async () => { const blockNumber = 1; const blockNumberFr = Fr.ONE; - const block = L2Block.random(blockNumber); + const block = await L2Block.random(blockNumber); const l2BlockSource: MockProxy = mock(); l2BlockSource.getBlock.mockImplementation((_blockNumber: number) => { diff --git a/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts b/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts index 22791753473..2169adb4f02 100644 --- a/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts +++ b/yarn-project/prover-client/src/prover-agent/agent-queue-rpc-integration.test.ts @@ -32,22 +32,22 @@ describe('Prover agent <-> queue integration', () => { let prover: ServerCircuitProver; type MakeInputs = { - [K in keyof ServerCircuitProver]: () => Parameters[0]; + [K in keyof ServerCircuitProver]: () => Promise[0]>; }; const makeInputs: MakeInputs = { getAvmProof: makeAvmCircuitInputs, - getBaseParityProof: makeBaseParityInputs, - getPrivateBaseRollupProof: makePrivateBaseRollupInputs, - getPublicBaseRollupProof: makePublicBaseRollupInputs, - getRootParityProof: makeRootParityInputs, - getBlockMergeRollupProof: makeBlockMergeRollupInputs, - getEmptyBlockRootRollupProof: makeEmptyBlockRootRollupInputs, - getBlockRootRollupProof: makeBlockRootRollupInputs, - getSingleTxBlockRootRollupProof: makeSingleTxBlockRootRollupInputs, - getMergeRollupProof: makeMergeRollupInputs, - getRootRollupProof: makeRootRollupInputs, - getTubeProof: () => new TubeInputs(ClientIvcProof.empty()), + getBaseParityProof: (...args) => Promise.resolve(makeBaseParityInputs(...args)), + getPrivateBaseRollupProof: (...args) => Promise.resolve(makePrivateBaseRollupInputs(...args)), + getPublicBaseRollupProof: (...args) => Promise.resolve(makePublicBaseRollupInputs(...args)), + getRootParityProof: (...args) => Promise.resolve(makeRootParityInputs(...args)), + getBlockMergeRollupProof: (...args) => Promise.resolve(makeBlockMergeRollupInputs(...args)), + getEmptyBlockRootRollupProof: (...args) => Promise.resolve(makeEmptyBlockRootRollupInputs(...args)), + getBlockRootRollupProof: (...args) => Promise.resolve(makeBlockRootRollupInputs(...args)), + getSingleTxBlockRootRollupProof: (...args) => Promise.resolve(makeSingleTxBlockRootRollupInputs(...args)), + getMergeRollupProof: (...args) => Promise.resolve(makeMergeRollupInputs(...args)), + getRootRollupProof: (...args) => Promise.resolve(makeRootRollupInputs(...args)), + getTubeProof: () => Promise.resolve(new TubeInputs(ClientIvcProof.empty())), }; beforeEach(async () => { @@ -72,7 +72,7 @@ describe('Prover agent <-> queue integration', () => { // TODO: This test hangs instead of failing when the Inputs are not registered on the RPC wrapper it.each(Object.entries(makeInputs))('can call %s over JSON-RPC', async (fnName, makeInputs) => { - const resp = await queue[fnName as keyof ServerCircuitProver](makeInputs() as any); + const resp = await queue[fnName as keyof ServerCircuitProver]((await makeInputs()) as any); expect(resp).toBeDefined(); }); }); diff --git a/yarn-project/prover-node/src/job/epoch-proving-job.test.ts b/yarn-project/prover-node/src/job/epoch-proving-job.test.ts index defb57872a3..a1bab2aa09e 100644 --- a/yarn-project/prover-node/src/job/epoch-proving-job.test.ts +++ b/yarn-project/prover-node/src/job/epoch-proving-job.test.ts @@ -10,7 +10,7 @@ import { } from '@aztec/circuit-types'; import { BlockHeader, Proof } from '@aztec/circuits.js'; import { RootRollupPublicInputs } from '@aztec/circuits.js/rollup'; -import { times } from '@aztec/foundation/collection'; +import { times, timesParallel } from '@aztec/foundation/collection'; import { sleep } from '@aztec/foundation/sleep'; import { type L1Publisher } from '@aztec/sequencer-client'; import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator/server'; @@ -65,7 +65,7 @@ describe('epoch-proving-job', () => { { parallelBlockLimit: opts.parallelBlockLimit ?? 32 }, ); - beforeEach(() => { + beforeEach(async () => { prover = mock(); publisher = mock(); l2BlockSource = mock(); @@ -80,7 +80,7 @@ describe('epoch-proving-job', () => { proof = Proof.empty(); epochNumber = 1; initialHeader = BlockHeader.empty(); - blocks = times(NUM_BLOCKS, i => L2Block.random(i + 1, TXS_PER_BLOCK)); + blocks = await timesParallel(NUM_BLOCKS, i => L2Block.random(i + 1, TXS_PER_BLOCK)); txs = times(NUM_TXS, i => mock({ getTxHash: () => blocks[i % NUM_BLOCKS].body.txEffects[i % TXS_PER_BLOCK].txHash, diff --git a/yarn-project/prover-node/src/prover-node.test.ts b/yarn-project/prover-node/src/prover-node.test.ts index ecc182fb6ff..1d210665a49 100644 --- a/yarn-project/prover-node/src/prover-node.test.ts +++ b/yarn-project/prover-node/src/prover-node.test.ts @@ -17,7 +17,7 @@ import { } from '@aztec/circuit-types'; import { type ContractDataSource, EthAddress } from '@aztec/circuits.js'; import { type EpochCache } from '@aztec/epoch-cache'; -import { times } from '@aztec/foundation/collection'; +import { times, timesParallel } from '@aztec/foundation/collection'; import { Signature } from '@aztec/foundation/eth-signature'; import { makeBackoff, retry } from '@aztec/foundation/retry'; import { sleep } from '@aztec/foundation/sleep'; @@ -103,7 +103,7 @@ describe('prover-node', () => { config, ); - beforeEach(() => { + beforeEach(async () => { prover = mock(); publisher = mock(); l2BlockSource = mock(); @@ -144,7 +144,7 @@ describe('prover-node', () => { quoteSigner.sign.mockImplementation(payload => Promise.resolve(new EpochProofQuote(payload, Signature.empty()))); // We create 3 fake blocks with 1 tx effect each - blocks = times(3, i => L2Block.random(i + 20, 1)); + blocks = await timesParallel(3, async i => await L2Block.random(i + 20, 1)); // Archiver returns a bunch of fake blocks l2BlockSource.getBlocksForEpoch.mockResolvedValue(blocks); diff --git a/yarn-project/prover-node/src/quote-provider/http.test.ts b/yarn-project/prover-node/src/quote-provider/http.test.ts index 2f498f5312e..cdb3829ba09 100644 --- a/yarn-project/prover-node/src/quote-provider/http.test.ts +++ b/yarn-project/prover-node/src/quote-provider/http.test.ts @@ -1,5 +1,5 @@ import { L2Block } from '@aztec/circuit-types'; -import { times } from '@aztec/foundation/collection'; +import { timesParallel } from '@aztec/foundation/collection'; import { promiseWithResolvers } from '@aztec/foundation/promise'; import { type Server, createServer } from 'http'; @@ -39,9 +39,9 @@ describe('HttpQuoteProvider', () => { port = (server.address() as AddressInfo).port; }); - beforeEach(() => { + beforeEach(async () => { provider = new HttpQuoteProvider(`http://127.0.0.1:${port}`); - blocks = times(3, i => L2Block.random(i + 1, 4)); + blocks = await timesParallel(3, i => L2Block.random(i + 1, 4)); response = { basisPointFee: 100, bondAmount: '100000000000000000000', validUntilSlot: '100' }; }); diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index a4f3a9129bc..e8872d4f128 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -10,7 +10,7 @@ import { } from '@aztec/circuits.js'; import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; -import { Fr } from '@aztec/foundation/fields'; +import { Fr, type Point } from '@aztec/foundation/fields'; import { toArray } from '@aztec/foundation/iterable'; import { type LogFn, createDebugOnlyLogger } from '@aztec/foundation/log'; import { @@ -297,7 +297,7 @@ export class KVPxeDatabase implements PxeDatabase { } async getNotes(filter: NotesFilter): Promise { - const publicKey: PublicKey | undefined = filter.owner ? filter.owner.toAddressPoint() : undefined; + const publicKey: PublicKey | undefined = filter.owner ? await filter.owner.toAddressPoint() : undefined; filter.status = filter.status ?? NoteStatus.ACTIVE; @@ -394,7 +394,7 @@ export class KVPxeDatabase implements PxeDatabase { return result; } - removeNullifiedNotes(nullifiers: InBlock[], accountAddressPoint: PublicKey): Promise { + removeNullifiedNotes(nullifiers: InBlock[], accountAddressPoint: Point): Promise { if (nullifiers.length === 0) { return Promise.resolve([]); } diff --git a/yarn-project/pxe/src/database/note_dao.test.ts b/yarn-project/pxe/src/database/note_dao.test.ts index 599519e310d..ff99f63c8bb 100644 --- a/yarn-project/pxe/src/database/note_dao.test.ts +++ b/yarn-project/pxe/src/database/note_dao.test.ts @@ -1,8 +1,8 @@ import { NoteDao } from './note_dao.js'; describe('Note DAO', () => { - it('convert to and from buffer', () => { - const note = NoteDao.random(); + it('convert to and from buffer', async () => { + const note = await NoteDao.random(); const buf = note.toBuffer(); expect(NoteDao.fromBuffer(buf)).toEqual(note); }); diff --git a/yarn-project/pxe/src/database/note_dao.ts b/yarn-project/pxe/src/database/note_dao.ts index 7c9e07d4c81..77b5ed85e80 100644 --- a/yarn-project/pxe/src/database/note_dao.ts +++ b/yarn-project/pxe/src/database/note_dao.ts @@ -127,9 +127,9 @@ export class NoteDao implements NoteData { return noteSize + AztecAddress.SIZE_IN_BYTES + Fr.SIZE_IN_BYTES * 4 + TxHash.SIZE + Point.SIZE_IN_BYTES + indexSize; } - static random({ + static async random({ note = Note.random(), - contractAddress = AztecAddress.random(), + contractAddress = undefined, storageSlot = Fr.random(), nonce = Fr.random(), noteHash = Fr.random(), @@ -138,12 +138,12 @@ export class NoteDao implements NoteData { l2BlockNumber = Math.floor(Math.random() * 1000), l2BlockHash = Fr.random().toString(), index = Fr.random().toBigInt(), - addressPoint = Point.random(), + addressPoint = undefined, noteTypeId = NoteSelector.random(), }: Partial = {}) { return new NoteDao( note, - contractAddress, + contractAddress ?? (await AztecAddress.random()), storageSlot, nonce, noteHash, @@ -152,7 +152,7 @@ export class NoteDao implements NoteData { l2BlockNumber, l2BlockHash, index, - addressPoint, + addressPoint ?? (await Point.random()), noteTypeId, ); } diff --git a/yarn-project/pxe/src/database/outgoing_note_dao.ts b/yarn-project/pxe/src/database/outgoing_note_dao.ts index 9cf40726d85..6d1d5117445 100644 --- a/yarn-project/pxe/src/database/outgoing_note_dao.ts +++ b/yarn-project/pxe/src/database/outgoing_note_dao.ts @@ -99,9 +99,9 @@ export class OutgoingNoteDao { return noteSize + AztecAddress.SIZE_IN_BYTES + Fr.SIZE_IN_BYTES * 2 + TxHash.SIZE + Point.SIZE_IN_BYTES; } - static random({ + static async random({ note = Note.random(), - contractAddress = AztecAddress.random(), + contractAddress = undefined, txHash = randomTxHash(), storageSlot = Fr.random(), noteTypeId = NoteSelector.random(), @@ -110,11 +110,11 @@ export class OutgoingNoteDao { l2BlockHash = Fr.random().toString(), noteHash = Fr.random(), index = Fr.random().toBigInt(), - ovpkM = Point.random(), + ovpkM = undefined, }: Partial = {}) { return new OutgoingNoteDao( note, - contractAddress, + contractAddress ?? (await AztecAddress.random()), storageSlot, noteTypeId, txHash, @@ -123,7 +123,7 @@ export class OutgoingNoteDao { nonce, noteHash, index, - ovpkM, + ovpkM ?? (await Point.random()), ); } } 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 a15a56bdf3a..ed315a9c376 100644 --- a/yarn-project/pxe/src/database/pxe_database_test_suite.ts +++ b/yarn-project/pxe/src/database/pxe_database_test_suite.ts @@ -8,11 +8,14 @@ import { } from '@aztec/circuits.js'; import { makeHeader } from '@aztec/circuits.js/testing'; import { FunctionType } from '@aztec/foundation/abi'; +import { timesParallel } from '@aztec/foundation/collection'; import { randomInt } from '@aztec/foundation/crypto'; import { Fr, Point } from '@aztec/foundation/fields'; import { BenchmarkingContractArtifact } from '@aztec/noir-contracts.js/Benchmarking'; import { TestContractArtifact } from '@aztec/noir-contracts.js/Test'; +import times from 'lodash.times'; + import { NoteDao } from './note_dao.js'; import { type PxeDatabase } from './pxe_database.js'; @@ -80,53 +83,62 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { let storageSlots: Fr[]; let notes: NoteDao[]; - const filteringTests: [() => NotesFilter, () => NoteDao[]][] = [ - [() => ({}), () => notes], + const filteringTests: [() => Promise, () => Promise][] = [ + [() => Promise.resolve({}), () => Promise.resolve(notes)], [ - () => ({ contractAddress: contractAddresses[0] }), - () => notes.filter(note => note.contractAddress.equals(contractAddresses[0])), + () => Promise.resolve({ contractAddress: contractAddresses[0] }), + () => Promise.resolve(notes.filter(note => note.contractAddress.equals(contractAddresses[0]))), ], - [() => ({ contractAddress: AztecAddress.random() }), () => []], + [async () => ({ contractAddress: await AztecAddress.random() }), () => Promise.resolve([])], [ - () => ({ storageSlot: storageSlots[0] }), - () => notes.filter(note => note.storageSlot.equals(storageSlots[0])), + () => Promise.resolve({ storageSlot: storageSlots[0] }), + () => Promise.resolve(notes.filter(note => note.storageSlot.equals(storageSlots[0]))), ], - [() => ({ storageSlot: Fr.random() }), () => []], + [() => Promise.resolve({ storageSlot: Fr.random() }), () => Promise.resolve([])], - [() => ({ txHash: notes[0].txHash }), () => [notes[0]]], - [() => ({ txHash: randomTxHash() }), () => []], + [() => Promise.resolve({ txHash: notes[0].txHash }), () => Promise.resolve([notes[0]])], + [() => Promise.resolve({ txHash: randomTxHash() }), () => Promise.resolve([])], [ - () => ({ owner: owners[0].address }), - () => notes.filter(note => note.addressPoint.equals(owners[0].address.toAddressPoint())), + () => Promise.resolve({ owner: owners[0].address }), + async () => { + const ownerAddressPoint = await owners[0].address.toAddressPoint(); + return notes.filter(note => note.addressPoint.equals(ownerAddressPoint)); + }, ], [ - () => ({ contractAddress: contractAddresses[0], storageSlot: storageSlots[0] }), + () => Promise.resolve({ contractAddress: contractAddresses[0], storageSlot: storageSlots[0] }), () => - notes.filter( - note => note.contractAddress.equals(contractAddresses[0]) && note.storageSlot.equals(storageSlots[0]), + Promise.resolve( + notes.filter( + note => note.contractAddress.equals(contractAddresses[0]) && note.storageSlot.equals(storageSlots[0]), + ), ), ], - [() => ({ contractAddress: contractAddresses[0], storageSlot: storageSlots[1] }), () => []], + [ + () => Promise.resolve({ contractAddress: contractAddresses[0], storageSlot: storageSlots[1] }), + () => Promise.resolve([]), + ], ]; beforeEach(async () => { - owners = Array.from({ length: 2 }).map(() => CompleteAddress.random()); - contractAddresses = Array.from({ length: 2 }).map(() => AztecAddress.random()); - storageSlots = Array.from({ length: 2 }).map(() => Fr.random()); + owners = times(2, () => CompleteAddress.random()); + contractAddresses = await timesParallel(2, () => AztecAddress.random()); + storageSlots = times(2, () => Fr.random()); - notes = Array.from({ length: 10 }).map((_, i) => - NoteDao.random({ + notes = await timesParallel(10, async i => { + const addressPoint = await owners[i % owners.length].address.toAddressPoint(); + return NoteDao.random({ contractAddress: contractAddresses[i % contractAddresses.length], storageSlot: storageSlots[i % storageSlots.length], - addressPoint: owners[i % owners.length].address.toAddressPoint(), + addressPoint, index: BigInt(i), l2BlockNumber: i, - }), - ); + }); + }); for (const owner of owners) { await database.addCompleteAddress(owner); @@ -135,9 +147,9 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { it.each(filteringTests)('stores notes in bulk and retrieves notes', async (getFilter, getExpected) => { await database.addNotes(notes); - const returnedNotes = await database.getNotes(getFilter()); - - expect(returnedNotes.sort()).toEqual(getExpected().sort()); + const returnedNotes = await database.getNotes(await getFilter()); + const expected = await getExpected(); + expect(returnedNotes.sort()).toEqual(expected.sort()); }); it.each(filteringTests)('stores notes one by one and retrieves notes', async (getFilter, getExpected) => { @@ -145,9 +157,10 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { await database.addNote(note); } - const returnedNotes = await database.getNotes(getFilter()); + const returnedNotes = await database.getNotes(await getFilter()); - expect(returnedNotes.sort()).toEqual(getExpected().sort()); + const expected = await getExpected(); + expect(returnedNotes.sort()).toEqual(expected.sort()); }); it.each(filteringTests)('retrieves nullified notes', async (getFilter, getExpected) => { @@ -155,26 +168,25 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { // Nullify all notes and use the same filter as other test cases for (const owner of owners) { - const notesToNullify = notes.filter(note => note.addressPoint.equals(owner.address.toAddressPoint())); + const ownerAddressPoint = await owner.address.toAddressPoint(); + const notesToNullify = notes.filter(note => note.addressPoint.equals(ownerAddressPoint)); const nullifiers = notesToNullify.map(note => ({ data: note.siloedNullifier, l2BlockNumber: note.l2BlockNumber, l2BlockHash: note.l2BlockHash, })); - await expect(database.removeNullifiedNotes(nullifiers, owner.address.toAddressPoint())).resolves.toEqual( - notesToNullify, - ); + await expect(database.removeNullifiedNotes(nullifiers, ownerAddressPoint)).resolves.toEqual(notesToNullify); } - - await expect(database.getNotes({ ...getFilter(), status: NoteStatus.ACTIVE_OR_NULLIFIED })).resolves.toEqual( - getExpected(), - ); + const filter = await getFilter(); + const returnedNotes = await database.getNotes({ ...filter, status: NoteStatus.ACTIVE_OR_NULLIFIED }); + const expected = await getExpected(); + expect(returnedNotes.sort()).toEqual(expected.sort()); }); it('skips nullified notes by default or when requesting active', async () => { await database.addNotes(notes); - - const notesToNullify = notes.filter(note => note.addressPoint.equals(owners[0].address.toAddressPoint())); + const ownerAddressPoint = await owners[0].address.toAddressPoint(); + const notesToNullify = notes.filter(note => note.addressPoint.equals(ownerAddressPoint)); const nullifiers = notesToNullify.map(note => ({ data: note.siloedNullifier, l2BlockNumber: note.l2BlockNumber, @@ -194,8 +206,9 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { it('handles note unnullification', async () => { await database.setHeader(makeHeader(randomInt(1000), 100, 0 /** slot number */)); await database.addNotes(notes); + const ownerAddressPoint = await owners[0].address.toAddressPoint(); - const notesToNullify = notes.filter(note => note.addressPoint.equals(owners[0].address.toAddressPoint())); + const notesToNullify = notes.filter(note => note.addressPoint.equals(ownerAddressPoint)); const nullifiers = notesToNullify.map(note => ({ data: note.siloedNullifier, l2BlockNumber: 99, @@ -213,8 +226,9 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { it('returns active and nullified notes when requesting either', async () => { await database.addNotes(notes); + const ownerAddressPoint = await owners[0].address.toAddressPoint(); - const notesToNullify = notes.filter(note => note.addressPoint.equals(owners[0].address.toAddressPoint())); + const notesToNullify = notes.filter(note => note.addressPoint.equals(ownerAddressPoint)); const nullifiers = notesToNullify.map(note => ({ data: note.siloedNullifier, l2BlockNumber: note.l2BlockNumber, @@ -275,7 +289,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { scopes: [owners[1].address], }), ).resolves.toEqual([notes[0]]); - + const ownerAddressPoint = await owners[0].address.toAddressPoint(); await expect( database.removeNullifiedNotes( [ @@ -285,7 +299,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { l2BlockNumber: notes[0].l2BlockNumber, }, ], - owners[0].address.toAddressPoint(), + ownerAddressPoint, ), ).resolves.toEqual([notes[0]]); @@ -340,7 +354,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { const address = CompleteAddress.random(); const otherAddress = new CompleteAddress( address.address, - new PublicKeys(Point.random(), Point.random(), Point.random(), Point.random()), + new PublicKeys(await Point.random(), await Point.random(), await Point.random(), await Point.random()), address.partialAddress, ); @@ -399,8 +413,8 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { }); it('stores a contract instance', async () => { - const address = AztecAddress.random(); - const instance = SerializableContractInstance.random().withAddress(address); + const address = await AztecAddress.random(); + const instance = (await SerializableContractInstance.random()).withAddress(address); await database.addContractInstance(instance); await expect(database.getContractInstance(address)).resolves.toEqual(instance); }); @@ -409,9 +423,9 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { describe('contract non-volatile database', () => { let contract: AztecAddress; - beforeEach(() => { + beforeEach(async () => { // Setup mock contract address - contract = AztecAddress.random(); + contract = await AztecAddress.random(); }); it('stores and loads a single value', async () => { @@ -445,7 +459,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) { }); it('stores values for different contracts independently', async () => { - const anotherContract = AztecAddress.random(); + const anotherContract = await AztecAddress.random(); const slot = new Fr(1); const values1 = [new Fr(42)]; const values2 = [new Fr(100)]; diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index 98b4b452d26..2b53c5bc8b7 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -133,7 +133,7 @@ describe('Kernel Prover', () => { const prove = (executionResult: PrivateExecutionResult) => prover.prove(txRequest, executionResult); - beforeEach(() => { + beforeEach(async () => { txRequest = makeTxRequest(); oracle = mock(); @@ -142,7 +142,7 @@ describe('Kernel Prover', () => { oracle.getContractAddressPreimage.mockResolvedValue({ contractClassId: Fr.random(), - publicKeys: PublicKeys.random(), + publicKeys: await PublicKeys.random(), saltedInitializationHash: Fr.random(), }); oracle.getContractClassIdPreimage.mockResolvedValue({ diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 132d0387819..ef9d310206b 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -279,13 +279,15 @@ export class PXEService implements PXE { const extendedNotes = noteDaos.map(async dao => { let owner = filter.owner; if (owner === undefined) { - const completeAddresses = (await this.db.getCompleteAddresses()).find(completeAddress => - completeAddress.address.toAddressPoint().equals(dao.addressPoint), - ); - if (completeAddresses === undefined) { + const completeAddresses = await this.db.getCompleteAddresses(); + const completeAddressIndex = ( + await Promise.all(completeAddresses.map(completeAddresses => completeAddresses.address.toAddressPoint())) + ).findIndex(addressPoint => addressPoint.equals(dao.addressPoint)); + const completeAddress = completeAddresses[completeAddressIndex]; + if (completeAddress === undefined) { throw new Error(`Cannot find complete address for addressPoint ${dao.addressPoint.toString()}`); } - owner = completeAddresses.address; + owner = completeAddress.address; } return new UniqueNote( dao.note, @@ -358,7 +360,7 @@ export class PXEService implements PXE { l2BlockNumber, l2BlockHash, index, - owner.address.toAddressPoint(), + await owner.address.toAddressPoint(), note.noteTypeId, ), scope, @@ -403,7 +405,7 @@ export class PXEService implements PXE { l2BlockNumber, l2BlockHash, index, - note.owner.toAddressPoint(), + await note.owner.toAddressPoint(), note.noteTypeId, ), ); @@ -872,18 +874,22 @@ export class PXEService implements PXE { }), ); - const visibleEvents = privateLogs.flatMap(log => { - for (const sk of vsks) { - // TODO: Verify that the first field of the log is the tag siloed with contract address. - // Or use tags to query logs, like we do with notes. - const decryptedEvent = L1EventPayload.decryptAsIncoming(log, sk); - if (decryptedEvent !== undefined) { - return [decryptedEvent]; - } - } + const visibleEvents = ( + await Promise.all( + privateLogs.map(async log => { + for (const sk of vsks) { + // TODO: Verify that the first field of the log is the tag siloed with contract address. + // Or use tags to query logs, like we do with notes. + const decryptedEvent = await L1EventPayload.decryptAsIncoming(log, sk); + if (decryptedEvent !== undefined) { + return [decryptedEvent]; + } + } - return []; - }); + return []; + }), + ) + ).flat(); const decodedEvents = visibleEvents .map(visibleEvent => { diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index 3bfeb2973b6..8c79681aab9 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -91,7 +91,7 @@ describe('PXEService', () => { }); it('throws when submitting a tx with a nullifier of already settled tx', async () => { - const settledTx = TxEffect.random(); + const settledTx = await TxEffect.random(); const duplicateTx = mockTx(); node.getTxEffect.mockResolvedValue(randomInBlock(settledTx)); diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index 9a60012bf44..2995f5569a2 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -35,7 +35,7 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => }); it('successfully adds a contract', async () => { - const contracts = [randomDeployedContract(), randomDeployedContract()]; + const contracts = await Promise.all([randomDeployedContract(), randomDeployedContract()]); for (const contract of contracts) { await pxe.registerContract(contract); } @@ -49,7 +49,7 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => const artifact = randomContractArtifact(); const contractClass = getContractClassFromArtifact(artifact); const contractClassId = contractClass.id; - const instance = randomContractInstanceWithAddress({ contractClassId }); + const instance = await randomContractInstanceWithAddress({ contractClassId }); await pxe.registerContractClass(artifact); expect(await pxe.getContractClass(contractClassId)).toMatchObject( @@ -64,12 +64,12 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => const artifact = randomContractArtifact(); const contractClass = getContractClassFromArtifact(artifact); const contractClassId = contractClass.id; - const instance = randomContractInstanceWithAddress({ contractClassId }); + const instance = await randomContractInstanceWithAddress({ contractClassId }); await expect( pxe.registerContract({ instance: { ...instance, - address: AztecAddress.random(), + address: await AztecAddress.random(), }, artifact, }), @@ -77,13 +77,13 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => }); it('refuses to register a contract with a class that has not been registered', async () => { - const instance = randomContractInstanceWithAddress(); + const instance = await randomContractInstanceWithAddress(); await expect(pxe.registerContract({ instance })).rejects.toThrow(/Missing contract artifact/i); }); it('refuses to register a contract with an artifact with mismatching class id', async () => { const artifact = randomContractArtifact(); - const instance = randomContractInstanceWithAddress(); + const instance = await randomContractInstanceWithAddress(); await expect(pxe.registerContract({ instance, artifact })).rejects.toThrow(/Artifact does not match/i); }); @@ -91,7 +91,7 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => // a larger setup and it's sufficiently tested in the e2e tests. it('throws when getting public storage for non-existent contract', async () => { - const contract = AztecAddress.random(); + const contract = await AztecAddress.random(); await expect(async () => await pxe.getPublicStorageAt(contract, new Fr(0n))).rejects.toThrow( `Contract ${contract.toString()} is not deployed`, ); diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 736c137d5da..7d3ddc67c5d 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -330,7 +330,7 @@ export class SimulatorOracle implements DBOracle { async #calculateAppTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) { const senderCompleteAddress = await this.getCompleteAddress(sender); const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender); - const secretPoint = computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient); + const secretPoint = await computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient); // Silo the secret so it can't be used to track other app's notes const appSecret = poseidon2Hash([secretPoint.x, secretPoint.y, contractAddress]); return appSecret; @@ -357,10 +357,12 @@ export class SimulatorOracle implements DBOracle { const senders = [...(await this.db.getSenderAddresses()), ...(await this.keyStore.getAccounts())].filter( (address, index, self) => index === self.findIndex(otherAddress => otherAddress.equals(address)), ); - const appTaggingSecrets = senders.map(contact => { - const sharedSecret = computeTaggingSecretPoint(recipientCompleteAddress, recipientIvsk, contact); - return poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]); - }); + const appTaggingSecrets = await Promise.all( + senders.map(async contact => { + const sharedSecret = await computeTaggingSecretPoint(recipientCompleteAddress, recipientIvsk, contact); + return poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]); + }), + ); const indexes = await this.db.getTaggingSecretsIndexesAsRecipient(appTaggingSecrets); return appTaggingSecrets.map((secret, i) => new IndexedTaggingSecret(secret, indexes[i])); } @@ -614,8 +616,8 @@ export class SimulatorOracle implements DBOracle { for (const scopedLog of scopedLogs) { const payload = scopedLog.isFromPublic - ? L1NotePayload.decryptAsIncomingFromPublic(PublicLog.fromBuffer(scopedLog.logData), addressSecret) - : L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret); + ? await L1NotePayload.decryptAsIncomingFromPublic(PublicLog.fromBuffer(scopedLog.logData), addressSecret) + : await L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret); if (!payload) { this.log.verbose('Unable to decrypt log'); @@ -720,7 +722,7 @@ export class SimulatorOracle implements DBOracle { }) .filter(nullifier => nullifier !== undefined) as InBlock[]; - const nullifiedNotes = await this.db.removeNullifiedNotes(foundNullifiers, recipient.toAddressPoint()); + const nullifiedNotes = await this.db.removeNullifiedNotes(foundNullifiers, await recipient.toAddressPoint()); nullifiedNotes.forEach(noteDao => { this.log.verbose(`Removed note for contract ${noteDao.contractAddress} at slot ${noteDao.storageSlot}`, { contract: noteDao.contractAddress, @@ -770,7 +772,7 @@ export class SimulatorOracle implements DBOracle { blockNumber!, blockHash!.toString(), uniqueNoteHashTreeIndex, - recipient.toAddressPoint(), + await recipient.toAddressPoint(), NoteSelector.empty(), // todo: remove ); } 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 cea8f8dc319..c7de0ca3906 100644 --- a/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts +++ b/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts @@ -48,8 +48,12 @@ const NUM_NOTE_HASHES_PER_BLOCK = TXS_PER_BLOCK * MAX_NOTE_HASHES_PER_TX; jest.setTimeout(30_000); -function getRandomNoteLogPayload(tag = Fr.random(), app = AztecAddress.random()): EncryptedLogPayload { - return new EncryptedLogPayload(tag, app, L1NotePayload.random(app).toIncomingBodyPlaintext()); +async function getRandomNoteLogPayload(tag = Fr.random(), app?: AztecAddress): Promise { + return new EncryptedLogPayload( + tag, + app ?? (await AztecAddress.random()), + (await L1NotePayload.random(app)).toIncomingBodyPlaintext(), + ); } /** A wrapper containing info about a note we want to mock and insert into a block. */ @@ -77,9 +81,9 @@ class MockNoteRequest { } } - encrypt(): Buffer { + async encrypt(): Promise { const ephSk = GrumpkinScalar.random(); - const log = this.logPayload.generatePayload(ephSk, this.recipient); + const log = await this.logPayload.generatePayload(ephSk, this.recipient); return log.toBuffer(); } @@ -104,13 +108,13 @@ class MockNoteRequest { } } -function computeSiloedTagForIndex( +async function computeSiloedTagForIndex( sender: { completeAddress: CompleteAddress; ivsk: Fq }, recipient: AztecAddress, contractAddress: AztecAddress, index: number, ) { - const secretPoint = computeTaggingSecretPoint(sender.completeAddress, sender.ivsk, recipient); + const secretPoint = await computeTaggingSecretPoint(sender.completeAddress, sender.ivsk, recipient); const appSecret = poseidon2Hash([secretPoint.x, secretPoint.y, contractAddress]); const tag = poseidon2Hash([appSecret, recipient, index]); return poseidon2Hash([contractAddress, tag]); @@ -137,7 +141,7 @@ describe('Simulator oracle', () => { simulationProvider = new WASMSimulator(); simulatorOracle = new SimulatorOracle(contractDataOracle, database, keyStore, aztecNode, simulationProvider); // Set up contract address - contractAddress = AztecAddress.random(); + contractAddress = await AztecAddress.random(); // Set up recipient account recipient = await keyStore.addAccount(new Fr(69), Fr.random()); await database.addCompleteAddress(recipient); @@ -147,22 +151,22 @@ describe('Simulator oracle', () => { const NUM_SENDERS = 10; let senders: { completeAddress: CompleteAddress; ivsk: Fq; secretKey: Fr }[]; - function generateMockLogs(tagIndex: number) { + async function generateMockLogs(tagIndex: number) { const logs: { [k: string]: TxScopedL2Log[] } = {}; // Add a random note from every address in the address book for our account with index tagIndex // Compute the tag as sender (knowledge of preaddress and ivsk) for (const sender of senders) { - const tag = computeSiloedTagForIndex(sender, recipient.address, contractAddress, tagIndex); + const tag = await computeSiloedTagForIndex(sender, recipient.address, contractAddress, tagIndex); const blockNumber = 1; const randomNote = new MockNoteRequest( - getRandomNoteLogPayload(tag, contractAddress), + await getRandomNoteLogPayload(tag, contractAddress), blockNumber, 1, 1, recipient.address, ); - const log = new TxScopedL2Log(TxHash.random(), 0, blockNumber, false, randomNote.encrypt()); + const log = new TxScopedL2Log(TxHash.random(), 0, blockNumber, false, await randomNote.encrypt()); logs[tag.toString()] = [log]; } // Accumulated logs intended for recipient: NUM_SENDERS @@ -170,9 +174,9 @@ describe('Simulator oracle', () => { // Add a random note from the first sender in the address book, repeating the tag // Compute the tag as sender (knowledge of preaddress and ivsk) const firstSender = senders[0]; - const tag = computeSiloedTagForIndex(firstSender, recipient.address, contractAddress, tagIndex); - const payload = getRandomNoteLogPayload(tag, contractAddress); - const logData = payload.generatePayload(GrumpkinScalar.random(), recipient.address).toBuffer(); + const tag = await computeSiloedTagForIndex(firstSender, recipient.address, contractAddress, tagIndex); + const payload = await getRandomNoteLogPayload(tag, contractAddress); + const logData = (await payload.generatePayload(GrumpkinScalar.random(), recipient.address)).toBuffer(); const log = new TxScopedL2Log(TxHash.random(), 1, 0, false, logData); logs[tag.toString()].push(log); // Accumulated logs intended for recipient: NUM_SENDERS + 1 @@ -181,16 +185,16 @@ describe('Simulator oracle', () => { // Compute the tag as sender (knowledge of preaddress and ivsk) for (let i = NUM_SENDERS / 2; i < NUM_SENDERS; i++) { const sender = senders[i]; - const tag = computeSiloedTagForIndex(sender, recipient.address, contractAddress, tagIndex + 1); + const tag = await computeSiloedTagForIndex(sender, recipient.address, contractAddress, tagIndex + 1); const blockNumber = 2; const randomNote = new MockNoteRequest( - getRandomNoteLogPayload(tag, contractAddress), + await getRandomNoteLogPayload(tag, contractAddress), blockNumber, 1, 1, recipient.address, ); - const log = new TxScopedL2Log(TxHash.random(), 0, blockNumber, false, randomNote.encrypt()); + const log = new TxScopedL2Log(TxHash.random(), 0, blockNumber, false, await randomNote.encrypt()); logs[tag.toString()] = [log]; } // Accumulated logs intended for recipient: NUM_SENDERS + 1 + NUM_SENDERS / 2 @@ -201,22 +205,21 @@ describe('Simulator oracle', () => { const keys = deriveKeys(Fr.random()); const partialAddress = Fr.random(); const randomRecipient = computeAddress(keys.publicKeys, partialAddress); - const tag = computeSiloedTagForIndex(sender, randomRecipient, contractAddress, tagIndex); + const tag = await computeSiloedTagForIndex(sender, randomRecipient, contractAddress, tagIndex); const blockNumber = 3; const randomNote = new MockNoteRequest( - getRandomNoteLogPayload(tag, contractAddress), + await getRandomNoteLogPayload(tag, contractAddress), blockNumber, 1, 1, randomRecipient, ); - const log = new TxScopedL2Log(TxHash.random(), 0, blockNumber, false, randomNote.encrypt()); + const log = new TxScopedL2Log(TxHash.random(), 0, blockNumber, false, await randomNote.encrypt()); logs[tag.toString()] = [log]; } // Accumulated logs intended for recipient: NUM_SENDERS + 1 + NUM_SENDERS / 2 // Set up the getTaggedLogs mock - aztecNode.getLogsByTags.mockImplementation(tags => { return Promise.resolve(tags.map(tag => logs[tag.toString()] ?? [])); }); @@ -239,7 +242,7 @@ describe('Simulator oracle', () => { it('should sync tagged logs', async () => { const tagIndex = 0; - generateMockLogs(tagIndex); + await generateMockLogs(tagIndex); const syncedLogs = await simulatorOracle.syncTaggedLogs(contractAddress, 3); // We expect to have all logs intended for the recipient, one per sender + 1 with a duplicated tag for the first // one + half of the logs for the second index @@ -248,10 +251,16 @@ describe('Simulator oracle', () => { // Recompute the secrets (as recipient) to ensure indexes are updated const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); - const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); - }); + const secrets = await Promise.all( + senders.map(async sender => { + const firstSenderSecretPoint = await computeTaggingSecretPoint( + recipient, + ivsk, + sender.completeAddress.address, + ); + return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + }), + ); // First sender should have 2 logs, but keep index 1 since they were built using the same tag // Next 4 senders should also have index 1 = offset + 1 @@ -273,14 +282,20 @@ describe('Simulator oracle', () => { } let tagIndex = 0; - generateMockLogs(tagIndex); + await generateMockLogs(tagIndex); // Recompute the secrets (as recipient) to ensure indexes are updated const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); - const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); - }); + const secrets = await Promise.all( + senders.map(async sender => { + const firstSenderSecretPoint = await computeTaggingSecretPoint( + recipient, + ivsk, + sender.completeAddress.address, + ); + return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + }), + ); const indexesAsSender = await database.getTaggingSecretsIndexesAsSender(secrets); expect(indexesAsSender).toStrictEqual([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); @@ -305,7 +320,7 @@ describe('Simulator oracle', () => { // We add more logs to the second half of the window to test that a second iteration in `syncTaggedLogsAsSender` // is handled correctly. tagIndex = 11; - generateMockLogs(tagIndex); + await generateMockLogs(tagIndex); for (let i = 0; i < senders.length; i++) { await simulatorOracle.syncTaggedLogsAsSender( contractAddress, @@ -322,17 +337,23 @@ describe('Simulator oracle', () => { it('should sync tagged logs with a sender index offset', async () => { const tagIndex = 5; - generateMockLogs(tagIndex); + await generateMockLogs(tagIndex); const syncedLogs = await simulatorOracle.syncTaggedLogs(contractAddress, 3); // We expect to have all logs intended for the recipient, one per sender + 1 with a duplicated tag for the first one + half of the logs for the second index expect(syncedLogs.get(recipient.address.toString())).toHaveLength(NUM_SENDERS + 1 + NUM_SENDERS / 2); // Recompute the secrets (as recipient) to ensure indexes are updated const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); - const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); - }); + const secrets = await Promise.all( + senders.map(async sender => { + const firstSenderSecretPoint = await computeTaggingSecretPoint( + recipient, + ivsk, + sender.completeAddress.address, + ); + return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + }), + ); // First sender should have 2 logs, but keep index 1 since they were built using the same tag // Next 4 senders should also have index 6 = offset + 1 @@ -349,14 +370,20 @@ describe('Simulator oracle', () => { it("should sync tagged logs for which indexes are not updated if they're inside the window", async () => { const tagIndex = 1; - generateMockLogs(tagIndex); + await generateMockLogs(tagIndex); // Recompute the secrets (as recipient) to update indexes const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); - const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); - }); + const secrets = await Promise.all( + senders.map(async sender => { + const firstSenderSecretPoint = await computeTaggingSecretPoint( + recipient, + ivsk, + sender.completeAddress.address, + ); + return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + }), + ); // Increase our indexes to 2 await database.setTaggingSecretsIndexesAsRecipient(secrets.map(secret => new IndexedTaggingSecret(secret, 2))); @@ -382,14 +409,20 @@ describe('Simulator oracle', () => { it("should not sync tagged logs for which indexes are not updated if they're outside the window", async () => { const tagIndex = 0; - generateMockLogs(tagIndex); + await generateMockLogs(tagIndex); // Recompute the secrets (as recipient) to update indexes const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); - const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); - }); + const secrets = await Promise.all( + senders.map(async sender => { + const firstSenderSecretPoint = await computeTaggingSecretPoint( + recipient, + ivsk, + sender.completeAddress.address, + ); + return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + }), + ); // We set the indexes to WINDOW_HALF_SIZE + 1 so that it's outside the window and for this reason no updates // should be triggered. @@ -414,14 +447,20 @@ describe('Simulator oracle', () => { it('should sync tagged logs from scratch after a DB wipe', async () => { const tagIndex = 0; - generateMockLogs(tagIndex); + await generateMockLogs(tagIndex); // Recompute the secrets (as recipient) to update indexes const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); - const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); - }); + const secrets = await Promise.all( + senders.map(async sender => { + const firstSenderSecretPoint = await computeTaggingSecretPoint( + recipient, + ivsk, + sender.completeAddress.address, + ); + return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + }), + ); await database.setTaggingSecretsIndexesAsRecipient( secrets.map(secret => new IndexedTaggingSecret(secret, WINDOW_HALF_SIZE + 2)), @@ -457,7 +496,7 @@ describe('Simulator oracle', () => { it('should not sync tagged logs with a blockNumber > maxBlockNumber', async () => { const tagIndex = 0; - generateMockLogs(tagIndex); + await generateMockLogs(tagIndex); const syncedLogs = await simulatorOracle.syncTaggedLogs(contractAddress, 1); // Only NUM_SENDERS + 1 logs should be synched, since the rest have blockNumber > 1 @@ -466,7 +505,7 @@ describe('Simulator oracle', () => { it('should not sync public tagged logs with incorrect contract address', async () => { const logs: { [k: string]: TxScopedL2Log[] } = {}; - const tag = computeSiloedTagForIndex(senders[0], recipient.address, contractAddress, 0); + const tag = await computeSiloedTagForIndex(senders[0], recipient.address, contractAddress, 0); // Create a public log with an address which doesn't match the tag const logData = PublicLog.fromFields([ AztecAddress.fromNumber(2).toField(), @@ -511,7 +550,7 @@ describe('Simulator oracle', () => { }; // Set up contract instance and artifact - const contractInstance = randomContractInstanceWithAddress(); + const contractInstance = await randomContractInstanceWithAddress(); const contractArtifact = randomContractArtifact(); contractArtifact.functions = [processLogFuncArtifact]; await database.addContractInstance(contractInstance); @@ -536,7 +575,7 @@ describe('Simulator oracle', () => { aztecNode.getTxEffect.mockReset(); }); - function mockTaggedLogs(requests: MockNoteRequest[], nullifiers: number = 0) { + async function mockTaggedLogs(requests: MockNoteRequest[], nullifiers: number = 0) { const txEffectsMap: { [k: string]: { noteHashes: Fr[]; txHash: TxHash; nullifiers: Fr[] } } = {}; const taggedLogs: TxScopedL2Log[] = []; const groupedByTx = requests.reduce<{ [i: number]: { [j: number]: MockNoteRequest[] } }>((acc, request) => { @@ -549,9 +588,9 @@ describe('Simulator oracle', () => { acc[request.blockNumber][request.txIndex].push(request); return acc; }, {}); - Object.keys(groupedByTx).forEach(blockNumberKey => { + for (const blockNumberKey in groupedByTx) { const blockNumber = parseInt(blockNumberKey); - Object.keys(groupedByTx[blockNumber]).forEach(txIndexKey => { + for (const txIndexKey in groupedByTx[blockNumber]) { const txIndex = parseInt(txIndexKey); const requestsInTx = groupedByTx[blockNumber][txIndex]; const maxNoteIndex = Math.max(...requestsInTx.map(request => request.noteHashIndex)); @@ -568,14 +607,14 @@ describe('Simulator oracle', () => { } const dataStartIndex = (request.blockNumber - 1) * NUM_NOTE_HASHES_PER_BLOCK + request.txIndex * MAX_NOTE_HASHES_PER_TX; - const taggedLog = new TxScopedL2Log(txHash, dataStartIndex, blockNumber, false, request.encrypt()); + const taggedLog = new TxScopedL2Log(txHash, dataStartIndex, blockNumber, false, await request.encrypt()); const note = request.snippetOfNoteDao.note; const noteHash = pedersenHash(note.items); txEffectsMap[txHash.toString()].noteHashes[request.noteHashIndex] = noteHash; taggedLogs.push(taggedLog); } - }); - }); + } + } aztecNode.getTxEffect.mockImplementation(txHash => { return Promise.resolve(randomInBlock(txEffectsMap[txHash.toString()] as TxEffect)); @@ -591,26 +630,26 @@ describe('Simulator oracle', () => { } it('should call processLog on multiple notes', async () => { const requests = [ - new MockNoteRequest(getRandomNoteLogPayload(Fr.random(), contractAddress), 1, 1, 1, recipient.address), + new MockNoteRequest(await getRandomNoteLogPayload(Fr.random(), contractAddress), 1, 1, 1, recipient.address), new MockNoteRequest( - getRandomNoteLogPayload(Fr.random(), contractAddress), + await getRandomNoteLogPayload(Fr.random(), contractAddress), 2, 3, 0, CompleteAddress.random().address, ), - new MockNoteRequest(getRandomNoteLogPayload(Fr.random(), contractAddress), 6, 3, 2, recipient.address), + new MockNoteRequest(await getRandomNoteLogPayload(Fr.random(), contractAddress), 6, 3, 2, recipient.address), new MockNoteRequest( - getRandomNoteLogPayload(Fr.random(), contractAddress), + await getRandomNoteLogPayload(Fr.random(), contractAddress), 9, 3, 2, CompleteAddress.random().address, ), - new MockNoteRequest(getRandomNoteLogPayload(Fr.random(), contractAddress), 12, 3, 2, recipient.address), + new MockNoteRequest(await getRandomNoteLogPayload(Fr.random(), contractAddress), 12, 3, 2, recipient.address), ]; - const taggedLogs = mockTaggedLogs(requests); + const taggedLogs = await mockTaggedLogs(requests); await simulatorOracle.processTaggedLogs(taggedLogs, recipient.address, simulator); @@ -622,11 +661,11 @@ 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(getRandomNoteLogPayload(), 2, 1, 1, CompleteAddress.random().address), - new MockNoteRequest(getRandomNoteLogPayload(), 2, 3, 0, CompleteAddress.random().address), + new MockNoteRequest(await getRandomNoteLogPayload(), 2, 1, 1, CompleteAddress.random().address), + new MockNoteRequest(await getRandomNoteLogPayload(), 2, 3, 0, CompleteAddress.random().address), ]; - const taggedLogs = mockTaggedLogs(requests); + const taggedLogs = await mockTaggedLogs(requests); await simulatorOracle.processTaggedLogs(taggedLogs, recipient.address, simulator); @@ -635,25 +674,28 @@ describe('Simulator oracle', () => { it('should remove nullified notes', async () => { const requests = [ - new MockNoteRequest(getRandomNoteLogPayload(Fr.random(), contractAddress), 1, 1, 1, recipient.address), - new MockNoteRequest(getRandomNoteLogPayload(Fr.random(), contractAddress), 6, 3, 2, recipient.address), - new MockNoteRequest(getRandomNoteLogPayload(Fr.random(), contractAddress), 12, 3, 2, recipient.address), + new MockNoteRequest(await getRandomNoteLogPayload(Fr.random(), contractAddress), 1, 1, 1, recipient.address), + new MockNoteRequest(await getRandomNoteLogPayload(Fr.random(), contractAddress), 6, 3, 2, recipient.address), + new MockNoteRequest(await getRandomNoteLogPayload(Fr.random(), contractAddress), 12, 3, 2, recipient.address), ]; getNotesSpy.mockResolvedValueOnce( Promise.resolve(requests.map(request => ({ siloedNullifier: Fr.random(), ...request.snippetOfNoteDao }))), ); let requestedNullifier; - aztecNode.findNullifiersIndexesWithBlock.mockImplementationOnce((_blockNumber, nullifiers) => { - const block = L2Block.random(2); + aztecNode.findNullifiersIndexesWithBlock.mockImplementationOnce(async (_blockNumber, nullifiers) => { + const block = await L2Block.random(2); requestedNullifier = wrapInBlock(nullifiers[0], block); - return Promise.resolve([wrapInBlock(1n, L2Block.random(2)), undefined, undefined]); + return [wrapInBlock(1n, await L2Block.random(2)), undefined, undefined]; }); await simulatorOracle.removeNullifiedNotes(contractAddress); expect(removeNullifiedNotesSpy).toHaveBeenCalledTimes(1); - expect(removeNullifiedNotesSpy).toHaveBeenCalledWith([requestedNullifier], recipient.address.toAddressPoint()); + expect(removeNullifiedNotesSpy).toHaveBeenCalledWith( + [requestedNullifier], + await recipient.address.toAddressPoint(), + ); }, 30_000); }); }); diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.test.ts b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts index a5cedf499cd..ac24ee43eb8 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.test.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts @@ -1,10 +1,10 @@ import { type AztecNode, L2Block, type L2BlockStream } from '@aztec/circuit-types'; +import { timesParallel } from '@aztec/foundation/collection'; import { openTmpStore } from '@aztec/kv-store/lmdb'; import { L2TipsStore } from '@aztec/kv-store/stores'; 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'; @@ -34,7 +34,7 @@ describe('Synchronizer', () => { }); it('sets header from latest block', async () => { - const block = L2Block.random(1, 4); + const block = await L2Block.random(1, 4); await synchronizer.handleBlockStreamEvent({ type: 'blocks-added', blocks: [block] }); const obtainedHeader = await database.getBlockHeader(); @@ -45,11 +45,14 @@ describe('Synchronizer', () => { const removeNotesAfter = jest.spyOn(database, 'removeNotesAfter').mockImplementation(() => Promise.resolve()); const unnullifyNotesAfter = jest.spyOn(database, 'unnullifyNotesAfter').mockImplementation(() => Promise.resolve()); const resetNoteSyncData = jest.spyOn(database, 'resetNoteSyncData').mockImplementation(() => Promise.resolve()); - aztecNode.getBlockHeader.mockImplementation(blockNumber => - Promise.resolve(L2Block.random(blockNumber as number).header), + aztecNode.getBlockHeader.mockImplementation( + async blockNumber => (await L2Block.random(blockNumber as number)).header, ); - await synchronizer.handleBlockStreamEvent({ type: 'blocks-added', blocks: times(5, L2Block.random) }); + await synchronizer.handleBlockStreamEvent({ + type: 'blocks-added', + blocks: await timesParallel(5, i => L2Block.random(i)), + }); await synchronizer.handleBlockStreamEvent({ type: 'chain-pruned', blockNumber: 3 }); expect(removeNotesAfter).toHaveBeenCalledWith(3); diff --git a/yarn-project/sequencer-client/src/config.test.ts b/yarn-project/sequencer-client/src/config.test.ts index 56f0dc464a9..e3fd9886903 100644 --- a/yarn-project/sequencer-client/src/config.test.ts +++ b/yarn-project/sequencer-client/src/config.test.ts @@ -3,9 +3,9 @@ import { AztecAddress, Fr, FunctionSelector } from '@aztec/circuits.js'; import { parseSequencerAllowList } from './config.js'; describe('sequencer config', () => { - it('parse a sequencer config', () => { - const instance = { address: AztecAddress.random() }; - const instanceFunction = { address: AztecAddress.random(), selector: FunctionSelector.random() }; + it('parse a sequencer config', async () => { + const instance = { address: await AztecAddress.random() }; + const instanceFunction = { address: await AztecAddress.random(), selector: FunctionSelector.random() }; const classId = { classId: Fr.random() }; const classFunction = { classId: Fr.random(), selector: FunctionSelector.random() }; diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts index 7f6e178fb82..0d2e668fef4 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts @@ -100,11 +100,11 @@ describe('L1Publisher', () => { const GAS_GUESS = 300_000n; - beforeEach(() => { + beforeEach(async () => { mockBlobSinkServer = undefined; blobSinkClient = new HttpBlobSinkClient(BLOB_SINK_URL); - l2Block = L2Block.random(42); + l2Block = await L2Block.random(42); header = l2Block.header.toBuffer(); archive = l2Block.archive.root.toBuffer(); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 1021f53b3e1..cd3debc369e 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -86,7 +86,7 @@ describe('sequencer', () => { const chainId = new Fr(12345); const version = Fr.ZERO; const coinbase = EthAddress.random(); - const feeRecipient = AztecAddress.random(); + let feeRecipient: AztecAddress; const gasFees = GasFees.empty(); const archive = Fr.random(); @@ -138,7 +138,8 @@ describe('sequencer', () => { }); }; - beforeEach(() => { + beforeEach(async () => { + feeRecipient = await AztecAddress.random(); initialBlockHeader = BlockHeader.empty(); lastBlockNumber = 0; newBlockNumber = lastBlockNumber + 1; diff --git a/yarn-project/sequencer-client/src/slasher/slasher_client.test.ts b/yarn-project/sequencer-client/src/slasher/slasher_client.test.ts index bb097b9da72..e379bcadd93 100644 --- a/yarn-project/sequencer-client/src/slasher/slasher_client.test.ts +++ b/yarn-project/sequencer-client/src/slasher/slasher_client.test.ts @@ -23,9 +23,9 @@ describe('In-Memory Slasher Client', () => { let client: SlasherClient; let config: SlasherConfig & L1ContractsConfig & L1ReaderConfig; - beforeEach(() => { + beforeEach(async () => { blockSource = new MockL2BlockSource(); - blockSource.createBlocks(100); + await blockSource.createBlocks(100); const l1Config = getL1ContractsConfigEnvVars(); @@ -105,7 +105,7 @@ describe('In-Memory Slasher Client', () => { finalized: { number: 90, hash: expect.any(String) }, }); - blockSource.addBlocks([L2Block.random(91), L2Block.random(92)]); + blockSource.addBlocks([await L2Block.random(91), await L2Block.random(92)]); // give the client a chance to react to the new blocks await sleep(100); diff --git a/yarn-project/sequencer-client/src/tx_validator/gas_validator.test.ts b/yarn-project/sequencer-client/src/tx_validator/gas_validator.test.ts index 07f67fdeb0b..50a8719f98d 100644 --- a/yarn-project/sequencer-client/src/tx_validator/gas_validator.test.ts +++ b/yarn-project/sequencer-client/src/tx_validator/gas_validator.test.ts @@ -22,7 +22,7 @@ describe('GasTxValidator', () => { let expectedBalanceSlot: Fr; let feeLimit: bigint; - beforeEach(() => { + beforeEach(async () => { publicStateSource = mock({ storageRead: mockFn().mockImplementation((_address: AztecAddress, _slot: Fr) => Fr.ZERO), }); @@ -31,7 +31,7 @@ describe('GasTxValidator', () => { gasFees = new GasFees(11, 22); tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 2 }); - tx.data.feePayer = AztecAddress.random(); + tx.data.feePayer = await AztecAddress.random(); tx.data.constants.txContext.gasSettings = GasSettings.default({ maxFeesPerGas: gasFees.clone() }); payer = tx.data.feePayer; expectedBalanceSlot = poseidon2Hash([FeeJuiceContract.storage.balances.slot, payer]); diff --git a/yarn-project/simulator/src/avm/avm_context.test.ts b/yarn-project/simulator/src/avm/avm_context.test.ts index 573adcb7eb1..4f381a6feb7 100644 --- a/yarn-project/simulator/src/avm/avm_context.test.ts +++ b/yarn-project/simulator/src/avm/avm_context.test.ts @@ -3,11 +3,11 @@ import { AztecAddress, Fr } from '@aztec/circuits.js'; import { allSameExcept, initContext } from './fixtures/index.js'; describe('Avm Context', () => { - it('New call should fork context correctly', () => { + it('New call should fork context correctly', async () => { const context = initContext(); context.machineState.pc = 20; - const newAddress = AztecAddress.random(); + const newAddress = await AztecAddress.random(); const newCalldata = [new Fr(1), new Fr(2)]; const allocatedGas = { l2Gas: 2, daGas: 3 }; // How much of the current call gas we pass to the nested call const newContext = context.createNestedContractCallContext(newAddress, newCalldata, allocatedGas, 'CALL'); @@ -32,11 +32,11 @@ describe('Avm Context', () => { expect(JSON.stringify(newContext.persistableState)).toEqual(JSON.stringify(context.persistableState.fork())); }); - it('New static call should fork context correctly', () => { + it('New static call should fork context correctly', async () => { const context = initContext(); context.machineState.pc = 20; - const newAddress = AztecAddress.random(); + const newAddress = await AztecAddress.random(); const newCalldata = [new Fr(1), new Fr(2)]; const allocatedGas = { l2Gas: 2, daGas: 3 }; const newContext = context.createNestedContractCallContext(newAddress, newCalldata, allocatedGas, 'STATICCALL'); diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 69e53f5e9bc..c83a668abee 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -34,6 +34,7 @@ import { MockedAvmTestContractDataSource, simulateAvmTestContractCall } from '.. import { type WorldStateDB } from '../public/public_db_sources.js'; import { type PublicSideEffectTraceInterface } from '../public/side_effect_trace_interface.js'; import { type AvmContext } from './avm_context.js'; +import { type AvmExecutionEnvironment } from './avm_execution_environment.js'; import { type MemoryValue, TypeTag, type Uint8, type Uint64 } from './avm_memory_types.js'; import { AvmSimulator } from './avm_simulator.js'; import { AvmEphemeralForest } from './avm_tree.js'; @@ -154,7 +155,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); it('call max unique contract classes', async () => { - const contractDataSource = new MockedAvmTestContractDataSource(); + const contractDataSource = await MockedAvmTestContractDataSource.create(); // args is initialized to MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS contract addresses with unique class IDs const args = Array.from(contractDataSource.contractInstances.values()) .map(instance => instance.address.toField()) @@ -172,7 +173,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); it('call too many unique contract classes fails', async () => { - const contractDataSource = new MockedAvmTestContractDataSource(); + const contractDataSource = await MockedAvmTestContractDataSource.create(); // args is initialized to MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS+1 contract addresses with unique class IDs // should fail because we are trying to call MAX+1 unique class IDs const args = Array.from(contractDataSource.contractInstances.values()).map(instance => instance.address.toField()); @@ -443,8 +444,11 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); describe('Environment getters', () => { - const address = AztecAddress.random(); - const sender = AztecAddress.random(); + let env: AvmExecutionEnvironment; + let context: AvmContext; + let address: AztecAddress; + let sender: AztecAddress; + const transactionFee = Fr.random(); const chainId = Fr.random(); const version = Fr.random(); @@ -453,35 +457,42 @@ describe('AVM simulator: transpiled Noir contracts', () => { const feePerDaGas = Fr.random(); const feePerL2Gas = Fr.random(); const gasFees = new GasFees(feePerDaGas, feePerL2Gas); - const globals = initGlobalVariables({ - chainId, - version, - blockNumber, - timestamp, - gasFees, - }); - const env = initExecutionEnvironment({ - address, - sender, - transactionFee, - globals, + + beforeAll(async () => { + address = await AztecAddress.random(); + sender = await AztecAddress.random(); + + const globals = initGlobalVariables({ + chainId, + version, + blockNumber, + timestamp, + gasFees, + }); + env = initExecutionEnvironment({ + address, + sender, + transactionFee, + globals, + }); }); - let context: AvmContext; + beforeEach(() => { context = initContext({ env }); }); it.each([ - ['address', address.toField(), 'get_address'], - ['sender', sender.toField(), 'get_sender'], - ['transactionFee', transactionFee.toField(), 'get_transaction_fee'], - ['chainId', chainId.toField(), 'get_chain_id'], - ['version', version.toField(), 'get_version'], - ['blockNumber', blockNumber.toField(), 'get_block_number'], - ['timestamp', timestamp.toField(), 'get_timestamp'], - ['feePerDaGas', feePerDaGas.toField(), 'get_fee_per_da_gas'], - ['feePerL2Gas', feePerL2Gas.toField(), 'get_fee_per_l2_gas'], - ])('%s getter', async (_name: string, value: Fr, functionName: string) => { + ['address', () => address.toField(), 'get_address'], + ['sender', () => sender.toField(), 'get_sender'], + ['transactionFee', () => transactionFee.toField(), 'get_transaction_fee'], + ['chainId', () => chainId.toField(), 'get_chain_id'], + ['version', () => version.toField(), 'get_version'], + ['blockNumber', () => blockNumber.toField(), 'get_block_number'], + ['timestamp', () => timestamp.toField(), 'get_timestamp'], + ['feePerDaGas', () => feePerDaGas.toField(), 'get_fee_per_da_gas'], + ['feePerL2Gas', () => feePerL2Gas.toField(), 'get_fee_per_l2_gas'], + ])('%s getter', async (_name: string, valueGetter: () => Fr, functionName: string) => { + const value = valueGetter(); const bytecode = getAvmTestContractBytecode(functionName); const results = await new AvmSimulator(context).executeBytecode(bytecode); @@ -919,7 +930,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { selector: FunctionSelector.random(), }); mockGetContractClass(worldStateDB, contractClass); - const contractInstance = makeContractInstanceFromClassId(contractClass.id); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id); mockGetContractInstance(worldStateDB, contractInstance); mockNullifierExists(worldStateDB, siloAddress(contractInstance.address)); @@ -943,7 +954,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { selector: FunctionSelector.random(), }); mockGetContractClass(worldStateDB, contractClass); - const contractInstance = makeContractInstanceFromClassId(contractClass.id); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id); mockGetContractInstance(worldStateDB, contractInstance); mockNullifierExists(worldStateDB, siloAddress(contractInstance.address)); @@ -970,7 +981,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { selector: FunctionSelector.random(), }); mockGetContractClass(worldStateDB, contractClass); - const contractInstance = makeContractInstanceFromClassId(contractClass.id); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id); mockGetContractInstance(worldStateDB, contractInstance); mockNullifierExists(worldStateDB, siloAddress(contractInstance.address)); @@ -992,7 +1003,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { selector: FunctionSelector.random(), }); mockGetContractClass(worldStateDB, contractClass); - const contractInstance = makeContractInstanceFromClassId(contractClass.id); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id); mockGetContractInstance(worldStateDB, contractInstance); mockNullifierExists(worldStateDB, siloAddress(contractInstance.address)); @@ -1022,7 +1033,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { selector: FunctionSelector.random(), }); mockGetContractClass(worldStateDB, contractClass); - const contractInstance = makeContractInstanceFromClassId(contractClass.id); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id); mockGetContractInstance(worldStateDB, contractInstance); mockNullifierExists(worldStateDB, siloAddress(contractInstance.address)); @@ -1047,7 +1058,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { selector: FunctionSelector.random(), }); mockGetContractClass(worldStateDB, contractClass); - const contractInstance = makeContractInstanceFromClassId(contractClass.id); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id); mockGetContractInstance(worldStateDB, contractInstance); mockNullifierExists(worldStateDB, siloAddress(contractInstance.address)); diff --git a/yarn-project/simulator/src/avm/journal/journal.test.ts b/yarn-project/simulator/src/avm/journal/journal.test.ts index afd936960e4..4fcfe104fcd 100644 --- a/yarn-project/simulator/src/avm/journal/journal.test.ts +++ b/yarn-project/simulator/src/avm/journal/journal.test.ts @@ -21,7 +21,7 @@ import { import { type AvmPersistableStateManager } from './journal.js'; describe('journal', () => { - const address = AztecAddress.random(); + let address: AztecAddress; const utxo = Fr.random(); const leafIndex = Fr.random(); @@ -29,7 +29,8 @@ describe('journal', () => { let trace: PublicSideEffectTraceInterface; let persistableState: AvmPersistableStateManager; - beforeEach(() => { + beforeEach(async () => { + address = await AztecAddress.random(); worldStateDB = mock(); trace = mock(); persistableState = initPersistableStateManager({ worldStateDB, trace }); diff --git a/yarn-project/simulator/src/avm/opcodes/contract.test.ts b/yarn-project/simulator/src/avm/opcodes/contract.test.ts index c1703f70b83..9311c9b3278 100644 --- a/yarn-project/simulator/src/avm/opcodes/contract.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/contract.test.ts @@ -12,18 +12,23 @@ import { mockGetContractInstance, mockNullifierExists } from '../test_utils.js'; import { ContractInstanceMember, GetContractInstance } from './contract.js'; describe('Contract opcodes', () => { - const address = AztecAddress.random(); - const contractInstance = SerializableContractInstance.random(); - const deployer = contractInstance.deployer; - const contractClassId = contractInstance.contractClassId; - const initializationHash = contractInstance.initializationHash; + let address: AztecAddress; + let contractInstance: SerializableContractInstance; + let deployer: AztecAddress; + let contractClassId: Fr; + let initializationHash: Fr; let worldStateDB: WorldStateDB; let trace: PublicSideEffectTraceInterface; let persistableState: AvmPersistableStateManager; let context: AvmContext; - beforeEach(() => { + beforeEach(async () => { + address = await AztecAddress.random(); + contractInstance = await SerializableContractInstance.random(); + deployer = contractInstance.deployer; + contractClassId = contractInstance.contractClassId; + initializationHash = contractInstance.initializationHash; worldStateDB = mock(); trace = mock(); persistableState = initPersistableStateManager({ worldStateDB, trace }); @@ -53,11 +58,12 @@ describe('Contract opcodes', () => { }); describe.each([ - [ContractInstanceMember.DEPLOYER, deployer.toField()], - [ContractInstanceMember.CLASS_ID, contractClassId.toField()], - [ContractInstanceMember.INIT_HASH, initializationHash.toField()], - ])('GETCONTRACTINSTANCE member instruction ', (memberEnum: ContractInstanceMember, value: Fr) => { + [ContractInstanceMember.DEPLOYER, () => deployer.toField()], + [ContractInstanceMember.CLASS_ID, () => contractClassId.toField()], + [ContractInstanceMember.INIT_HASH, () => initializationHash.toField()], + ])('GETCONTRACTINSTANCE member instruction ', (memberEnum: ContractInstanceMember, valueGetter: () => Fr) => { it(`Should read '${ContractInstanceMember[memberEnum]}' correctly`, async () => { + const value = valueGetter(); mockGetContractInstance(worldStateDB, contractInstance.withAddress(address)); mockNullifierExists(worldStateDB, address.toField()); diff --git a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts index 1ec8e0e0175..d0661db2417 100644 --- a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts @@ -10,9 +10,9 @@ import { initContext, initExecutionEnvironment, initGlobalVariables } from '../f import { Opcode } from '../serialization/instruction_serialization.js'; import { EnvironmentVariable, GetEnvVar } from './environment_getters.js'; +const address = await AztecAddress.random(); +const sender = await AztecAddress.random(); describe('Environment getters', () => { - const address = AztecAddress.random(); - const sender = AztecAddress.random(); const transactionFee = Fr.random(); const chainId = Fr.random(); const version = Fr.random(); @@ -29,15 +29,16 @@ describe('Environment getters', () => { timestamp, gasFees, }); - const env = initExecutionEnvironment({ - address, - sender, - transactionFee, - globals, - isStaticCall, - }); + let context: AvmContext; - beforeEach(() => { + beforeEach(async () => { + const env = initExecutionEnvironment({ + address, + sender, + transactionFee, + globals, + isStaticCall, + }); context = initContext({ env }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts index dbc32d22a9e..9f137f87dae 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts @@ -127,7 +127,7 @@ describe('External Calls', () => { selector: FunctionSelector.random(), }); mockGetContractClass(worldStateDB, contractClass); - const contractInstance = makeContractInstanceFromClassId(contractClass.id); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id); mockGetContractInstance(worldStateDB, contractInstance); mockNullifierExists(worldStateDB, contractInstance.address.toField()); @@ -180,7 +180,7 @@ describe('External Calls', () => { selector: FunctionSelector.random(), }); mockGetContractClass(worldStateDB, contractClass); - const contractInstance = makeContractInstanceFromClassId(contractClass.id); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id); mockGetContractInstance(worldStateDB, contractInstance); mockNullifierExists(worldStateDB, contractInstance.address.toField()); @@ -267,7 +267,7 @@ describe('External Calls', () => { selector: FunctionSelector.random(), }); mockGetContractClass(worldStateDB, contractClass); - const contractInstance = makeContractInstanceFromClassId(contractClass.id); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id); mockGetContractInstance(worldStateDB, contractInstance); const instruction = new StaticCall( diff --git a/yarn-project/simulator/src/avm/opcodes/storage.test.ts b/yarn-project/simulator/src/avm/opcodes/storage.test.ts index 4676771757d..7d9b435fd54 100644 --- a/yarn-project/simulator/src/avm/opcodes/storage.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/storage.test.ts @@ -13,9 +13,10 @@ import { SLoad, SStore } from './storage.js'; describe('Storage Instructions', () => { let context: AvmContext; let persistableState: MockProxy; - const address = AztecAddress.random(); + let address: AztecAddress; beforeEach(async () => { + address = await AztecAddress.random(); persistableState = mock(); context = initContext({ persistableState: persistableState, diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 57945ef2d20..af37a144f76 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -85,7 +85,7 @@ describe('Private Execution test suite', () => { let header = BlockHeader.empty(); let logger: Logger; - const defaultContractAddress = AztecAddress.random(); + let defaultContractAddress: AztecAddress; const ownerSk = Fr.fromHexString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); const recipientSk = Fr.fromHexString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec'); let owner: AztecAddress; @@ -113,7 +113,7 @@ describe('Private Execution test suite', () => { artifact, args = [], msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE), - contractAddress = defaultContractAddress, + contractAddress = undefined, txContext = {}, }: { artifact: FunctionArtifact; @@ -123,6 +123,7 @@ describe('Private Execution test suite', () => { txContext?: Partial>; }) => { const hashedArguments = HashedValues.fromValues(encodeArguments(artifact, args)); + contractAddress = contractAddress ?? defaultContractAddress; const txRequest = TxExecutionRequest.from({ origin: contractAddress, firstCallArgsHash: hashedArguments.hash, @@ -181,7 +182,7 @@ describe('Private Execution test suite', () => { return trees[name]; }; - beforeAll(() => { + beforeAll(async () => { logger = createLogger('simulator:test:private_execution'); const ownerPartialAddress = Fr.random(); @@ -194,6 +195,7 @@ describe('Private Execution test suite', () => { owner = ownerCompleteAddress.address; recipient = recipientCompleteAddress.address; + defaultContractAddress = await AztecAddress.random(); }); beforeEach(async () => { @@ -268,7 +270,7 @@ describe('Private Execution test suite', () => { describe('stateful test contract', () => { const valueNoteTypeId = StatefulTestContractArtifact.notes['ValueNote'].id; - const contractAddress = defaultContractAddress; + let contractAddress: AztecAddress; const mockFirstNullifier = new Fr(1111); let currentNoteIndex = 0n; @@ -298,7 +300,8 @@ describe('Private Execution test suite', () => { }; }; - beforeEach(() => { + beforeEach(async () => { + contractAddress = await AztecAddress.random(); oracle.getFunctionArtifactByName.mockImplementation((_, functionName: string) => Promise.resolve(getFunctionArtifact(StatefulTestContractArtifact, functionName)), ); @@ -382,7 +385,12 @@ describe('Private Execution test suite', () => { await insertLeaves(consumedNotes.map(n => n.uniqueNoteHash)); const args = [recipient, amountToTransfer]; - const { entrypoint: result, firstNullifier } = await runSimulator({ args, artifact, msgSender: owner }); + const { entrypoint: result, firstNullifier } = await runSimulator({ + args, + artifact, + msgSender: owner, + contractAddress, + }); // The two notes were nullified const nullifiers = getNonEmptyItems(result.publicInputs.nullifiers).map(n => n.value); @@ -442,7 +450,7 @@ describe('Private Execution test suite', () => { await insertLeaves(consumedNotes.map(n => n.uniqueNoteHash)); const args = [recipient, amountToTransfer]; - const { entrypoint: result } = await runSimulator({ args, artifact, msgSender: owner }); + const { entrypoint: result } = await runSimulator({ args, artifact, msgSender: owner, contractAddress }); const nullifiers = getNonEmptyItems(result.publicInputs.nullifiers).map(n => n.value); expect(nullifiers).toEqual(consumedNotes.map(n => n.innerNullifier)); @@ -471,8 +479,8 @@ describe('Private Execution test suite', () => { it('parent should call child', async () => { const childArtifact = getFunctionArtifact(ChildContractArtifact, 'value'); const parentArtifact = getFunctionArtifact(ParentContractArtifact, 'entry_point'); - const parentAddress = AztecAddress.random(); - const childAddress = AztecAddress.random(); + const parentAddress = await AztecAddress.random(); + const childAddress = await AztecAddress.random(); const childSelector = FunctionSelector.fromNameAndParameters(childArtifact.name, childArtifact.parameters); oracle.getFunctionArtifact.mockImplementation(() => Promise.resolve(childArtifact)); @@ -519,7 +527,7 @@ describe('Private Execution test suite', () => { }); it('test function should be callable through autogenerated interface', async () => { - const testAddress = AztecAddress.random(); + const testAddress = await AztecAddress.random(); const parentArtifact = getFunctionArtifact(ImportTestContractArtifact, 'main_contract'); const testCodeGenSelector = FunctionSelector.fromNameAndParameters( testCodeGenArtifact.name, @@ -540,8 +548,11 @@ describe('Private Execution test suite', () => { }); describe('consuming messages', () => { - const contractAddress = defaultContractAddress; + let contractAddress: AztecAddress; + beforeEach(async () => { + contractAddress = await AztecAddress.random(); + }); describe('L1 to L2', () => { const artifact = getFunctionArtifact(TestContractArtifact, 'consume_mint_to_private_message'); let bridgedAmount = 100n; @@ -627,7 +638,7 @@ describe('Private Execution test suite', () => { }); it('Invalid recipient', async () => { - crossChainMsgRecipient = AztecAddress.random(); + crossChainMsgRecipient = await AztecAddress.random(); preimage = computePreimage(); @@ -766,7 +777,7 @@ describe('Private Execution test suite', () => { }, ]); - const { entrypoint: result } = await runSimulator({ artifact, args: [secret] }); + const { entrypoint: result } = await runSimulator({ artifact, args: [secret], contractAddress }); // Check a nullifier has been inserted. const nullifiers = getNonEmptyItems(result.publicInputs.nullifiers); @@ -783,9 +794,9 @@ describe('Private Execution test suite', () => { const parentArtifact = getFunctionArtifact(ParentContractArtifact, 'enqueue_call_to_child'); const childContractArtifact = ChildContractArtifact.functions.find(fn => fn.name === 'public_dispatch')!; expect(childContractArtifact).toBeDefined(); - const childAddress = AztecAddress.random(); + const childAddress = await AztecAddress.random(); const childSelector = FunctionSelector.fromSignature('pub_set_value(Field)'); - const parentAddress = AztecAddress.random(); + const parentAddress = await AztecAddress.random(); oracle.getFunctionArtifact.mockImplementation(() => Promise.resolve({ ...childContractArtifact, isInternal })); @@ -831,14 +842,14 @@ describe('Private Execution test suite', () => { it('should default to not being a fee payer', async () => { // arbitrary random function that doesn't set a fee payer const entrypoint = getFunctionArtifact(TestContractArtifact, 'get_this_address'); - const contractAddress = AztecAddress.random(); + const contractAddress = await AztecAddress.random(); const { entrypoint: result } = await runSimulator({ artifact: entrypoint, contractAddress }); expect(result.publicInputs.isFeePayer).toBe(false); }); it('should be able to set a fee payer', async () => { const entrypoint = getFunctionArtifact(TestContractArtifact, 'test_setting_fee_payer'); - const contractAddress = AztecAddress.random(); + const contractAddress = await AztecAddress.random(); const { entrypoint: result } = await runSimulator({ artifact: entrypoint, contractAddress }); expect(result.publicInputs.isFeePayer).toBe(true); }); @@ -863,7 +874,7 @@ describe('Private Execution test suite', () => { const amountToTransfer = 100n; - const contractAddress = AztecAddress.random(); + const contractAddress = await AztecAddress.random(); const artifact = getFunctionArtifact(PendingNoteHashesContractArtifact, 'test_insert_then_get_then_nullify_flat'); const sender = owner; @@ -921,7 +932,7 @@ describe('Private Execution test suite', () => { const amountToTransfer = 100n; - const contractAddress = AztecAddress.random(); + const contractAddress = await AztecAddress.random(); const artifact = getFunctionArtifact( PendingNoteHashesContractArtifact, 'test_insert_then_get_then_nullify_all_in_nested_calls', @@ -994,7 +1005,7 @@ describe('Private Execution test suite', () => { const amountToTransfer = 100n; - const contractAddress = AztecAddress.random(); + const contractAddress = await AztecAddress.random(); const artifact = getFunctionArtifact(PendingNoteHashesContractArtifact, 'test_bad_get_then_insert_flat'); @@ -1041,7 +1052,7 @@ describe('Private Execution test suite', () => { describe('Context oracles', () => { it('this_address should return the current context address', async () => { - const contractAddress = AztecAddress.random(); + const contractAddress = await AztecAddress.random(); // Tweak the contract artifact so we can extract return values const artifact = getFunctionArtifact(TestContractArtifact, 'get_this_address'); diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index 2e243f400ac..18cf8df8085 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -22,14 +22,14 @@ describe('Simulator', () => { let contractAddress: AztecAddress; let appNullifierSecretKey: Fr; - beforeEach(() => { + beforeEach(async () => { const ownerSk = Fr.fromHexString('2dcc5485a58316776299be08c78fa3788a1a7961ae30dc747fb1be17692a8d32'); const allOwnerKeys = deriveKeys(ownerSk); ownerMasterNullifierPublicKey = allOwnerKeys.publicKeys.masterNullifierPublicKey; const ownerMasterNullifierSecretKey = allOwnerKeys.masterNullifierSecretKey; - contractAddress = AztecAddress.random(); + contractAddress = await AztecAddress.random(); const ownerPartialAddress = Fr.random(); const ownerCompleteAddress = CompleteAddress.fromSecretKeyAndPartialAddress(ownerSk, ownerPartialAddress); diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index ad270fc9864..b9ed1df73a8 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -51,7 +51,7 @@ describe('Unconstrained Execution test suite', () => { }); it('should run the summed_values function', async () => { - const contractAddress = AztecAddress.random(); + const contractAddress = await AztecAddress.random(); const artifact = StatefulTestContractArtifact.functions.find(f => f.name === 'summed_values')!; const notes: Note[] = [...Array(5).fill(buildNote(1n, owner)), ...Array(2).fill(buildNote(2n, owner))]; @@ -82,7 +82,7 @@ describe('Unconstrained Execution test suite', () => { returnTypes: artifact.returnTypes, }; - const result = await acirSimulator.runUnconstrained(execRequest, artifact, AztecAddress.random()); + const result = await acirSimulator.runUnconstrained(execRequest, artifact, await AztecAddress.random()); expect(result).toEqual(9n); }, 30_000); diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts index d7399f2b885..a3ca1010560 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts @@ -34,7 +34,6 @@ import { PublicEnqueuedCallSideEffectTrace, SideEffectArrayLengths } from './enq import { SideEffectLimitReachedError } from './side_effect_errors.js'; describe('Enqueued-call Side Effect Trace', () => { - const address = AztecAddress.random(); const bytecode = Buffer.from('0xdeadbeef'); const utxo = Fr.random(); const leafIndex = Fr.random(); @@ -51,8 +50,10 @@ describe('Enqueued-call Side Effect Trace', () => { let startCounter: number; let startCounterPlus1: number; let trace: PublicEnqueuedCallSideEffectTrace; + let address: AztecAddress; - beforeEach(() => { + beforeEach(async () => { + address = await AztecAddress.random(); startCounter = randomInt(/*max=*/ 1000000); startCounterPlus1 = startCounter + 1; trace = new PublicEnqueuedCallSideEffectTrace(startCounter); @@ -159,8 +160,8 @@ describe('Enqueued-call Side Effect Trace', () => { expect(trace.getSideEffects().publicLogs).toEqual([expectedLog]); }); - it('Should trace get contract instance', () => { - const instance = SerializableContractInstance.random(); + it('Should trace get contract instance', async () => { + const instance = await SerializableContractInstance.random(); const { version: _, ...instanceWithoutVersion } = instance; const lowLeafPreimage = new NullifierLeafPreimage(/*siloedNullifier=*/ address.toField(), Fr.ZERO, 0n); const exists = true; @@ -178,8 +179,8 @@ describe('Enqueued-call Side Effect Trace', () => { ]); }); - it('Should trace get bytecode', () => { - const instance = SerializableContractInstance.random(); + it('Should trace get bytecode', async () => { + const instance = await SerializableContractInstance.random(); const contractClass: ContractClassIdPreimage = { artifactHash: Fr.random(), privateFunctionsRoot: Fr.random(), @@ -318,19 +319,19 @@ describe('Enqueued-call Side Effect Trace', () => { ); }); - it('Should enforce maximum number of calls to unique contract class IDs', () => { + it('Should enforce maximum number of calls to unique contract class IDs', async () => { const firstAddr = AztecAddress.fromNumber(0); - const firstInstance = SerializableContractInstance.random(); + const firstInstance = await SerializableContractInstance.random(); trace.traceGetBytecode(firstAddr, /*exists=*/ true, bytecode, firstInstance); for (let i = 1; i < MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS; i++) { const addr = AztecAddress.fromNumber(i); - const instance = SerializableContractInstance.random(); + const instance = await SerializableContractInstance.random(); trace.traceGetBytecode(addr, /*exists=*/ true, bytecode, instance); } const addr = AztecAddress.fromNumber(MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS); - const instance = SerializableContractInstance.random(); + const instance = await SerializableContractInstance.random(); expect(() => trace.traceGetBytecode(addr, /*exists=*/ true, bytecode, instance)).toThrow( SideEffectLimitReachedError, ); @@ -339,7 +340,7 @@ describe('Enqueued-call Side Effect Trace', () => { trace.traceGetBytecode(firstAddr, /*exists=*/ true, bytecode, firstInstance); const differentAddr = AztecAddress.fromNumber(MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS + 1); - const instanceWithSameClassId = SerializableContractInstance.random({ + const instanceWithSameClassId = await SerializableContractInstance.random({ contractClassId: firstInstance.contractClassId, }); // can re-trace different contract address if it has a duplicate class ID diff --git a/yarn-project/simulator/src/public/fixtures/index.ts b/yarn-project/simulator/src/public/fixtures/index.ts index b7da98b72bc..ab3fbfa965d 100644 --- a/yarn-project/simulator/src/public/fixtures/index.ts +++ b/yarn-project/simulator/src/public/fixtures/index.ts @@ -52,19 +52,22 @@ export async function simulateAvmTestContractGenerateCircuitInputs( teardownFunctionName?: string, teardownArgs: Fr[] = [], expectRevert: boolean = false, - contractDataSource = new MockedAvmTestContractDataSource(), + contractDataSource?: MockedAvmTestContractDataSource, assertionErrString?: string, ): Promise { const globals = GlobalVariables.empty(); globals.timestamp = TIMESTAMP; const merkleTrees = await (await MerkleTrees.new(openTmpStore())).fork(); + if (!contractDataSource) { + contractDataSource = await MockedAvmTestContractDataSource.create(); + } await contractDataSource.deployContracts(merkleTrees); const worldStateDB = new WorldStateDB(merkleTrees, contractDataSource); const simulator = new PublicTxSimulator(merkleTrees, worldStateDB, globals, /*doMerkleOperations=*/ true); - const sender = AztecAddress.random(); + const sender = await AztecAddress.random(); const callContext = new CallContext( sender, contractDataSource.firstContractInstance.address, @@ -116,11 +119,15 @@ export async function simulateAvmTestContractCall( functionName: string, args: Fr[] = [], expectRevert: boolean = false, - contractDataSource = new MockedAvmTestContractDataSource(), + contractDataSource?: MockedAvmTestContractDataSource, ) { const globals = GlobalVariables.empty(); globals.timestamp = TIMESTAMP; + if (!contractDataSource) { + contractDataSource = await MockedAvmTestContractDataSource.create(); + } + const merkleTrees = await (await MerkleTrees.new(openTmpStore())).fork(); await contractDataSource.deployContracts(merkleTrees); const worldStateDB = new WorldStateDB(merkleTrees, contractDataSource); @@ -134,7 +141,7 @@ export async function simulateAvmTestContractCall( doMerkleOperations: true, }); - const sender = AztecAddress.random(); + const sender = await AztecAddress.random(); const functionSelector = getAvmTestContractFunctionSelector(functionName); args = [functionSelector.toField(), ...args]; const environment = initExecutionEnvironment({ @@ -228,45 +235,13 @@ export class MockedAvmTestContractDataSource implements ContractDataSource { ); public instanceSameClassAsFirstContract: ContractInstanceWithAddress = SerializableContractInstance.default().withAddress(AztecAddress.fromNumber(0)); - public otherContractInstance: ContractInstanceWithAddress; + public otherContractInstance!: ContractInstanceWithAddress; - constructor(private skipContractDeployments: boolean = false) { + private constructor(private skipContractDeployments: boolean) { this.bytecode = getAvmTestContractBytecode(this.fnName); this.fnSelector = getAvmTestContractFunctionSelector(this.fnName); this.publicFn = { bytecode: this.bytecode, selector: this.fnSelector }; this.bytecodeCommitment = computePublicBytecodeCommitment(this.bytecode); - - // create enough unique classes to hit the limit (plus two extra) - for (let i = 0; i < MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS + 1; i++) { - const contractClass = makeContractClassPublic(/*seed=*/ i, this.publicFn); - const contractInstance = makeContractInstanceFromClassId(contractClass.id, /*seed=*/ i); - this.contractClasses.set(contractClass.id.toString(), contractClass); - this.contractInstances.set(contractInstance.address.toString(), contractInstance); - if (i === 0) { - this.firstContractInstance = contractInstance; - } - } - // a contract with the same class but different instance/address as the first contract - this.instanceSameClassAsFirstContract = makeContractInstanceFromClassId( - this.firstContractInstance.contractClassId, - /*seed=*/ 1000, - ); - - // The values here should match those in `avm_simulator.test.ts` - // Used for GETCONTRACTINSTANCE test - this.otherContractInstance = new SerializableContractInstance({ - version: 1, - salt: new Fr(0x123), - deployer: new AztecAddress(new Fr(0x456)), - contractClassId: new Fr(0x789), - initializationHash: new Fr(0x101112), - publicKeys: new PublicKeys( - new Point(new Fr(0x131415), new Fr(0x161718), false), - new Point(new Fr(0x192021), new Fr(0x222324), false), - new Point(new Fr(0x252627), new Fr(0x282930), false), - new Point(new Fr(0x313233), new Fr(0x343536), false), - ), - }).withAddress(AztecAddress.fromNumber(0x4444)); } async deployContracts(merkleTrees: MerkleTreeWriteOperations) { @@ -298,14 +273,39 @@ export class MockedAvmTestContractDataSource implements ContractDataSource { } } - public static async create( - merkleTrees: MerkleTreeWriteOperations, - skipContractDeployments: boolean = false, - ): Promise { + public static async create(skipContractDeployments: boolean = false): Promise { const dataSource = new MockedAvmTestContractDataSource(skipContractDeployments); - if (!skipContractDeployments) { - await dataSource.deployContracts(merkleTrees); + // create enough unique classes to hit the limit (plus two extra) + for (let i = 0; i < MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS + 1; i++) { + const contractClass = makeContractClassPublic(/*seed=*/ i, dataSource.publicFn); + const contractInstance = await makeContractInstanceFromClassId(contractClass.id, /*seed=*/ i); + dataSource.contractClasses.set(contractClass.id.toString(), contractClass); + dataSource.contractInstances.set(contractInstance.address.toString(), contractInstance); + if (i === 0) { + dataSource.firstContractInstance = contractInstance; + } } + // a contract with the same class but different instance/address as the first contract + dataSource.instanceSameClassAsFirstContract = await makeContractInstanceFromClassId( + dataSource.firstContractInstance.contractClassId, + /*seed=*/ 1000, + ); + + // The values here should match those in `avm_simulator.test.ts` + // Used for GETCONTRACTINSTANCE test + dataSource.otherContractInstance = new SerializableContractInstance({ + version: 1, + salt: new Fr(0x123), + deployer: new AztecAddress(new Fr(0x456)), + contractClassId: new Fr(0x789), + initializationHash: new Fr(0x101112), + publicKeys: new PublicKeys( + new Point(new Fr(0x131415), new Fr(0x161718), false), + new Point(new Fr(0x192021), new Fr(0x222324), false), + new Point(new Fr(0x252627), new Fr(0x282930), false), + new Point(new Fr(0x313233), new Fr(0x343536), false), + ), + }).withAddress(AztecAddress.fromNumber(0x4444)); return dataSource; } diff --git a/yarn-project/simulator/src/public/public_db_sources.test.ts b/yarn-project/simulator/src/public/public_db_sources.test.ts index 3fa901bb9e4..304d5f29b44 100644 --- a/yarn-project/simulator/src/public/public_db_sources.test.ts +++ b/yarn-project/simulator/src/public/public_db_sources.test.ts @@ -19,8 +19,8 @@ describe('world_state_public_db', () => { let worldStateDB: WorldStateDB; - beforeEach(() => { - addresses = Array(DB_VALUES_SIZE).fill(0).map(AztecAddress.random); + beforeEach(async () => { + addresses = await Promise.all(Array(DB_VALUES_SIZE).fill(0).map(AztecAddress.random)); slots = Array(DB_VALUES_SIZE).fill(0).map(Fr.random); dbValues = Array(DB_VALUES_SIZE).fill(0).map(Fr.random); const publicDataEntries = Array(DB_VALUES_SIZE) diff --git a/yarn-project/simulator/src/public/public_tx_simulator.test.ts b/yarn-project/simulator/src/public/public_tx_simulator.test.ts index 393a47a1568..3b03c62e63d 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.test.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.test.ts @@ -823,7 +823,7 @@ describe('public_tx_simulator', () => { describe('fees', () => { it('deducts fees from the fee payer balance', async () => { - const feePayer = AztecAddress.random(); + const feePayer = await AztecAddress.random(); await setFeeBalance(feePayer, Fr.MAX_FIELD_VALUE); const tx = mockTxWithPublicCalls({ @@ -838,7 +838,7 @@ describe('public_tx_simulator', () => { }); it('fails if fee payer cant pay for the tx', async () => { - const feePayer = AztecAddress.random(); + const feePayer = await AztecAddress.random(); await expect( simulator.simulate( @@ -854,7 +854,7 @@ describe('public_tx_simulator', () => { it('allows disabling fee balance checks for fee estimation', async () => { simulator = createSimulator({ enforceFeePayment: false }); - const feePayer = AztecAddress.random(); + const feePayer = await AztecAddress.random(); const txResult = await simulator.simulate( mockTxWithPublicCalls({ diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index b10bae922ad..38e5b02762c 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -95,7 +95,6 @@ import { TXEWorldStateDB } from '../util/txe_world_state_db.js'; export class TXE implements TypedOracle { private blockNumber = 0; private sideEffectCounter = 0; - private contractAddress: AztecAddress; private msgSender: AztecAddress; private functionSelector = FunctionSelector.fromField(new Fr(0)); private isStaticCall = false; @@ -123,16 +122,16 @@ export class TXE implements TypedOracle { debug: LogFn; - constructor( + private constructor( private logger: Logger, private trees: MerkleTrees, private executionCache: HashedValuesCache, private keyStore: KeyStore, private txeDatabase: TXEDatabase, + private contractAddress: AztecAddress, ) { this.noteCache = new ExecutionNoteCache(this.getTxRequestHash()); this.contractDataOracle = new ContractDataOracle(txeDatabase); - this.contractAddress = AztecAddress.random(); this.node = new TXENode(this.blockNumber, this.VERSION, this.CHAIN_ID, this.trees); @@ -149,6 +148,16 @@ export class TXE implements TypedOracle { this.debug = createDebugOnlyLogger('aztec:kv-pxe-database'); } + static async create( + logger: Logger, + trees: MerkleTrees, + executionCache: HashedValuesCache, + keyStore: KeyStore, + txeDatabase: TXEDatabase, + ) { + return new TXE(logger, trees, executionCache, keyStore, txeDatabase, await AztecAddress.random()); + } + // Utils async #getTreesAt(blockNumber: number) { @@ -937,7 +946,7 @@ export class TXE implements TypedOracle { async #calculateAppTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) { const senderCompleteAddress = await this.getCompleteAddress(sender); const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender); - const secretPoint = computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient); + const secretPoint = await computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient); // Silo the secret to the app so it can't be used to track other app's notes const appSecret = poseidon2Hash([secretPoint.x, secretPoint.y, contractAddress]); return appSecret; diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index f3ea96ee1c7..2fa308e766f 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -53,7 +53,7 @@ export class TXEService { await txeDatabase.addContractInstance(instance); } logger.debug(`TXE service initialized`); - const txe = new TXE(logger, trees, executionCache, keyStore, txeDatabase); + const txe = await TXE.create(logger, trees, executionCache, keyStore, txeDatabase); const service = new TXEService(logger, txe); await service.advanceBlocksBy(toSingle(new Fr(1n))); return service; diff --git a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts index c58ddf9ab05..b1cc2df2cd8 100644 --- a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts +++ b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts @@ -8,7 +8,7 @@ import { } from '@aztec/circuit-types'; import { Fr, MerkleTreeCalculator } from '@aztec/circuits.js'; import { L1_TO_L2_MSG_SUBTREE_HEIGHT } from '@aztec/circuits.js/constants'; -import { times } from '@aztec/foundation/collection'; +import { times, timesParallel } from '@aztec/foundation/collection'; import { randomInt } from '@aztec/foundation/crypto'; import { type Logger, createLogger } from '@aztec/foundation/log'; import { SHA256Trunc } from '@aztec/merkle-tree'; @@ -88,7 +88,7 @@ describe('ServerWorldStateSynchronizer', () => { const pushBlocks = async (from: number, to: number) => { await server.handleBlockStreamEvent({ type: 'blocks-added', - blocks: times(to - from + 1, i => L2Block.random(i + from, 4, 3, 1, inHash)), + blocks: await timesParallel(to - from + 1, i => L2Block.random(i + from, 4, 3, 1, inHash)), }); server.latest.number = to; }; diff --git a/yarn-project/world-state/src/test/integration.test.ts b/yarn-project/world-state/src/test/integration.test.ts index 1f60c0bafaf..e8b9c8aded9 100644 --- a/yarn-project/world-state/src/test/integration.test.ts +++ b/yarn-project/world-state/src/test/integration.test.ts @@ -115,33 +115,33 @@ describe('world-state integration', () => { describe('block syncing', () => { it('performs initial sync from the archiver from genesis', async () => { - archiver.createBlocks(5); + await archiver.createBlocks(5); await synchronizer.start(); await expectSynchedToBlock(5); }); it('syncs new blocks from the archiver from genesis', async () => { await synchronizer.start(); - archiver.createBlocks(5); + await archiver.createBlocks(5); await awaitSync(5); await expectSynchedToBlock(5); }); it('syncs new blocks as they are added to archiver', async () => { - archiver.createBlocks(5); + await archiver.createBlocks(5); await synchronizer.start(); - archiver.createBlocks(3); + await archiver.createBlocks(3); await awaitSync(8); await expectSynchedToBlock(8); }); it('syncs new blocks via multiple batches', async () => { - archiver.createBlocks(10); + await archiver.createBlocks(10); await synchronizer.start(); await expectSynchedToBlock(10); - archiver.createBlocks(10); + await archiver.createBlocks(10); await awaitSync(20); await expectSynchedToBlock(20); }); @@ -150,7 +150,7 @@ describe('world-state integration', () => { const getBlocksSpy = jest.spyOn(archiver, 'getBlocks'); await synchronizer.start(); - archiver.createBlocks(5); + await archiver.createBlocks(5); await awaitSync(5); await expectSynchedToBlock(5); await synchronizer.stopBlockStream(); @@ -162,11 +162,11 @@ describe('world-state integration', () => { new WorldStateInstrumentation(getTelemetryClient()), ); - archiver.createBlocks(3); + await archiver.createBlocks(3); await synchronizer.start(); await expectSynchedToBlock(8); - archiver.createBlocks(4); + await archiver.createBlocks(4); await awaitSync(12); await expectSynchedToBlock(12); @@ -184,7 +184,7 @@ describe('world-state integration', () => { new WorldStateInstrumentation(getTelemetryClient()), ); - archiver.createBlocks(5); + await archiver.createBlocks(5); archiver.setProvenBlockNumber(3); await synchronizer.start(); await expectSynchedToBlock(3); @@ -197,7 +197,7 @@ describe('world-state integration', () => { describe('reorgs', () => { it('prunes blocks upon a reorg and resyncs', async () => { - archiver.createBlocks(5); + await archiver.createBlocks(5); await synchronizer.start(); await expectSynchedToBlock(5); @@ -206,7 +206,7 @@ describe('world-state integration', () => { archiver.setPrefilledBlocks(blocks, messages); archiver.removeBlocks(3); - archiver.createBlocks(2); + await archiver.createBlocks(2); await sleep(2000); await awaitSync(4); await expectSynchedToBlock(4); @@ -225,44 +225,44 @@ describe('world-state integration', () => { }); it('syncs immediately to the latest block', async () => { - archiver.createBlocks(5); + await archiver.createBlocks(5); await synchronizer.start(); await expectSynchedToBlock(5); - archiver.createBlocks(2); + await archiver.createBlocks(2); await expectSynchedToBlock(5); await synchronizer.syncImmediate(); await expectSynchedToBlock(7); }); it('syncs immediately to at least the target block', async () => { - archiver.createBlocks(5); + await archiver.createBlocks(5); await synchronizer.start(); await expectSynchedToBlock(5); - archiver.createBlocks(2); + await archiver.createBlocks(2); await expectSynchedToBlock(5); await synchronizer.syncImmediate(6); await expectSynchedToBlock(7); }); it('syncs immediately to a past block', async () => { - archiver.createBlocks(5); + await archiver.createBlocks(5); await synchronizer.start(); await expectSynchedToBlock(5); - archiver.createBlocks(2); + await archiver.createBlocks(2); await expectSynchedToBlock(5); await synchronizer.syncImmediate(4); await expectSynchedToBlock(5); }); it('fails to sync to unreachable block', async () => { - archiver.createBlocks(5); + await archiver.createBlocks(5); await synchronizer.start(); await expectSynchedToBlock(5); - archiver.createBlocks(2); + await archiver.createBlocks(2); await expectSynchedToBlock(5); await expect(() => synchronizer.syncImmediate(9)).rejects.toThrow(/unable to sync/i); }); @@ -270,7 +270,7 @@ describe('world-state integration', () => { describe('finalized chain', () => { it('syncs finalized chain tip', async () => { - archiver.createBlocks(5); + await archiver.createBlocks(5); archiver.setProvenBlockNumber(3); await synchronizer.start(); diff --git a/yarn-project/world-state/src/test/utils.ts b/yarn-project/world-state/src/test/utils.ts index cfba854fd05..3cb4db582b1 100644 --- a/yarn-project/world-state/src/test/utils.ts +++ b/yarn-project/world-state/src/test/utils.ts @@ -17,7 +17,7 @@ import { padArrayEnd } from '@aztec/foundation/collection'; import { type NativeWorldStateService } from '../native/native_world_state.js'; export async function mockBlock(blockNum: number, size: number, fork: MerkleTreeWriteOperations) { - const l2Block = L2Block.random(blockNum, size); + const l2Block = await L2Block.random(blockNum, size); const l1ToL2Messages = Array(16).fill(0).map(Fr.random); // Sync the append only trees