From b1c756a1c4f8cf1832925a151d2a2108a32a041d Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 23 Dec 2025 20:24:32 +0000 Subject: [PATCH 1/7] feat: expanding return value of getLogsByTags --- .../archiver/kv_archiver_store/log_store.ts | 4 + yarn-project/pxe/src/logs/log_service.test.ts | 36 ++------- yarn-project/pxe/src/logs/log_service.ts | 56 ++++--------- ...ate_logs_for_sender_recipient_pair.test.ts | 2 + .../utils/find_highest_indexes.test.ts | 3 + .../utils/load_logs_for_range.test.ts | 2 + .../sync/sync_sender_tagging_indexes.test.ts | 12 ++- ...load_and_store_new_tagging_indexes.test.ts | 12 ++- .../stdlib/src/logs/tx_scoped_l2_log.ts | 79 +++++++++++++++++-- 9 files changed, 127 insertions(+), 79 deletions(-) diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts index 7b1b8b306738..e35f5bdd50fd 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts @@ -86,6 +86,8 @@ export class LogStore { blockHash, block.timestamp, log, + txEffect.noteHashes, + txEffect.nullifiers[0], ).toBuffer(), ); privateTaggedLogs.set(tag.toString(), currentLogs); @@ -110,6 +112,8 @@ export class LogStore { blockHash, block.timestamp, log, + txEffect.noteHashes, + txEffect.nullifiers[0], ).toBuffer(), ); publicTaggedLogs.set(key, currentLogs); diff --git a/yarn-project/pxe/src/logs/log_service.test.ts b/yarn-project/pxe/src/logs/log_service.test.ts index db6c7d006a0a..abe73ce546d6 100644 --- a/yarn-project/pxe/src/logs/log_service.test.ts +++ b/yarn-project/pxe/src/logs/log_service.test.ts @@ -7,7 +7,7 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address'; import { L2BlockHash } from '@aztec/stdlib/block'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; import { PublicLog, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; -import { TxHash, randomIndexedTxEffect } from '@aztec/stdlib/tx'; +import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -75,11 +75,6 @@ describe('LogService', () => { aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); aztecNode.getPrivateLogsByTags.mockResolvedValue([[]]); - const indexedTxEffect = await randomIndexedTxEffect(); - - aztecNode.getTxEffect.mockImplementation((txHash: TxHash) => - txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), - ); const request = new LogRetrievalRequest(contractAddress, new Tag(scopedLog.log.fields[0])); @@ -94,12 +89,6 @@ describe('LogService', () => { aztecNode.getPrivateLogsByTags.mockResolvedValue([[scopedLog]]); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[]]); - const indexedTxEffect = await randomIndexedTxEffect(); - aztecNode.getTxEffect.mockResolvedValue(indexedTxEffect); - - aztecNode.getTxEffect.mockImplementation((txHash: TxHash) => - txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), - ); const request = new LogRetrievalRequest(contractAddress, new Tag(scopedLog.log.fields[0])); @@ -130,20 +119,15 @@ describe('LogService', () => { const logContractAddress = (scopedLog.log as PublicLog).contractAddress; aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); - const indexedTxEffect = await randomIndexedTxEffect(); - aztecNode.getTxEffect.mockImplementation((txHash: TxHash) => - txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), - ); const result = (await logService.getPublicLogByTag(tag, logContractAddress))!; expect(result.logPayload).toEqual(scopedLog.log.getEmittedFieldsWithoutTag()); - expect(result.uniqueNoteHashesInTx).toEqual(indexedTxEffect.data.noteHashes); + expect(result.uniqueNoteHashesInTx).toEqual(scopedLog.noteHashes); expect(result.txHash).toEqual(scopedLog.txHash); - expect(result.firstNullifierInTx).toEqual(indexedTxEffect.data.nullifiers[0]); + expect(result.firstNullifierInTx).toEqual(scopedLog.firstNullifier); expect(aztecNode.getPublicLogsByTagsFromContract).toHaveBeenCalledWith(logContractAddress, [tag]); - expect(aztecNode.getTxEffect).toHaveBeenCalledWith(scopedLog.txHash); }); it('throws if multiple logs found for tag', async () => { @@ -154,17 +138,6 @@ describe('LogService', () => { await expect(logService.getPublicLogByTag(tag, logContractAddress)).rejects.toThrow(/Got 2 logs for tag/); }); - it('throws if tx effect not found', async () => { - const scopedLog = await TxScopedL2Log.random(true); - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); - aztecNode.getTxEffect.mockResolvedValue(undefined); - const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - - await expect(logService.getPublicLogByTag(tag, logContractAddress)).rejects.toThrow( - /failed to retrieve tx effects/, - ); - }); - it('returns log fields that are actually emitted', async () => { const logContractAddress = await AztecAddress.random(); const logPlaintext = [Fr.random()]; @@ -182,10 +155,11 @@ describe('LogService', () => { L2BlockHash.random(), 0n, log, + [], + Fr.ZERO, ); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLogWithPadding]]); - aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); const result = await logService.getPublicLogByTag(tag, logContractAddress); diff --git a/yarn-project/pxe/src/logs/log_service.ts b/yarn-project/pxe/src/logs/log_service.ts index cd774093d5f0..c91399f4d588 100644 --- a/yarn-project/pxe/src/logs/log_service.ts +++ b/yarn-project/pxe/src/logs/log_service.ts @@ -88,19 +88,11 @@ export class LogService { const scopedLog = logsForTag[0]; - // getLogsByTag doesn't have all of the information that we need (notably note hashes and the first nullifier), so - // we need to make a second call to the node for `getTxEffect`. - // TODO(#9789): bundle this information in the `getLogsByTag` call. - const txEffect = await this.aztecNode.getTxEffect(scopedLog.txHash); - if (txEffect == undefined) { - throw new Error(`Unexpected: failed to retrieve tx effects for tx ${scopedLog.txHash} which is known to exist`); - } - return new PublicLogWithTxData( scopedLog.log.getEmittedFieldsWithoutTag(), scopedLog.txHash, - txEffect.data.noteHashes, - txEffect.data.nullifiers[0], + scopedLog.noteHashes, + scopedLog.firstNullifier, ); } @@ -120,19 +112,11 @@ export class LogService { const scopedLog = logsForTag[0]; - // getLogsByTag doesn't have all of the information that we need (notably note hashes and the first nullifier), so - // we need to make a second call to the node for `getTxEffect`. - // TODO(#9789): bundle this information in the `getLogsByTag` call. - const txEffect = await this.aztecNode.getTxEffect(scopedLog.txHash); - if (txEffect == undefined) { - throw new Error(`Unexpected: failed to retrieve tx effects for tx ${scopedLog.txHash} which is known to exist`); - } - return new PrivateLogWithTxData( scopedLog.log.getEmittedFieldsWithoutTag(), scopedLog.txHash, - txEffect.data.noteHashes, - txEffect.data.nullifiers[0], + scopedLog.noteHashes, + scopedLog.firstNullifier, ); } @@ -209,32 +193,24 @@ export class LogService { ); } - async #storePendingTaggedLogs( + #storePendingTaggedLogs( contractAddress: AztecAddress, capsuleArrayBaseSlot: Fr, recipient: AztecAddress, privateLogs: TxScopedL2Log[], ) { - // Build all pending tagged logs upfront with their tx effects - const pendingTaggedLogs = await Promise.all( - privateLogs.map(async scopedLog => { - // TODO(#9789): get these effects along with the log - const txEffect = await this.aztecNode.getTxEffect(scopedLog.txHash); - if (!txEffect) { - throw new Error(`Could not find tx effect for tx hash ${scopedLog.txHash}`); - } - - const pendingTaggedLog = new PendingTaggedLog( - scopedLog.log.fields, - scopedLog.txHash, - txEffect.data.noteHashes, - txEffect.data.nullifiers[0], - recipient, - ); + // Build all pending tagged logs from the scoped logs + const pendingTaggedLogs = privateLogs.map(scopedLog => { + const pendingTaggedLog = new PendingTaggedLog( + scopedLog.log.fields, + scopedLog.txHash, + scopedLog.noteHashes, + scopedLog.firstNullifier, + recipient, + ); - return pendingTaggedLog.toFields(); - }), - ); + return pendingTaggedLog.toFields(); + }); // TODO: This looks like it could belong more at the oracle interface level return this.capsuleDataProvider.appendToCapsuleArray(contractAddress, capsuleArrayBaseSlot, pendingTaggedLogs); diff --git a/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts index dec3c567d3d3..6c46c70f4084 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts @@ -43,6 +43,8 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { L2BlockHash.fromField(blockHash), blockTimestamp, PrivateLog.random(tag), + [], + Fr.ZERO, ); } diff --git a/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts index 6a5239916cf8..78f7c28096de 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts @@ -1,5 +1,6 @@ import { MAX_INCLUDE_BY_TIMESTAMP_DURATION } from '@aztec/constants'; import { BlockNumber } from '@aztec/foundation/branded-types'; +import { Fr } from '@aztec/foundation/curves/bn254'; import { L2BlockHash } from '@aztec/stdlib/block'; import { PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs'; import { TxHash } from '@aztec/stdlib/tx'; @@ -18,6 +19,8 @@ describe('findHighestIndexes', () => { L2BlockHash.random(), blockTimestamp, PrivateLog.random(), + [], + Fr.ZERO, ); } diff --git a/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts index 1165c2c82eea..efaa591c603f 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts @@ -36,6 +36,8 @@ describe('loadLogsForRange', () => { L2BlockHash.fromField(blockHash), blockTimestamp, PrivateLog.random(tag.value), + [], + Fr.ZERO, ); } diff --git a/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts b/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts index 8f6b1fd39cd2..10abfad2e581 100644 --- a/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts @@ -27,7 +27,17 @@ describe('syncSenderTaggingIndexes', () => { } function makeLog(txHash: TxHash, tag: Fr) { - return new TxScopedL2Log(txHash, 0, 0, BlockNumber(0), L2BlockHash.random(), 0n, PrivateLog.random(tag)); + return new TxScopedL2Log( + txHash, + 0, + 0, + BlockNumber(0), + L2BlockHash.random(), + 0n, + PrivateLog.random(tag), + [], + Fr.ZERO, + ); } async function setUp() { diff --git a/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts b/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts index 8ad3b8fc0b3f..28ba7636fa40 100644 --- a/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts @@ -26,7 +26,17 @@ describe('loadAndStoreNewTaggingIndexes', () => { } function makeLog(txHash: TxHash, tag: Fr) { - return new TxScopedL2Log(txHash, 0, 0, BlockNumber(0), L2BlockHash.random(), 0n, PrivateLog.random(tag)); + return new TxScopedL2Log( + txHash, + 0, + 0, + BlockNumber(0), + L2BlockHash.random(), + 0n, + PrivateLog.random(tag), + [], + Fr.ZERO, + ); } beforeAll(async () => { diff --git a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts index bee03d8472d2..ed313d01bc7d 100644 --- a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts +++ b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts @@ -1,5 +1,13 @@ import { BlockNumber, BlockNumberSchema } from '@aztec/foundation/branded-types'; -import { BufferReader, bigintToUInt64BE, boolToBuffer, numToUInt32BE } from '@aztec/foundation/serialize'; +import { Fr } from '@aztec/foundation/curves/bn254'; +import { schemas as foundationSchemas } from '@aztec/foundation/schemas'; +import { + BufferReader, + bigintToUInt64BE, + boolToBuffer, + numToUInt32BE, + serializeArrayOfBufferableToVector, +} from '@aztec/foundation/serialize'; import { z } from 'zod'; @@ -43,6 +51,14 @@ export class TxScopedL2Log { * The log data as either a PrivateLog or PublicLog */ public log: PrivateLog | PublicLog, + /* + * The note hashes from the tx effect + */ + public noteHashes: Fr[], + /* + * The first nullifier from the tx effect + */ + public firstNullifier: Fr, ) {} get isFromPublic() { @@ -59,10 +75,32 @@ export class TxScopedL2Log { blockHash: L2BlockHash.schema, blockTimestamp: schemas.UInt64, log: z.union([PrivateLog.schema, PublicLog.schema]), + noteHashes: z.array(foundationSchemas.Fr), + firstNullifier: foundationSchemas.Fr, }) .transform( - ({ txHash, dataStartIndexForTx, logIndexInTx, blockNumber, blockHash, blockTimestamp, log }) => - new TxScopedL2Log(txHash, dataStartIndexForTx, logIndexInTx, blockNumber, blockHash, blockTimestamp, log), + ({ + txHash, + dataStartIndexForTx, + logIndexInTx, + blockNumber, + blockHash, + blockTimestamp, + log, + noteHashes, + firstNullifier, + }) => + new TxScopedL2Log( + txHash, + dataStartIndexForTx, + logIndexInTx, + blockNumber, + blockHash, + blockTimestamp, + log, + noteHashes, + firstNullifier, + ), ); } @@ -76,6 +114,8 @@ export class TxScopedL2Log { bigintToUInt64BE(this.blockTimestamp), boolToBuffer(this.isFromPublic), this.log.toBuffer(), + serializeArrayOfBufferableToVector(this.noteHashes, 1), + this.firstNullifier.toBuffer(), ]); } @@ -89,13 +129,37 @@ export class TxScopedL2Log { const blockTimestamp = reader.readUInt64(); const isFromPublic = reader.readBoolean(); const log = isFromPublic ? PublicLog.fromBuffer(reader) : PrivateLog.fromBuffer(reader); + const noteHashes = reader.readVector(Fr); + const firstNullifier = reader.readObject(Fr); - return new TxScopedL2Log(txHash, dataStartIndexForTx, logIndexInTx, blockNumber, blockHash, blockTimestamp, log); + return new TxScopedL2Log( + txHash, + dataStartIndexForTx, + logIndexInTx, + blockNumber, + blockHash, + blockTimestamp, + log, + noteHashes, + firstNullifier, + ); } static async random(isFromPublic = Math.random() < 0.5) { const log = isFromPublic ? await PublicLog.random() : PrivateLog.random(); - return new TxScopedL2Log(TxHash.random(), 1, 1, BlockNumber(1), L2BlockHash.random(), 1n, log); + const noteHashes = [Fr.random(), Fr.random()]; + const firstNullifier = Fr.random(); + return new TxScopedL2Log( + TxHash.random(), + 1, + 1, + BlockNumber(1), + L2BlockHash.random(), + 1n, + log, + noteHashes, + firstNullifier, + ); } equals(other: TxScopedL2Log) { @@ -108,7 +172,10 @@ export class TxScopedL2Log { this.blockTimestamp === other.blockTimestamp && ((this.log instanceof PublicLog && other.log instanceof PublicLog) || (this.log instanceof PrivateLog && other.log instanceof PrivateLog)) && - this.log.equals(other.log as any) + this.log.equals(other.log as any) && + this.noteHashes.length === other.noteHashes.length && + this.noteHashes.every((h, i) => h.equals(other.noteHashes[i])) && + this.firstNullifier.equals(other.firstNullifier) ); } } From 56ace7f78319d2c0ae7d1c69a67946e7c5802476 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 23 Dec 2025 20:46:13 +0000 Subject: [PATCH 2/7] dropping unused values from the type --- .../archiver/kv_archiver_store/log_store.ts | 34 +++----- yarn-project/pxe/src/logs/log_service.test.ts | 4 - ...ate_logs_for_sender_recipient_pair.test.ts | 35 +++----- .../utils/find_highest_indexes.test.ts | 4 - .../utils/load_logs_for_range.test.ts | 87 ++++++++----------- .../sync/sync_sender_tagging_indexes.test.ts | 13 +-- ...load_and_store_new_tagging_indexes.test.ts | 13 +-- .../stdlib/src/logs/tx_scoped_l2_log.ts | 75 +--------------- 8 files changed, 65 insertions(+), 200 deletions(-) diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts index e35f5bdd50fd..1a61816d4439 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts @@ -1,4 +1,4 @@ -import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX } from '@aztec/constants'; +import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants'; import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { createLogger } from '@aztec/foundation/log'; @@ -57,21 +57,16 @@ export class LogStore { * @param block - The L2 block to extract logs from. * @returns An object containing the private and public tagged logs for the block. */ - async #extractTaggedLogsFromBlock(block: L2BlockNew) { - const blockHash = L2BlockHash.fromField(await block.hash()); + #extractTaggedLogsFromBlock(block: L2BlockNew) { // SiloedTag (as string) -> array of log buffers. const privateTaggedLogs = new Map(); // "{contractAddress}_{tag}" (as string) -> array of log buffers. const publicTaggedLogs = new Map(); - const dataStartIndexForBlock = - block.header.state.partial.noteHashTree.nextAvailableLeafIndex - - block.body.txEffects.length * MAX_NOTE_HASHES_PER_TX; - block.body.txEffects.forEach((txEffect, txIndex) => { + block.body.txEffects.forEach(txEffect => { const txHash = txEffect.txHash; - const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX; - txEffect.privateLogs.forEach((log, logIndex) => { + txEffect.privateLogs.forEach(log => { // Private logs use SiloedTag (already siloed by kernel) const tag = log.fields[0]; this.#log.debug(`Found private log with tag ${tag.toString()} in block ${block.number}`); @@ -80,10 +75,7 @@ export class LogStore { currentLogs.push( new TxScopedL2Log( txHash, - dataStartIndexForTx, - logIndex, block.number, - blockHash, block.timestamp, log, txEffect.noteHashes, @@ -93,7 +85,7 @@ export class LogStore { privateTaggedLogs.set(tag.toString(), currentLogs); }); - txEffect.publicLogs.forEach((log, logIndex) => { + txEffect.publicLogs.forEach(log => { // Public logs use Tag directly (not siloed) and are stored with contract address const tag = log.fields[0]; const contractAddress = log.contractAddress; @@ -106,10 +98,7 @@ export class LogStore { currentLogs.push( new TxScopedL2Log( txHash, - dataStartIndexForTx, - logIndex, block.number, - blockHash, block.timestamp, log, txEffect.noteHashes, @@ -129,10 +118,11 @@ export class LogStore { * @returns A map from tag (as string) to an array of serialized private logs belonging to that tag, and a map from * "{contractAddress}_{tag}" (as string) to an array of serialized public logs belonging to that key. */ - async #extractTaggedLogs( - blocks: L2BlockNew[], - ): Promise<{ privateTaggedLogs: Map; publicTaggedLogs: Map }> { - const taggedLogsInBlocks = await Promise.all(blocks.map(block => this.#extractTaggedLogsFromBlock(block))); + #extractTaggedLogs(blocks: L2BlockNew[]): { + privateTaggedLogs: Map; + publicTaggedLogs: Map; + } { + const taggedLogsInBlocks = blocks.map(block => this.#extractTaggedLogsFromBlock(block)); // Now we merge the maps from each block into a single map. const privateTaggedLogs = taggedLogsInBlocks.reduce((acc, { privateTaggedLogs }) => { @@ -159,8 +149,8 @@ export class LogStore { * @param blocks - The blocks for which to add the logs. * @returns True if the operation is successful. */ - async addLogs(blocks: L2BlockNew[]): Promise { - const { privateTaggedLogs, publicTaggedLogs } = await this.#extractTaggedLogs(blocks); + addLogs(blocks: L2BlockNew[]): Promise { + const { privateTaggedLogs, publicTaggedLogs } = this.#extractTaggedLogs(blocks); const keysOfPrivateLogsToUpdate = Array.from(privateTaggedLogs.keys()); const keysOfPublicLogsToUpdate = Array.from(publicTaggedLogs.keys()); diff --git a/yarn-project/pxe/src/logs/log_service.test.ts b/yarn-project/pxe/src/logs/log_service.test.ts index abe73ce546d6..e485992526c2 100644 --- a/yarn-project/pxe/src/logs/log_service.test.ts +++ b/yarn-project/pxe/src/logs/log_service.test.ts @@ -4,7 +4,6 @@ import { Fr } from '@aztec/foundation/curves/bn254'; import { KeyStore } from '@aztec/key-store'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; -import { L2BlockHash } from '@aztec/stdlib/block'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; import { PublicLog, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; import { TxHash } from '@aztec/stdlib/tx'; @@ -149,10 +148,7 @@ describe('LogService', () => { }); const scopedLogWithPadding = new TxScopedL2Log( TxHash.random(), - randomInt(100), - randomInt(100), BlockNumber(randomInt(100)), - L2BlockHash.random(), 0n, log, [], diff --git a/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts index 6c46c70f4084..4f6b294a523d 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts @@ -3,7 +3,6 @@ import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; -import { L2BlockHash } from '@aztec/stdlib/block'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; import { DirectionalAppTaggingSecret, PrivateLog, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; import { makeBlockHeader } from '@aztec/stdlib/testing'; @@ -33,14 +32,10 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { return SiloedTag.compute(tag, app); } - // Move blockTimestamp before tag in args in makeLog - function makeLog(blockHash: Fr, blockNumber: number, blockTimestamp: bigint, tag: Fr) { + function makeLog(blockNumber: number, blockTimestamp: bigint, tag: Fr) { return new TxScopedL2Log( TxHash.random(), - 0, - 0, BlockNumber(blockNumber), - L2BlockHash.fromField(blockHash), blockTimestamp, PrivateLog.random(tag), [], @@ -92,7 +87,6 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { const logBlockTimestamp = currentTimestamp - 5000n; // not aged const logIndex = 5; const logTag = await computeSiloedTagForIndex(logIndex); - const logBlockHeader = makeBlockHeader(0, { timestamp: logBlockTimestamp }); aztecNode.getL2Tips.mockResolvedValue({ finalized: { number: BlockNumber(finalizedBlockNumber) }, @@ -102,11 +96,9 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { // The log is finalized aztecNode.getPrivateLogsByTags.mockImplementation((tags: SiloedTag[]) => { - return Promise.all( - tags.map(async (t: SiloedTag) => - t.equals(logTag) - ? [makeLog(await logBlockHeader.hash(), finalizedBlockNumber, logBlockTimestamp, logTag.value)] - : [], + return Promise.resolve( + tags.map((t: SiloedTag) => + t.equals(logTag) ? [makeLog(finalizedBlockNumber, logBlockTimestamp, logTag.value)] : [], ), ); }); @@ -130,7 +122,6 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { const logBlockTimestamp = currentTimestamp - BigInt(MAX_INCLUDE_BY_TIMESTAMP_DURATION) - 1000n; // aged const logIndex = 7; const logTag = await computeSiloedTagForIndex(logIndex); - const logBlockHeader = makeBlockHeader(0, { timestamp: logBlockTimestamp }); aztecNode.getL2Tips.mockResolvedValue({ finalized: { number: BlockNumber(finalizedBlockNumber) }, @@ -140,11 +131,9 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { // The log is finalized aztecNode.getPrivateLogsByTags.mockImplementation((tags: SiloedTag[]) => { - return Promise.all( - tags.map(async (t: SiloedTag) => - t.equals(logTag) - ? [makeLog(await logBlockHeader.hash(), finalizedBlockNumber, logBlockTimestamp, logTag.value)] - : [], + return Promise.resolve( + tags.map((t: SiloedTag) => + t.equals(logTag) ? [makeLog(finalizedBlockNumber, logBlockTimestamp, logTag.value)] : [], ), ); }); @@ -173,8 +162,6 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { const log2Index = highestFinalizedIndex + UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN; // At the window boundary const log1Tag = await computeSiloedTagForIndex(log1Index); const log2Tag = await computeSiloedTagForIndex(log2Index); - const log1BlockHeader = makeBlockHeader(0, { timestamp: log1BlockTimestamp }); - const log2BlockHeader = makeBlockHeader(1, { timestamp: log2BlockTimestamp }); // Set existing highest aged index and highest finalized index await taggingDataProvider.updateHighestAgedIndex(secret, highestAgedIndex); @@ -191,12 +178,12 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { aztecNode.getPrivateLogsByTags.mockImplementation((tags: SiloedTag[]) => { numQueriedTags += tags.length; - return Promise.all( - tags.map(async (t: SiloedTag) => { + return Promise.resolve( + tags.map((t: SiloedTag) => { if (t.equals(log1Tag)) { - return [makeLog(await log1BlockHeader.hash(), finalizedBlockNumber, log1BlockTimestamp, log1Tag.value)]; + return [makeLog(finalizedBlockNumber, log1BlockTimestamp, log1Tag.value)]; } else if (t.equals(log2Tag)) { - return [makeLog(await log2BlockHeader.hash(), finalizedBlockNumber, log2BlockTimestamp, log2Tag.value)]; + return [makeLog(finalizedBlockNumber, log2BlockTimestamp, log2Tag.value)]; } return []; }), diff --git a/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts index 78f7c28096de..41534038ebe0 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts @@ -1,7 +1,6 @@ import { MAX_INCLUDE_BY_TIMESTAMP_DURATION } from '@aztec/constants'; import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; -import { L2BlockHash } from '@aztec/stdlib/block'; import { PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs'; import { TxHash } from '@aztec/stdlib/tx'; @@ -13,10 +12,7 @@ describe('findHighestIndexes', () => { function makeLog(blockNumber: number, blockTimestamp: bigint): TxScopedL2Log { return new TxScopedL2Log( TxHash.random(), - 0, - 0, BlockNumber(blockNumber), - L2BlockHash.random(), blockTimestamp, PrivateLog.random(), [], diff --git a/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts index efaa591c603f..fdedec373fc9 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts @@ -1,10 +1,8 @@ import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; -import { L2BlockHash } from '@aztec/stdlib/block'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; import { DirectionalAppTaggingSecret, PrivateLog, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; -import { makeBlockHeader } from '@aztec/stdlib/testing'; import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -27,13 +25,10 @@ describe('loadLogsForRange', () => { return SiloedTag.compute(tag, app); } - function makeLog(txHash: TxHash, blockHash: Fr, blockNumber: number, blockTimestamp: bigint, tag: SiloedTag) { + function makeLog(txHash: TxHash, blockNumber: number, blockTimestamp: bigint, tag: SiloedTag) { return new TxScopedL2Log( txHash, - 0, - 0, BlockNumber(blockNumber), - L2BlockHash.fromField(blockHash), blockTimestamp, PrivateLog.random(tag.value), [], @@ -71,16 +66,14 @@ describe('loadLogsForRange', () => { const timestamp2 = 2000n; const tag1 = await computeSiloedTagForIndex(index1); const tag2 = await computeSiloedTagForIndex(index2); - const blockHeader1 = makeBlockHeader(0, { timestamp: timestamp1 }); - const blockHeader2 = makeBlockHeader(1, { timestamp: timestamp2 }); aztecNode.getPrivateLogsByTags.mockImplementation((tags: SiloedTag[]) => { return Promise.all( - tags.map(async (t: SiloedTag) => { + tags.map((t: SiloedTag) => { if (t.equals(tag1)) { - return [makeLog(txHash1, await blockHeader1.hash(), blockNumber1, timestamp1, tag1)]; + return [makeLog(txHash1, blockNumber1, timestamp1, tag1)]; } else if (t.equals(tag2)) { - return [makeLog(txHash2, await blockHeader2.hash(), blockNumber2, timestamp2, tag2)]; + return [makeLog(txHash2, blockNumber2, timestamp2, tag2)]; } return []; }), @@ -108,17 +101,12 @@ describe('loadLogsForRange', () => { const timestamp1 = 1000n; const timestamp2 = 2000n; const tag = await computeSiloedTagForIndex(index); - const blockHeader1 = makeBlockHeader(0, { timestamp: timestamp1 }); - const blockHeader2 = makeBlockHeader(1, { timestamp: timestamp2 }); aztecNode.getPrivateLogsByTags.mockImplementation((tags: SiloedTag[]) => { - return Promise.all( - tags.map(async (t: SiloedTag) => + return Promise.resolve( + tags.map((t: SiloedTag) => t.equals(tag) - ? [ - makeLog(txHash1, await blockHeader1.hash(), blockNumber1, timestamp1, tag), - makeLog(txHash2, await blockHeader2.hash(), blockNumber2, timestamp2, tag), - ] + ? [makeLog(txHash1, blockNumber1, timestamp1, tag), makeLog(txHash2, blockNumber2, timestamp2, tag)] : [], ), ); @@ -143,18 +131,18 @@ describe('loadLogsForRange', () => { const timestamp = 1000n; const tag1 = await computeSiloedTagForIndex(index1); const tag2 = await computeSiloedTagForIndex(index2); - const blockHeader = makeBlockHeader(0, { timestamp }); - - aztecNode.getPrivateLogsByTags.mockImplementation(async (tags: SiloedTag[]) => { - const blockHash = await blockHeader.hash(); - return tags.map((t: SiloedTag) => { - if (t.equals(tag1)) { - return [makeLog(txHash1, blockHash, blockNumber, timestamp, tag1)]; - } else if (t.equals(tag2)) { - return [makeLog(txHash2, blockHash, blockNumber, timestamp, tag2)]; - } - return []; - }); + + aztecNode.getPrivateLogsByTags.mockImplementation((tags: SiloedTag[]) => { + return Promise.resolve( + tags.map((t: SiloedTag) => { + if (t.equals(tag1)) { + return [makeLog(txHash1, blockNumber, timestamp, tag1)]; + } else if (t.equals(tag2)) { + return [makeLog(txHash2, blockNumber, timestamp, tag2)]; + } + return []; + }), + ); }); const result = await loadLogsForRange(secret, app, aztecNode, 0, 10, NON_INTERFERING_ANCHOR_BLOCK_NUMBER); @@ -177,18 +165,18 @@ describe('loadLogsForRange', () => { const timestamp = 1000n; const tagAtStart = await computeSiloedTagForIndex(start); const tagAtEnd = await computeSiloedTagForIndex(end); - const blockHeader = makeBlockHeader(0, { timestamp }); - - aztecNode.getPrivateLogsByTags.mockImplementation(async (tags: SiloedTag[]) => { - const blockHash = await blockHeader.hash(); - return tags.map((t: SiloedTag) => { - if (t.equals(tagAtStart)) { - return [makeLog(txHashAtStart, blockHash, 5, timestamp, tagAtStart)]; - } else if (t.equals(tagAtEnd)) { - return [makeLog(txHashAtEnd, blockHash, 6, timestamp, tagAtEnd)]; - } - return []; - }); + + aztecNode.getPrivateLogsByTags.mockImplementation((tags: SiloedTag[]) => { + return Promise.resolve( + tags.map((t: SiloedTag) => { + if (t.equals(tagAtStart)) { + return [makeLog(txHashAtStart, 5, timestamp, tagAtStart)]; + } else if (t.equals(tagAtEnd)) { + return [makeLog(txHashAtEnd, 6, timestamp, tagAtEnd)]; + } + return []; + }), + ); }); const result = await loadLogsForRange(secret, app, aztecNode, start, end, NON_INTERFERING_ANCHOR_BLOCK_NUMBER); @@ -205,18 +193,15 @@ describe('loadLogsForRange', () => { const index = 3; const timestamp = 1000n; const tag = await computeSiloedTagForIndex(index); - const blockHeaderBefore = makeBlockHeader(0, { timestamp }); - const blockHeaderAtAnchor = makeBlockHeader(1, { timestamp }); - const blockHeaderAfter = makeBlockHeader(2, { timestamp }); aztecNode.getPrivateLogsByTags.mockImplementation((tags: SiloedTag[]) => { - return Promise.all( - tags.map(async (t: SiloedTag) => + return Promise.resolve( + tags.map((t: SiloedTag) => t.equals(tag) ? [ - makeLog(TxHash.random(), await blockHeaderBefore.hash(), anchorBlockNumber - 1, timestamp, tag), - makeLog(TxHash.random(), await blockHeaderAtAnchor.hash(), anchorBlockNumber, timestamp, tag), - makeLog(TxHash.random(), await blockHeaderAfter.hash(), anchorBlockNumber + 1, timestamp, tag), + makeLog(TxHash.random(), anchorBlockNumber - 1, timestamp, tag), + makeLog(TxHash.random(), anchorBlockNumber, timestamp, tag), + makeLog(TxHash.random(), anchorBlockNumber + 1, timestamp, tag), ] : [], ), diff --git a/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts b/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts index 10abfad2e581..baaa7316a556 100644 --- a/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts @@ -2,7 +2,6 @@ import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; -import { L2BlockHash } from '@aztec/stdlib/block'; import type { AztecNode } from '@aztec/stdlib/interfaces/client'; import { PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs'; import { TxHash, TxStatus } from '@aztec/stdlib/tx'; @@ -27,17 +26,7 @@ describe('syncSenderTaggingIndexes', () => { } function makeLog(txHash: TxHash, tag: Fr) { - return new TxScopedL2Log( - txHash, - 0, - 0, - BlockNumber(0), - L2BlockHash.random(), - 0n, - PrivateLog.random(tag), - [], - Fr.ZERO, - ); + return new TxScopedL2Log(txHash, BlockNumber(0), 0n, PrivateLog.random(tag), [], Fr.ZERO); } async function setUp() { diff --git a/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts b/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts index 28ba7636fa40..78942e0555b2 100644 --- a/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts @@ -2,7 +2,6 @@ import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; -import { L2BlockHash } from '@aztec/stdlib/block'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; import { DirectionalAppTaggingSecret, PrivateLog, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; import { TxHash } from '@aztec/stdlib/tx'; @@ -26,17 +25,7 @@ describe('loadAndStoreNewTaggingIndexes', () => { } function makeLog(txHash: TxHash, tag: Fr) { - return new TxScopedL2Log( - txHash, - 0, - 0, - BlockNumber(0), - L2BlockHash.random(), - 0n, - PrivateLog.random(tag), - [], - Fr.ZERO, - ); + return new TxScopedL2Log(txHash, BlockNumber(0), 0n, PrivateLog.random(tag), [], Fr.ZERO); } beforeAll(async () => { diff --git a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts index ed313d01bc7d..94c8a281429b 100644 --- a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts +++ b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts @@ -11,7 +11,6 @@ import { import { z } from 'zod'; -import { L2BlockHash } from '../block/block_hash.js'; import { schemas } from '../schemas/schemas.js'; import { TxHash } from '../tx/tx_hash.js'; import type { UInt64 } from '../types/shared.js'; @@ -25,24 +24,10 @@ export class TxScopedL2Log { * Hash of the tx where the log is included */ public txHash: TxHash, - /* - * The next available leaf index for the note hash tree for this transaction. It is stored - * with the log so the noteHashIndex can be reconstructed after decryption. - */ - public dataStartIndexForTx: number, - /* - * The index of the log in the transaction. Note that public and private logs are in separate arrays in the tx - * effect and for this reason these indices are independent (a private and public log can have the same index). - */ - public logIndexInTx: number, /* * The block this log is included in */ public blockNumber: BlockNumber, - /* - * The block this log is included in - */ - public blockHash: L2BlockHash, /* * The timestamp of the block this log is included in */ @@ -69,48 +54,22 @@ export class TxScopedL2Log { return z .object({ txHash: TxHash.schema, - dataStartIndexForTx: z.number(), - logIndexInTx: z.number(), blockNumber: BlockNumberSchema, - blockHash: L2BlockHash.schema, blockTimestamp: schemas.UInt64, log: z.union([PrivateLog.schema, PublicLog.schema]), noteHashes: z.array(foundationSchemas.Fr), firstNullifier: foundationSchemas.Fr, }) .transform( - ({ - txHash, - dataStartIndexForTx, - logIndexInTx, - blockNumber, - blockHash, - blockTimestamp, - log, - noteHashes, - firstNullifier, - }) => - new TxScopedL2Log( - txHash, - dataStartIndexForTx, - logIndexInTx, - blockNumber, - blockHash, - blockTimestamp, - log, - noteHashes, - firstNullifier, - ), + ({ txHash, blockNumber, blockTimestamp, log, noteHashes, firstNullifier }) => + new TxScopedL2Log(txHash, blockNumber, blockTimestamp, log, noteHashes, firstNullifier), ); } toBuffer() { return Buffer.concat([ this.txHash.toBuffer(), - numToUInt32BE(this.dataStartIndexForTx), - numToUInt32BE(this.logIndexInTx), numToUInt32BE(this.blockNumber), - this.blockHash.toBuffer(), bigintToUInt64BE(this.blockTimestamp), boolToBuffer(this.isFromPublic), this.log.toBuffer(), @@ -122,53 +81,27 @@ export class TxScopedL2Log { static fromBuffer(buffer: Buffer) { const reader = BufferReader.asReader(buffer); const txHash = reader.readObject(TxHash); - const dataStartIndexForTx = reader.readNumber(); - const logIndexInTx = reader.readNumber(); const blockNumber = BlockNumber(reader.readNumber()); - const blockHash = reader.readObject(L2BlockHash); const blockTimestamp = reader.readUInt64(); const isFromPublic = reader.readBoolean(); const log = isFromPublic ? PublicLog.fromBuffer(reader) : PrivateLog.fromBuffer(reader); const noteHashes = reader.readVector(Fr); const firstNullifier = reader.readObject(Fr); - return new TxScopedL2Log( - txHash, - dataStartIndexForTx, - logIndexInTx, - blockNumber, - blockHash, - blockTimestamp, - log, - noteHashes, - firstNullifier, - ); + return new TxScopedL2Log(txHash, blockNumber, blockTimestamp, log, noteHashes, firstNullifier); } static async random(isFromPublic = Math.random() < 0.5) { const log = isFromPublic ? await PublicLog.random() : PrivateLog.random(); const noteHashes = [Fr.random(), Fr.random()]; const firstNullifier = Fr.random(); - return new TxScopedL2Log( - TxHash.random(), - 1, - 1, - BlockNumber(1), - L2BlockHash.random(), - 1n, - log, - noteHashes, - firstNullifier, - ); + return new TxScopedL2Log(TxHash.random(), BlockNumber(1), 1n, log, noteHashes, firstNullifier); } equals(other: TxScopedL2Log) { return ( this.txHash.equals(other.txHash) && - this.dataStartIndexForTx === other.dataStartIndexForTx && - this.logIndexInTx === other.logIndexInTx && this.blockNumber === other.blockNumber && - this.blockHash.equals(other.blockHash) && this.blockTimestamp === other.blockTimestamp && ((this.log instanceof PublicLog && other.log instanceof PublicLog) || (this.log instanceof PrivateLog && other.log instanceof PrivateLog)) && From 64e0cfb0a1de5c40ba095a674deaa22820c0a060 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 23 Dec 2025 21:28:37 +0000 Subject: [PATCH 3/7] cleanup --- .../archiver/kv_archiver_store/log_store.ts | 4 +- yarn-project/pxe/src/logs/log_service.test.ts | 36 ++++----- yarn-project/pxe/src/logs/log_service.ts | 6 +- ...ate_logs_for_sender_recipient_pair.test.ts | 12 +-- .../utils/find_highest_indexes.test.ts | 14 +--- .../utils/load_logs_for_range.test.ts | 11 +-- .../sync/sync_sender_tagging_indexes.test.ts | 5 +- ...load_and_store_new_tagging_indexes.test.ts | 5 +- .../stdlib/src/interfaces/archiver.test.ts | 8 +- .../stdlib/src/interfaces/aztec-node.test.ts | 8 +- .../src/interfaces/get_logs_response.test.ts | 4 +- .../stdlib/src/logs/tx_scoped_l2_log.ts | 75 ++++++++++++------- 12 files changed, 88 insertions(+), 100 deletions(-) diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts index 1a61816d4439..aec5c3362807 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts @@ -77,7 +77,7 @@ export class LogStore { txHash, block.number, block.timestamp, - log, + log.getEmittedFields(), txEffect.noteHashes, txEffect.nullifiers[0], ).toBuffer(), @@ -100,7 +100,7 @@ export class LogStore { txHash, block.number, block.timestamp, - log, + log.getEmittedFields(), txEffect.noteHashes, txEffect.nullifiers[0], ).toBuffer(), diff --git a/yarn-project/pxe/src/logs/log_service.test.ts b/yarn-project/pxe/src/logs/log_service.test.ts index e485992526c2..dedd0e8560a7 100644 --- a/yarn-project/pxe/src/logs/log_service.test.ts +++ b/yarn-project/pxe/src/logs/log_service.test.ts @@ -1,11 +1,10 @@ import { BlockNumber } from '@aztec/foundation/branded-types'; -import { randomInt } from '@aztec/foundation/crypto/random'; import { Fr } from '@aztec/foundation/curves/bn254'; import { KeyStore } from '@aztec/key-store'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; -import { PublicLog, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; +import { Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -69,13 +68,12 @@ describe('LogService', () => { }); it('returns a public log if one is found', async () => { - const scopedLog = await TxScopedL2Log.random(true); - (scopedLog.log as PublicLog).contractAddress = contractAddress; + const scopedLog = TxScopedL2Log.randomPrivate(); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); aztecNode.getPrivateLogsByTags.mockResolvedValue([[]]); - const request = new LogRetrievalRequest(contractAddress, new Tag(scopedLog.log.fields[0])); + const request = new LogRetrievalRequest(contractAddress, new Tag(scopedLog.logData[0])); const responses = await logService.bulkRetrieveLogs([request]); @@ -84,12 +82,12 @@ describe('LogService', () => { }); it('returns a private log if one is found', async () => { - const scopedLog = await TxScopedL2Log.random(false); + const scopedLog = TxScopedL2Log.randomPrivate(); aztecNode.getPrivateLogsByTags.mockResolvedValue([[scopedLog]]); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[]]); - const request = new LogRetrievalRequest(contractAddress, new Tag(scopedLog.log.fields[0])); + const request = new LogRetrievalRequest(contractAddress, new Tag(scopedLog.logData[0])); const responses = await logService.bulkRetrieveLogs([request]); @@ -114,14 +112,14 @@ describe('LogService', () => { }); it('returns log data when single log found', async () => { - const scopedLog = await TxScopedL2Log.random(true); - const logContractAddress = (scopedLog.log as PublicLog).contractAddress; + const logContractAddress = await AztecAddress.random(); + const scopedLog = TxScopedL2Log.randomPrivate(); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); const result = (await logService.getPublicLogByTag(tag, logContractAddress))!; - expect(result.logPayload).toEqual(scopedLog.log.getEmittedFieldsWithoutTag()); + expect(result.logPayload).toEqual(scopedLog.logData.slice(1)); expect(result.uniqueNoteHashesInTx).toEqual(scopedLog.noteHashes); expect(result.txHash).toEqual(scopedLog.txHash); expect(result.firstNullifierInTx).toEqual(scopedLog.firstNullifier); @@ -130,9 +128,9 @@ describe('LogService', () => { }); it('throws if multiple logs found for tag', async () => { - const scopedLog = await TxScopedL2Log.random(true); + const logContractAddress = await AztecAddress.random(); + const scopedLog = TxScopedL2Log.randomPrivate(); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog, scopedLog]]); - const logContractAddress = (scopedLog.log as PublicLog).contractAddress; await expect(logService.getPublicLogByTag(tag, logContractAddress)).rejects.toThrow(/Got 2 logs for tag/); }); @@ -142,17 +140,13 @@ describe('LogService', () => { const logPlaintext = [Fr.random()]; const logContent = [tag.value, ...logPlaintext]; - const log = PublicLog.from({ - contractAddress: logContractAddress, - fields: logContent, - }); const scopedLogWithPadding = new TxScopedL2Log( TxHash.random(), - BlockNumber(randomInt(100)), - 0n, - log, - [], - Fr.ZERO, + BlockNumber(1), + 1n, + logContent, + [Fr.random(), Fr.random()], + Fr.random(), ); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLogWithPadding]]); diff --git a/yarn-project/pxe/src/logs/log_service.ts b/yarn-project/pxe/src/logs/log_service.ts index c91399f4d588..b5e7f0247e39 100644 --- a/yarn-project/pxe/src/logs/log_service.ts +++ b/yarn-project/pxe/src/logs/log_service.ts @@ -89,7 +89,7 @@ export class LogService { const scopedLog = logsForTag[0]; return new PublicLogWithTxData( - scopedLog.log.getEmittedFieldsWithoutTag(), + scopedLog.logData.slice(1), // Skip the tag scopedLog.txHash, scopedLog.noteHashes, scopedLog.firstNullifier, @@ -113,7 +113,7 @@ export class LogService { const scopedLog = logsForTag[0]; return new PrivateLogWithTxData( - scopedLog.log.getEmittedFieldsWithoutTag(), + scopedLog.logData.slice(1), // Skip the tag scopedLog.txHash, scopedLog.noteHashes, scopedLog.firstNullifier, @@ -202,7 +202,7 @@ export class LogService { // Build all pending tagged logs from the scoped logs const pendingTaggedLogs = privateLogs.map(scopedLog => { const pendingTaggedLog = new PendingTaggedLog( - scopedLog.log.fields, + scopedLog.logData, scopedLog.txHash, scopedLog.noteHashes, scopedLog.firstNullifier, diff --git a/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts index 4f6b294a523d..bfabf854dc8f 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts @@ -4,9 +4,8 @@ import { Fr } from '@aztec/foundation/curves/bn254'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; -import { DirectionalAppTaggingSecret, PrivateLog, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; +import { DirectionalAppTaggingSecret, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; import { makeBlockHeader } from '@aztec/stdlib/testing'; -import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -33,14 +32,7 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { } function makeLog(blockNumber: number, blockTimestamp: bigint, tag: Fr) { - return new TxScopedL2Log( - TxHash.random(), - BlockNumber(blockNumber), - blockTimestamp, - PrivateLog.random(tag), - [], - Fr.ZERO, - ); + return TxScopedL2Log.randomPrivate({ blockNumber, blockTimestamp, tag }); } beforeAll(async () => { diff --git a/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts index 41534038ebe0..a6ef8bb88ff4 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts @@ -1,8 +1,5 @@ import { MAX_INCLUDE_BY_TIMESTAMP_DURATION } from '@aztec/constants'; -import { BlockNumber } from '@aztec/foundation/branded-types'; -import { Fr } from '@aztec/foundation/curves/bn254'; -import { PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs'; -import { TxHash } from '@aztec/stdlib/tx'; +import { TxScopedL2Log } from '@aztec/stdlib/logs'; import { findHighestIndexes } from './find_highest_indexes.js'; @@ -10,14 +7,7 @@ describe('findHighestIndexes', () => { const currentTimestamp = BigInt(Math.floor(Date.now() / 1000)); function makeLog(blockNumber: number, blockTimestamp: bigint): TxScopedL2Log { - return new TxScopedL2Log( - TxHash.random(), - BlockNumber(blockNumber), - blockTimestamp, - PrivateLog.random(), - [], - Fr.ZERO, - ); + return TxScopedL2Log.randomPrivate({ blockNumber, blockTimestamp }); } it('returns undefined for highestAgedIndex when no logs are at least 24 hours old', () => { diff --git a/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts index fdedec373fc9..777281bc0ed0 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts @@ -2,7 +2,7 @@ import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; -import { DirectionalAppTaggingSecret, PrivateLog, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; +import { DirectionalAppTaggingSecret, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -26,14 +26,7 @@ describe('loadLogsForRange', () => { } function makeLog(txHash: TxHash, blockNumber: number, blockTimestamp: bigint, tag: SiloedTag) { - return new TxScopedL2Log( - txHash, - BlockNumber(blockNumber), - blockTimestamp, - PrivateLog.random(tag.value), - [], - Fr.ZERO, - ); + return TxScopedL2Log.randomPrivate({ txHash, blockNumber, blockTimestamp, tag: tag.value }); } beforeAll(async () => { diff --git a/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts b/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts index baaa7316a556..001a875d0f76 100644 --- a/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts @@ -1,9 +1,8 @@ -import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/client'; -import { PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs'; +import { TxScopedL2Log } from '@aztec/stdlib/logs'; import { TxHash, TxStatus } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -26,7 +25,7 @@ describe('syncSenderTaggingIndexes', () => { } function makeLog(txHash: TxHash, tag: Fr) { - return new TxScopedL2Log(txHash, BlockNumber(0), 0n, PrivateLog.random(tag), [], Fr.ZERO); + return TxScopedL2Log.randomPrivate({ txHash, tag }); } async function setUp() { diff --git a/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts b/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts index 78942e0555b2..bcd17dc1511d 100644 --- a/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts @@ -1,9 +1,8 @@ -import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; -import { DirectionalAppTaggingSecret, PrivateLog, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; +import { DirectionalAppTaggingSecret, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -25,7 +24,7 @@ describe('loadAndStoreNewTaggingIndexes', () => { } function makeLog(txHash: TxHash, tag: Fr) { - return new TxScopedL2Log(txHash, BlockNumber(0), 0n, PrivateLog.random(tag), [], Fr.ZERO); + return TxScopedL2Log.randomPrivate({ txHash, tag }); } beforeAll(async () => { diff --git a/yarn-project/stdlib/src/interfaces/archiver.test.ts b/yarn-project/stdlib/src/interfaces/archiver.test.ts index 052bebf963ea..92b519387021 100644 --- a/yarn-project/stdlib/src/interfaces/archiver.test.ts +++ b/yarn-project/stdlib/src/interfaces/archiver.test.ts @@ -449,18 +449,18 @@ class MockArchiver implements ArchiverApi { expect(blockNumber).toEqual(BlockNumber(1)); return Promise.resolve(`0x01`); } - async getPrivateLogsByTags(tags: SiloedTag[], _logsPerTag?: number): Promise { + getPrivateLogsByTags(tags: SiloedTag[], _logsPerTag?: number): Promise { expect(tags[0]).toBeInstanceOf(SiloedTag); - return [await Promise.all(tags.map(() => TxScopedL2Log.random(false)))]; + return Promise.resolve([tags.map(() => TxScopedL2Log.randomPrivate())]); } - async getPublicLogsByTagsFromContract( + getPublicLogsByTagsFromContract( contractAddress: AztecAddress, tags: Tag[], _logsPerTag?: number, ): Promise { expect(contractAddress).toBeInstanceOf(AztecAddress); expect(tags[0]).toBeInstanceOf(Tag); - return [await Promise.all(tags.map(() => TxScopedL2Log.random(true)))]; + return Promise.resolve([tags.map(() => TxScopedL2Log.randomPrivate())]); } async getPublicLogs(filter: LogFilter): Promise { expect(filter.txHash).toBeInstanceOf(TxHash); diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts index 7f4da739c97e..d760a15ddada 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts @@ -721,12 +721,12 @@ class MockAztecNode implements AztecNode { expect(filter.contractAddress).toBeInstanceOf(AztecAddress); return Promise.resolve({ logs: [await ExtendedContractClassLog.random()], maxLogsHit: true }); } - async getPrivateLogsByTags(tags: SiloedTag[], _logsPerTag?: number): Promise { + getPrivateLogsByTags(tags: SiloedTag[], _logsPerTag?: number): Promise { expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(SiloedTag); - return [[await TxScopedL2Log.random(false)]]; + return Promise.resolve([[TxScopedL2Log.randomPrivate()]]); } - async getPublicLogsByTagsFromContract( + getPublicLogsByTagsFromContract( contractAddress: AztecAddress, tags: Tag[], _logsPerTag?: number, @@ -734,7 +734,7 @@ class MockAztecNode implements AztecNode { expect(contractAddress).toBeInstanceOf(AztecAddress); expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(Tag); - return [[await TxScopedL2Log.random(true)]]; + return Promise.resolve([[TxScopedL2Log.randomPrivate()]]); } sendTx(tx: Tx): Promise { expect(tx).toBeInstanceOf(Tx); diff --git a/yarn-project/stdlib/src/interfaces/get_logs_response.test.ts b/yarn-project/stdlib/src/interfaces/get_logs_response.test.ts index 065b16d75069..6dbf78cb69b0 100644 --- a/yarn-project/stdlib/src/interfaces/get_logs_response.test.ts +++ b/yarn-project/stdlib/src/interfaces/get_logs_response.test.ts @@ -3,8 +3,8 @@ import { jsonStringify } from '@aztec/foundation/json-rpc'; import { TxScopedL2Log } from '../logs/tx_scoped_l2_log.js'; describe('TxScopedL2Log', () => { - it('serializes to JSON', async () => { - const log = await TxScopedL2Log.random(); + it('serializes to JSON', () => { + const log = TxScopedL2Log.randomPrivate(); expect(TxScopedL2Log.schema.parse(JSON.parse(jsonStringify(log)))).toEqual(log); }); }); diff --git a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts index 94c8a281429b..4b34289bd726 100644 --- a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts +++ b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts @@ -4,7 +4,6 @@ import { schemas as foundationSchemas } from '@aztec/foundation/schemas'; import { BufferReader, bigintToUInt64BE, - boolToBuffer, numToUInt32BE, serializeArrayOfBufferableToVector, } from '@aztec/foundation/serialize'; @@ -17,7 +16,6 @@ import type { UInt64 } from '../types/shared.js'; import { PrivateLog } from './private_log.js'; import { PublicLog } from './public_log.js'; -// TODO(F-231): Drop this and return the PrivateLogWithTxData and PublicLogWithTxData from Aztec node instead. export class TxScopedL2Log { constructor( /* @@ -33,9 +31,9 @@ export class TxScopedL2Log { */ public blockTimestamp: UInt64, /* - * The log data as either a PrivateLog or PublicLog + * The log data as an array of field elements */ - public log: PrivateLog | PublicLog, + public logData: Fr[], /* * The note hashes from the tx effect */ @@ -46,23 +44,19 @@ export class TxScopedL2Log { public firstNullifier: Fr, ) {} - get isFromPublic() { - return this.log instanceof PublicLog; - } - static get schema() { return z .object({ txHash: TxHash.schema, blockNumber: BlockNumberSchema, blockTimestamp: schemas.UInt64, - log: z.union([PrivateLog.schema, PublicLog.schema]), + logData: z.array(foundationSchemas.Fr), noteHashes: z.array(foundationSchemas.Fr), firstNullifier: foundationSchemas.Fr, }) .transform( - ({ txHash, blockNumber, blockTimestamp, log, noteHashes, firstNullifier }) => - new TxScopedL2Log(txHash, blockNumber, blockTimestamp, log, noteHashes, firstNullifier), + ({ txHash, blockNumber, blockTimestamp, logData, noteHashes, firstNullifier }) => + new TxScopedL2Log(txHash, blockNumber, blockTimestamp, logData, noteHashes, firstNullifier), ); } @@ -71,9 +65,8 @@ export class TxScopedL2Log { this.txHash.toBuffer(), numToUInt32BE(this.blockNumber), bigintToUInt64BE(this.blockTimestamp), - boolToBuffer(this.isFromPublic), - this.log.toBuffer(), - serializeArrayOfBufferableToVector(this.noteHashes, 1), + serializeArrayOfBufferableToVector(this.logData), + serializeArrayOfBufferableToVector(this.noteHashes), this.firstNullifier.toBuffer(), ]); } @@ -83,19 +76,11 @@ export class TxScopedL2Log { const txHash = reader.readObject(TxHash); const blockNumber = BlockNumber(reader.readNumber()); const blockTimestamp = reader.readUInt64(); - const isFromPublic = reader.readBoolean(); - const log = isFromPublic ? PublicLog.fromBuffer(reader) : PrivateLog.fromBuffer(reader); + const logData = reader.readVector(Fr); const noteHashes = reader.readVector(Fr); const firstNullifier = reader.readObject(Fr); - return new TxScopedL2Log(txHash, blockNumber, blockTimestamp, log, noteHashes, firstNullifier); - } - - static async random(isFromPublic = Math.random() < 0.5) { - const log = isFromPublic ? await PublicLog.random() : PrivateLog.random(); - const noteHashes = [Fr.random(), Fr.random()]; - const firstNullifier = Fr.random(); - return new TxScopedL2Log(TxHash.random(), BlockNumber(1), 1n, log, noteHashes, firstNullifier); + return new TxScopedL2Log(txHash, blockNumber, blockTimestamp, logData, noteHashes, firstNullifier); } equals(other: TxScopedL2Log) { @@ -103,12 +88,48 @@ export class TxScopedL2Log { this.txHash.equals(other.txHash) && this.blockNumber === other.blockNumber && this.blockTimestamp === other.blockTimestamp && - ((this.log instanceof PublicLog && other.log instanceof PublicLog) || - (this.log instanceof PrivateLog && other.log instanceof PrivateLog)) && - this.log.equals(other.log as any) && + this.logData.length === other.logData.length && + this.logData.every((f, i) => f.equals(other.logData[i])) && this.noteHashes.length === other.noteHashes.length && this.noteHashes.every((h, i) => h.equals(other.noteHashes[i])) && this.firstNullifier.equals(other.firstNullifier) ); } + + static randomPrivate(opts?: { + tag?: Fr; + txHash?: TxHash; + blockNumber?: number; + blockTimestamp?: bigint; + noteHashes?: Fr[]; + firstNullifier?: Fr; + }) { + const log = PrivateLog.random(opts?.tag); + return new TxScopedL2Log( + opts?.txHash ?? TxHash.random(), + BlockNumber(opts?.blockNumber ?? 1), + opts?.blockTimestamp ?? 1n, + log.getEmittedFields(), + opts?.noteHashes ?? [Fr.random(), Fr.random()], + opts?.firstNullifier ?? Fr.random(), + ); + } + + static async randomPublic(opts?: { + txHash?: TxHash; + blockNumber?: number; + blockTimestamp?: bigint; + noteHashes?: Fr[]; + firstNullifier?: Fr; + }) { + const log = await PublicLog.random(); + return new TxScopedL2Log( + opts?.txHash ?? TxHash.random(), + BlockNumber(opts?.blockNumber ?? 1), + opts?.blockTimestamp ?? 1n, + log.getEmittedFields(), + opts?.noteHashes ?? [Fr.random(), Fr.random()], + opts?.firstNullifier ?? Fr.random(), + ); + } } From 468d96db047aff9dc778f30ec8841091c179b219 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 23 Dec 2025 21:42:34 +0000 Subject: [PATCH 4/7] cleanup --- yarn-project/pxe/src/logs/log_service.test.ts | 9 ++-- ...ate_logs_for_sender_recipient_pair.test.ts | 6 +-- .../utils/find_highest_indexes.test.ts | 3 +- .../utils/load_logs_for_range.test.ts | 5 ++- .../sync/sync_sender_tagging_indexes.test.ts | 4 +- ...load_and_store_new_tagging_indexes.test.ts | 5 ++- .../stdlib/src/interfaces/archiver.test.ts | 5 ++- .../stdlib/src/interfaces/aztec-node.test.ts | 5 ++- .../src/interfaces/get_logs_response.test.ts | 3 +- .../stdlib/src/logs/tx_scoped_l2_log.ts | 39 ---------------- yarn-project/stdlib/src/tests/factories.ts | 45 +++++++++++++++++++ 11 files changed, 71 insertions(+), 58 deletions(-) diff --git a/yarn-project/pxe/src/logs/log_service.test.ts b/yarn-project/pxe/src/logs/log_service.test.ts index dedd0e8560a7..75d7701a5cc9 100644 --- a/yarn-project/pxe/src/logs/log_service.test.ts +++ b/yarn-project/pxe/src/logs/log_service.test.ts @@ -5,6 +5,7 @@ import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; import { Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; +import { randomTxScopedPrivateL2Log } from '@aztec/stdlib/testing'; import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -68,7 +69,7 @@ describe('LogService', () => { }); it('returns a public log if one is found', async () => { - const scopedLog = TxScopedL2Log.randomPrivate(); + const scopedLog = randomTxScopedPrivateL2Log(); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); aztecNode.getPrivateLogsByTags.mockResolvedValue([[]]); @@ -82,7 +83,7 @@ describe('LogService', () => { }); it('returns a private log if one is found', async () => { - const scopedLog = TxScopedL2Log.randomPrivate(); + const scopedLog = randomTxScopedPrivateL2Log(); aztecNode.getPrivateLogsByTags.mockResolvedValue([[scopedLog]]); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[]]); @@ -113,7 +114,7 @@ describe('LogService', () => { it('returns log data when single log found', async () => { const logContractAddress = await AztecAddress.random(); - const scopedLog = TxScopedL2Log.randomPrivate(); + const scopedLog = randomTxScopedPrivateL2Log(); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); @@ -129,7 +130,7 @@ describe('LogService', () => { it('throws if multiple logs found for tag', async () => { const logContractAddress = await AztecAddress.random(); - const scopedLog = TxScopedL2Log.randomPrivate(); + const scopedLog = randomTxScopedPrivateL2Log(); aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog, scopedLog]]); await expect(logService.getPublicLogByTag(tag, logContractAddress)).rejects.toThrow(/Got 2 logs for tag/); diff --git a/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts index bfabf854dc8f..6ca7fba0d38d 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.test.ts @@ -4,8 +4,8 @@ import { Fr } from '@aztec/foundation/curves/bn254'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; -import { DirectionalAppTaggingSecret, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; -import { makeBlockHeader } from '@aztec/stdlib/testing'; +import { DirectionalAppTaggingSecret, SiloedTag, Tag } from '@aztec/stdlib/logs'; +import { makeBlockHeader, randomTxScopedPrivateL2Log } from '@aztec/stdlib/testing'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -32,7 +32,7 @@ describe('loadPrivateLogsForSenderRecipientPair', () => { } function makeLog(blockNumber: number, blockTimestamp: bigint, tag: Fr) { - return TxScopedL2Log.randomPrivate({ blockNumber, blockTimestamp, tag }); + return randomTxScopedPrivateL2Log({ blockNumber, blockTimestamp, tag }); } beforeAll(async () => { diff --git a/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts index a6ef8bb88ff4..73adcd51f51d 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/utils/find_highest_indexes.test.ts @@ -1,5 +1,6 @@ import { MAX_INCLUDE_BY_TIMESTAMP_DURATION } from '@aztec/constants'; import { TxScopedL2Log } from '@aztec/stdlib/logs'; +import { randomTxScopedPrivateL2Log } from '@aztec/stdlib/testing'; import { findHighestIndexes } from './find_highest_indexes.js'; @@ -7,7 +8,7 @@ describe('findHighestIndexes', () => { const currentTimestamp = BigInt(Math.floor(Date.now() / 1000)); function makeLog(blockNumber: number, blockTimestamp: bigint): TxScopedL2Log { - return TxScopedL2Log.randomPrivate({ blockNumber, blockTimestamp }); + return randomTxScopedPrivateL2Log({ blockNumber, blockTimestamp }); } it('returns undefined for highestAgedIndex when no logs are at least 24 hours old', () => { diff --git a/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts b/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts index 777281bc0ed0..42ef7f523f88 100644 --- a/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts +++ b/yarn-project/pxe/src/tagging/recipient_sync/utils/load_logs_for_range.test.ts @@ -2,7 +2,8 @@ import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; -import { DirectionalAppTaggingSecret, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; +import { DirectionalAppTaggingSecret, SiloedTag, Tag } from '@aztec/stdlib/logs'; +import { randomTxScopedPrivateL2Log } from '@aztec/stdlib/testing'; import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -26,7 +27,7 @@ describe('loadLogsForRange', () => { } function makeLog(txHash: TxHash, blockNumber: number, blockTimestamp: bigint, tag: SiloedTag) { - return TxScopedL2Log.randomPrivate({ txHash, blockNumber, blockTimestamp, tag: tag.value }); + return randomTxScopedPrivateL2Log({ txHash, blockNumber, blockTimestamp, tag: tag.value }); } beforeAll(async () => { diff --git a/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts b/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts index 001a875d0f76..16c5361ca9fa 100644 --- a/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/sync/sync_sender_tagging_indexes.test.ts @@ -2,7 +2,7 @@ import { Fr } from '@aztec/foundation/curves/bn254'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/client'; -import { TxScopedL2Log } from '@aztec/stdlib/logs'; +import { randomTxScopedPrivateL2Log } from '@aztec/stdlib/testing'; import { TxHash, TxStatus } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -25,7 +25,7 @@ describe('syncSenderTaggingIndexes', () => { } function makeLog(txHash: TxHash, tag: Fr) { - return TxScopedL2Log.randomPrivate({ txHash, tag }); + return randomTxScopedPrivateL2Log({ txHash, tag }); } async function setUp() { diff --git a/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts b/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts index bcd17dc1511d..c6c26c8fe78f 100644 --- a/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts +++ b/yarn-project/pxe/src/tagging/sync/utils/load_and_store_new_tagging_indexes.test.ts @@ -2,7 +2,8 @@ import { Fr } from '@aztec/foundation/curves/bn254'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; -import { DirectionalAppTaggingSecret, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; +import { DirectionalAppTaggingSecret, SiloedTag, Tag } from '@aztec/stdlib/logs'; +import { randomTxScopedPrivateL2Log } from '@aztec/stdlib/testing'; import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -24,7 +25,7 @@ describe('loadAndStoreNewTaggingIndexes', () => { } function makeLog(txHash: TxHash, tag: Fr) { - return TxScopedL2Log.randomPrivate({ txHash, tag }); + return randomTxScopedPrivateL2Log({ txHash, tag }); } beforeAll(async () => { diff --git a/yarn-project/stdlib/src/interfaces/archiver.test.ts b/yarn-project/stdlib/src/interfaces/archiver.test.ts index 92b519387021..217ab736e5b3 100644 --- a/yarn-project/stdlib/src/interfaces/archiver.test.ts +++ b/yarn-project/stdlib/src/interfaces/archiver.test.ts @@ -30,6 +30,7 @@ import type { LogFilter } from '../logs/log_filter.js'; import { SiloedTag } from '../logs/siloed_tag.js'; import { Tag } from '../logs/tag.js'; import { TxScopedL2Log } from '../logs/tx_scoped_l2_log.js'; +import { randomTxScopedPrivateL2Log } from '../tests/factories.js'; import { getTokenContractArtifact } from '../tests/fixtures.js'; import { BlockHeader } from '../tx/block_header.js'; import type { IndexedTxEffect } from '../tx/indexed_tx_effect.js'; @@ -451,7 +452,7 @@ class MockArchiver implements ArchiverApi { } getPrivateLogsByTags(tags: SiloedTag[], _logsPerTag?: number): Promise { expect(tags[0]).toBeInstanceOf(SiloedTag); - return Promise.resolve([tags.map(() => TxScopedL2Log.randomPrivate())]); + return Promise.resolve([tags.map(() => randomTxScopedPrivateL2Log())]); } getPublicLogsByTagsFromContract( contractAddress: AztecAddress, @@ -460,7 +461,7 @@ class MockArchiver implements ArchiverApi { ): Promise { expect(contractAddress).toBeInstanceOf(AztecAddress); expect(tags[0]).toBeInstanceOf(Tag); - return Promise.resolve([tags.map(() => TxScopedL2Log.randomPrivate())]); + return Promise.resolve([tags.map(() => randomTxScopedPrivateL2Log())]); } async getPublicLogs(filter: LogFilter): Promise { expect(filter.txHash).toBeInstanceOf(TxHash); diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts index d760a15ddada..a2c16db0e04c 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts @@ -43,6 +43,7 @@ import type { LogFilter } from '../logs/log_filter.js'; import { SiloedTag } from '../logs/siloed_tag.js'; import { Tag } from '../logs/tag.js'; import { TxScopedL2Log } from '../logs/tx_scoped_l2_log.js'; +import { randomTxScopedPrivateL2Log } from '../tests/factories.js'; import { getTokenContractArtifact } from '../tests/fixtures.js'; import { MerkleTreeId } from '../trees/merkle_tree_id.js'; import { NullifierMembershipWitness } from '../trees/nullifier_membership_witness.js'; @@ -724,7 +725,7 @@ class MockAztecNode implements AztecNode { getPrivateLogsByTags(tags: SiloedTag[], _logsPerTag?: number): Promise { expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(SiloedTag); - return Promise.resolve([[TxScopedL2Log.randomPrivate()]]); + return Promise.resolve([[randomTxScopedPrivateL2Log()]]); } getPublicLogsByTagsFromContract( contractAddress: AztecAddress, @@ -734,7 +735,7 @@ class MockAztecNode implements AztecNode { expect(contractAddress).toBeInstanceOf(AztecAddress); expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(Tag); - return Promise.resolve([[TxScopedL2Log.randomPrivate()]]); + return Promise.resolve([[randomTxScopedPrivateL2Log()]]); } sendTx(tx: Tx): Promise { expect(tx).toBeInstanceOf(Tx); diff --git a/yarn-project/stdlib/src/interfaces/get_logs_response.test.ts b/yarn-project/stdlib/src/interfaces/get_logs_response.test.ts index 6dbf78cb69b0..c2a32c8d5a02 100644 --- a/yarn-project/stdlib/src/interfaces/get_logs_response.test.ts +++ b/yarn-project/stdlib/src/interfaces/get_logs_response.test.ts @@ -1,10 +1,11 @@ import { jsonStringify } from '@aztec/foundation/json-rpc'; import { TxScopedL2Log } from '../logs/tx_scoped_l2_log.js'; +import { randomTxScopedPrivateL2Log } from '../tests/factories.js'; describe('TxScopedL2Log', () => { it('serializes to JSON', () => { - const log = TxScopedL2Log.randomPrivate(); + const log = randomTxScopedPrivateL2Log(); expect(TxScopedL2Log.schema.parse(JSON.parse(jsonStringify(log)))).toEqual(log); }); }); diff --git a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts index 4b34289bd726..6eea00114399 100644 --- a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts +++ b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts @@ -13,8 +13,6 @@ import { z } from 'zod'; import { schemas } from '../schemas/schemas.js'; import { TxHash } from '../tx/tx_hash.js'; import type { UInt64 } from '../types/shared.js'; -import { PrivateLog } from './private_log.js'; -import { PublicLog } from './public_log.js'; export class TxScopedL2Log { constructor( @@ -95,41 +93,4 @@ export class TxScopedL2Log { this.firstNullifier.equals(other.firstNullifier) ); } - - static randomPrivate(opts?: { - tag?: Fr; - txHash?: TxHash; - blockNumber?: number; - blockTimestamp?: bigint; - noteHashes?: Fr[]; - firstNullifier?: Fr; - }) { - const log = PrivateLog.random(opts?.tag); - return new TxScopedL2Log( - opts?.txHash ?? TxHash.random(), - BlockNumber(opts?.blockNumber ?? 1), - opts?.blockTimestamp ?? 1n, - log.getEmittedFields(), - opts?.noteHashes ?? [Fr.random(), Fr.random()], - opts?.firstNullifier ?? Fr.random(), - ); - } - - static async randomPublic(opts?: { - txHash?: TxHash; - blockNumber?: number; - blockTimestamp?: bigint; - noteHashes?: Fr[]; - firstNullifier?: Fr; - }) { - const log = await PublicLog.random(); - return new TxScopedL2Log( - opts?.txHash ?? TxHash.random(), - BlockNumber(opts?.blockNumber ?? 1), - opts?.blockTimestamp ?? 1n, - log.getEmittedFields(), - opts?.noteHashes ?? [Fr.random(), Fr.random()], - opts?.firstNullifier ?? Fr.random(), - ); - } } diff --git a/yarn-project/stdlib/src/tests/factories.ts b/yarn-project/stdlib/src/tests/factories.ts index 1d50888685ab..050bbcfb69a9 100644 --- a/yarn-project/stdlib/src/tests/factories.ts +++ b/yarn-project/stdlib/src/tests/factories.ts @@ -131,6 +131,7 @@ import { PublicKeys, computeAddress } from '../keys/index.js'; import { ContractClassLog, ContractClassLogFields } from '../logs/index.js'; import { PrivateLog } from '../logs/private_log.js'; import { FlatPublicLogs, PublicLog } from '../logs/public_log.js'; +import { TxScopedL2Log } from '../logs/tx_scoped_l2_log.js'; import { CountedL2ToL1Message, L2ToL1Message, ScopedL2ToL1Message } from '../messaging/l2_to_l1_message.js'; import { ParityBasePrivateInputs } from '../parity/parity_base_private_inputs.js'; import { ParityPublicInputs } from '../parity/parity_public_inputs.js'; @@ -173,6 +174,7 @@ import { StateReference } from '../tx/state_reference.js'; import { TreeSnapshots } from '../tx/tree_snapshots.js'; import { TxConstantData } from '../tx/tx_constant_data.js'; import { TxContext } from '../tx/tx_context.js'; +import { TxHash } from '../tx/tx_hash.js'; import { TxRequest } from '../tx/tx_request.js'; import { Vector } from '../types/index.js'; import { VkData } from '../vks/index.js'; @@ -1696,3 +1698,46 @@ export async function makeAvmCircuitInputs( export function fr(n: number): Fr { return new Fr(BigInt(n)); } + +/** + * Creates a random TxScopedL2Log with private log data. + */ +export function randomTxScopedPrivateL2Log(opts?: { + tag?: Fr; + txHash?: TxHash; + blockNumber?: number; + blockTimestamp?: bigint; + noteHashes?: Fr[]; + firstNullifier?: Fr; +}) { + const log = PrivateLog.random(opts?.tag); + return new TxScopedL2Log( + opts?.txHash ?? TxHash.random(), + BlockNumber(opts?.blockNumber ?? 1), + opts?.blockTimestamp ?? 1n, + log.getEmittedFields(), + opts?.noteHashes ?? [Fr.random(), Fr.random()], + opts?.firstNullifier ?? Fr.random(), + ); +} + +/** + * Creates a random TxScopedL2Log with public log data. + */ +export async function randomTxScopedPublicL2Log(opts?: { + txHash?: TxHash; + blockNumber?: number; + blockTimestamp?: bigint; + noteHashes?: Fr[]; + firstNullifier?: Fr; +}) { + const log = await PublicLog.random(); + return new TxScopedL2Log( + opts?.txHash ?? TxHash.random(), + BlockNumber(opts?.blockNumber ?? 1), + opts?.blockTimestamp ?? 1n, + log.getEmittedFields(), + opts?.noteHashes ?? [Fr.random(), Fr.random()], + opts?.firstNullifier ?? Fr.random(), + ); +} From ee964356e02182b403ee36260a14b2d223ac7aeb Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 24 Dec 2025 01:10:22 +0000 Subject: [PATCH 5/7] test fixes --- .../src/archiver/archiver_store_test_suite.ts | 40 +++++-------------- yarn-project/stdlib/src/tx/tx_effect.ts | 4 +- 2 files changed, 13 insertions(+), 31 deletions(-) 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 0cd292f299ef..48732c8f07d4 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -2276,17 +2276,13 @@ export function describeArchiverDataStore( [ expect.objectContaining({ blockNumber: 2, - blockHash: L2BlockHash.fromField(await logsCheckpoints[2 - 1].checkpoint.blocks[0].header.hash()), - log: makePrivateLog(tags[0]), - isFromPublic: false, + logData: makePrivateLog(tags[0]).getEmittedFields(), }), ], [ expect.objectContaining({ blockNumber: 1, - blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()), - log: makePrivateLog(tags[1]), - isFromPublic: false, + logData: makePrivateLog(tags[1]).getEmittedFields(), }), ], ]); @@ -2312,15 +2308,11 @@ export function describeArchiverDataStore( [ expect.objectContaining({ blockNumber: 1, - blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()), - log: makePrivateLog(tags[0]), - isFromPublic: false, + logData: makePrivateLog(tags[0]).getEmittedFields(), }), expect.objectContaining({ blockNumber: newBlockNumber, - blockHash: L2BlockHash.fromField(await newCheckpoint.checkpoint.blocks[0].header.hash()), - log: newLog, - isFromPublic: false, + logData: newLog.getEmittedFields(), }), ], ]); @@ -2338,9 +2330,7 @@ export function describeArchiverDataStore( [ expect.objectContaining({ blockNumber: 1, - blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()), - log: makePrivateLog(tags[1]), - isFromPublic: false, + logData: makePrivateLog(tags[1]).getEmittedFields(), }), ], ]); @@ -2425,17 +2415,13 @@ export function describeArchiverDataStore( [ expect.objectContaining({ blockNumber: 2, - blockHash: L2BlockHash.fromField(await logsCheckpoints[2 - 1].checkpoint.blocks[0].header.hash()), - log: makePublicLog(tags[0]), - isFromPublic: true, + logData: makePublicLog(tags[0]).getEmittedFields(), }), ], [ expect.objectContaining({ blockNumber: 1, - blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()), - log: makePublicLog(tags[1]), - isFromPublic: true, + logData: makePublicLog(tags[1]).getEmittedFields(), }), ], ]); @@ -2461,15 +2447,11 @@ export function describeArchiverDataStore( [ expect.objectContaining({ blockNumber: 1, - blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()), - log: makePublicLog(tags[0]), - isFromPublic: true, + logData: makePublicLog(tags[0]).getEmittedFields(), }), expect.objectContaining({ blockNumber: newBlockNumber, - blockHash: L2BlockHash.fromField(await newCheckpoint.checkpoint.blocks[0].header.hash()), - log: newLog, - isFromPublic: true, + logData: newLog.getEmittedFields(), }), ], ]); @@ -2487,9 +2469,7 @@ export function describeArchiverDataStore( [ expect.objectContaining({ blockNumber: 1, - blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()), - log: makePublicLog(tags[1]), - isFromPublic: true, + logData: makePublicLog(tags[1]).getEmittedFields(), }), ], ]); diff --git a/yarn-project/stdlib/src/tx/tx_effect.ts b/yarn-project/stdlib/src/tx/tx_effect.ts index c0bbef9ed2a4..ad861091fb9d 100644 --- a/yarn-project/stdlib/src/tx/tx_effect.ts +++ b/yarn-project/stdlib/src/tx/tx_effect.ts @@ -214,12 +214,14 @@ export class TxEffect { maxEffects?: number; } = {}): Promise { const count = (max: number, num?: number) => num ?? Math.min(maxEffects ?? randomInt(max), max); + // Every tx effect must have at least 1 nullifier (the first nullifier is used for log indexing) + const countNullifiers = (max: number, num?: number) => Math.max(1, count(max, num)); return new TxEffect( RevertCode.random(), TxHash.random(), new Fr(Math.floor(Math.random() * 100_000)), makeTuple(count(MAX_NOTE_HASHES_PER_TX, numNoteHashes), Fr.random), - makeTuple(count(MAX_NULLIFIERS_PER_TX, numNullifiers), Fr.random), + makeTuple(countNullifiers(MAX_NULLIFIERS_PER_TX, numNullifiers), Fr.random), makeTuple(count(MAX_L2_TO_L1_MSGS_PER_TX, numL2ToL1Msgs), Fr.random), makeTuple(count(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, numPublicDataWrites), PublicDataWrite.random), makeTuple(count(MAX_PRIVATE_LOGS_PER_TX, numPrivateLogs), () => PrivateLog.random()), From 6b89008ef8de4fb40d8d1b459d5a9bc8515ecef7 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 24 Dec 2025 01:10:33 +0000 Subject: [PATCH 6/7] migration notes --- .../docs/resources/migration_notes.md | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/docs/docs-developers/docs/resources/migration_notes.md b/docs/docs-developers/docs/resources/migration_notes.md index 68d285815afe..bb104d239e64 100644 --- a/docs/docs-developers/docs/resources/migration_notes.md +++ b/docs/docs-developers/docs/resources/migration_notes.md @@ -9,26 +9,34 @@ Aztec is in full-speed development. Literally every version breaks compatibility ## TBD +### [Aztec Node] changes to `getLogsByTags` endpoint + +`getLogsByTags` endpoint has been optimized for our new log sync algorithm and these are the changes: + +- The `logsPerTag` pagination argument has been removed. Pagination was unnecessary here, since multiple logs per tag typically only occur if several devices are sending logs from the same sender to a recipient, which is unlikely to generate enough logs to require pagination. +- The structure of `TxScopedL2Log` has been revised to meet the requirements of our new log sync algorithm. +- The endpoint has been separated into two versions: `getPrivateLogsByTags` and `getPublicLogsByTagsFromContract`. This change was made because it was never desirable in PXE to mix public and private logs. The public version requires both a `Tag` and a contract address as input. In contrast to the private version—which uses `SiloedTag` (a tag that hashes the raw tag with the emitting contract's address)—the public version uses the raw `Tag` type, since kernels do not hash the tag with the contract address for public logs. + ### [AVM] Gas cost multipliers for public execution to reach simulation/proving parity Gas costs for several AVM opcodes have been adjusted with multipliers to better align public simulation costs with actual proving costs. -| Opcode | Multiplier | Previous Cost | New Cost | -|--------|------------|---------------|----------| -| FDIV | 25x | 9 | 225 | -| SLOAD | 10x | 129 | 1,290 | -| SSTORE | 20x | 1,657 | 33,140 | -| NOTEHASHEXISTS | 4x | 126 | 504 | -| EMITNOTEHASH | 15x | 1,285 | 19,275 | -| NULLIFIEREXISTS | 7x | 132 | 924 | -| EMITNULLIFIER | 20x | 1,540 | 30,800 | -| L1TOL2MSGEXISTS | 5x | 108 | 540 | -| SENDL2TOL1MSG | 2x | 209 | 418 | -| CALL | 3x | 3,312 | 9,936 | -| STATICCALL | 3x | 3,312 | 9,936 | -| GETCONTRACTINSTANCE | 4x | 1,527 | 6,108 | -| POSEIDON2 | 15x | 24 | 360 | -| ECADD | 10x | 27 | 270 | +| Opcode | Multiplier | Previous Cost | New Cost | +| ------------------- | ---------- | ------------- | -------- | +| FDIV | 25x | 9 | 225 | +| SLOAD | 10x | 129 | 1,290 | +| SSTORE | 20x | 1,657 | 33,140 | +| NOTEHASHEXISTS | 4x | 126 | 504 | +| EMITNOTEHASH | 15x | 1,285 | 19,275 | +| NULLIFIEREXISTS | 7x | 132 | 924 | +| EMITNULLIFIER | 20x | 1,540 | 30,800 | +| L1TOL2MSGEXISTS | 5x | 108 | 540 | +| SENDL2TOL1MSG | 2x | 209 | 418 | +| CALL | 3x | 3,312 | 9,936 | +| STATICCALL | 3x | 3,312 | 9,936 | +| GETCONTRACTINSTANCE | 4x | 1,527 | 6,108 | +| POSEIDON2 | 15x | 24 | 360 | +| ECADD | 10x | 27 | 270 | **Impact**: Contracts with public bytecode performing any of these operations will see increased gas consumption. From eb9692abf4563d62f7b7751bafc6e3031d021422 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 24 Dec 2025 01:22:29 +0000 Subject: [PATCH 7/7] final cleanup --- yarn-project/pxe/src/logs/log_service.test.ts | 65 +------------------ yarn-project/pxe/src/logs/log_service.ts | 11 ++-- 2 files changed, 5 insertions(+), 71 deletions(-) diff --git a/yarn-project/pxe/src/logs/log_service.test.ts b/yarn-project/pxe/src/logs/log_service.test.ts index 75d7701a5cc9..c5d50795dacb 100644 --- a/yarn-project/pxe/src/logs/log_service.test.ts +++ b/yarn-project/pxe/src/logs/log_service.test.ts @@ -1,12 +1,10 @@ -import { BlockNumber } from '@aztec/foundation/branded-types'; import { Fr } from '@aztec/foundation/curves/bn254'; import { KeyStore } from '@aztec/key-store'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { AztecNode } from '@aztec/stdlib/interfaces/server'; -import { Tag, TxScopedL2Log } from '@aztec/stdlib/logs'; +import { Tag } from '@aztec/stdlib/logs'; import { randomTxScopedPrivateL2Log } from '@aztec/stdlib/testing'; -import { TxHash } from '@aztec/stdlib/tx'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -96,65 +94,4 @@ describe('LogService', () => { expect(responses[0]).not.toBeNull(); }); }); - - describe('getPublicLogByTag', () => { - const tag = new Tag(Fr.random()); - - beforeEach(() => { - aztecNode.getPublicLogsByTagsFromContract.mockReset(); - aztecNode.getTxEffect.mockReset(); - }); - - it('returns null if no logs found for tag', async () => { - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[]]); - - const result = await logService.getPublicLogByTag(tag, contractAddress); - expect(result).toBeNull(); - }); - - it('returns log data when single log found', async () => { - const logContractAddress = await AztecAddress.random(); - const scopedLog = randomTxScopedPrivateL2Log(); - - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); - - const result = (await logService.getPublicLogByTag(tag, logContractAddress))!; - - expect(result.logPayload).toEqual(scopedLog.logData.slice(1)); - expect(result.uniqueNoteHashesInTx).toEqual(scopedLog.noteHashes); - expect(result.txHash).toEqual(scopedLog.txHash); - expect(result.firstNullifierInTx).toEqual(scopedLog.firstNullifier); - - expect(aztecNode.getPublicLogsByTagsFromContract).toHaveBeenCalledWith(logContractAddress, [tag]); - }); - - it('throws if multiple logs found for tag', async () => { - const logContractAddress = await AztecAddress.random(); - const scopedLog = randomTxScopedPrivateL2Log(); - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog, scopedLog]]); - - await expect(logService.getPublicLogByTag(tag, logContractAddress)).rejects.toThrow(/Got 2 logs for tag/); - }); - - it('returns log fields that are actually emitted', async () => { - const logContractAddress = await AztecAddress.random(); - const logPlaintext = [Fr.random()]; - const logContent = [tag.value, ...logPlaintext]; - - const scopedLogWithPadding = new TxScopedL2Log( - TxHash.random(), - BlockNumber(1), - 1n, - logContent, - [Fr.random(), Fr.random()], - Fr.random(), - ); - - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLogWithPadding]]); - - const result = await logService.getPublicLogByTag(tag, logContractAddress); - - expect(result?.logPayload).toEqual(logPlaintext); - }); - }); }); diff --git a/yarn-project/pxe/src/logs/log_service.ts b/yarn-project/pxe/src/logs/log_service.ts index b5e7f0247e39..3d4a4819fd68 100644 --- a/yarn-project/pxe/src/logs/log_service.ts +++ b/yarn-project/pxe/src/logs/log_service.ts @@ -39,10 +39,9 @@ export class LogService { public async bulkRetrieveLogs(logRetrievalRequests: LogRetrievalRequest[]): Promise<(LogRetrievalResponse | null)[]> { return await Promise.all( logRetrievalRequests.map(async request => { - // TODO(F-231): remove these internal functions and have node endpoints that do this instead const [publicLog, privateLog] = await Promise.all([ - this.getPublicLogByTag(request.tag, request.contractAddress), - this.getPrivateLogByTag(await SiloedTag.compute(request.tag, request.contractAddress)), + this.#getPublicLogByTag(request.tag, request.contractAddress), + this.#getPrivateLogByTag(await SiloedTag.compute(request.tag, request.contractAddress)), ]); if (publicLog !== null) { @@ -72,8 +71,7 @@ export class LogService { ); } - // TODO(F-231): delete this function and implement this behavior in the node instead - public async getPublicLogByTag(tag: Tag, contractAddress: AztecAddress): Promise { + async #getPublicLogByTag(tag: Tag, contractAddress: AztecAddress): Promise { const logs = await this.aztecNode.getPublicLogsByTagsFromContract(contractAddress, [tag]); const logsForTag = logs[0]; @@ -96,8 +94,7 @@ export class LogService { ); } - // TODO(F-231): delete this function and implement this behavior in the node instead - public async getPrivateLogByTag(siloedTag: SiloedTag): Promise { + async #getPrivateLogByTag(siloedTag: SiloedTag): Promise { const logs = await this.aztecNode.getPrivateLogsByTags([siloedTag]); const logsForTag = logs[0];