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