From 8c91b25be590027fb56b65d5b78091919c6a987b Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 3 Oct 2023 13:40:22 +0000 Subject: [PATCH 01/60] WIP --- .../aztec-node/src/aztec-node/server.ts | 19 +++++++++ .../pxe/src/pxe_service/pxe_service.ts | 20 +++++++-- .../types/src/interfaces/aztec-node.ts | 17 +++++++- yarn-project/types/src/interfaces/pxe.ts | 25 ++++++----- .../src/logs/extended_unencrypted_l2_log.ts | 41 +++++++++++++++++++ yarn-project/types/src/logs/index.ts | 1 + yarn-project/types/src/logs/l2_logs_source.ts | 18 ++++++++ 7 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 yarn-project/types/src/logs/extended_unencrypted_l2_log.ts diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index f9b828e89df..f92f45ef3db 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -3,6 +3,7 @@ import { CONTRACT_TREE_HEIGHT, CircuitsWasm, Fr, + FunctionSelector, GlobalVariables, HistoricBlockData, L1_TO_L2_MSG_TREE_HEIGHT, @@ -24,6 +25,7 @@ import { ContractData, ContractDataSource, ExtendedContractData, + ExtendedUnencryptedL2Log, L1ToL2MessageAndIndex, L1ToL2MessageSource, L2Block, @@ -225,6 +227,23 @@ export class AztecNodeService implements AztecNode { return logSource.getLogs(from, limit, logType); } + /** + * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. + * @param from - Number of the L2 block to which corresponds the first logs to be returned. + * @param limit - The maximum number of logs to return. + * @param contractAddress - The contract address to filter logs by. + * @param selector - The event selector to filter logs by. + * @returns The requested logs. + */ + public getUnencryptedLogs( + from: number, + limit: number, + contractAddress: AztecAddress, + selector: FunctionSelector, + ): Promise { + return this.unencryptedLogsSource.getUnencryptedLogs(from, limit, contractAddress, selector); + } + /** * Method to submit a transaction to the p2p pool. * @param tx - The transaction to be submitted. diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 83177e46e96..a714794c8e5 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -12,6 +12,7 @@ import { CompleteAddress, EthAddress, FunctionData, + FunctionSelector, GrumpkinPrivateKey, KernelCircuitPublicInputsFinal, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, @@ -31,10 +32,10 @@ import { ContractData, DeployedContract, ExtendedContractData, + ExtendedUnencryptedL2Log, FunctionCall, KeyStore, L2Block, - L2BlockL2Logs, L2Tx, LogType, MerkleTreeId, @@ -384,8 +385,21 @@ export class PXEService implements PXE { return await this.node.getContractData(contractAddress); } - public async getUnencryptedLogs(from: number, limit: number): Promise { - return await this.node.getLogs(from, limit, LogType.UNENCRYPTED); + /** + * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. + * @param from - Number of the L2 block to which corresponds the first logs to be returned. + * @param limit - The maximum number of logs to return. + * @param contractAddress - The contract address to filter logs by. + * @param selector - The event selector to filter logs by. + * @returns The requested logs. + */ + public getUnencryptedLogs( + from: number, + limit: number, + contractAddress: AztecAddress, + selector: FunctionSelector, + ): Promise { + return this.node.getUnencryptedLogs(from, limit, contractAddress, selector); } async #getFunctionCall(functionName: string, args: any[], to: AztecAddress): Promise { diff --git a/yarn-project/types/src/interfaces/aztec-node.ts b/yarn-project/types/src/interfaces/aztec-node.ts index 231e1ea9446..d5798912e73 100644 --- a/yarn-project/types/src/interfaces/aztec-node.ts +++ b/yarn-project/types/src/interfaces/aztec-node.ts @@ -1,4 +1,4 @@ -import { HistoricBlockData } from '@aztec/circuits.js'; +import { FunctionSelector, HistoricBlockData } from '@aztec/circuits.js'; import { L1ContractAddresses } from '@aztec/ethereum'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; @@ -90,6 +90,21 @@ export interface AztecNode extends StateInfoProvider { */ getLogs(from: number, limit: number, logType: LogType): Promise; + /** + * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. + * @param from - Number of the L2 block to which corresponds the first logs to be returned. + * @param limit - The maximum number of logs to return. + * @param contractAddress - The contract address to filter logs by. + * @param selector - The event selector to filter logs by. + * @returns The requested logs. + */ + getUnencryptedLogs( + from: number, + limit: number, + contractAddress: AztecAddress, + selector: FunctionSelector, + ): Promise; + /** * Method to submit a transaction to the p2p pool. * @param tx - The transaction to be submitted. diff --git a/yarn-project/types/src/interfaces/pxe.ts b/yarn-project/types/src/interfaces/pxe.ts index b3907ebab6d..ce608fdf7f2 100644 --- a/yarn-project/types/src/interfaces/pxe.ts +++ b/yarn-project/types/src/interfaces/pxe.ts @@ -1,16 +1,16 @@ -import { AztecAddress, Fr, GrumpkinPrivateKey, PartialAddress } from '@aztec/circuits.js'; +import { AztecAddress, Fr, FunctionSelector, GrumpkinPrivateKey, PartialAddress } from '@aztec/circuits.js'; import { AuthWitness, CompleteAddress, ContractData, ExtendedContractData, - L2BlockL2Logs, + ExtendedUnencryptedL2Log, L2Tx, NotePreimage, Tx, TxExecutionRequest, TxHash, - TxReceipt, + TxReceipt } from '@aztec/types'; import { DeployedContract } from './deployed-contract.js'; @@ -231,14 +231,19 @@ export interface PXE { getContractData(contractAddress: AztecAddress): Promise; /** - * Gets unencrypted public logs from the specified block range. Logs are grouped by block and then by - * transaction. Use the `L2BlockL2Logs.unrollLogs` helper function to get an flattened array of logs instead. - * - * @param from - Number of the L2 block to which corresponds the first unencrypted logs to be returned. - * @param limit - The maximum number of unencrypted logs to return. - * @returns The requested unencrypted logs. + * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. + * @param from - Number of the L2 block to which corresponds the first logs to be returned. + * @param limit - The maximum number of logs to return. + * @param contractAddress - The contract address to filter logs by. + * @param selector - The event selector to filter logs by. + * @returns The requested logs. */ - getUnencryptedLogs(from: number, limit: number): Promise; + getUnencryptedLogs( + from: number, + limit: number, + contractAddress: AztecAddress, + selector: FunctionSelector, + ): Promise; /** * Fetches the current block number. diff --git a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts new file mode 100644 index 00000000000..22f4d410795 --- /dev/null +++ b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts @@ -0,0 +1,41 @@ +import { toBufferBE } from '@aztec/foundation/bigint-buffer'; +import { BufferReader } from '@aztec/foundation/serialize'; + +import { TxHash, UnencryptedL2Log } from '../index.js'; + +/** + * Represents an individual unencrypted log entry extended with info about the block and tx it was emitted in. + */ +export class ExtendedUnencryptedL2Log { + constructor( + /** Number of L2 block the log was emitted in. */ + public readonly blockNumber: number, + /** Selector of the event/log topic. */ + public readonly txHash: TxHash, + /** The data contents of the log. */ + public readonly log: UnencryptedL2Log, + ) {} + + /** + * Serializes log to a buffer. + * @returns A buffer containing the serialized log. + */ + public toBuffer(): Buffer { + return Buffer.concat([toBufferBE(BigInt(this.blockNumber), 4), this.txHash.buffer, this.log.toBuffer()]); + } + + /** + * Deserializes log from a buffer. + * @param buffer - The buffer or buffer reader containing the log. + * @returns Deserialized instance of `Log`. + */ + public static fromBuffer(buffer: Buffer | BufferReader): ExtendedUnencryptedL2Log { + const reader = BufferReader.asReader(buffer); + + const blockNumber = reader.readNumber(); + const txHash = new TxHash(reader.readBytes(TxHash.SIZE)); + const log = UnencryptedL2Log.fromBuffer(reader); + + return new ExtendedUnencryptedL2Log(blockNumber, txHash, log); + } +} diff --git a/yarn-project/types/src/logs/index.ts b/yarn-project/types/src/logs/index.ts index cea46901df1..aefddf0d2f2 100644 --- a/yarn-project/types/src/logs/index.ts +++ b/yarn-project/types/src/logs/index.ts @@ -5,3 +5,4 @@ export * from './log_type.js'; export * from './note_spending_info/index.js'; export * from './tx_l2_logs.js'; export * from './unencrypted_l2_log.js'; +export * from './extended_unencrypted_l2_log.js'; diff --git a/yarn-project/types/src/logs/l2_logs_source.ts b/yarn-project/types/src/logs/l2_logs_source.ts index a21d5ccedd3..e5a8ffd522d 100644 --- a/yarn-project/types/src/logs/l2_logs_source.ts +++ b/yarn-project/types/src/logs/l2_logs_source.ts @@ -1,3 +1,6 @@ +import { AztecAddress, FunctionSelector } from '@aztec/circuits.js'; + +import { ExtendedUnencryptedL2Log } from './extended_unencrypted_l2_log.js'; import { L2BlockL2Logs } from './l2_block_l2_logs.js'; import { LogType } from './log_type.js'; @@ -14,6 +17,21 @@ export interface L2LogsSource { */ getLogs(from: number, limit: number, logType: LogType): Promise; + /** + * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. + * @param from - Number of the L2 block to which corresponds the first logs to be returned. + * @param limit - The maximum number of logs to return. + * @param contractAddress - The contract address to filter logs by. + * @param selector - The event selector to filter logs by. + * @returns The requested logs. + */ + getUnencryptedLogs( + from: number, + limit: number, + contractAddress: AztecAddress, + selector: FunctionSelector, + ): Promise; + /** * Starts the encrypted logs source. * @param blockUntilSynced - If true, blocks until the data source has fully synced. From cb916ee557be9c2e97257b096968fd01efbf79b6 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 3 Oct 2023 14:49:18 +0000 Subject: [PATCH 02/60] WIP --- yarn-project/aztec.js/src/wallet/base_wallet.ts | 12 +++++++++--- yarn-project/types/src/interfaces/aztec-node.ts | 1 + yarn-project/types/src/interfaces/pxe.ts | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index fb7949db8b3..0dc04543159 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -1,9 +1,10 @@ -import { AztecAddress, Fr, GrumpkinPrivateKey, PartialAddress } from '@aztec/circuits.js'; +import { AztecAddress, Fr, FunctionSelector, GrumpkinPrivateKey, PartialAddress } from '@aztec/circuits.js'; import { AuthWitness, ContractData, DeployedContract, ExtendedContractData, + ExtendedUnencryptedL2Log, FunctionCall, L2BlockL2Logs, L2Tx, @@ -96,8 +97,13 @@ export abstract class BaseWallet implements Wallet { getContractData(contractAddress: AztecAddress): Promise { return this.pxe.getContractData(contractAddress); } - getUnencryptedLogs(from: number, limit: number): Promise { - return this.pxe.getUnencryptedLogs(from, limit); + public getUnencryptedLogs( + from: number, + limit: number, + contractAddress: AztecAddress, + selector: FunctionSelector, + ): Promise { + return this.pxe.getUnencryptedLogs(from, limit, contractAddress, selector); } getBlockNumber(): Promise { return this.pxe.getBlockNumber(); diff --git a/yarn-project/types/src/interfaces/aztec-node.ts b/yarn-project/types/src/interfaces/aztec-node.ts index d5798912e73..1d0c95f4761 100644 --- a/yarn-project/types/src/interfaces/aztec-node.ts +++ b/yarn-project/types/src/interfaces/aztec-node.ts @@ -6,6 +6,7 @@ import { Fr } from '@aztec/foundation/fields'; import { ContractData, ExtendedContractData, + ExtendedUnencryptedL2Log, L2Block, L2BlockL2Logs, L2Tx, diff --git a/yarn-project/types/src/interfaces/pxe.ts b/yarn-project/types/src/interfaces/pxe.ts index ce608fdf7f2..f2d74d277c5 100644 --- a/yarn-project/types/src/interfaces/pxe.ts +++ b/yarn-project/types/src/interfaces/pxe.ts @@ -10,7 +10,7 @@ import { Tx, TxExecutionRequest, TxHash, - TxReceipt + TxReceipt, } from '@aztec/types'; import { DeployedContract } from './deployed-contract.js'; From 90885db7cea02518693d221e297135ca5517db12 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 4 Oct 2023 10:21:57 +0000 Subject: [PATCH 03/60] WIP --- .../archiver/src/archiver/archiver.ts | 11 +++++ .../archiver/src/archiver/archiver_store.ts | 42 +++++++++++++++++++ .../aztec.js/src/wallet/base_wallet.ts | 13 ++---- .../pxe/src/pxe_service/pxe_service.ts | 19 +++------ .../types/src/interfaces/aztec-node.ts | 15 ++----- yarn-project/types/src/interfaces/pxe.ts | 17 +++----- yarn-project/types/src/logs/index.ts | 1 + yarn-project/types/src/logs/l2_logs_source.ts | 17 ++------ yarn-project/types/src/logs/log_filter.ts | 17 ++++++++ 9 files changed, 93 insertions(+), 59 deletions(-) create mode 100644 yarn-project/types/src/logs/log_filter.ts diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index ea9c82d3822..6aa42353bdb 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -10,6 +10,7 @@ import { ContractDataSource, EncodedContractFunction, ExtendedContractData, + ExtendedUnencryptedL2Log, INITIAL_L2_BLOCK_NUM, L1ToL2Message, L1ToL2MessageSource, @@ -18,6 +19,7 @@ import { L2BlockSource, L2LogsSource, L2Tx, + LogFilter, LogType, TxHash, } from '@aztec/types'; @@ -389,6 +391,15 @@ export class Archiver implements L2BlockSource, L2LogsSource, ContractDataSource return this.store.getLogs(from, limit, logType); } + /** + * Gets unencrypted logs based on the provided filter. + * @param filter - The filter to apply to the logs. + * @returns The requested logs. + */ + getUnencryptedLogs(filter: LogFilter): Promise { + return this.store.getUnencryptedLogs(filter); + } + /** * Gets the number of the latest L2 block processed by the block source implementation. * @returns The number of the latest L2 block processed by the block source implementation. diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index b64a973f677..e6ce920e888 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -3,11 +3,13 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { ContractData, ExtendedContractData, + ExtendedUnencryptedL2Log, INITIAL_L2_BLOCK_NUM, L1ToL2Message, L2Block, L2BlockL2Logs, L2Tx, + LogFilter, LogType, TxHash, } from '@aztec/types'; @@ -94,6 +96,13 @@ export interface ArchiverDataStore { */ getLogs(from: number, limit: number, logType: LogType): Promise; + /** + * Gets unencrypted logs based on the provided filter. + * @param filter - The filter to apply to the logs. + * @returns The requested logs. + */ + getUnencryptedLogs(filter: LogFilter): Promise; + /** * Add new extended contract data from an L2 block to the store's list. * @param data - List of contracts' data to be added. @@ -347,6 +356,39 @@ export class MemoryArchiverStore implements ArchiverDataStore { return Promise.resolve(logs.slice(startIndex, endIndex)); } + /** + * Gets unencrypted logs based on the provided filter. + * @param filter - The filter to apply to the logs. + * @returns The requested logs. + */ + getUnencryptedLogs(filter: LogFilter): Promise { + const MAX_LOGS = 1000; + + const fromBlockIndex = (filter.fromBlock || INITIAL_L2_BLOCK_NUM) - INITIAL_L2_BLOCK_NUM; + if (fromBlockIndex > this.unencryptedLogs.length) { + return Promise.resolve([]); + } + + const toBlockIndex = + Math.min(filter.toBlock || this.unencryptedLogs.length, this.unencryptedLogs.length) - INITIAL_L2_BLOCK_NUM; + if (toBlockIndex < fromBlockIndex) { + return Promise.resolve([]); + } + + const limit = Math.min(filter.limit || MAX_LOGS, MAX_LOGS); + const contractAddress = filter.contractAddress; + const selector = filter.selector; + + const logs: ExtendedUnencryptedL2Log[] = []; + + for (let i = fromBlockIndex; i < toBlockIndex; i++) { + const _logs = this.unencryptedLogs[i]; + // TODO + } + + return Promise.resolve(logs); + } + /** * Get the extended contract data for this contract. * @param contractAddress - The contract data address. diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 0dc04543159..b32c1eb4fd3 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr, FunctionSelector, GrumpkinPrivateKey, PartialAddress } from '@aztec/circuits.js'; +import { AztecAddress, Fr, GrumpkinPrivateKey, PartialAddress } from '@aztec/circuits.js'; import { AuthWitness, ContractData, @@ -6,8 +6,8 @@ import { ExtendedContractData, ExtendedUnencryptedL2Log, FunctionCall, - L2BlockL2Logs, L2Tx, + LogFilter, NodeInfo, NotePreimage, PXE, @@ -97,13 +97,8 @@ export abstract class BaseWallet implements Wallet { getContractData(contractAddress: AztecAddress): Promise { return this.pxe.getContractData(contractAddress); } - public getUnencryptedLogs( - from: number, - limit: number, - contractAddress: AztecAddress, - selector: FunctionSelector, - ): Promise { - return this.pxe.getUnencryptedLogs(from, limit, contractAddress, selector); + getUnencryptedLogs(filter: LogFilter): Promise { + return this.pxe.getUnencryptedLogs(filter); } getBlockNumber(): Promise { return this.pxe.getBlockNumber(); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index a714794c8e5..e217fcec912 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -12,7 +12,6 @@ import { CompleteAddress, EthAddress, FunctionData, - FunctionSelector, GrumpkinPrivateKey, KernelCircuitPublicInputsFinal, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, @@ -37,7 +36,7 @@ import { KeyStore, L2Block, L2Tx, - LogType, + LogFilter, MerkleTreeId, NodeInfo, NotePreimage, @@ -386,20 +385,12 @@ export class PXEService implements PXE { } /** - * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. - * @param from - Number of the L2 block to which corresponds the first logs to be returned. - * @param limit - The maximum number of logs to return. - * @param contractAddress - The contract address to filter logs by. - * @param selector - The event selector to filter logs by. + * Gets unencrypted logs based on the provided filter. + * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - public getUnencryptedLogs( - from: number, - limit: number, - contractAddress: AztecAddress, - selector: FunctionSelector, - ): Promise { - return this.node.getUnencryptedLogs(from, limit, contractAddress, selector); + public getUnencryptedLogs(filter: LogFilter): Promise { + return this.node.getUnencryptedLogs(filter); } async #getFunctionCall(functionName: string, args: any[], to: AztecAddress): Promise { diff --git a/yarn-project/types/src/interfaces/aztec-node.ts b/yarn-project/types/src/interfaces/aztec-node.ts index 1d0c95f4761..0ebd21c4d42 100644 --- a/yarn-project/types/src/interfaces/aztec-node.ts +++ b/yarn-project/types/src/interfaces/aztec-node.ts @@ -10,6 +10,7 @@ import { L2Block, L2BlockL2Logs, L2Tx, + LogFilter, LogType, MerkleTreeId, StateInfoProvider, @@ -92,19 +93,11 @@ export interface AztecNode extends StateInfoProvider { getLogs(from: number, limit: number, logType: LogType): Promise; /** - * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. - * @param from - Number of the L2 block to which corresponds the first logs to be returned. - * @param limit - The maximum number of logs to return. - * @param contractAddress - The contract address to filter logs by. - * @param selector - The event selector to filter logs by. + * Gets unencrypted logs based on the provided filter. + * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs( - from: number, - limit: number, - contractAddress: AztecAddress, - selector: FunctionSelector, - ): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Method to submit a transaction to the p2p pool. diff --git a/yarn-project/types/src/interfaces/pxe.ts b/yarn-project/types/src/interfaces/pxe.ts index f2d74d277c5..4c0fdd0bc1b 100644 --- a/yarn-project/types/src/interfaces/pxe.ts +++ b/yarn-project/types/src/interfaces/pxe.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr, FunctionSelector, GrumpkinPrivateKey, PartialAddress } from '@aztec/circuits.js'; +import { AztecAddress, Fr, GrumpkinPrivateKey, PartialAddress } from '@aztec/circuits.js'; import { AuthWitness, CompleteAddress, @@ -6,6 +6,7 @@ import { ExtendedContractData, ExtendedUnencryptedL2Log, L2Tx, + LogFilter, NotePreimage, Tx, TxExecutionRequest, @@ -231,19 +232,11 @@ export interface PXE { getContractData(contractAddress: AztecAddress): Promise; /** - * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. - * @param from - Number of the L2 block to which corresponds the first logs to be returned. - * @param limit - The maximum number of logs to return. - * @param contractAddress - The contract address to filter logs by. - * @param selector - The event selector to filter logs by. + * Gets unencrypted logs based on the provided filter. + * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs( - from: number, - limit: number, - contractAddress: AztecAddress, - selector: FunctionSelector, - ): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Fetches the current block number. diff --git a/yarn-project/types/src/logs/index.ts b/yarn-project/types/src/logs/index.ts index aefddf0d2f2..6acc9289d9b 100644 --- a/yarn-project/types/src/logs/index.ts +++ b/yarn-project/types/src/logs/index.ts @@ -2,6 +2,7 @@ export * from './function_l2_logs.js'; export * from './l2_block_l2_logs.js'; export * from './l2_logs_source.js'; export * from './log_type.js'; +export * from './log_filter.js'; export * from './note_spending_info/index.js'; export * from './tx_l2_logs.js'; export * from './unencrypted_l2_log.js'; diff --git a/yarn-project/types/src/logs/l2_logs_source.ts b/yarn-project/types/src/logs/l2_logs_source.ts index e5a8ffd522d..af318629cc6 100644 --- a/yarn-project/types/src/logs/l2_logs_source.ts +++ b/yarn-project/types/src/logs/l2_logs_source.ts @@ -1,7 +1,6 @@ -import { AztecAddress, FunctionSelector } from '@aztec/circuits.js'; - import { ExtendedUnencryptedL2Log } from './extended_unencrypted_l2_log.js'; import { L2BlockL2Logs } from './l2_block_l2_logs.js'; +import { LogFilter } from './log_filter.js'; import { LogType } from './log_type.js'; /** @@ -18,19 +17,11 @@ export interface L2LogsSource { getLogs(from: number, limit: number, logType: LogType): Promise; /** - * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. - * @param from - Number of the L2 block to which corresponds the first logs to be returned. - * @param limit - The maximum number of logs to return. - * @param contractAddress - The contract address to filter logs by. - * @param selector - The event selector to filter logs by. + * Gets unencrypted logs based on the provided filter. + * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs( - from: number, - limit: number, - contractAddress: AztecAddress, - selector: FunctionSelector, - ): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Starts the encrypted logs source. diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts new file mode 100644 index 00000000000..e9e7ca0696f --- /dev/null +++ b/yarn-project/types/src/logs/log_filter.ts @@ -0,0 +1,17 @@ +import { AztecAddress, FunctionSelector } from '@aztec/circuits.js'; + +/** + * Log filter used to fetch L2 logs. + */ +export type LogFilter = { + /** The block number from which to start fetching logs (inclusive). */ + fromBlock?: number; + /** The block number until which to fetch logs (not inclusive). */ + toBlock?: number; + /** Maximum number of logs to fetch. */ + limit?: number; + /** The contract address to filter logs by. */ + contractAddress?: AztecAddress; + /** The event selector to filter logs by. */ + selector?: FunctionSelector; +}; From 22c9cc50519f6630a4e549c4ceabe2fad2f047ea Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 4 Oct 2023 13:21:51 +0000 Subject: [PATCH 04/60] WIP --- .../aztec-node/src/aztec-node/server.ts | 18 ++----- yarn-project/cli/package.json | 1 + yarn-project/cli/src/index.ts | 35 +++++++++----- yarn-project/cli/src/utils.ts | 47 +++++++++++++++++++ .../src/e2e_nested_contract.test.ts | 11 +++-- .../end-to-end/src/e2e_ordering.test.ts | 15 +++--- yarn-project/end-to-end/src/fixtures/utils.ts | 22 ++++----- .../src/guides/dapp_testing.test.ts | 9 ++-- .../foundation/src/abi/function_selector.ts | 16 +++++++ yarn-project/yarn.lock | 1 + 10 files changed, 123 insertions(+), 52 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index f92f45ef3db..fb3344b1ada 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -3,7 +3,6 @@ import { CONTRACT_TREE_HEIGHT, CircuitsWasm, Fr, - FunctionSelector, GlobalVariables, HistoricBlockData, L1_TO_L2_MSG_TREE_HEIGHT, @@ -33,6 +32,7 @@ import { L2BlockSource, L2LogsSource, L2Tx, + LogFilter, LogType, MerkleTreeId, SiblingPath, @@ -228,20 +228,12 @@ export class AztecNodeService implements AztecNode { } /** - * Gets up to `limit` amount of logs starting from `from` from contract `contractAddress` and event defined by `selector`. - * @param from - Number of the L2 block to which corresponds the first logs to be returned. - * @param limit - The maximum number of logs to return. - * @param contractAddress - The contract address to filter logs by. - * @param selector - The event selector to filter logs by. + * Gets unencrypted logs based on the provided filter. + * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - public getUnencryptedLogs( - from: number, - limit: number, - contractAddress: AztecAddress, - selector: FunctionSelector, - ): Promise { - return this.unencryptedLogsSource.getUnencryptedLogs(from, limit, contractAddress, selector); + getUnencryptedLogs(filter: LogFilter): Promise { + return this.unencryptedLogsSource.getUnencryptedLogs(filter); } /** diff --git a/yarn-project/cli/package.json b/yarn-project/cli/package.json index a2041b081ea..ebd7f5f1e8f 100644 --- a/yarn-project/cli/package.json +++ b/yarn-project/cli/package.json @@ -35,6 +35,7 @@ }, "dependencies": { "@aztec/aztec.js": "workspace:^", + "@aztec/circuits.js": "workspace:^", "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/l1-artifacts": "workspace:^", diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 8e60c31a4a7..952ce47a609 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -13,7 +13,7 @@ import { JsonStringify } from '@aztec/foundation/json-rpc'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; import { fileURLToPath } from '@aztec/foundation/url'; import { compileContract, generateNoirInterface, generateTypescriptInterface } from '@aztec/noir-compiler/cli'; -import { CompleteAddress, ContractData, L2BlockL2Logs } from '@aztec/types'; +import { CompleteAddress, ContractData, L2BlockL2Logs, LogFilter } from '@aztec/types'; import { createSecp256k1PeerId } from '@libp2p/peer-id-factory'; import { Command, Option } from 'commander'; @@ -34,6 +34,9 @@ import { parseAztecAddress, parseField, parseFields, + parseOptionalAztecAddress, + parseOptionalInteger, + parseOptionalSelector, parsePartialAddress, parsePrivateKey, parsePublicKey, @@ -289,21 +292,31 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { program .command('get-logs') .description('Gets all the unencrypted logs from L2 blocks in the range specified.') - .option('-f, --from ', 'Initial block number for getting logs (defaults to 1).') - .option('-l, --limit ', 'How many blocks to fetch (defaults to 100).') + .option( + '-f, --fromBlock ', + 'Initial block number for getting logs (defaults to 1).', + parseOptionalInteger, + ) + .option('-t, --toBlock ', 'Up to which block to fetch logs (defaults to latest).', parseOptionalInteger) + .option( + '-l, --limit ', + 'How many logs to fetch (defaults to maximum value of 1000).', + parseOptionalInteger, + ) + .option('-c, --contractAddress ', 'Contract address to filter logs by.', parseOptionalAztecAddress) + .option('-s, --selector ', 'Event selector to filter logs by.', parseOptionalSelector) .addOption(pxeOption) - .action(async options => { - const { from, limit } = options; - const fromBlock = from ? parseInt(from) : 1; - const limitCount = limit ? parseInt(limit) : 100; + .action(async ({ fromBlock, toBlock, limit, contractAddress, selector, rpcUrl }) => { + const client = await createCompatibleClient(rpcUrl, debugLogger); + + const filter: LogFilter = { fromBlock, toBlock, limit, contractAddress, selector }; + const logs = await client.getUnencryptedLogs(filter); - const client = await createCompatibleClient(options.rpcUrl, debugLogger); - const logs = await client.getUnencryptedLogs(fromBlock, limitCount); if (!logs.length) { - log(`No logs found in blocks ${fromBlock} to ${fromBlock + limitCount}`); + log(`No logs found in blocks ${fromBlock} to ${toBlock}`); } else { log('Logs found: \n'); - L2BlockL2Logs.unrollLogs(logs).forEach(fnLog => log(`${fnLog.toString('ascii')}\n`)); + logs.forEach(unencryptedLog => log(`${unencryptedLog.log.data.toString('ascii')}\n`)); } }); diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index 0937bed88eb..7e62727499c 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -1,4 +1,5 @@ import { AztecAddress, Fr, GrumpkinScalar, PXE, Point, TxHash } from '@aztec/aztec.js'; +import { FunctionSelector } from '@aztec/circuits.js'; import { L1ContractArtifactsForDeployment, createEthereumChain, deployL1Contracts } from '@aztec/ethereum'; import { ContractArtifact } from '@aztec/foundation/abi'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; @@ -209,6 +210,52 @@ export function parseAztecAddress(address: string): AztecAddress { } } +/** + * Parses an AztecAddress from a string. Throws InvalidArgumentError if the string is not a valid. + * @param address - A serialised Aztec address + * @returns An Aztec address + */ +export function parseOptionalAztecAddress(address: string): AztecAddress | undefined { + if (!address) { + return undefined; + } + return parseAztecAddress(address); +} + +/** + * Parses a selector from a string. Throws InvalidArgumentError if the string is not a valid. + * @param selector - A serialised selector. + * @returns A selector. + */ +export function parseOptionalSelector(selector: string): FunctionSelector | undefined { + if (!selector) { + return undefined; + } + try { + return FunctionSelector.fromString(selector); + } catch { + throw new InvalidArgumentError(`Invalid selector: ${selector}`); + } +} + +/** + * Parses a string into an integer or returns undefined if the input is falsy. + * + * @param value - The string to parse into an integer. + * @returns The parsed integer, or undefined if the input string is falsy. + * @throws If the input is not a valid integer. + */ +export function parseOptionalInteger(value: string): number | undefined { + if (!value) { + return undefined; + } + const parsed = parseInt(value, 10); + if (isNaN(parsed)) { + throw new InvalidArgumentError(`Invalid integer: ${value}`); + } + return parsed; +} + /** * Parses a TxHash from a string. Throws InvalidArgumentError if the string is not a valid. * @param txHash - A transaction hash diff --git a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts index 8136b5f60a8..9ef120b657c 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts @@ -114,10 +114,13 @@ describe('e2e_nested_contract', () => { ]; const tx = await new BatchCall(wallet, actions).send().wait(); - const logs = L2BlockL2Logs.unrollLogs(await wallet.getUnencryptedLogs(tx.blockNumber!, 1)).map(log => - toBigIntBE(UnencryptedL2Log.fromBuffer(log).data), - ); - expect(logs).toEqual([20n, 40n]); + const filter = { + fromBlock: tx.blockNumber!, + limit: 2, // 2 logs expected + }; + const extendedLogs = await wallet.getUnencryptedLogs(filter); + const processedLogs = extendedLogs.map(extendedLog => toBigIntBE(extendedLog.log.data)); + expect(processedLogs).toEqual([20n, 40n]); expect(await getChildStoredValue(childContract)).toEqual(40n); }); }); diff --git a/yarn-project/end-to-end/src/e2e_ordering.test.ts b/yarn-project/end-to-end/src/e2e_ordering.test.ts index f53fa53d544..bbdda1e38ca 100644 --- a/yarn-project/end-to-end/src/e2e_ordering.test.ts +++ b/yarn-project/end-to-end/src/e2e_ordering.test.ts @@ -5,7 +5,7 @@ import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; import { Fr } from '@aztec/foundation/fields'; import { toBigInt } from '@aztec/foundation/serialize'; import { ChildContract, ParentContract } from '@aztec/noir-contracts/types'; -import { L2BlockL2Logs, PXE, TxStatus, UnencryptedL2Log } from '@aztec/types'; +import { PXE, TxStatus } from '@aztec/types'; import { setup } from './fixtures/utils.js'; @@ -16,12 +16,13 @@ describe('e2e_ordering', () => { let teardown: () => Promise; const expectLogsFromLastBlockToBe = async (logMessages: bigint[]) => { - const l2BlockNum = await pxe.getBlockNumber(); - const unencryptedLogs = await pxe.getUnencryptedLogs(l2BlockNum, 1); - const unrolledLogs = L2BlockL2Logs.unrollLogs(unencryptedLogs) - .map(log => UnencryptedL2Log.fromBuffer(log)) - .map(log => log.data); - const bigintLogs = unrolledLogs.map((log: Buffer) => toBigIntBE(log)); + const fromBlock = await pxe.getBlockNumber(); + const logFilter = { + fromBlock, + toBlock: fromBlock + 1, + }; + const unencryptedLogs = await pxe.getUnencryptedLogs(logFilter); + const bigintLogs = unencryptedLogs.map(extendedLog => toBigIntBE(extendedLog.log.data)); expect(bigintLogs).toStrictEqual(logMessages); }; diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index be53fabf8c2..150d58d0613 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -39,15 +39,7 @@ import { } from '@aztec/l1-artifacts'; import { NonNativeTokenContract, TokenBridgeContract, TokenContract } from '@aztec/noir-contracts/types'; import { PXEService, createPXEService, getPXEServiceConfig } from '@aztec/pxe'; -import { - AztecNode, - L2BlockL2Logs, - LogType, - PXE, - TxStatus, - UnencryptedL2Log, - createAztecNodeRpcClient, -} from '@aztec/types'; +import { AztecNode, L2BlockL2Logs, LogType, PXE, TxStatus, createAztecNodeRpcClient } from '@aztec/types'; import * as path from 'path'; import { @@ -527,13 +519,15 @@ export const expectsNumOfEncryptedLogsInTheLastBlockToBe = async ( */ export const expectUnencryptedLogsFromLastBlockToBe = async (pxe: PXE, logMessages: string[]) => { // docs:start:get_logs - // Get the latest block number to retrieve logs from - const l2BlockNum = await pxe.getBlockNumber(); // Get the unencrypted logs from the last block - const unencryptedLogs = await pxe.getUnencryptedLogs(l2BlockNum, 1); + const fromBlock = await pxe.getBlockNumber(); + const logFilter = { + fromBlock, + toBlock: fromBlock + 1, + }; + const unencryptedLogs = await pxe.getUnencryptedLogs(logFilter); // docs:end:get_logs - const unrolledLogs = L2BlockL2Logs.unrollLogs(unencryptedLogs).map(log => UnencryptedL2Log.fromBuffer(log)); - const asciiLogs = unrolledLogs.map(log => log.data.toString('ascii')); + const asciiLogs = unencryptedLogs.map(extendedLog => extendedLog.log.data.toString('ascii')); expect(asciiLogs).toStrictEqual(logMessages); }; diff --git a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts index d5adfd24890..1f95cb17931 100644 --- a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts +++ b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts @@ -208,9 +208,12 @@ describe('guides/dapp/testing', () => { // docs:start:unencrypted-logs const value = Fr.fromString('ef'); // Only 1 bytes will make its way in there :( so no larger stuff const tx = await testContract.methods.emit_unencrypted(value).send().wait(); - const logs = await pxe.getUnencryptedLogs(tx.blockNumber!, 1); - const log = UnencryptedL2Log.fromBuffer(L2BlockL2Logs.unrollLogs(logs)[0]); - expect(Fr.fromBuffer(log.data)).toEqual(value); + const filter = { + fromBlock: tx.blockNumber!, + limit: 1, // 1 log expected + }; + const logs = await pxe.getUnencryptedLogs(filter); + expect(Fr.fromBuffer(logs[0].log.data)).toEqual(value); // docs:end:unencrypted-logs }); diff --git a/yarn-project/foundation/src/abi/function_selector.ts b/yarn-project/foundation/src/abi/function_selector.ts index 88c7919e4a5..fbfc56f79b6 100644 --- a/yarn-project/foundation/src/abi/function_selector.ts +++ b/yarn-project/foundation/src/abi/function_selector.ts @@ -104,6 +104,22 @@ export class FunctionSelector { return selector; } + /** + * Create an AztecAddress instance from a hex-encoded string. + * The input 'address' should be prefixed with '0x' or not, and have exactly 64 hex characters. + * Throws an error if the input length is invalid or address value is out of range. + * + * @param selector - The hex-encoded string representing the Aztec address. + * @returns An AztecAddress instance. + */ + static fromString(selector: string) { + const buf = Buffer.from(selector.replace(/^0x/i, ''), 'hex'); + if (buf.length !== FunctionSelector.SIZE) { + throw new Error(`Invalid length ${buf.length}.`); + } + return FunctionSelector.fromBuffer(buf); + } + /** * Creates an empty function selector. * @returns An empty function selector. diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 8de88d3e484..ad0255507c5 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -315,6 +315,7 @@ __metadata: resolution: "@aztec/cli@workspace:cli" dependencies: "@aztec/aztec.js": "workspace:^" + "@aztec/circuits.js": "workspace:^" "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/l1-artifacts": "workspace:^" From 2b17ce9676383d2e5c9e4d67dd78a13da383acd7 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 4 Oct 2023 13:23:27 +0000 Subject: [PATCH 05/60] WIP --- yarn-project/end-to-end/src/guides/dapp_testing.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts index 1f95cb17931..a779be2cbae 100644 --- a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts +++ b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts @@ -3,10 +3,8 @@ import { AccountWallet, CheatCodes, Fr, - L2BlockL2Logs, NotePreimage, PXE, - UnencryptedL2Log, computeMessageSecretHash, createAccount, createPXEClient, From d4179015d8454619eb9e6865f52797bb050301f5 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 4 Oct 2023 14:20:36 +0000 Subject: [PATCH 06/60] filtration --- .../archiver/src/archiver/archiver_store.ts | 20 +++++++++++++++++-- .../types/src/logs/l2_block_l2_logs.ts | 4 +--- yarn-project/types/src/logs/tx_l2_logs.ts | 12 +++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index e6ce920e888..0d88d9a3561 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -7,11 +7,13 @@ import { INITIAL_L2_BLOCK_NUM, L1ToL2Message, L2Block, + L2BlockContext, L2BlockL2Logs, L2Tx, LogFilter, LogType, TxHash, + UnencryptedL2Log, } from '@aztec/types'; import { L1ToL2MessageStore, PendingL1ToL2MessageStore } from './l1_to_l2_message_store.js'; @@ -382,8 +384,22 @@ export class MemoryArchiverStore implements ArchiverDataStore { const logs: ExtendedUnencryptedL2Log[] = []; for (let i = fromBlockIndex; i < toBlockIndex; i++) { - const _logs = this.unencryptedLogs[i]; - // TODO + const blockContext = new L2BlockContext(this.l2Blocks[i]); + const blockLogs = this.unencryptedLogs[i]; + for (let j = 0; j < blockLogs.txLogs.length; j++) { + const txLogs = blockLogs.txLogs[j].unrollLogs().map(log => UnencryptedL2Log.fromBuffer(log)); + for (const log of txLogs) { + if ( + (!contractAddress || log.contractAddress.equals(contractAddress)) && + (!selector || log.selector.equals(selector)) + ) { + logs.push(new ExtendedUnencryptedL2Log(blockContext.block.number, blockContext.getTxHash(j), log)); + if (logs.length === limit) { + return Promise.resolve(logs); + } + } + } + } } return Promise.resolve(logs); diff --git a/yarn-project/types/src/logs/l2_block_l2_logs.ts b/yarn-project/types/src/logs/l2_block_l2_logs.ts index 9c8702bfb02..c41a744e2aa 100644 --- a/yarn-project/types/src/logs/l2_block_l2_logs.ts +++ b/yarn-project/types/src/logs/l2_block_l2_logs.ts @@ -86,9 +86,7 @@ export class L2BlockL2Logs { const logs: Buffer[] = []; for (const blockLog of blockLogs) { for (const txLog of blockLog.txLogs) { - for (const functionLog of txLog.functionLogs) { - logs.push(...functionLog.logs); - } + logs.push(...txLog.unrollLogs()); } } return logs; diff --git a/yarn-project/types/src/logs/tx_l2_logs.ts b/yarn-project/types/src/logs/tx_l2_logs.ts index 98fb94d1be6..d9388b9df84 100644 --- a/yarn-project/types/src/logs/tx_l2_logs.ts +++ b/yarn-project/types/src/logs/tx_l2_logs.ts @@ -82,6 +82,18 @@ export class TxL2Logs { }; } + /** + * Unrolls logs from this tx. + * @returns Unrolled logs. + */ + public unrollLogs(): Buffer[] { + const logs = []; + for (const functionLog of this.functionLogs) { + logs.push(...functionLog.logs); + } + return logs; + } + /** * Convert a plain JSON object to a TxL2Logs class object. * @param obj - A plain TxL2Logs JSON object. From 1a41b01155e94892cdc8349e812207395d14dab9 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 4 Oct 2023 14:22:21 +0000 Subject: [PATCH 07/60] storing block contexts --- .../archiver/src/archiver/archiver_store.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 0d88d9a3561..70a1907c0a3 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -163,7 +163,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { /** * An array containing all the L2 blocks that have been fetched so far. */ - private l2Blocks: L2Block[] = []; + private l2BlockContexts: L2BlockContext[] = []; /** * An array containing all the L2 Txs in the L2 blocks that have been fetched so far. @@ -211,7 +211,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns True if the operation is successful (always in this implementation). */ public addL2Blocks(blocks: L2Block[]): Promise { - this.l2Blocks.push(...blocks); + this.l2BlockContexts.push(...blocks.map(block => new L2BlockContext(block))); this.l2Txs.push(...blocks.flatMap(b => b.getTxs())); return Promise.resolve(true); } @@ -298,12 +298,12 @@ export class MemoryArchiverStore implements ArchiverDataStore { if (limit < 1) { throw new Error(`Invalid block range from: ${from}, limit: ${limit}`); } - if (from < INITIAL_L2_BLOCK_NUM || from > this.l2Blocks.length) { + if (from < INITIAL_L2_BLOCK_NUM || from > this.l2BlockContexts.length) { return Promise.resolve([]); } const startIndex = from - INITIAL_L2_BLOCK_NUM; const endIndex = startIndex + limit; - return Promise.resolve(this.l2Blocks.slice(startIndex, endIndex)); + return Promise.resolve(this.l2BlockContexts.slice(startIndex, endIndex).map(blockContext => blockContext.block)); } /** @@ -384,7 +384,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { const logs: ExtendedUnencryptedL2Log[] = []; for (let i = fromBlockIndex; i < toBlockIndex; i++) { - const blockContext = new L2BlockContext(this.l2Blocks[i]); + const blockContext = this.l2BlockContexts[i]; const blockLogs = this.unencryptedLogs[i]; for (let j = 0; j < blockLogs.txLogs.length; j++) { const txLogs = blockLogs.txLogs[j].unrollLogs().map(log => UnencryptedL2Log.fromBuffer(log)); @@ -421,7 +421,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns All extended contract data in the block (if found). */ public getExtendedContractDataInBlock(blockNum: number): Promise { - if (blockNum > this.l2Blocks.length) { + if (blockNum > this.l2BlockContexts.length) { return Promise.resolve([]); } return Promise.resolve(this.extendedContractDataByBlock[blockNum] || []); @@ -437,8 +437,8 @@ export class MemoryArchiverStore implements ArchiverDataStore { if (contractAddress.isZero()) { return Promise.resolve(undefined); } - for (const block of this.l2Blocks) { - for (const contractData of block.newContractData) { + for (const blockContext of this.l2BlockContexts) { + for (const contractData of blockContext.block.newContractData) { if (contractData.contractAddress.equals(contractAddress)) { return Promise.resolve(contractData); } @@ -454,10 +454,10 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns ContractData with the portal address (if we didn't throw an error). */ public getContractDataInBlock(l2BlockNum: number): Promise { - if (l2BlockNum > this.l2Blocks.length) { + if (l2BlockNum > this.l2BlockContexts.length) { return Promise.resolve([]); } - const block = this.l2Blocks[l2BlockNum]; + const block = this.l2BlockContexts[l2BlockNum].block; return Promise.resolve(block.newContractData); } @@ -466,8 +466,8 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns The number of the latest L2 block processed. */ public getBlockNumber(): Promise { - if (this.l2Blocks.length === 0) return Promise.resolve(INITIAL_L2_BLOCK_NUM - 1); - return Promise.resolve(this.l2Blocks[this.l2Blocks.length - 1].number); + if (this.l2BlockContexts.length === 0) return Promise.resolve(INITIAL_L2_BLOCK_NUM - 1); + return Promise.resolve(this.l2BlockContexts[this.l2BlockContexts.length - 1].block.number); } /** @@ -475,6 +475,6 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns The length of L2 Blocks array. */ public getBlocksLength(): number { - return this.l2Blocks.length; + return this.l2BlockContexts.length; } } From c78f67719848fc786656234c5024a32cf632e4fe Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 4 Oct 2023 14:42:25 +0000 Subject: [PATCH 08/60] fix --- yarn-project/cli/tsconfig.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yarn-project/cli/tsconfig.json b/yarn-project/cli/tsconfig.json index 7bd5491149a..f99c5e7e8c4 100644 --- a/yarn-project/cli/tsconfig.json +++ b/yarn-project/cli/tsconfig.json @@ -9,6 +9,9 @@ { "path": "../aztec.js" }, + { + "path": "../circuits.js" + }, { "path": "../ethereum" }, From 1fde9a8fb30e5cef8cf3927175ad906367407d09 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 06:47:27 +0000 Subject: [PATCH 09/60] linter fixes --- yarn-project/cli/src/index.ts | 2 +- yarn-project/end-to-end/src/e2e_nested_contract.test.ts | 2 +- yarn-project/types/src/interfaces/aztec-node.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 952ce47a609..7d2eb24d6b1 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -13,7 +13,7 @@ import { JsonStringify } from '@aztec/foundation/json-rpc'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; import { fileURLToPath } from '@aztec/foundation/url'; import { compileContract, generateNoirInterface, generateTypescriptInterface } from '@aztec/noir-compiler/cli'; -import { CompleteAddress, ContractData, L2BlockL2Logs, LogFilter } from '@aztec/types'; +import { CompleteAddress, ContractData, LogFilter } from '@aztec/types'; import { createSecp256k1PeerId } from '@libp2p/peer-id-factory'; import { Command, Option } from 'commander'; diff --git a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts index 9ef120b657c..82ac96a1a31 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts @@ -3,7 +3,7 @@ import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; import { DebugLogger } from '@aztec/foundation/log'; import { toBigInt } from '@aztec/foundation/serialize'; import { ChildContract, ImportTestContract, ParentContract, TestContract } from '@aztec/noir-contracts/types'; -import { L2BlockL2Logs, PXE, UnencryptedL2Log } from '@aztec/types'; +import { PXE } from '@aztec/types'; import { setup } from './fixtures/utils.js'; diff --git a/yarn-project/types/src/interfaces/aztec-node.ts b/yarn-project/types/src/interfaces/aztec-node.ts index 0ebd21c4d42..a1e21798f46 100644 --- a/yarn-project/types/src/interfaces/aztec-node.ts +++ b/yarn-project/types/src/interfaces/aztec-node.ts @@ -1,4 +1,4 @@ -import { FunctionSelector, HistoricBlockData } from '@aztec/circuits.js'; +import { HistoricBlockData } from '@aztec/circuits.js'; import { L1ContractAddresses } from '@aztec/ethereum'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; From cfb8d6ed5c50752a4a82c407f983d012602cd39b Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 07:26:23 +0000 Subject: [PATCH 10/60] fix --- yarn-project/archiver/src/archiver/archiver_store.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 70a1907c0a3..c7b38d568a1 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -371,8 +371,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { return Promise.resolve([]); } - const toBlockIndex = - Math.min(filter.toBlock || this.unencryptedLogs.length, this.unencryptedLogs.length) - INITIAL_L2_BLOCK_NUM; + const toBlockIndex = (filter.toBlock || this.unencryptedLogs.length + INITIAL_L2_BLOCK_NUM) - INITIAL_L2_BLOCK_NUM; if (toBlockIndex < fromBlockIndex) { return Promise.resolve([]); } From 9b4149c0f010e9fa7d7a48d0355a75c8206e68cf Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 07:43:41 +0000 Subject: [PATCH 11/60] fix --- .../src/aztec-node/http_rpc_server.ts | 2 ++ yarn-project/aztec.js/src/pxe_client.ts | 2 ++ .../pxe/src/pxe_http/pxe_http_server.ts | 2 ++ .../src/aztec_node/rpc/http_rpc_client.ts | 2 ++ .../src/logs/extended_unencrypted_l2_log.ts | 18 ++++++++++++++++++ 5 files changed, 26 insertions(+) diff --git a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts index 51205c979af..3b1bbbdc1ea 100644 --- a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts +++ b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts @@ -7,6 +7,7 @@ import { AztecNode, ContractData, ExtendedContractData, + ExtendedUnencryptedL2Log, L1ToL2MessageAndIndex, L2Block, L2BlockL2Logs, @@ -28,6 +29,7 @@ export function createAztecNodeRpcServer(node: AztecNode) { AztecAddress, EthAddress, ExtendedContractData, + ExtendedUnencryptedL2Log, ContractData, Fr, HistoricBlockData, diff --git a/yarn-project/aztec.js/src/pxe_client.ts b/yarn-project/aztec.js/src/pxe_client.ts index 0514626c1a9..b6cb23db772 100644 --- a/yarn-project/aztec.js/src/pxe_client.ts +++ b/yarn-project/aztec.js/src/pxe_client.ts @@ -4,6 +4,7 @@ import { AuthWitness, ContractData, ExtendedContractData, + ExtendedUnencryptedL2Log, L2BlockL2Logs, L2Tx, NotePreimage, @@ -25,6 +26,7 @@ export const createPXEClient = (url: string, fetch = makeFetch([1, 2, 3], true)) TxExecutionRequest, ContractData, ExtendedContractData, + ExtendedUnencryptedL2Log, TxHash, EthAddress, Point, diff --git a/yarn-project/pxe/src/pxe_http/pxe_http_server.ts b/yarn-project/pxe/src/pxe_http/pxe_http_server.ts index e8eb1a864c1..93b40e1b91e 100644 --- a/yarn-project/pxe/src/pxe_http/pxe_http_server.ts +++ b/yarn-project/pxe/src/pxe_http/pxe_http_server.ts @@ -6,6 +6,7 @@ import { CompleteAddress, ContractData, ExtendedContractData, + ExtendedUnencryptedL2Log, L2Block, L2BlockL2Logs, L2Tx, @@ -37,6 +38,7 @@ export function createPXERpcServer(pxeService: PXE): JsonRpcServer { TxExecutionRequest, ContractData, ExtendedContractData, + ExtendedUnencryptedL2Log, TxHash, EthAddress, Point, diff --git a/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts b/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts index 96cdfb6676e..e02414067e5 100644 --- a/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts +++ b/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts @@ -7,6 +7,7 @@ import { AztecNode, ContractData, ExtendedContractData, + ExtendedUnencryptedL2Log, L1ToL2MessageAndIndex, L2Block, L2BlockL2Logs, @@ -29,6 +30,7 @@ export function createAztecNodeRpcClient(url: string, fetch = defaultFetch): Azt AztecAddress, EthAddress, ExtendedContractData, + ExtendedUnencryptedL2Log, ContractData, Fr, HistoricBlockData, diff --git a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts index 22f4d410795..b677e19b8a7 100644 --- a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts @@ -24,6 +24,14 @@ export class ExtendedUnencryptedL2Log { return Buffer.concat([toBufferBE(BigInt(this.blockNumber), 4), this.txHash.buffer, this.log.toBuffer()]); } + /** + * Serializes log to a string. + * @returns A string containing the serialized log. + */ + public toString(): string { + return this.toBuffer().toString('hex'); + } + /** * Deserializes log from a buffer. * @param buffer - The buffer or buffer reader containing the log. @@ -38,4 +46,14 @@ export class ExtendedUnencryptedL2Log { return new ExtendedUnencryptedL2Log(blockNumber, txHash, log); } + + /** + * Deserializes `ExtendedUnencryptedL2Log` object from a hex string representation. + * @param data - A hex string representation of the log. + * @returns An `ExtendedUnencryptedL2Log` object. + */ + public static fromString(data: string): ExtendedUnencryptedL2Log { + const buffer = Buffer.from(data, 'hex'); + return ExtendedUnencryptedL2Log.fromBuffer(buffer); + } } From 1fd65201b5c9ba6935aa35439da35369491cc2dc Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 08:06:09 +0000 Subject: [PATCH 12/60] updated CLI --- yarn-project/cli/src/index.ts | 4 ++-- .../types/src/logs/extended_unencrypted_l2_log.ts | 8 ++++++++ yarn-project/types/src/logs/unencrypted_l2_log.ts | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 7d2eb24d6b1..4500b3b3314 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -313,10 +313,10 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { const logs = await client.getUnencryptedLogs(filter); if (!logs.length) { - log(`No logs found in blocks ${fromBlock} to ${toBlock}`); + log(`No logs found in blocks ${fromBlock} to ${toBlock ?? 'latest'}`); } else { log('Logs found: \n'); - logs.forEach(unencryptedLog => log(`${unencryptedLog.log.data.toString('ascii')}\n`)); + logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); } }); diff --git a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts index b677e19b8a7..97792f31546 100644 --- a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts @@ -32,6 +32,14 @@ export class ExtendedUnencryptedL2Log { return this.toBuffer().toString('hex'); } + /** + * Serializes log to a human readable string. + * @returns A human readable representation of the log. + */ + public toHumanReadable(): string { + return `${this.log.toHumanReadable()} (blockNumber: ${this.blockNumber}, txHash: ${this.txHash.toString()})`; + } + /** * Deserializes log from a buffer. * @param buffer - The buffer or buffer reader containing the log. diff --git a/yarn-project/types/src/logs/unencrypted_l2_log.ts b/yarn-project/types/src/logs/unencrypted_l2_log.ts index e4707f3ad34..598b85bd7fa 100644 --- a/yarn-project/types/src/logs/unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/unencrypted_l2_log.ts @@ -45,7 +45,7 @@ export class UnencryptedL2Log { */ public toHumanReadable(): string { return `UnencryptedL2Log(contractAddress: ${this.contractAddress.toString()}, selector: ${this.selector.toString()}, data: ${this.data.toString( - 'hex', + 'ascii', )})`; } From 40d28aa237abe1edb23ec5aad74193cce4266c96 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 08:49:34 +0000 Subject: [PATCH 13/60] filtering by txHash --- .../archiver/src/archiver/archiver_store.ts | 8 ++++ yarn-project/cli/src/index.ts | 12 ++++-- yarn-project/cli/src/utils.ts | 38 +++++++++++++++---- .../src/logs/extended_unencrypted_l2_log.ts | 6 +-- yarn-project/types/src/logs/log_filter.ts | 7 ++++ 5 files changed, 57 insertions(+), 14 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index c7b38d568a1..255262f39f6 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -362,10 +362,17 @@ export class MemoryArchiverStore implements ArchiverDataStore { * Gets unencrypted logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. + * @throws If txHash and block range are both defined. */ getUnencryptedLogs(filter: LogFilter): Promise { const MAX_LOGS = 1000; + if (filter.txHash && (filter.fromBlock || filter.toBlock)) { + throw new Error('Cannot filter by txHash and block range at the same time'); + } + + const txHash = filter.txHash; + const fromBlockIndex = (filter.fromBlock || INITIAL_L2_BLOCK_NUM) - INITIAL_L2_BLOCK_NUM; if (fromBlockIndex > this.unencryptedLogs.length) { return Promise.resolve([]); @@ -389,6 +396,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { const txLogs = blockLogs.txLogs[j].unrollLogs().map(log => UnencryptedL2Log.fromBuffer(log)); for (const log of txLogs) { if ( + (!txHash || blockContext.getTxHash(j).equals(txHash)) && (!contractAddress || log.contractAddress.equals(contractAddress)) && (!selector || log.selector.equals(selector)) ) { diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 4500b3b3314..947b0560238 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -37,6 +37,7 @@ import { parseOptionalAztecAddress, parseOptionalInteger, parseOptionalSelector, + parseOptionalTxHash, parsePartialAddress, parsePrivateKey, parsePublicKey, @@ -292,6 +293,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { program .command('get-logs') .description('Gets all the unencrypted logs from L2 blocks in the range specified.') + .option('-tx, --txHash ', 'A transaction hash to get the receipt for.', parseOptionalTxHash) .option( '-f, --fromBlock ', 'Initial block number for getting logs (defaults to 1).', @@ -306,14 +308,18 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { .option('-c, --contractAddress ', 'Contract address to filter logs by.', parseOptionalAztecAddress) .option('-s, --selector ', 'Event selector to filter logs by.', parseOptionalSelector) .addOption(pxeOption) - .action(async ({ fromBlock, toBlock, limit, contractAddress, selector, rpcUrl }) => { + .action(async ({ txHash, fromBlock, toBlock, limit, contractAddress, selector, rpcUrl }) => { const client = await createCompatibleClient(rpcUrl, debugLogger); - const filter: LogFilter = { fromBlock, toBlock, limit, contractAddress, selector }; + const filter: LogFilter = { txHash, fromBlock, toBlock, limit, contractAddress, selector }; const logs = await client.getUnencryptedLogs(filter); if (!logs.length) { - log(`No logs found in blocks ${fromBlock} to ${toBlock ?? 'latest'}`); + const filterOptions = Object.entries(filter) + .filter(([, value]) => value !== undefined) + .map(([key, value]) => `${key}: ${value}`) + .join(', '); + log(`No logs found for filter: {${filterOptions}}`); } else { log('Logs found: \n'); logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index 7e62727499c..e393528ad19 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -198,9 +198,10 @@ export function parseSaltFromHexString(str: string): Fr { } /** - * Parses an AztecAddress from a string. Throws InvalidArgumentError if the string is not a valid. + * Parses an AztecAddress from a string. * @param address - A serialised Aztec address * @returns An Aztec address + * @throws InvalidArgumentError if the input string is not valid. */ export function parseAztecAddress(address: string): AztecAddress { try { @@ -211,9 +212,10 @@ export function parseAztecAddress(address: string): AztecAddress { } /** - * Parses an AztecAddress from a string. Throws InvalidArgumentError if the string is not a valid. + * Parses an AztecAddress from a string. * @param address - A serialised Aztec address * @returns An Aztec address + * @throws InvalidArgumentError if the input string is not valid. */ export function parseOptionalAztecAddress(address: string): AztecAddress | undefined { if (!address) { @@ -223,9 +225,10 @@ export function parseOptionalAztecAddress(address: string): AztecAddress | undef } /** - * Parses a selector from a string. Throws InvalidArgumentError if the string is not a valid. + * Parses a selector from a string. * @param selector - A serialised selector. * @returns A selector. + * @throws InvalidArgumentError if the input string is not valid. */ export function parseOptionalSelector(selector: string): FunctionSelector | undefined { if (!selector) { @@ -257,9 +260,10 @@ export function parseOptionalInteger(value: string): number | undefined { } /** - * Parses a TxHash from a string. Throws InvalidArgumentError if the string is not a valid. + * Parses a TxHash from a string. * @param txHash - A transaction hash * @returns A TxHash instance + * @throws InvalidArgumentError if the input string is not valid. */ export function parseTxHash(txHash: string): TxHash { try { @@ -270,9 +274,24 @@ export function parseTxHash(txHash: string): TxHash { } /** - * Parses a public key from a string. Throws InvalidArgumentError if the string is not a valid. + * Parses an optional TxHash from a string. + * Calls parseTxHash internally. + * @param txHash - A transaction hash + * @returns A TxHash instance, or undefined if the input string is falsy. + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parseOptionalTxHash(txHash: string): TxHash | undefined { + if (!txHash) { + return undefined; + } + return parseTxHash(txHash); +} + +/** + * Parses a public key from a string. * @param publicKey - A public key * @returns A Point instance + * @throws InvalidArgumentError if the input string is not valid. */ export function parsePublicKey(publicKey: string): Point { try { @@ -283,9 +302,10 @@ export function parsePublicKey(publicKey: string): Point { } /** - * Parses a partial address from a string. Throws InvalidArgumentError if the string is not a valid. + * Parses a partial address from a string. * @param address - A partial address * @returns A Fr instance + * @throws InvalidArgumentError if the input string is not valid. */ export function parsePartialAddress(address: string): Fr { try { @@ -296,9 +316,10 @@ export function parsePartialAddress(address: string): Fr { } /** - * Parses a private key from a string. Throws InvalidArgumentError if the string is not a valid. + * Parses a private key from a string. * @param privateKey - A string * @returns A private key + * @throws InvalidArgumentError if the input string is not valid. */ export function parsePrivateKey(privateKey: string): GrumpkinScalar { try { @@ -315,9 +336,10 @@ export function parsePrivateKey(privateKey: string): GrumpkinScalar { } /** - * Parses a field from a string. Throws InvalidArgumentError if the string is not a valid field value. + * Parses a field from a string. * @param field - A string representing the field. * @returns A field. + * @throws InvalidArgumentError if the input string is not valid. */ export function parseField(field: string): Fr { try { diff --git a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts index 97792f31546..64cb21f4d0c 100644 --- a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts @@ -36,9 +36,9 @@ export class ExtendedUnencryptedL2Log { * Serializes log to a human readable string. * @returns A human readable representation of the log. */ - public toHumanReadable(): string { - return `${this.log.toHumanReadable()} (blockNumber: ${this.blockNumber}, txHash: ${this.txHash.toString()})`; - } + public toHumanReadable(): string { + return `${this.log.toHumanReadable()} (blockNumber: ${this.blockNumber}, txHash: ${this.txHash.toString()})`; + } /** * Deserializes log from a buffer. diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index e9e7ca0696f..0959e3dbd8e 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -1,9 +1,16 @@ import { AztecAddress, FunctionSelector } from '@aztec/circuits.js'; +import { TxHash } from '../index.js'; + /** * Log filter used to fetch L2 logs. */ export type LogFilter = { + /** + * Hash of a transaction from which to fetch the logs. + * @remarks If this is set, `fromBlock` and `toBlock` can't be defined. + */ + txHash?: TxHash; /** The block number from which to start fetching logs (inclusive). */ fromBlock?: number; /** The block number until which to fetch logs (not inclusive). */ From 2a3952095dd91e92b5346664046fc7463d06a6bc Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 08:59:06 +0000 Subject: [PATCH 14/60] fix --- .../aztec-node/src/aztec-node/http_rpc_server.ts | 3 ++- yarn-project/aztec.js/src/pxe_client.ts | 11 ++++++++++- yarn-project/pxe/src/pxe_http/pxe_http_server.ts | 2 ++ .../types/src/aztec_node/rpc/http_rpc_client.ts | 3 ++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts index 3b1bbbdc1ea..c1da62e6b29 100644 --- a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts +++ b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts @@ -1,4 +1,4 @@ -import { HistoricBlockData } from '@aztec/circuits.js'; +import { FunctionSelector, HistoricBlockData } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; @@ -32,6 +32,7 @@ export function createAztecNodeRpcServer(node: AztecNode) { ExtendedUnencryptedL2Log, ContractData, Fr, + FunctionSelector, HistoricBlockData, L2Block, L2Tx, diff --git a/yarn-project/aztec.js/src/pxe_client.ts b/yarn-project/aztec.js/src/pxe_client.ts index b6cb23db772..ad666a9f0e0 100644 --- a/yarn-project/aztec.js/src/pxe_client.ts +++ b/yarn-project/aztec.js/src/pxe_client.ts @@ -1,4 +1,12 @@ -import { AztecAddress, CompleteAddress, EthAddress, Fr, GrumpkinScalar, Point } from '@aztec/circuits.js'; +import { + AztecAddress, + CompleteAddress, + EthAddress, + Fr, + FunctionSelector, + GrumpkinScalar, + Point, +} from '@aztec/circuits.js'; import { createJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client'; import { AuthWitness, @@ -22,6 +30,7 @@ export const createPXEClient = (url: string, fetch = makeFetch([1, 2, 3], true)) url, { CompleteAddress, + FunctionSelector, AztecAddress, TxExecutionRequest, ContractData, diff --git a/yarn-project/pxe/src/pxe_http/pxe_http_server.ts b/yarn-project/pxe/src/pxe_http/pxe_http_server.ts index 93b40e1b91e..635a790758e 100644 --- a/yarn-project/pxe/src/pxe_http/pxe_http_server.ts +++ b/yarn-project/pxe/src/pxe_http/pxe_http_server.ts @@ -1,3 +1,4 @@ +import { FunctionSelector } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, GrumpkinScalar, Point } from '@aztec/foundation/fields'; import { JsonRpcServer } from '@aztec/foundation/json-rpc/server'; @@ -39,6 +40,7 @@ export function createPXERpcServer(pxeService: PXE): JsonRpcServer { ContractData, ExtendedContractData, ExtendedUnencryptedL2Log, + FunctionSelector, TxHash, EthAddress, Point, diff --git a/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts b/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts index e02414067e5..8eae196b641 100644 --- a/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts +++ b/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts @@ -1,4 +1,4 @@ -import { HistoricBlockData } from '@aztec/circuits.js'; +import { FunctionSelector, HistoricBlockData } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; @@ -33,6 +33,7 @@ export function createAztecNodeRpcClient(url: string, fetch = defaultFetch): Azt ExtendedUnencryptedL2Log, ContractData, Fr, + FunctionSelector, HistoricBlockData, L2Block, L2Tx, From 7afad93f418333811e3843fa55ab7f49aee56a8b Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 09:53:29 +0000 Subject: [PATCH 15/60] WIP --- .../archiver/src/archiver/archiver_store.ts | 5 ++++- yarn-project/aztec.js/src/contract/sent_tx.ts | 10 +++++++++- .../src/e2e_public_token_contract.test.ts | 4 ++-- yarn-project/end-to-end/src/fixtures/utils.ts | 15 ++++++++++++++- yarn-project/types/src/logs/l2_logs_source.ts | 15 +-------------- yarn-project/types/src/tx/tx.ts | 10 ++++++++++ 6 files changed, 40 insertions(+), 19 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 255262f39f6..6493392edfd 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -373,7 +373,10 @@ export class MemoryArchiverStore implements ArchiverDataStore { const txHash = filter.txHash; - const fromBlockIndex = (filter.fromBlock || INITIAL_L2_BLOCK_NUM) - INITIAL_L2_BLOCK_NUM; + const fromBlockIndex = filter.fromBlock === undefined ? 0 : filter.fromBlock - INITIAL_L2_BLOCK_NUM; + if (fromBlockIndex < 0) { + throw new Error(`"fromBlock" (${filter.fromBlock}) smaller than genesis block number (${INITIAL_L2_BLOCK_NUM}).`); + } if (fromBlockIndex > this.unencryptedLogs.length) { return Promise.resolve([]); } diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts index 9ab94c115e3..f47953dc01c 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -1,6 +1,6 @@ import { FieldsOf } from '@aztec/circuits.js'; import { retryUntil } from '@aztec/foundation/retry'; -import { PXE, TxHash, TxReceipt, TxStatus } from '@aztec/types'; +import { ExtendedUnencryptedL2Log, PXE, TxHash, TxReceipt, TxStatus } from '@aztec/types'; import every from 'lodash.every'; @@ -80,6 +80,14 @@ export class SentTx { return receipt.status === TxStatus.MINED; } + /** + * Gets unencrypted logs emitted by this tx. + * @returns The requested logs. + */ + public async getUnencryptedLogs(): Promise { + return this.pxe.getUnencryptedLogs({ txHash: await this.getTxHash() }); + } + protected async waitForReceipt(opts?: WaitOpts): Promise { const txHash = await this.getTxHash(); return await retryUntil( diff --git a/yarn-project/end-to-end/src/e2e_public_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_public_token_contract.test.ts index 32b85181195..2707988a2fc 100644 --- a/yarn-project/end-to-end/src/e2e_public_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_token_contract.test.ts @@ -5,7 +5,7 @@ import { CompleteAddress, PXE, TxStatus } from '@aztec/types'; import times from 'lodash.times'; -import { expectUnencryptedLogsFromLastBlockToBe, setup } from './fixtures/utils.js'; +import { expectUnencryptedLogsFromLastBlockToBe, expectUnencryptedLogsInTxToBe, setup } from './fixtures/utils.js'; describe('e2e_public_token_contract', () => { let pxe: PXE; @@ -52,7 +52,7 @@ describe('e2e_public_token_contract', () => { const balance = await contract.methods.publicBalanceOf(recipient.toField()).view({ from: recipient }); expect(balance).toBe(mintAmount); - await expectUnencryptedLogsFromLastBlockToBe(pxe, ['Coins minted']); + await expectUnencryptedLogsInTxToBe(tx, ['Coins minted']); }, 45_000); // Regression for https://github.com/AztecProtocol/aztec-packages/issues/640 diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 150d58d0613..ebfd625105b 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -6,6 +6,7 @@ import { CompleteAddress, EthAddress, EthCheatCodes, + SentTx, Wallet, createAccounts, createPXEClient, @@ -514,7 +515,19 @@ export const expectsNumOfEncryptedLogsInTheLastBlockToBe = async ( /** * Checks that the last block contains the given expected unencrypted log messages. - * @param pxe - The instance of PXE for retrieving the logs. + * @param tx - An instance of SentTx for which to retrieve the logs. + * @param logMessages - The set of expected log messages. + */ +export const expectUnencryptedLogsInTxToBe = async (tx: SentTx, logMessages: string[]) => { + const unencryptedLogs = await tx.getUnencryptedLogs(); + const asciiLogs = unencryptedLogs.map(extendedLog => extendedLog.log.data.toString('ascii')); + + expect(asciiLogs).toStrictEqual(logMessages); +}; + +/** + * Checks that the last block contains the given expected unencrypted log messages. + * @param pxe - An instance of PXE for retrieving the logs. * @param logMessages - The set of expected log messages. */ export const expectUnencryptedLogsFromLastBlockToBe = async (pxe: PXE, logMessages: string[]) => { diff --git a/yarn-project/types/src/logs/l2_logs_source.ts b/yarn-project/types/src/logs/l2_logs_source.ts index af318629cc6..4e606baad32 100644 --- a/yarn-project/types/src/logs/l2_logs_source.ts +++ b/yarn-project/types/src/logs/l2_logs_source.ts @@ -4,7 +4,7 @@ import { LogFilter } from './log_filter.js'; import { LogType } from './log_type.js'; /** - * Interface of classes allowing for the retrieval of encrypted logs. + * Interface of classes allowing for the retrieval of logs. */ export interface L2LogsSource { /** @@ -23,19 +23,6 @@ export interface L2LogsSource { */ getUnencryptedLogs(filter: LogFilter): Promise; - /** - * Starts the encrypted logs source. - * @param blockUntilSynced - If true, blocks until the data source has fully synced. - * @returns A promise signalling completion of the start process. - */ - start(blockUntilSynced: boolean): Promise; - - /** - * Stops the encrypted logs source. - * @returns A promise signalling completion of the stop process. - */ - stop(): Promise; - /** * Gets the number of the latest L2 block processed by the implementation. * @returns The number of the latest L2 block processed by the implementation. diff --git a/yarn-project/types/src/tx/tx.ts b/yarn-project/types/src/tx/tx.ts index 4486aa8b8ab..6fe4540a8ef 100644 --- a/yarn-project/types/src/tx/tx.ts +++ b/yarn-project/types/src/tx/tx.ts @@ -10,6 +10,7 @@ import { arrayNonEmptyLength } from '@aztec/foundation/collection'; import { BufferReader, Tuple } from '@aztec/foundation/serialize'; import { ExtendedContractData } from '../contract_data.js'; +import { ExtendedUnencryptedL2Log, L2LogsSource } from '../index.js'; import { TxL2Logs } from '../logs/tx_l2_logs.js'; import { TxHash } from './tx_hash.js'; @@ -112,6 +113,15 @@ export class Tx { }; } + /** + * Gets unencrypted logs emitted by this tx. + * @param logsSource - An instance of L2LogsSource which can be used to obtain the logs. + * @returns The requested logs. + */ + public async getUnencryptedLogs(logsSource: L2LogsSource): Promise { + return logsSource.getUnencryptedLogs({ txHash: await this.getTxHash() }); + } + /** * Convert a plain JSON object to a Tx class object. * @param obj - A plain Tx JSON object. From 8f790256bc3fc7604904c58507106c3881f19440 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 10:25:11 +0000 Subject: [PATCH 16/60] WIP --- docs/docs/dev_docs/contracts/syntax/events.md | 11 ++++++++++- .../archiver/src/archiver/archiver.test.ts | 2 +- yarn-project/archiver/src/archiver/archiver.ts | 2 +- .../archiver/src/archiver/archiver_store.test.ts | 4 ++-- .../archiver/src/archiver/archiver_store.ts | 10 +++++----- yarn-project/archiver/src/archiver/config.ts | 3 +++ yarn-project/archiver/src/index.ts | 2 +- yarn-project/aztec.js/src/index.ts | 1 + yarn-project/cli/README.md | 15 +++++++-------- yarn-project/cli/src/index.ts | 9 ++------- yarn-project/types/src/logs/log_filter.ts | 2 -- 11 files changed, 33 insertions(+), 28 deletions(-) diff --git a/docs/docs/dev_docs/contracts/syntax/events.md b/docs/docs/dev_docs/contracts/syntax/events.md index 77bd761d968..3bbbb288305 100644 --- a/docs/docs/dev_docs/contracts/syntax/events.md +++ b/docs/docs/dev_docs/contracts/syntax/events.md @@ -111,7 +111,7 @@ Once emitted, unencrypted events are stored in AztecNode and can be queried by a ```bash -aztec-cli get-logs --from 5 --limit 1 +aztec-cli get-logs --fromBlock 5 ``` @@ -122,6 +122,15 @@ aztec-cli get-logs --from 5 --limit 1 +Get logs functionality provides a variety of filtering options. +To display them run: + +```bash +aztec-cli get-logs --help +``` + +or check the definition of `LogFilter` type. + ## Costs All event data is pushed to Ethereum as calldata by the sequencer and for this reason the cost of emitting an event is non-trivial. diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 89dd1a0a433..5b19fbc742d 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -22,7 +22,7 @@ describe('Archiver', () => { beforeEach(() => { publicClient = mock>(); - archiverStore = new MemoryArchiverStore(); + archiverStore = new MemoryArchiverStore(1000); }); it('can start, sync and stop and handle l1 to l2 messages and logs', async () => { diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 6aa42353bdb..54585242271 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -102,7 +102,7 @@ export class Archiver implements L2BlockSource, L2LogsSource, ContractDataSource transport: http(chain.rpcUrl), pollingInterval: config.viemPollingIntervalMS, }); - const archiverStore = new MemoryArchiverStore(); + const archiverStore = new MemoryArchiverStore(config.maxLogs ?? 1000); const archiver = new Archiver( publicClient, config.l1Contracts.rollupAddress, diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 036af5976f8..96b730f87f8 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -6,7 +6,7 @@ describe('Archiver Memory Store', () => { let archiverStore: ArchiverDataStore; beforeEach(() => { - archiverStore = new MemoryArchiverStore(); + archiverStore = new MemoryArchiverStore(1000); }); it('can store and retrieve blocks', async () => { @@ -34,7 +34,7 @@ describe('Archiver Memory Store', () => { .fill(0) .map(_ => L2BlockL2Logs.random(6, 3, 2)); await archiverStore.addLogs(logs, logType); - // Offset indices by INTIAL_L2_BLOCK_NUM to ensure we are correctly aligned + // Offset indices by INITIAL_L2_BLOCK_NUM to ensure we are correctly aligned for (const [from, limit] of [ [0 + INITIAL_L2_BLOCK_NUM, 10], [3 + INITIAL_L2_BLOCK_NUM, 3], diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 6493392edfd..292ebf05dee 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -203,7 +203,10 @@ export class MemoryArchiverStore implements ArchiverDataStore { */ private pendingL1ToL2Messages: PendingL1ToL2MessageStore = new PendingL1ToL2MessageStore(); - constructor() {} + constructor( + /** The max number of logs that can be obtained in 1 "getUnencryptedLogs" call. */ + public readonly maxLogs: number, + ) {} /** * Append new blocks to the store's list. @@ -365,8 +368,6 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @throws If txHash and block range are both defined. */ getUnencryptedLogs(filter: LogFilter): Promise { - const MAX_LOGS = 1000; - if (filter.txHash && (filter.fromBlock || filter.toBlock)) { throw new Error('Cannot filter by txHash and block range at the same time'); } @@ -386,7 +387,6 @@ export class MemoryArchiverStore implements ArchiverDataStore { return Promise.resolve([]); } - const limit = Math.min(filter.limit || MAX_LOGS, MAX_LOGS); const contractAddress = filter.contractAddress; const selector = filter.selector; @@ -404,7 +404,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { (!selector || log.selector.equals(selector)) ) { logs.push(new ExtendedUnencryptedL2Log(blockContext.block.number, blockContext.getTxHash(j), log)); - if (logs.length === limit) { + if (logs.length === this.maxLogs) { return Promise.resolve(logs); } } diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index 292475dcdfb..61b91368f15 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -46,6 +46,9 @@ export interface ArchiverConfig { * Optional dir to store data. If omitted will store in memory. */ dataDirectory?: string; + + /** The max number of logs that can be obtained in 1 "getUnencryptedLogs" call. */ + maxLogs?: number; } /** diff --git a/yarn-project/archiver/src/index.ts b/yarn-project/archiver/src/index.ts index b327c5f9bb4..0f206b45ca0 100644 --- a/yarn-project/archiver/src/index.ts +++ b/yarn-project/archiver/src/index.ts @@ -24,7 +24,7 @@ async function main() { transport: http(rpcUrl), }); - const archiverStore = new MemoryArchiverStore(); + const archiverStore = new MemoryArchiverStore(1000); const archiver = new Archiver( publicClient, diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index eade673bd6a..b845b00e285 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -15,6 +15,7 @@ export { DeployedContract, FunctionCall, L2BlockL2Logs, + LogFilter, UnencryptedL2Log, NodeInfo, NotePreimage, diff --git a/yarn-project/cli/README.md b/yarn-project/cli/README.md index 0ae7ead9837..aa5aec84b79 100644 --- a/yarn-project/cli/README.md +++ b/yarn-project/cli/README.md @@ -392,24 +392,23 @@ Gets all the unencrypted logs from L2 blocks in the specified range. Syntax: ```shell -aztec-cli get-logs --from --limit [options] +aztec-cli get-logs --fromBlock ``` - -- `from`: Block number to start fetching logs from. -- `limit`: Maximum number of block logs to obtain. - Options: - `-u, --rpc-url `: URL of PXE Service. Default: `http://localhost:8080`. -This command retrieves and displays all the unencrypted logs from L2 blocks in the specified range. It shows the logs found in the blocks and unrolls them for readability. - +This command retrieves and displays all the unencrypted logs from L2 blocks in the specified range or from a specific transaction. Example usage: ```shell -aztec-cli get-logs --from 1000 --limit 10 +aztec-cli get-logs --txHash 21fef567e01f8508e30843ebcef9c5f6ff27b29d66783cfcdbd070c3a9174234 +aztec-cli get-logs --fromBlock 4 --toBlock 5 --contractAddress 0x1db5f68861c5960c37205d3d5b23466240359c115c49e45982865ea7ace69a02 +aztec-cli get-logs --fromBlock 4 --toBlock 5 --contractAddress 0x1db5f68861c5960c37205d3d5b23466240359c115c49e45982865ea7ace69a02 --selector 00000005 ``` +Run `aztec-cli get-logs --help` for more information on the filtering options. + ### block-number Gets the current Aztec L2 block number. diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 947b0560238..d51851895aa 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -300,18 +300,13 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { parseOptionalInteger, ) .option('-t, --toBlock ', 'Up to which block to fetch logs (defaults to latest).', parseOptionalInteger) - .option( - '-l, --limit ', - 'How many logs to fetch (defaults to maximum value of 1000).', - parseOptionalInteger, - ) .option('-c, --contractAddress ', 'Contract address to filter logs by.', parseOptionalAztecAddress) .option('-s, --selector ', 'Event selector to filter logs by.', parseOptionalSelector) .addOption(pxeOption) - .action(async ({ txHash, fromBlock, toBlock, limit, contractAddress, selector, rpcUrl }) => { + .action(async ({ txHash, fromBlock, toBlock, contractAddress, selector, rpcUrl }) => { const client = await createCompatibleClient(rpcUrl, debugLogger); - const filter: LogFilter = { txHash, fromBlock, toBlock, limit, contractAddress, selector }; + const filter: LogFilter = { txHash, fromBlock, toBlock, contractAddress, selector }; const logs = await client.getUnencryptedLogs(filter); if (!logs.length) { diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index 0959e3dbd8e..11d6770660c 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -15,8 +15,6 @@ export type LogFilter = { fromBlock?: number; /** The block number until which to fetch logs (not inclusive). */ toBlock?: number; - /** Maximum number of logs to fetch. */ - limit?: number; /** The contract address to filter logs by. */ contractAddress?: AztecAddress; /** The event selector to filter logs by. */ From 5da07de71cd0797f9e62ed5b7dd06a51a3aeff39 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 10:31:17 +0000 Subject: [PATCH 17/60] WIP --- yarn-project/types/src/tx/tx.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/types/src/tx/tx.ts b/yarn-project/types/src/tx/tx.ts index 6fe4540a8ef..cd90356b2aa 100644 --- a/yarn-project/types/src/tx/tx.ts +++ b/yarn-project/types/src/tx/tx.ts @@ -115,7 +115,7 @@ export class Tx { /** * Gets unencrypted logs emitted by this tx. - * @param logsSource - An instance of L2LogsSource which can be used to obtain the logs. + * @param logsSource - An instance of `L2LogsSource` which can be used to obtain the logs. * @returns The requested logs. */ public async getUnencryptedLogs(logsSource: L2LogsSource): Promise { From c89774b0ce20a3e00e5bf04e9ef78cc0389457cb Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 10:38:05 +0000 Subject: [PATCH 18/60] WIP --- yarn-project/acir-simulator/src/acvm/oracle/oracle.ts | 2 +- yarn-project/types/src/logs/log_filter.ts | 5 ++++- yarn-project/types/src/logs/unencrypted_l2_log.ts | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts b/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts index 14c2d9736a3..a03140c3b22 100644 --- a/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts @@ -165,7 +165,7 @@ export class Oracle { const logPayload = Buffer.concat(message.map(charBuffer => convertACVMFieldToBuffer(charBuffer).subarray(-1))); const log = new UnencryptedL2Log( AztecAddress.fromString(contractAddress), - FunctionSelector.fromField(fromACVMField(eventSelector)), + FunctionSelector.fromField(fromACVMField(eventSelector)), // TODO https://github.com/AztecProtocol/aztec-packages/issues/2704 logPayload, ); diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index 11d6770660c..aeb7407b1ce 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -17,6 +17,9 @@ export type LogFilter = { toBlock?: number; /** The contract address to filter logs by. */ contractAddress?: AztecAddress; - /** The event selector to filter logs by. */ + /** + * Selector of the event/log topic. + * TODO: https://github.com/AztecProtocol/aztec-packages/issues/2704 + */ selector?: FunctionSelector; }; diff --git a/yarn-project/types/src/logs/unencrypted_l2_log.ts b/yarn-project/types/src/logs/unencrypted_l2_log.ts index 598b85bd7fa..6499f7f1ee5 100644 --- a/yarn-project/types/src/logs/unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/unencrypted_l2_log.ts @@ -17,7 +17,10 @@ export class UnencryptedL2Log { * TODO: Optimize this once it makes sense. */ public readonly contractAddress: AztecAddress, - /** Selector of the event/log topic. */ + /** + * Selector of the event/log topic. + * TODO: https://github.com/AztecProtocol/aztec-packages/issues/2704 + */ public readonly selector: FunctionSelector, /** The data contents of the log. */ public readonly data: Buffer, From 155a3f792163c36c540f995066a2e36dbceeef89 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 5 Oct 2023 12:23:31 +0000 Subject: [PATCH 19/60] --follow flag --- yarn-project/cli/src/index.ts | 41 +++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index d51851895aa..be1bbd6f9de 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -11,6 +11,7 @@ import { import { StructType, decodeFunctionSignatureWithParameterNames } from '@aztec/foundation/abi'; import { JsonStringify } from '@aztec/foundation/json-rpc'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; +import { RunningPromise } from '@aztec/foundation/running-promise'; import { fileURLToPath } from '@aztec/foundation/url'; import { compileContract, generateNoirInterface, generateTypescriptInterface } from '@aztec/noir-compiler/cli'; import { CompleteAddress, ContractData, LogFilter } from '@aztec/types'; @@ -303,21 +304,39 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { .option('-c, --contractAddress ', 'Contract address to filter logs by.', parseOptionalAztecAddress) .option('-s, --selector ', 'Event selector to filter logs by.', parseOptionalSelector) .addOption(pxeOption) - .action(async ({ txHash, fromBlock, toBlock, contractAddress, selector, rpcUrl }) => { + .option('--follow', 'If set, will keep polling for new logs until interrupted.') + .action(async ({ txHash, fromBlock, toBlock, contractAddress, selector, rpcUrl, follow }) => { const client = await createCompatibleClient(rpcUrl, debugLogger); + if (follow) { + if (txHash) throw Error('Cannot use --follow with --txHash'); + if (toBlock) throw Error('Cannot use --follow with --toBlock'); + } + const filter: LogFilter = { txHash, fromBlock, toBlock, contractAddress, selector }; - const logs = await client.getUnencryptedLogs(filter); - - if (!logs.length) { - const filterOptions = Object.entries(filter) - .filter(([, value]) => value !== undefined) - .map(([key, value]) => `${key}: ${value}`) - .join(', '); - log(`No logs found for filter: {${filterOptions}}`); + + const fetchLogs = async () => { + const logs = await client.getUnencryptedLogs(filter); + + if (!logs.length) { + const filterOptions = Object.entries(filter) + .filter(([, value]) => value !== undefined) + .map(([key, value]) => `${key}: ${value}`) + .join(', '); + if (!follow) log(`No logs found for filter: {${filterOptions}}`); + } else { + if (!follow) log('Logs found: \n'); + logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); + // Set `fromBlock` to the block number of the next block after the block of last log we fetched. + filter.fromBlock = logs[logs.length - 1].blockNumber + 1; + } + }; + + if (follow) { + log('Fetching logs...'); + new RunningPromise(fetchLogs, 1000).start(); } else { - log('Logs found: \n'); - logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); + await fetchLogs(); } }); From 3d18b3983c89a157cc87642120c2205eadecd0fd Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 6 Oct 2023 07:13:02 +0000 Subject: [PATCH 20/60] no running promise --- yarn-project/cli/src/index.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index be1bbd6f9de..cc25596643e 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -11,7 +11,7 @@ import { import { StructType, decodeFunctionSignatureWithParameterNames } from '@aztec/foundation/abi'; import { JsonStringify } from '@aztec/foundation/json-rpc'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; -import { RunningPromise } from '@aztec/foundation/running-promise'; +import { sleep } from '@aztec/foundation/sleep'; import { fileURLToPath } from '@aztec/foundation/url'; import { compileContract, generateNoirInterface, generateTypescriptInterface } from '@aztec/noir-compiler/cli'; import { CompleteAddress, ContractData, LogFilter } from '@aztec/types'; @@ -334,7 +334,10 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { if (follow) { log('Fetching logs...'); - new RunningPromise(fetchLogs, 1000).start(); + while (true) { + await fetchLogs(); + await sleep(1000); + } } else { await fetchLogs(); } From 7c366a867fba8ce25f1b66463f57f9f1b715ea8f Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 6 Oct 2023 13:20:47 +0000 Subject: [PATCH 21/60] waiting for tx to be mined before getting logs --- yarn-project/aztec.js/src/contract/sent_tx.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts index f47953dc01c..82d08a58518 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -82,9 +82,11 @@ export class SentTx { /** * Gets unencrypted logs emitted by this tx. + * @remarks This function will wait for the tx to be mined if it hasn't been already. * @returns The requested logs. */ public async getUnencryptedLogs(): Promise { + await this.wait(); return this.pxe.getUnencryptedLogs({ txHash: await this.getTxHash() }); } From 747a5ab054ebcf4ecf2b0651bf368179b1ffdedf Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 6 Oct 2023 14:06:23 +0000 Subject: [PATCH 22/60] consistent arg names --- yarn-project/cli/src/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index cc25596643e..0b0b806d91a 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -294,23 +294,23 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { program .command('get-logs') .description('Gets all the unencrypted logs from L2 blocks in the range specified.') - .option('-tx, --txHash ', 'A transaction hash to get the receipt for.', parseOptionalTxHash) + .option('-tx, --tx-hash ', 'A transaction hash to get the receipt for.', parseOptionalTxHash) .option( - '-f, --fromBlock ', + '-f, --from-block ', 'Initial block number for getting logs (defaults to 1).', parseOptionalInteger, ) - .option('-t, --toBlock ', 'Up to which block to fetch logs (defaults to latest).', parseOptionalInteger) - .option('-c, --contractAddress ', 'Contract address to filter logs by.', parseOptionalAztecAddress) - .option('-s, --selector ', 'Event selector to filter logs by.', parseOptionalSelector) + .option('-t, --to-block ', 'Up to which block to fetch logs (defaults to latest).', parseOptionalInteger) + .option('-ca, --contract-address
', 'Contract address to filter logs by.', parseOptionalAztecAddress) + .option('-s, --selector ', 'Event selector to filter logs by.', parseOptionalSelector) .addOption(pxeOption) .option('--follow', 'If set, will keep polling for new logs until interrupted.') .action(async ({ txHash, fromBlock, toBlock, contractAddress, selector, rpcUrl, follow }) => { const client = await createCompatibleClient(rpcUrl, debugLogger); if (follow) { - if (txHash) throw Error('Cannot use --follow with --txHash'); - if (toBlock) throw Error('Cannot use --follow with --toBlock'); + if (txHash) throw Error('Cannot use --follow with --tx-hash'); + if (toBlock) throw Error('Cannot use --follow with --to-block'); } const filter: LogFilter = { txHash, fromBlock, toBlock, contractAddress, selector }; From a3fef6f1796afd3e2cfa12624ebd813d538852a2 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 6 Oct 2023 14:10:58 +0000 Subject: [PATCH 23/60] Palla's suggestion --- yarn-project/types/src/logs/tx_l2_logs.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/yarn-project/types/src/logs/tx_l2_logs.ts b/yarn-project/types/src/logs/tx_l2_logs.ts index d9388b9df84..12a79b9f6dd 100644 --- a/yarn-project/types/src/logs/tx_l2_logs.ts +++ b/yarn-project/types/src/logs/tx_l2_logs.ts @@ -87,11 +87,7 @@ export class TxL2Logs { * @returns Unrolled logs. */ public unrollLogs(): Buffer[] { - const logs = []; - for (const functionLog of this.functionLogs) { - logs.push(...functionLog.logs); - } - return logs; + return this.functionLogs.flatMap(functionLog => functionLog.logs); } /** From d30a1e1d47cd344ac755e27d45f50617f2408760 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 6 Oct 2023 14:40:32 +0000 Subject: [PATCH 24/60] number parsing fix --- yarn-project/cli/src/utils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index e393528ad19..0039a5c53bf 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -252,9 +252,9 @@ export function parseOptionalInteger(value: string): number | undefined { if (!value) { return undefined; } - const parsed = parseInt(value, 10); - if (isNaN(parsed)) { - throw new InvalidArgumentError(`Invalid integer: ${value}`); + const parsed = Number(value); + if (!Number.isInteger(parsed)) { + throw new InvalidArgumentError('Invalid integer.'); } return parsed; } From d9007688fe97764dcdc92a868d727997a70450bd Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 6 Oct 2023 14:43:30 +0000 Subject: [PATCH 25/60] better naming --- .../archiver/src/archiver/archiver_store.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 292ebf05dee..dfcd48832da 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -174,13 +174,13 @@ export class MemoryArchiverStore implements ArchiverDataStore { * An array containing all the encrypted logs that have been fetched so far. * Note: Index in the "outer" array equals to (corresponding L2 block's number - INITIAL_L2_BLOCK_NUM). */ - private encryptedLogs: L2BlockL2Logs[] = []; + private encryptedLogsPerBlock: L2BlockL2Logs[] = []; /** * An array containing all the unencrypted logs that have been fetched so far. * Note: Index in the "outer" array equals to (corresponding L2 block's number - INITIAL_L2_BLOCK_NUM). */ - private unencryptedLogs: L2BlockL2Logs[] = []; + private unencryptedLogsPerBlock: L2BlockL2Logs[] = []; /** * A sparse array containing all the extended contract data that have been fetched so far. @@ -226,7 +226,9 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns True if the operation is successful. */ addLogs(data: L2BlockL2Logs[], logType: LogType): Promise { - logType === LogType.ENCRYPTED ? this.encryptedLogs.push(...data) : this.unencryptedLogs.push(...data); + logType === LogType.ENCRYPTED + ? this.encryptedLogsPerBlock.push(...data) + : this.unencryptedLogsPerBlock.push(...data); return Promise.resolve(true); } @@ -352,7 +354,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { if (from < INITIAL_L2_BLOCK_NUM || limit < 1) { throw new Error(`Invalid block range from: ${from}, limit: ${limit}`); } - const logs = logType === LogType.ENCRYPTED ? this.encryptedLogs : this.unencryptedLogs; + const logs = logType === LogType.ENCRYPTED ? this.encryptedLogsPerBlock : this.unencryptedLogsPerBlock; if (from > logs.length) { return Promise.resolve([]); } @@ -378,11 +380,12 @@ export class MemoryArchiverStore implements ArchiverDataStore { if (fromBlockIndex < 0) { throw new Error(`"fromBlock" (${filter.fromBlock}) smaller than genesis block number (${INITIAL_L2_BLOCK_NUM}).`); } - if (fromBlockIndex > this.unencryptedLogs.length) { + if (fromBlockIndex > this.unencryptedLogsPerBlock.length) { return Promise.resolve([]); } - const toBlockIndex = (filter.toBlock || this.unencryptedLogs.length + INITIAL_L2_BLOCK_NUM) - INITIAL_L2_BLOCK_NUM; + const toBlockIndex = + (filter.toBlock || this.unencryptedLogsPerBlock.length + INITIAL_L2_BLOCK_NUM) - INITIAL_L2_BLOCK_NUM; if (toBlockIndex < fromBlockIndex) { return Promise.resolve([]); } @@ -394,7 +397,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { for (let i = fromBlockIndex; i < toBlockIndex; i++) { const blockContext = this.l2BlockContexts[i]; - const blockLogs = this.unencryptedLogs[i]; + const blockLogs = this.unencryptedLogsPerBlock[i]; for (let j = 0; j < blockLogs.txLogs.length; j++) { const txLogs = blockLogs.txLogs[j].unrollLogs().map(log => UnencryptedL2Log.fromBuffer(log)); for (const log of txLogs) { From fc7cc85d7cab737f78113d9eea63b858a3146d00 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 08:46:20 +0000 Subject: [PATCH 26/60] WIP --- .../archiver/src/archiver/archiver.ts | 2 +- .../archiver/src/archiver/archiver_store.ts | 29 ++++++++++---- yarn-project/cli/src/index.ts | 23 ++++++----- yarn-project/cli/src/utils.ts | 14 +++++++ .../src/logs/extended_unencrypted_l2_log.ts | 31 ++++++++++++++- yarn-project/types/src/logs/index.ts | 1 + yarn-project/types/src/logs/log_filter.ts | 27 ++++++++++++- yarn-project/types/src/logs/log_id.ts | 38 +++++++++++++++++++ 8 files changed, 144 insertions(+), 21 deletions(-) create mode 100644 yarn-project/types/src/logs/log_id.ts diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 54585242271..823b7b9d515 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -167,7 +167,7 @@ export class Archiver implements L2BlockSource, L2LogsSource, ContractDataSource * This is a problem for example when setting the last block number marker for L1 to L2 messages - * this.lastProcessedBlockNumber = currentBlockNumber; * It's possible that we actually received messages in block currentBlockNumber + 1 meaning the next time - * we do this sync we get the same message again. Addtionally, the call to get cancelled L1 to L2 messages + * we do this sync we get the same message again. Additionally, the call to get cancelled L1 to L2 messages * could read from a block not present when retrieving pending messages. If a message was added and cancelled * in the same eth block then we could try and cancel a non-existent pending message. * diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index dfcd48832da..2dd3625e625 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -14,6 +14,7 @@ import { LogType, TxHash, UnencryptedL2Log, + validateLogFilter, } from '@aztec/types'; import { L1ToL2MessageStore, PendingL1ToL2MessageStore } from './l1_to_l2_message_store.js'; @@ -370,13 +371,17 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @throws If txHash and block range are both defined. */ getUnencryptedLogs(filter: LogFilter): Promise { - if (filter.txHash && (filter.fromBlock || filter.toBlock)) { - throw new Error('Cannot filter by txHash and block range at the same time'); - } + validateLogFilter(filter); const txHash = filter.txHash; - const fromBlockIndex = filter.fromBlock === undefined ? 0 : filter.fromBlock - INITIAL_L2_BLOCK_NUM; + let fromBlockIndex = 0; + if (filter.fromBlock !== undefined) { + fromBlockIndex = filter.fromBlock - INITIAL_L2_BLOCK_NUM; + } else if (filter.fromLog !== undefined) { + fromBlockIndex = filter.fromLog.blockNumber - INITIAL_L2_BLOCK_NUM; + } + if (fromBlockIndex < 0) { throw new Error(`"fromBlock" (${filter.fromBlock}) smaller than genesis block number (${INITIAL_L2_BLOCK_NUM}).`); } @@ -393,26 +398,34 @@ export class MemoryArchiverStore implements ArchiverDataStore { const contractAddress = filter.contractAddress; const selector = filter.selector; + let txIndexInBlock = 0; + if (filter.fromLog !== undefined) { + txIndexInBlock = filter.fromLog.logIndex; + } + const logs: ExtendedUnencryptedL2Log[] = []; for (let i = fromBlockIndex; i < toBlockIndex; i++) { const blockContext = this.l2BlockContexts[i]; const blockLogs = this.unencryptedLogsPerBlock[i]; - for (let j = 0; j < blockLogs.txLogs.length; j++) { - const txLogs = blockLogs.txLogs[j].unrollLogs().map(log => UnencryptedL2Log.fromBuffer(log)); + for (; txIndexInBlock < blockLogs.txLogs.length; txIndexInBlock++) { + const txLogs = blockLogs.txLogs[txIndexInBlock].unrollLogs().map(log => UnencryptedL2Log.fromBuffer(log)); for (const log of txLogs) { if ( - (!txHash || blockContext.getTxHash(j).equals(txHash)) && + (!txHash || blockContext.getTxHash(txIndexInBlock).equals(txHash)) && (!contractAddress || log.contractAddress.equals(contractAddress)) && (!selector || log.selector.equals(selector)) ) { - logs.push(new ExtendedUnencryptedL2Log(blockContext.block.number, blockContext.getTxHash(j), log)); + logs.push( + new ExtendedUnencryptedL2Log(blockContext.block.number, blockContext.getTxHash(txIndexInBlock), log), + ); if (logs.length === this.maxLogs) { return Promise.resolve(logs); } } } } + txIndexInBlock = 0; } return Promise.resolve(logs); diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 0b0b806d91a..e1d9d9bdaf4 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -14,7 +14,7 @@ import { DebugLogger, LogFn } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; import { fileURLToPath } from '@aztec/foundation/url'; import { compileContract, generateNoirInterface, generateTypescriptInterface } from '@aztec/noir-compiler/cli'; -import { CompleteAddress, ContractData, LogFilter } from '@aztec/types'; +import { CompleteAddress, ContractData, LogFilter, validateLogFilter } from '@aztec/types'; import { createSecp256k1PeerId } from '@libp2p/peer-id-factory'; import { Command, Option } from 'commander'; @@ -37,6 +37,7 @@ import { parseFields, parseOptionalAztecAddress, parseOptionalInteger, + parseOptionalLogId, parseOptionalSelector, parseOptionalTxHash, parsePartialAddress, @@ -296,27 +297,30 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { .description('Gets all the unencrypted logs from L2 blocks in the range specified.') .option('-tx, --tx-hash ', 'A transaction hash to get the receipt for.', parseOptionalTxHash) .option( - '-f, --from-block ', + '-fb, --from-block ', 'Initial block number for getting logs (defaults to 1).', parseOptionalInteger, ) - .option('-t, --to-block ', 'Up to which block to fetch logs (defaults to latest).', parseOptionalInteger) + .option('-tb, --to-block ', 'Up to which block to fetch logs (defaults to latest).', parseOptionalInteger) + .option('-fl --from-log ', 'Initial log id for getting logs.', parseOptionalLogId) .option('-ca, --contract-address
', 'Contract address to filter logs by.', parseOptionalAztecAddress) .option('-s, --selector ', 'Event selector to filter logs by.', parseOptionalSelector) .addOption(pxeOption) .option('--follow', 'If set, will keep polling for new logs until interrupted.') - .action(async ({ txHash, fromBlock, toBlock, contractAddress, selector, rpcUrl, follow }) => { - const client = await createCompatibleClient(rpcUrl, debugLogger); + .action(async ({ txHash, fromBlock, toBlock, fromLog, contractAddress, selector, rpcUrl, follow }) => { + const pxe = await createCompatibleClient(rpcUrl, debugLogger); if (follow) { if (txHash) throw Error('Cannot use --follow with --tx-hash'); if (toBlock) throw Error('Cannot use --follow with --to-block'); } - const filter: LogFilter = { txHash, fromBlock, toBlock, contractAddress, selector }; + const filter: LogFilter = { txHash, fromBlock, toBlock, fromLog, contractAddress, selector }; + + validateLogFilter(filter); const fetchLogs = async () => { - const logs = await client.getUnencryptedLogs(filter); + const logs = await pxe.getUnencryptedLogs(filter); if (!logs.length) { const filterOptions = Object.entries(filter) @@ -327,8 +331,9 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { } else { if (!follow) log('Logs found: \n'); logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); - // Set `fromBlock` to the block number of the next block after the block of last log we fetched. - filter.fromBlock = logs[logs.length - 1].blockNumber + 1; + // Disable `fromBlock` and continue using the `fromLog` filter. + filter.fromBlock = undefined; + filter.fromLog = await logs[logs.length - 1].getLogId(pxe); } }; diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index 0039a5c53bf..0a70c2c7ea2 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -15,6 +15,7 @@ import { RollupAbi, RollupBytecode, } from '@aztec/l1-artifacts'; +import { LogId, parseLogId } from '@aztec/types'; import { InvalidArgumentError } from 'commander'; import fs from 'fs'; @@ -224,6 +225,19 @@ export function parseOptionalAztecAddress(address: string): AztecAddress | undef return parseAztecAddress(address); } +/** + * Parses an optional log ID string into a LogId object. + * + * @param logId - The log ID string to parse. + * @returns The parsed LogId object, or undefined if the log ID is missing or empty. + */ +export function parseOptionalLogId(logId: string): LogId | undefined { + if (!logId) { + return undefined; + } + return parseLogId(logId); +} + /** * Parses a selector from a string. * @param selector - A serialised selector. diff --git a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts index 64cb21f4d0c..7e5a83eff81 100644 --- a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts @@ -1,7 +1,9 @@ import { toBufferBE } from '@aztec/foundation/bigint-buffer'; import { BufferReader } from '@aztec/foundation/serialize'; -import { TxHash, UnencryptedL2Log } from '../index.js'; +import isEqual from 'lodash.isequal'; + +import { LogId, PXE, TxHash, UnencryptedL2Log } from '../index.js'; /** * Represents an individual unencrypted log entry extended with info about the block and tx it was emitted in. @@ -40,6 +42,33 @@ export class ExtendedUnencryptedL2Log { return `${this.log.toHumanReadable()} (blockNumber: ${this.blockNumber}, txHash: ${this.txHash.toString()})`; } + /** + * Checks if two ExtendedUnencryptedL2Log objects are equal. + * @param other - Another ExtendedUnencryptedL2Log object to compare with. + * @returns True if the two objects are equal, false otherwise. + */ + public equals(other: ExtendedUnencryptedL2Log): boolean { + return isEqual(this, other); + } + + /** + * Gets a globally unique log id. + * @param pxe - The PXE instance to use for retrieving logs. + * @returns A globally unique log id. + */ + public async getLogId(pxe: PXE): Promise { + const txLogs = await pxe.getUnencryptedLogs({ txHash: this.txHash }); + const logIndex = txLogs.findIndex(log => log.equals(this)); + if (logIndex === -1) { + throw new Error(`Log ${this.toHumanReadable()} not found in tx ${this.txHash.toString()}`); + } + return { + blockNumber: this.blockNumber, + txIndex: this.txHash, + logIndex: logIndex, + }; + } + /** * Deserializes log from a buffer. * @param buffer - The buffer or buffer reader containing the log. diff --git a/yarn-project/types/src/logs/index.ts b/yarn-project/types/src/logs/index.ts index 6acc9289d9b..d34c300eb27 100644 --- a/yarn-project/types/src/logs/index.ts +++ b/yarn-project/types/src/logs/index.ts @@ -1,6 +1,7 @@ export * from './function_l2_logs.js'; export * from './l2_block_l2_logs.js'; export * from './l2_logs_source.js'; +export * from './log_id.js'; export * from './log_type.js'; export * from './log_filter.js'; export * from './note_spending_info/index.js'; diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index aeb7407b1ce..363af301bbb 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -1,6 +1,6 @@ import { AztecAddress, FunctionSelector } from '@aztec/circuits.js'; -import { TxHash } from '../index.js'; +import { LogId, TxHash } from '../index.js'; /** * Log filter used to fetch L2 logs. @@ -11,10 +11,18 @@ export type LogFilter = { * @remarks If this is set, `fromBlock` and `toBlock` can't be defined. */ txHash?: TxHash; - /** The block number from which to start fetching logs (inclusive). */ + /** + * The block number from which to start fetching logs (inclusive). + * @remarks If this is set, `txHash` and `fromLog` can't be defined. + */ fromBlock?: number; /** The block number until which to fetch logs (not inclusive). */ toBlock?: number; + /** + * Log id from which to start fetching logs (inclusive). + * @remarks If this is set, `fromBlock` and `txHash` can't be defined. + */ + fromLog?: LogId; /** The contract address to filter logs by. */ contractAddress?: AztecAddress; /** @@ -23,3 +31,18 @@ export type LogFilter = { */ selector?: FunctionSelector; }; + +/** + * Validates a log filter. + * @param filter - Log filter to validate. + * @throws If the filter is invalid. + */ +export function validateLogFilter(filter: LogFilter) { + if (filter.txHash && (filter.fromBlock || filter.toBlock || filter.fromLog)) { + throw new Error("If txHash is set, fromBlock, toBlock, and fromLog can't be defined."); + } + + if (filter.fromBlock !== undefined && filter.fromLog) { + throw new Error("If fromBlock is set, fromLog can't be defined."); + } +} diff --git a/yarn-project/types/src/logs/log_id.ts b/yarn-project/types/src/logs/log_id.ts new file mode 100644 index 00000000000..d9ca24493e4 --- /dev/null +++ b/yarn-project/types/src/logs/log_id.ts @@ -0,0 +1,38 @@ + +/** A globally unique log id. */ +export type LogId = { + /** The block number in which the tx containing the log was included. */ + blockNumber: number; + /** The index of a tx in a block. */ + txIndex: number; + /** The index of the log within a transaction. */ + logIndex: number; +}; + +/** + * Parses a log id from a string. + * @param logId - A string representation of a log id. + * @returns A log id. + */ +export function parseLogId(logId: string): LogId { + const [rawBlockNumber, rawTxIndex, rawLogIndex] = logId.split('-'); + const blockNumber = Number(rawBlockNumber); + const txIndex = Number(rawTxIndex); + const logIndex = Number(rawLogIndex); + + if (!Number.isInteger(blockNumber)) { + throw new Error(`Invalid block number in log id: ${logId}`); + } + if (!Number.isInteger(txIndex)) { + throw new Error(`Invalid tx index in log id: ${logId}`); + } + if (!Number.isInteger(logIndex)) { + throw new Error(`Invalid log index in log id: ${logId}`); + } + + return { + blockNumber, + txIndex, + logIndex, + }; +} From 3baa54ef252ba0af783b5addd7e0e36649c6ff15 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 09:39:21 +0000 Subject: [PATCH 27/60] WIP --- .../archiver/src/archiver/archiver_store.ts | 17 ++- .../src/aztec-node/http_rpc_server.ts | 2 + yarn-project/aztec.js/src/pxe_client.ts | 2 + yarn-project/cli/src/index.ts | 10 +- yarn-project/cli/src/utils.ts | 4 +- .../pxe/src/pxe_http/pxe_http_server.ts | 2 + .../src/aztec_node/rpc/http_rpc_client.ts | 2 + .../src/logs/extended_unencrypted_l2_log.ts | 36 ++---- yarn-project/types/src/logs/log_filter.ts | 8 +- yarn-project/types/src/logs/log_id.ts | 111 +++++++++++++----- 10 files changed, 117 insertions(+), 77 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 2dd3625e625..2b5bf3777e9 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -11,6 +11,7 @@ import { L2BlockL2Logs, L2Tx, LogFilter, + LogId, LogType, TxHash, UnencryptedL2Log, @@ -378,8 +379,8 @@ export class MemoryArchiverStore implements ArchiverDataStore { let fromBlockIndex = 0; if (filter.fromBlock !== undefined) { fromBlockIndex = filter.fromBlock - INITIAL_L2_BLOCK_NUM; - } else if (filter.fromLog !== undefined) { - fromBlockIndex = filter.fromLog.blockNumber - INITIAL_L2_BLOCK_NUM; + } else if (filter.afterLog !== undefined) { + fromBlockIndex = filter.afterLog.blockNumber - INITIAL_L2_BLOCK_NUM; } if (fromBlockIndex < 0) { @@ -399,8 +400,10 @@ export class MemoryArchiverStore implements ArchiverDataStore { const selector = filter.selector; let txIndexInBlock = 0; - if (filter.fromLog !== undefined) { - txIndexInBlock = filter.fromLog.logIndex; + let logIndexInTx = 0; + if (filter.afterLog !== undefined) { + txIndexInBlock = filter.afterLog.logIndex; + logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log } const logs: ExtendedUnencryptedL2Log[] = []; @@ -410,20 +413,22 @@ export class MemoryArchiverStore implements ArchiverDataStore { const blockLogs = this.unencryptedLogsPerBlock[i]; for (; txIndexInBlock < blockLogs.txLogs.length; txIndexInBlock++) { const txLogs = blockLogs.txLogs[txIndexInBlock].unrollLogs().map(log => UnencryptedL2Log.fromBuffer(log)); - for (const log of txLogs) { + for (; logIndexInTx < txLogs.length; logIndexInTx++) { + const log = txLogs[logIndexInTx]; if ( (!txHash || blockContext.getTxHash(txIndexInBlock).equals(txHash)) && (!contractAddress || log.contractAddress.equals(contractAddress)) && (!selector || log.selector.equals(selector)) ) { logs.push( - new ExtendedUnencryptedL2Log(blockContext.block.number, blockContext.getTxHash(txIndexInBlock), log), + new ExtendedUnencryptedL2Log(new LogId(blockContext.block.number, txIndexInBlock, logIndexInTx), log), ); if (logs.length === this.maxLogs) { return Promise.resolve(logs); } } } + logIndexInTx = 0; } txIndexInBlock = 0; } diff --git a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts index c1da62e6b29..03f94ab8252 100644 --- a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts +++ b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts @@ -12,6 +12,7 @@ import { L2Block, L2BlockL2Logs, L2Tx, + LogId, SiblingPath, Tx, TxHash, @@ -36,6 +37,7 @@ export function createAztecNodeRpcServer(node: AztecNode) { HistoricBlockData, L2Block, L2Tx, + LogId, TxHash, SiblingPath, L1ToL2MessageAndIndex, diff --git a/yarn-project/aztec.js/src/pxe_client.ts b/yarn-project/aztec.js/src/pxe_client.ts index ad666a9f0e0..4e03af4ffbc 100644 --- a/yarn-project/aztec.js/src/pxe_client.ts +++ b/yarn-project/aztec.js/src/pxe_client.ts @@ -15,6 +15,7 @@ import { ExtendedUnencryptedL2Log, L2BlockL2Logs, L2Tx, + LogId, NotePreimage, PXE, Tx, @@ -44,6 +45,7 @@ export const createPXEClient = (url: string, fetch = makeFetch([1, 2, 3], true)) NotePreimage, AuthWitness, L2Tx, + LogId, }, { Tx, TxReceipt, L2BlockL2Logs }, false, diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index e1d9d9bdaf4..91a4153e303 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -302,12 +302,12 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { parseOptionalInteger, ) .option('-tb, --to-block ', 'Up to which block to fetch logs (defaults to latest).', parseOptionalInteger) - .option('-fl --from-log ', 'Initial log id for getting logs.', parseOptionalLogId) + .option('-al --after-log ', 'ID of a log after which to fetch the logs.', parseOptionalLogId) .option('-ca, --contract-address
', 'Contract address to filter logs by.', parseOptionalAztecAddress) .option('-s, --selector ', 'Event selector to filter logs by.', parseOptionalSelector) .addOption(pxeOption) .option('--follow', 'If set, will keep polling for new logs until interrupted.') - .action(async ({ txHash, fromBlock, toBlock, fromLog, contractAddress, selector, rpcUrl, follow }) => { + .action(async ({ txHash, fromBlock, toBlock, afterLog, contractAddress, selector, rpcUrl, follow }) => { const pxe = await createCompatibleClient(rpcUrl, debugLogger); if (follow) { @@ -315,7 +315,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { if (toBlock) throw Error('Cannot use --follow with --to-block'); } - const filter: LogFilter = { txHash, fromBlock, toBlock, fromLog, contractAddress, selector }; + const filter: LogFilter = { txHash, fromBlock, toBlock, afterLog, contractAddress, selector }; validateLogFilter(filter); @@ -331,9 +331,9 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { } else { if (!follow) log('Logs found: \n'); logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); - // Disable `fromBlock` and continue using the `fromLog` filter. + // Disable `fromBlock` and continue using the `afterLog` filter. filter.fromBlock = undefined; - filter.fromLog = await logs[logs.length - 1].getLogId(pxe); + filter.afterLog = logs[logs.length - 1].logId; } }; diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index 0a70c2c7ea2..150ebe8abc4 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -15,7 +15,7 @@ import { RollupAbi, RollupBytecode, } from '@aztec/l1-artifacts'; -import { LogId, parseLogId } from '@aztec/types'; +import { LogId } from '@aztec/types'; import { InvalidArgumentError } from 'commander'; import fs from 'fs'; @@ -235,7 +235,7 @@ export function parseOptionalLogId(logId: string): LogId | undefined { if (!logId) { return undefined; } - return parseLogId(logId); + return LogId.fromString(logId); } /** diff --git a/yarn-project/pxe/src/pxe_http/pxe_http_server.ts b/yarn-project/pxe/src/pxe_http/pxe_http_server.ts index 635a790758e..64eb01c1f56 100644 --- a/yarn-project/pxe/src/pxe_http/pxe_http_server.ts +++ b/yarn-project/pxe/src/pxe_http/pxe_http_server.ts @@ -11,6 +11,7 @@ import { L2Block, L2BlockL2Logs, L2Tx, + LogId, NotePreimage, PXE, Tx, @@ -50,6 +51,7 @@ export function createPXERpcServer(pxeService: PXE): JsonRpcServer { AuthWitness, L2Block, L2Tx, + LogId, }, { Tx, TxReceipt, L2BlockL2Logs }, false, diff --git a/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts b/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts index 8eae196b641..0dd96e503a7 100644 --- a/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts +++ b/yarn-project/types/src/aztec_node/rpc/http_rpc_client.ts @@ -12,6 +12,7 @@ import { L2Block, L2BlockL2Logs, L2Tx, + LogId, SiblingPath, Tx, TxHash, @@ -37,6 +38,7 @@ export function createAztecNodeRpcClient(url: string, fetch = defaultFetch): Azt HistoricBlockData, L2Block, L2Tx, + LogId, TxHash, SiblingPath, L1ToL2MessageAndIndex, diff --git a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts index 7e5a83eff81..41e39a0e26e 100644 --- a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts @@ -1,19 +1,16 @@ -import { toBufferBE } from '@aztec/foundation/bigint-buffer'; import { BufferReader } from '@aztec/foundation/serialize'; import isEqual from 'lodash.isequal'; -import { LogId, PXE, TxHash, UnencryptedL2Log } from '../index.js'; +import { LogId, TxHash, UnencryptedL2Log } from '../index.js'; /** * Represents an individual unencrypted log entry extended with info about the block and tx it was emitted in. */ export class ExtendedUnencryptedL2Log { constructor( - /** Number of L2 block the log was emitted in. */ - public readonly blockNumber: number, - /** Selector of the event/log topic. */ - public readonly txHash: TxHash, + /** Globally unique id of the log. */ + public readonly logId: LogId, /** The data contents of the log. */ public readonly log: UnencryptedL2Log, ) {} @@ -23,7 +20,7 @@ export class ExtendedUnencryptedL2Log { * @returns A buffer containing the serialized log. */ public toBuffer(): Buffer { - return Buffer.concat([toBufferBE(BigInt(this.blockNumber), 4), this.txHash.buffer, this.log.toBuffer()]); + return Buffer.concat([this.logId.toBuffer(), this.log.toBuffer()]); } /** @@ -39,7 +36,7 @@ export class ExtendedUnencryptedL2Log { * @returns A human readable representation of the log. */ public toHumanReadable(): string { - return `${this.log.toHumanReadable()} (blockNumber: ${this.blockNumber}, txHash: ${this.txHash.toString()})`; + return `${this.logId.toHumanReadable()}, ${this.log.toHumanReadable()}`; } /** @@ -51,24 +48,6 @@ export class ExtendedUnencryptedL2Log { return isEqual(this, other); } - /** - * Gets a globally unique log id. - * @param pxe - The PXE instance to use for retrieving logs. - * @returns A globally unique log id. - */ - public async getLogId(pxe: PXE): Promise { - const txLogs = await pxe.getUnencryptedLogs({ txHash: this.txHash }); - const logIndex = txLogs.findIndex(log => log.equals(this)); - if (logIndex === -1) { - throw new Error(`Log ${this.toHumanReadable()} not found in tx ${this.txHash.toString()}`); - } - return { - blockNumber: this.blockNumber, - txIndex: this.txHash, - logIndex: logIndex, - }; - } - /** * Deserializes log from a buffer. * @param buffer - The buffer or buffer reader containing the log. @@ -77,11 +56,10 @@ export class ExtendedUnencryptedL2Log { public static fromBuffer(buffer: Buffer | BufferReader): ExtendedUnencryptedL2Log { const reader = BufferReader.asReader(buffer); - const blockNumber = reader.readNumber(); - const txHash = new TxHash(reader.readBytes(TxHash.SIZE)); + const logId = LogId.fromBuffer(reader); const log = UnencryptedL2Log.fromBuffer(reader); - return new ExtendedUnencryptedL2Log(blockNumber, txHash, log); + return new ExtendedUnencryptedL2Log(logId, log); } /** diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index 363af301bbb..033db8ed36d 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -19,10 +19,10 @@ export type LogFilter = { /** The block number until which to fetch logs (not inclusive). */ toBlock?: number; /** - * Log id from which to start fetching logs (inclusive). + * Log id after which to start fetching logs . * @remarks If this is set, `fromBlock` and `txHash` can't be defined. */ - fromLog?: LogId; + afterLog?: LogId; /** The contract address to filter logs by. */ contractAddress?: AztecAddress; /** @@ -38,11 +38,11 @@ export type LogFilter = { * @throws If the filter is invalid. */ export function validateLogFilter(filter: LogFilter) { - if (filter.txHash && (filter.fromBlock || filter.toBlock || filter.fromLog)) { + if (filter.txHash && (filter.fromBlock || filter.toBlock || filter.afterLog)) { throw new Error("If txHash is set, fromBlock, toBlock, and fromLog can't be defined."); } - if (filter.fromBlock !== undefined && filter.fromLog) { + if (filter.fromBlock !== undefined && filter.afterLog) { throw new Error("If fromBlock is set, fromLog can't be defined."); } } diff --git a/yarn-project/types/src/logs/log_id.ts b/yarn-project/types/src/logs/log_id.ts index d9ca24493e4..cfde8a0680d 100644 --- a/yarn-project/types/src/logs/log_id.ts +++ b/yarn-project/types/src/logs/log_id.ts @@ -1,38 +1,87 @@ +import { toBufferBE } from '@aztec/foundation/bigint-buffer'; +import { BufferReader } from '@aztec/foundation/serialize'; /** A globally unique log id. */ -export type LogId = { - /** The block number in which the tx containing the log was included. */ - blockNumber: number; - /** The index of a tx in a block. */ - txIndex: number; - /** The index of the log within a transaction. */ - logIndex: number; -}; - -/** - * Parses a log id from a string. - * @param logId - A string representation of a log id. - * @returns A log id. - */ -export function parseLogId(logId: string): LogId { - const [rawBlockNumber, rawTxIndex, rawLogIndex] = logId.split('-'); - const blockNumber = Number(rawBlockNumber); - const txIndex = Number(rawTxIndex); - const logIndex = Number(rawLogIndex); - - if (!Number.isInteger(blockNumber)) { - throw new Error(`Invalid block number in log id: ${logId}`); +export class LogId { + /** + * Parses a log id from a string. + * @param blockNumber - The block number. + * @param txIndex - The transaction index. + * @param logIndex - The log index. + */ + constructor( + /** The block number the log was emitted in. */ + public readonly blockNumber: number, + /** The index of a tx in a block the log was emitted in. */ + public readonly txIndex: number, + /** The index of a log the tx was emitted in. */ + public readonly logIndex: number, + ) { + if (!Number.isInteger(blockNumber)) { + throw new Error(`Invalid block number: ${blockNumber}`); + } + if (!Number.isInteger(txIndex)) { + throw new Error(`Invalid tx index: ${txIndex}`); + } + if (!Number.isInteger(logIndex)) { + throw new Error(`Invalid log index: ${logIndex}`); + } } - if (!Number.isInteger(txIndex)) { - throw new Error(`Invalid tx index in log id: ${logId}`); + + /** + * Serializes log id to a buffer. + * @returns A buffer containing the serialized log id. + */ + public toBuffer(): Buffer { + return Buffer.concat([ + toBufferBE(BigInt(this.blockNumber), 4), + toBufferBE(BigInt(this.txIndex), 4), + toBufferBE(BigInt(this.logIndex), 4), + ]); + } + + /** + * Creates a LogId from a buffer. + * @param buffer - A buffer containing the serialized log id. + * @returns A log id. + */ + static fromBuffer(buffer: Buffer | BufferReader): LogId { + const reader = BufferReader.asReader(buffer); + + const blockNumber = reader.readNumber(); + const txIndex = reader.readNumber(); + const logIndex = reader.readNumber(); + + return new LogId(blockNumber, txIndex, logIndex); } - if (!Number.isInteger(logIndex)) { - throw new Error(`Invalid log index in log id: ${logId}`); + + /** + * Converts the LogId instance to a string. + * @returns A string representation of the log id. + */ + public toString(): string { + return `${this.blockNumber}-${this.txIndex}-${this.logIndex}`; } - return { - blockNumber, - txIndex, - logIndex, - }; + /** + * Creates a LogId from a string. + * @param data - A string representation of a log id. + * @returns A log id. + */ + static fromString(data: string): LogId { + const [rawBlockNumber, rawTxIndex, rawLogIndex] = data.split('-'); + const blockNumber = Number(rawBlockNumber); + const txIndex = Number(rawTxIndex); + const logIndex = Number(rawLogIndex); + + return new LogId(blockNumber, txIndex, logIndex); + } + + /** + * Serializes log id to a human readable string. + * @returns A human readable representation of the log id. + */ + public toHumanReadable(): string { + return `logId: (blockNumber: ${this.blockNumber}, txIndex: ${this.txIndex}, logIndex: ${this.logIndex})`; + } } From 0c66f69a152db1bbcdf8274cd19dd5b4c1f2ca7b Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 09:47:27 +0000 Subject: [PATCH 28/60] fix --- yarn-project/archiver/src/archiver/archiver_store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 2b5bf3777e9..8877ab0d055 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -402,7 +402,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { let txIndexInBlock = 0; let logIndexInTx = 0; if (filter.afterLog !== undefined) { - txIndexInBlock = filter.afterLog.logIndex; + txIndexInBlock = filter.afterLog.txIndex; logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log } From 5e35226e8fd34e61c23b3160d964e0a56ce06022 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 09:58:40 +0000 Subject: [PATCH 29/60] updated stale filter definition --- yarn-project/end-to-end/src/e2e_nested_contract.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts index 82ac96a1a31..b229aab85dc 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts @@ -114,11 +114,9 @@ describe('e2e_nested_contract', () => { ]; const tx = await new BatchCall(wallet, actions).send().wait(); - const filter = { + const extendedLogs = await wallet.getUnencryptedLogs({ fromBlock: tx.blockNumber!, - limit: 2, // 2 logs expected - }; - const extendedLogs = await wallet.getUnencryptedLogs(filter); + }); const processedLogs = extendedLogs.map(extendedLog => toBigIntBE(extendedLog.log.data)); expect(processedLogs).toEqual([20n, 40n]); expect(await getChildStoredValue(childContract)).toEqual(40n); From 8a1ebbd774fa3e159ee0029f76672b13c5bfa3ff Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 10:13:36 +0000 Subject: [PATCH 30/60] after-log message --- yarn-project/cli/src/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 91a4153e303..064af5cd8b1 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -345,6 +345,9 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { } } else { await fetchLogs(); + if (!txHash) { + log('\nTo continue fetching logs after the latest one set the --after-log param to ' + filter.afterLog); + } } }); From 71757127d2baebf6309b7fe8604af80e5b016816 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 10:14:44 +0000 Subject: [PATCH 31/60] linter fix --- yarn-project/types/src/logs/extended_unencrypted_l2_log.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts index 41e39a0e26e..f3d974db534 100644 --- a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts @@ -2,7 +2,7 @@ import { BufferReader } from '@aztec/foundation/serialize'; import isEqual from 'lodash.isequal'; -import { LogId, TxHash, UnencryptedL2Log } from '../index.js'; +import { LogId, UnencryptedL2Log } from '../index.js'; /** * Represents an individual unencrypted log entry extended with info about the block and tx it was emitted in. From 02f446d86500fc0ac4a485747ea2c220beea526e Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 10:22:04 +0000 Subject: [PATCH 32/60] chore: removed circuits.js dependency --- yarn-project/cli/package.json | 1 - yarn-project/yarn.lock | 1 - 2 files changed, 2 deletions(-) diff --git a/yarn-project/cli/package.json b/yarn-project/cli/package.json index ebd7f5f1e8f..a2041b081ea 100644 --- a/yarn-project/cli/package.json +++ b/yarn-project/cli/package.json @@ -35,7 +35,6 @@ }, "dependencies": { "@aztec/aztec.js": "workspace:^", - "@aztec/circuits.js": "workspace:^", "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/l1-artifacts": "workspace:^", diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index ad0255507c5..8de88d3e484 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -315,7 +315,6 @@ __metadata: resolution: "@aztec/cli@workspace:cli" dependencies: "@aztec/aztec.js": "workspace:^" - "@aztec/circuits.js": "workspace:^" "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/l1-artifacts": "workspace:^" From 2fc9dff82af3221175b0d8e62f9d073e427e4b08 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 10:35:38 +0000 Subject: [PATCH 33/60] log_id.test.ts --- yarn-project/types/src/logs/log_id.test.ts | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 yarn-project/types/src/logs/log_id.test.ts diff --git a/yarn-project/types/src/logs/log_id.test.ts b/yarn-project/types/src/logs/log_id.test.ts new file mode 100644 index 00000000000..dd01771262c --- /dev/null +++ b/yarn-project/types/src/logs/log_id.test.ts @@ -0,0 +1,25 @@ +import { LogId } from './log_id.js'; + +describe('LogId', () => { + let logId: LogId; + beforeEach(() => { + const blockNumber = Math.floor(Math.random() * 1000); + const txIndex = Math.floor(Math.random() * 1000); + const logIndex = Math.floor(Math.random() * 1000); + logId = new LogId(blockNumber, txIndex, logIndex); + }); + + it('toBuffer and fromBuffer works', () => { + const buffer = logId.toBuffer(); + const parsedLogId = LogId.fromBuffer(buffer); + + expect(parsedLogId).toEqual(logId); + }); + + it('toBuffer and fromBuffer works', () => { + const buffer = logId.toBuffer(); + const parsedLogId = LogId.fromBuffer(buffer); + + expect(parsedLogId).toEqual(logId); + }); +}); From 6f587a0717f0aeec6b325694dc6fb89f48ad856d Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 11:33:28 +0000 Subject: [PATCH 34/60] updated issue --- yarn-project/acir-simulator/src/acvm/oracle/oracle.ts | 2 +- yarn-project/types/src/logs/log_filter.ts | 2 +- yarn-project/types/src/logs/unencrypted_l2_log.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts b/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts index a03140c3b22..c0dfdc3e214 100644 --- a/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts @@ -165,7 +165,7 @@ export class Oracle { const logPayload = Buffer.concat(message.map(charBuffer => convertACVMFieldToBuffer(charBuffer).subarray(-1))); const log = new UnencryptedL2Log( AztecAddress.fromString(contractAddress), - FunctionSelector.fromField(fromACVMField(eventSelector)), // TODO https://github.com/AztecProtocol/aztec-packages/issues/2704 + FunctionSelector.fromField(fromACVMField(eventSelector)), // TODO https://github.com/AztecProtocol/aztec-packages/issues/2632 logPayload, ); diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index 033db8ed36d..6867547c667 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -27,7 +27,7 @@ export type LogFilter = { contractAddress?: AztecAddress; /** * Selector of the event/log topic. - * TODO: https://github.com/AztecProtocol/aztec-packages/issues/2704 + * TODO: https://github.com/AztecProtocol/aztec-packages/issues/2632 */ selector?: FunctionSelector; }; diff --git a/yarn-project/types/src/logs/unencrypted_l2_log.ts b/yarn-project/types/src/logs/unencrypted_l2_log.ts index 6499f7f1ee5..777c9811db4 100644 --- a/yarn-project/types/src/logs/unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/unencrypted_l2_log.ts @@ -19,7 +19,7 @@ export class UnencryptedL2Log { public readonly contractAddress: AztecAddress, /** * Selector of the event/log topic. - * TODO: https://github.com/AztecProtocol/aztec-packages/issues/2704 + * TODO: https://github.com/AztecProtocol/aztec-packages/issues/2632 */ public readonly selector: FunctionSelector, /** The data contents of the log. */ From 351609918fdf673be9e3fd4015b7469f96d7c6ff Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 11:33:42 +0000 Subject: [PATCH 35/60] exposing function selector through aztec.js --- yarn-project/aztec.js/src/index.ts | 4 +++- yarn-project/cli/src/utils.ts | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index b845b00e285..dd8d2ecc845 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -7,7 +7,9 @@ export * from './contract_deployer/deploy_method.js'; export * from './sandbox/index.js'; export * from './wallet/index.js'; -export { AztecAddress, EthAddress, Point, Fr, GrumpkinScalar } from '@aztec/circuits.js'; +// TODO https://github.com/AztecProtocol/aztec-packages/issues/2632 --> FunctionSelector might not need to be exposed +// here once the issue is resolved. +export { AztecAddress, EthAddress, Point, Fr, FunctionSelector, GrumpkinScalar } from '@aztec/circuits.js'; export { PXE, ContractData, diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index 150ebe8abc4..66b6012e54f 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -1,5 +1,4 @@ -import { AztecAddress, Fr, GrumpkinScalar, PXE, Point, TxHash } from '@aztec/aztec.js'; -import { FunctionSelector } from '@aztec/circuits.js'; +import { AztecAddress, Fr, FunctionSelector, GrumpkinScalar, PXE, Point, TxHash } from '@aztec/aztec.js'; import { L1ContractArtifactsForDeployment, createEthereumChain, deployL1Contracts } from '@aztec/ethereum'; import { ContractArtifact } from '@aztec/foundation/abi'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; From 1f0361a03ffc6a71576561c6c1d40b81efa9a0d1 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 12:24:13 +0000 Subject: [PATCH 36/60] test: invalid filter --- .../src/archiver/archiver_store.test.ts | 35 ++++++++++++++++++- .../archiver/src/archiver/archiver_store.ts | 2 +- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 96b730f87f8..fb614e0cbb1 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -1,4 +1,6 @@ -import { INITIAL_L2_BLOCK_NUM, L2Block, L2BlockL2Logs, LogType } from '@aztec/types'; +import { INITIAL_L2_BLOCK_NUM, L2Block, L2BlockL2Logs, LogId, LogType, TxHash } from '@aztec/types'; + +import { randomBytes } from 'crypto'; import { ArchiverDataStore, MemoryArchiverStore } from './archiver_store.js'; @@ -71,4 +73,35 @@ describe('Archiver Memory Store', () => { ); }, ); + + it('throws when log filter is invalid', async () => { + const txHash = new TxHash(randomBytes(TxHash.SIZE)); + const fromBlock = 1; + const toBlock = 2; + const afterLog = new LogId(1, 2, 3); + + const filter1 = { + txHash, + fromBlock, + }; + await expect(async () => await archiverStore.getUnencryptedLogs(filter1)).rejects.toThrow(`If txHash is set`); + + const filter2 = { + txHash, + toBlock, + }; + await expect(async () => await archiverStore.getUnencryptedLogs(filter2)).rejects.toThrow(`If txHash is set`); + + const filter3 = { + txHash, + afterLog, + }; + await expect(async () => await archiverStore.getUnencryptedLogs(filter3)).rejects.toThrow(`If txHash is set`); + + const filter4 = { + fromBlock, + afterLog, + }; + await expect(async () => await archiverStore.getUnencryptedLogs(filter4)).rejects.toThrow(`If fromBlock is set`); + }); }); diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 8877ab0d055..c354fda6793 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -369,7 +369,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { * Gets unencrypted logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. - * @throws If txHash and block range are both defined. + * @throws If filter is invalid. */ getUnencryptedLogs(filter: LogFilter): Promise { validateLogFilter(filter); From 9128dac7dd3cf01e2773a0242425a22a78457cf1 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 12:26:44 +0000 Subject: [PATCH 37/60] test: fromBlock --- .../archiver/src/archiver/archiver_store.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index fb614e0cbb1..3134d17706f 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -104,4 +104,15 @@ describe('Archiver Memory Store', () => { }; await expect(async () => await archiverStore.getUnencryptedLogs(filter4)).rejects.toThrow(`If fromBlock is set`); }); + + it('throws fromBlock is smaller than genesis block', async () => { + const fromBlock = INITIAL_L2_BLOCK_NUM - 1; + + await expect( + async () => + await archiverStore.getUnencryptedLogs({ + fromBlock, + }), + ).rejects.toThrow(`smaller than genesis block number`); + }); }); From bc104b7acedc97cdc4c202c0025ad0e7360863bf Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 13:04:40 +0000 Subject: [PATCH 38/60] better naming --- yarn-project/cli/src/index.ts | 2 +- yarn-project/types/src/logs/extended_unencrypted_l2_log.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 064af5cd8b1..7735fc88ebb 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -333,7 +333,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); // Disable `fromBlock` and continue using the `afterLog` filter. filter.fromBlock = undefined; - filter.afterLog = logs[logs.length - 1].logId; + filter.afterLog = logs[logs.length - 1].id; } }; diff --git a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts index f3d974db534..e5cc7d46a33 100644 --- a/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/types/src/logs/extended_unencrypted_l2_log.ts @@ -10,7 +10,7 @@ import { LogId, UnencryptedL2Log } from '../index.js'; export class ExtendedUnencryptedL2Log { constructor( /** Globally unique id of the log. */ - public readonly logId: LogId, + public readonly id: LogId, /** The data contents of the log. */ public readonly log: UnencryptedL2Log, ) {} @@ -20,7 +20,7 @@ export class ExtendedUnencryptedL2Log { * @returns A buffer containing the serialized log. */ public toBuffer(): Buffer { - return Buffer.concat([this.logId.toBuffer(), this.log.toBuffer()]); + return Buffer.concat([this.id.toBuffer(), this.log.toBuffer()]); } /** @@ -36,7 +36,7 @@ export class ExtendedUnencryptedL2Log { * @returns A human readable representation of the log. */ public toHumanReadable(): string { - return `${this.logId.toHumanReadable()}, ${this.log.toHumanReadable()}`; + return `${this.id.toHumanReadable()}, ${this.log.toHumanReadable()}`; } /** From 753873f9b0834f11ae4c5328de4d801a6f47a4c7 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 13:17:50 +0000 Subject: [PATCH 39/60] testing tx hash filter --- .../src/archiver/archiver_store.test.ts | 117 ++++++++++++------ yarn-project/types/src/l2_block.ts | 14 ++- .../types/src/logs/function_l2_logs.ts | 16 ++- .../types/src/logs/l2_block_l2_logs.ts | 11 +- yarn-project/types/src/logs/tx_l2_logs.ts | 10 +- 5 files changed, 118 insertions(+), 50 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 3134d17706f..76096e26153 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -1,4 +1,4 @@ -import { INITIAL_L2_BLOCK_NUM, L2Block, L2BlockL2Logs, LogId, LogType, TxHash } from '@aztec/types'; +import { INITIAL_L2_BLOCK_NUM, L2Block, L2BlockContext, L2BlockL2Logs, LogId, LogType, TxHash } from '@aztec/types'; import { randomBytes } from 'crypto'; @@ -16,7 +16,7 @@ describe('Archiver Memory Store', () => { .fill(0) .map((_, index) => L2Block.random(index)); await archiverStore.addL2Blocks(blocks); - // Offset indices by INTIAL_L2_BLOCK_NUM to ensure we are correctly aligned + // Offset indices by INITIAL_L2_BLOCK_NUM to ensure we are correctly aligned for (const [from, limit] of [ [0 + INITIAL_L2_BLOCK_NUM, 10], [3 + INITIAL_L2_BLOCK_NUM, 3], @@ -74,45 +74,82 @@ describe('Archiver Memory Store', () => { }, ); - it('throws when log filter is invalid', async () => { - const txHash = new TxHash(randomBytes(TxHash.SIZE)); - const fromBlock = 1; - const toBlock = 2; - const afterLog = new LogId(1, 2, 3); - - const filter1 = { - txHash, - fromBlock, - }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter1)).rejects.toThrow(`If txHash is set`); - - const filter2 = { - txHash, - toBlock, - }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter2)).rejects.toThrow(`If txHash is set`); - - const filter3 = { - txHash, - afterLog, - }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter3)).rejects.toThrow(`If txHash is set`); - - const filter4 = { - fromBlock, - afterLog, - }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter4)).rejects.toThrow(`If fromBlock is set`); - }); + describe('getUnencryptedLogs', () => { + it('throws when log filter is invalid', async () => { + const txHash = new TxHash(randomBytes(TxHash.SIZE)); + const fromBlock = 1; + const toBlock = 2; + const afterLog = new LogId(1, 2, 3); + + const filter1 = { + txHash, + fromBlock, + }; + await expect(async () => await archiverStore.getUnencryptedLogs(filter1)).rejects.toThrow(`If txHash is set`); + + const filter2 = { + txHash, + toBlock, + }; + await expect(async () => await archiverStore.getUnencryptedLogs(filter2)).rejects.toThrow(`If txHash is set`); + + const filter3 = { + txHash, + afterLog, + }; + await expect(async () => await archiverStore.getUnencryptedLogs(filter3)).rejects.toThrow(`If txHash is set`); + + const filter4 = { + fromBlock, + afterLog, + }; + await expect(async () => await archiverStore.getUnencryptedLogs(filter4)).rejects.toThrow(`If fromBlock is set`); + }); + + it('throws fromBlock is smaller than genesis block', async () => { + const fromBlock = INITIAL_L2_BLOCK_NUM - 1; + + await expect( + async () => + await archiverStore.getUnencryptedLogs({ + fromBlock, + }), + ).rejects.toThrow(`smaller than genesis block number`); + }); + + it('txHash filter is respected', async () => { + const txsPerBlock = 4; + const numPublicFunctionCalls = 3; + const numUnencryptedLogs = 4; + const numBlocks = 10; + + const blocks = Array(numBlocks) + .fill(0) + .map((_, index: number) => + L2Block.random(index + 1, txsPerBlock, 2, numPublicFunctionCalls, 2, numUnencryptedLogs), + ); + + await archiverStore.addL2Blocks(blocks); + await archiverStore.addLogs( + blocks.map(block => block.newUnencryptedLogs!), + LogType.UNENCRYPTED, + ); + + // get random tx + const targetBlockIndex = Math.floor(Math.random() * numBlocks); + const targetTxIndex = Math.floor(Math.random() * txsPerBlock); + const targetTxHash = new L2BlockContext(blocks[targetBlockIndex]).getTxHash(targetTxIndex); + + const logs = await archiverStore.getUnencryptedLogs({ txHash: targetTxHash }); - it('throws fromBlock is smaller than genesis block', async () => { - const fromBlock = INITIAL_L2_BLOCK_NUM - 1; + const expectedNumLogs = numPublicFunctionCalls * numUnencryptedLogs; + expect(logs.length).toEqual(expectedNumLogs); - await expect( - async () => - await archiverStore.getUnencryptedLogs({ - fromBlock, - }), - ).rejects.toThrow(`smaller than genesis block number`); + const targeBlockNumber = targetBlockIndex + INITIAL_L2_BLOCK_NUM; + for (const log of logs) { + expect(log.id.blockNumber).toEqual(targeBlockNumber); + expect(log.id.txIndex).toEqual(targetTxIndex); + } + }); }); }); diff --git a/yarn-project/types/src/l2_block.ts b/yarn-project/types/src/l2_block.ts index 3890bbf1817..1014d0f6517 100644 --- a/yarn-project/types/src/l2_block.ts +++ b/yarn-project/types/src/l2_block.ts @@ -179,8 +179,18 @@ export class L2Block { const newPublicDataWrites = times(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * txsPerBlock, PublicDataWrite.random); const newL1ToL2Messages = times(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, Fr.random); const newL2ToL1Msgs = times(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.random); - const newEncryptedLogs = L2BlockL2Logs.random(txsPerBlock, numPrivateFunctionCalls, numEncryptedLogs); - const newUnencryptedLogs = L2BlockL2Logs.random(txsPerBlock, numPublicFunctionCalls, numUnencryptedLogs); + const newEncryptedLogs = L2BlockL2Logs.random( + txsPerBlock, + numPrivateFunctionCalls, + numEncryptedLogs, + LogType.ENCRYPTED, + ); + const newUnencryptedLogs = L2BlockL2Logs.random( + txsPerBlock, + numPublicFunctionCalls, + numUnencryptedLogs, + LogType.UNENCRYPTED, + ); return L2Block.fromFields({ number: l2BlockNum, diff --git a/yarn-project/types/src/logs/function_l2_logs.ts b/yarn-project/types/src/logs/function_l2_logs.ts index b504490537e..ae7608b0e07 100644 --- a/yarn-project/types/src/logs/function_l2_logs.ts +++ b/yarn-project/types/src/logs/function_l2_logs.ts @@ -4,6 +4,9 @@ import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serializ import { randomBytes } from 'crypto'; +import { LogType } from './log_type.js'; +import { UnencryptedL2Log } from './unencrypted_l2_log.js'; + /** * Data container of logs emitted in 1 function invocation (corresponds to 1 kernel iteration). */ @@ -65,14 +68,19 @@ export class FunctionL2Logs { /** * Creates a new L2Logs object with `numLogs` logs. * @param numLogs - The number of logs to create. + * @param logType - The type of logs to generate. * @returns A new FunctionL2Logs object. */ - public static random(numLogs: number): FunctionL2Logs { + public static random(numLogs: number, logType = LogType.ENCRYPTED): FunctionL2Logs { const logs: Buffer[] = []; for (let i = 0; i < numLogs; i++) { - const randomEphPubKey = Point.random(); - const randomLogContent = randomBytes(144 - Point.SIZE_IN_BYTES); - logs.push(Buffer.concat([randomLogContent, randomEphPubKey.toBuffer()])); + if (logType === LogType.ENCRYPTED) { + const randomEphPubKey = Point.random(); + const randomLogContent = randomBytes(144 - Point.SIZE_IN_BYTES); + logs.push(Buffer.concat([randomLogContent, randomEphPubKey.toBuffer()])); + } else { + logs.push(UnencryptedL2Log.random().toBuffer()); + } } return new FunctionL2Logs(logs); } diff --git a/yarn-project/types/src/logs/l2_block_l2_logs.ts b/yarn-project/types/src/logs/l2_block_l2_logs.ts index c41a744e2aa..b04fc79caf2 100644 --- a/yarn-project/types/src/logs/l2_block_l2_logs.ts +++ b/yarn-project/types/src/logs/l2_block_l2_logs.ts @@ -2,6 +2,7 @@ import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serializ import isEqual from 'lodash.isequal'; +import { LogType } from './log_type.js'; import { TxL2Logs } from './tx_l2_logs.js'; /** @@ -67,12 +68,18 @@ export class L2BlockL2Logs { * @param numTxs - The number of txs in the block. * @param numFunctionInvocations - The number of function invocations in the tx. * @param numLogsIn1Invocation - The number of logs emitted in each function invocation. + * @param logType - The type of logs to generate. * @returns A new `L2BlockL2Logs` object. */ - public static random(numTxs: number, numFunctionInvocations: number, numLogsIn1Invocation: number): L2BlockL2Logs { + public static random( + numTxs: number, + numFunctionInvocations: number, + numLogsIn1Invocation: number, + logType = LogType.ENCRYPTED, + ): L2BlockL2Logs { const txLogs: TxL2Logs[] = []; for (let i = 0; i < numTxs; i++) { - txLogs.push(TxL2Logs.random(numFunctionInvocations, numLogsIn1Invocation)); + txLogs.push(TxL2Logs.random(numFunctionInvocations, numLogsIn1Invocation, logType)); } return new L2BlockL2Logs(txLogs); } diff --git a/yarn-project/types/src/logs/tx_l2_logs.ts b/yarn-project/types/src/logs/tx_l2_logs.ts index 12a79b9f6dd..ced07071e5d 100644 --- a/yarn-project/types/src/logs/tx_l2_logs.ts +++ b/yarn-project/types/src/logs/tx_l2_logs.ts @@ -1,6 +1,7 @@ import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; import { FunctionL2Logs } from './function_l2_logs.js'; +import { LogType } from './log_type.js'; /** * Data container of logs emitted in 1 tx. @@ -62,12 +63,17 @@ export class TxL2Logs { * in each invocation. * @param numFunctionInvocations - The number of function invocations in the tx. * @param numLogsIn1Invocation - The number of logs emitted in each function invocation. + * @param logType - The type of logs to generate. * @returns A new `TxL2Logs` object. */ - public static random(numFunctionInvocations: number, numLogsIn1Invocation: number): TxL2Logs { + public static random( + numFunctionInvocations: number, + numLogsIn1Invocation: number, + logType = LogType.ENCRYPTED, + ): TxL2Logs { const functionLogs: FunctionL2Logs[] = []; for (let i = 0; i < numFunctionInvocations; i++) { - functionLogs.push(FunctionL2Logs.random(numLogsIn1Invocation)); + functionLogs.push(FunctionL2Logs.random(numLogsIn1Invocation, logType)); } return new TxL2Logs(functionLogs); } From 66921139a4879ac8e646adff7db4bf7d89b3357d Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 13:28:21 +0000 Subject: [PATCH 40/60] test: fromBlock and toBlock filter params --- .../src/archiver/archiver_store.test.ts | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 76096e26153..2fc944e3790 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -117,7 +117,7 @@ describe('Archiver Memory Store', () => { ).rejects.toThrow(`smaller than genesis block number`); }); - it('txHash filter is respected', async () => { + it('txHash filter param is respected', async () => { const txsPerBlock = 4; const numPublicFunctionCalls = 3; const numUnencryptedLogs = 4; @@ -151,5 +151,39 @@ describe('Archiver Memory Store', () => { expect(log.id.txIndex).toEqual(targetTxIndex); } }); + + it('fromBlock and toBlock filter params are respected', async () => { + const txsPerBlock = 4; + const numPublicFunctionCalls = 3; + const numUnencryptedLogs = 4; + const numBlocks = 10; + + const blocks = Array(numBlocks) + .fill(0) + .map((_, index: number) => + L2Block.random(index + 1, txsPerBlock, 2, numPublicFunctionCalls, 2, numUnencryptedLogs), + ); + + await archiverStore.addL2Blocks(blocks); + await archiverStore.addLogs( + blocks.map(block => block.newUnencryptedLogs!), + LogType.UNENCRYPTED, + ); + + // Set fromBlock and toBlock + const fromBlock = 3; + const toBlock = 7; + + const logs = await archiverStore.getUnencryptedLogs({ fromBlock, toBlock }); + + const expectedNumLogs = txsPerBlock * numPublicFunctionCalls * numUnencryptedLogs * (toBlock - fromBlock); + expect(logs.length).toEqual(expectedNumLogs); + + for (const log of logs) { + const blockNumber = log.id.blockNumber; + expect(blockNumber).toBeGreaterThanOrEqual(fromBlock); + expect(blockNumber).toBeLessThan(toBlock); + } + }); }); }); From 765f5bbd51596801ec1f390347f47c9fb2e50b89 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 13:34:11 +0000 Subject: [PATCH 41/60] test: afterLog filter param --- .../src/archiver/archiver_store.test.ts | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 2fc944e3790..1bfda73ba70 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -185,5 +185,44 @@ describe('Archiver Memory Store', () => { expect(blockNumber).toBeLessThan(toBlock); } }); + + it('afterLog filter param is respected', async () => { + const txsPerBlock = 4; + const numPublicFunctionCalls = 3; + const numUnencryptedLogs = 4; + const numBlocks = 10; + + const blocks = Array(numBlocks) + .fill(0) + .map((_, index: number) => + L2Block.random(index + 1, txsPerBlock, 2, numPublicFunctionCalls, 2, numUnencryptedLogs), + ); + + await archiverStore.addL2Blocks(blocks); + await archiverStore.addLogs( + blocks.map(block => block.newUnencryptedLogs!), + LogType.UNENCRYPTED, + ); + + // Get a random log as reference + const targetBlockIndex = Math.floor(Math.random() * numBlocks); + const targetTxIndex = Math.floor(Math.random() * txsPerBlock); + const targetLogIndex = Math.floor(Math.random() * numUnencryptedLogs); + + const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex); + + const logs = await archiverStore.getUnencryptedLogs({ afterLog }); + + for (const log of logs) { + const logId = log.id; + expect(logId.blockNumber).toBeGreaterThanOrEqual(afterLog.blockNumber); + if (logId.blockNumber === afterLog.blockNumber) { + expect(logId.txIndex).toBeGreaterThanOrEqual(afterLog.txIndex); + if (logId.txIndex === afterLog.txIndex) { + expect(logId.logIndex).toBeGreaterThan(afterLog.logIndex); + } + } + } + }); }); }); From 913eac16c9acfd336f03bcab5fab40139da6f39b Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 13:41:41 +0000 Subject: [PATCH 42/60] cleanup --- .../src/archiver/archiver_store.test.ts | 53 +++++-------------- 1 file changed, 12 insertions(+), 41 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 1bfda73ba70..9d69f6d010b 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -74,7 +74,7 @@ describe('Archiver Memory Store', () => { }, ); - describe('getUnencryptedLogs', () => { + describe('getUnencryptedLogs errors', () => { it('throws when log filter is invalid', async () => { const txHash = new TxHash(randomBytes(TxHash.SIZE)); const fromBlock = 1; @@ -116,14 +116,17 @@ describe('Archiver Memory Store', () => { }), ).rejects.toThrow(`smaller than genesis block number`); }); + }); - it('txHash filter param is respected', async () => { - const txsPerBlock = 4; - const numPublicFunctionCalls = 3; - const numUnencryptedLogs = 4; - const numBlocks = 10; + describe('getUnencryptedLogs filter', () => { + const txsPerBlock = 4; + const numPublicFunctionCalls = 3; + const numUnencryptedLogs = 4; + const numBlocks = 10; + let blocks: L2Block[]; - const blocks = Array(numBlocks) + beforeEach(async () => { + blocks = Array(numBlocks) .fill(0) .map((_, index: number) => L2Block.random(index + 1, txsPerBlock, 2, numPublicFunctionCalls, 2, numUnencryptedLogs), @@ -134,7 +137,9 @@ describe('Archiver Memory Store', () => { blocks.map(block => block.newUnencryptedLogs!), LogType.UNENCRYPTED, ); + }); + it('txHash filter param is respected', async () => { // get random tx const targetBlockIndex = Math.floor(Math.random() * numBlocks); const targetTxIndex = Math.floor(Math.random() * txsPerBlock); @@ -153,23 +158,6 @@ describe('Archiver Memory Store', () => { }); it('fromBlock and toBlock filter params are respected', async () => { - const txsPerBlock = 4; - const numPublicFunctionCalls = 3; - const numUnencryptedLogs = 4; - const numBlocks = 10; - - const blocks = Array(numBlocks) - .fill(0) - .map((_, index: number) => - L2Block.random(index + 1, txsPerBlock, 2, numPublicFunctionCalls, 2, numUnencryptedLogs), - ); - - await archiverStore.addL2Blocks(blocks); - await archiverStore.addLogs( - blocks.map(block => block.newUnencryptedLogs!), - LogType.UNENCRYPTED, - ); - // Set fromBlock and toBlock const fromBlock = 3; const toBlock = 7; @@ -187,23 +175,6 @@ describe('Archiver Memory Store', () => { }); it('afterLog filter param is respected', async () => { - const txsPerBlock = 4; - const numPublicFunctionCalls = 3; - const numUnencryptedLogs = 4; - const numBlocks = 10; - - const blocks = Array(numBlocks) - .fill(0) - .map((_, index: number) => - L2Block.random(index + 1, txsPerBlock, 2, numPublicFunctionCalls, 2, numUnencryptedLogs), - ); - - await archiverStore.addL2Blocks(blocks); - await archiverStore.addLogs( - blocks.map(block => block.newUnencryptedLogs!), - LogType.UNENCRYPTED, - ); - // Get a random log as reference const targetBlockIndex = Math.floor(Math.random() * numBlocks); const targetTxIndex = Math.floor(Math.random() * txsPerBlock); From f8664f5183a705e120b5bf8ad7cba52d7b1812c1 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 14:06:05 +0000 Subject: [PATCH 43/60] better naming --- yarn-project/types/src/l2_block.ts | 24 +++++++++---------- .../types/src/logs/l2_block_l2_logs.ts | 14 +++++------ yarn-project/types/src/logs/tx_l2_logs.ts | 17 +++++-------- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/yarn-project/types/src/l2_block.ts b/yarn-project/types/src/l2_block.ts index 1014d0f6517..e42e87de978 100644 --- a/yarn-project/types/src/l2_block.ts +++ b/yarn-project/types/src/l2_block.ts @@ -158,19 +158,19 @@ export class L2Block { * Creates an L2 block containing random data. * @param l2BlockNum - The number of the L2 block. * @param txsPerBlock - The number of transactions to include in the block. - * @param numPrivateFunctionCalls - The number of private function calls to include in each transaction. - * @param numPublicFunctionCalls - The number of public function calls to include in each transaction. - * @param numEncryptedLogs - The number of encrypted logs to include in each transaction. - * @param numUnencryptedLogs - The number of unencrypted logs to include in each transaction. + * @param numPrivateCallsPerTx - The number of private function calls to include in each transaction. + * @param numPublicCallsPerTx - The number of public function calls to include in each transaction. + * @param numEncryptedLogsPerCall - The number of encrypted logs per 1 private function invocation. + * @param numUnencryptedLogsPerCall - The number of unencrypted logs per 1 public function invocation. * @returns The L2 block. */ static random( l2BlockNum: number, txsPerBlock = 4, - numPrivateFunctionCalls = 2, - numPublicFunctionCalls = 3, - numEncryptedLogs = 2, - numUnencryptedLogs = 1, + numPrivateCallsPerTx = 2, + numPublicCallsPerTx = 3, + numEncryptedLogsPerCall = 2, + numUnencryptedLogsPerCall = 1, ): L2Block { const newNullifiers = times(MAX_NEW_NULLIFIERS_PER_TX * txsPerBlock, Fr.random); const newCommitments = times(MAX_NEW_COMMITMENTS_PER_TX * txsPerBlock, Fr.random); @@ -181,14 +181,14 @@ export class L2Block { const newL2ToL1Msgs = times(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.random); const newEncryptedLogs = L2BlockL2Logs.random( txsPerBlock, - numPrivateFunctionCalls, - numEncryptedLogs, + numPrivateCallsPerTx, + numEncryptedLogsPerCall, LogType.ENCRYPTED, ); const newUnencryptedLogs = L2BlockL2Logs.random( txsPerBlock, - numPublicFunctionCalls, - numUnencryptedLogs, + numPublicCallsPerTx, + numUnencryptedLogsPerCall, LogType.UNENCRYPTED, ); diff --git a/yarn-project/types/src/logs/l2_block_l2_logs.ts b/yarn-project/types/src/logs/l2_block_l2_logs.ts index b04fc79caf2..20ceb324e2e 100644 --- a/yarn-project/types/src/logs/l2_block_l2_logs.ts +++ b/yarn-project/types/src/logs/l2_block_l2_logs.ts @@ -63,23 +63,23 @@ export class L2BlockL2Logs { } /** - * Creates a new `L2BlockL2Logs` object with `numFunctionInvocations` function logs and `numLogsIn1Invocation` logs - * in each invocation. + * Creates a new `L2BlockL2Logs` object with `numCalls` function logs and `numLogsPerCall` logs in each function + * call. * @param numTxs - The number of txs in the block. - * @param numFunctionInvocations - The number of function invocations in the tx. - * @param numLogsIn1Invocation - The number of logs emitted in each function invocation. + * @param numCalls - The number of function calls in the tx. + * @param numLogsPerCall - The number of logs emitted in each function call. * @param logType - The type of logs to generate. * @returns A new `L2BlockL2Logs` object. */ public static random( numTxs: number, - numFunctionInvocations: number, - numLogsIn1Invocation: number, + numCalls: number, + numLogsPerCall: number, logType = LogType.ENCRYPTED, ): L2BlockL2Logs { const txLogs: TxL2Logs[] = []; for (let i = 0; i < numTxs; i++) { - txLogs.push(TxL2Logs.random(numFunctionInvocations, numLogsIn1Invocation, logType)); + txLogs.push(TxL2Logs.random(numCalls, numLogsPerCall, logType)); } return new L2BlockL2Logs(txLogs); } diff --git a/yarn-project/types/src/logs/tx_l2_logs.ts b/yarn-project/types/src/logs/tx_l2_logs.ts index ced07071e5d..2cf264841f9 100644 --- a/yarn-project/types/src/logs/tx_l2_logs.ts +++ b/yarn-project/types/src/logs/tx_l2_logs.ts @@ -59,21 +59,16 @@ export class TxL2Logs { } /** - * Creates a new `TxL2Logs` object with `numFunctionInvocations` function logs and `numLogsIn1Invocation` logs - * in each invocation. - * @param numFunctionInvocations - The number of function invocations in the tx. - * @param numLogsIn1Invocation - The number of logs emitted in each function invocation. + * Creates a new `TxL2Logs` object with `numCalls` function logs and `numLogsPerCall` logs in each invocation. + * @param numCalls - The number of function calls in the tx. + * @param numLogsPerCall - The number of logs emitted in each function call. * @param logType - The type of logs to generate. * @returns A new `TxL2Logs` object. */ - public static random( - numFunctionInvocations: number, - numLogsIn1Invocation: number, - logType = LogType.ENCRYPTED, - ): TxL2Logs { + public static random(numCalls: number, numLogsPerCall: number, logType = LogType.ENCRYPTED): TxL2Logs { const functionLogs: FunctionL2Logs[] = []; - for (let i = 0; i < numFunctionInvocations; i++) { - functionLogs.push(FunctionL2Logs.random(numLogsIn1Invocation, logType)); + for (let i = 0; i < numCalls; i++) { + functionLogs.push(FunctionL2Logs.random(numLogsPerCall, logType)); } return new TxL2Logs(functionLogs); } From e770eec8f5d90c3434cd5146f54b9aff6052e88d Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 15:33:26 +0000 Subject: [PATCH 44/60] test: selector filter param --- .../src/archiver/archiver_store.test.ts | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 9d69f6d010b..9e42bb37c35 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -1,4 +1,13 @@ -import { INITIAL_L2_BLOCK_NUM, L2Block, L2BlockContext, L2BlockL2Logs, LogId, LogType, TxHash } from '@aztec/types'; +import { + INITIAL_L2_BLOCK_NUM, + L2Block, + L2BlockContext, + L2BlockL2Logs, + LogId, + LogType, + TxHash, + UnencryptedL2Log, +} from '@aztec/types'; import { randomBytes } from 'crypto'; @@ -195,5 +204,24 @@ describe('Archiver Memory Store', () => { } } }); + + it('selector filter param is respected', async () => { + // Get a random selector from the logs + const targetBlockIndex = Math.floor(Math.random() * numBlocks); + const targetTxIndex = Math.floor(Math.random() * txsPerBlock); + const targetFunctionLogIndex = Math.floor(Math.random() * numPublicFunctionCalls); + const targetLogIndex = Math.floor(Math.random() * numUnencryptedLogs); + const targetSelector = UnencryptedL2Log.fromBuffer( + blocks[targetBlockIndex].newUnencryptedLogs!.txLogs[targetTxIndex].functionLogs[targetFunctionLogIndex].logs[ + targetLogIndex + ], + ).selector; + + const extendedLogs = await archiverStore.getUnencryptedLogs({ selector: targetSelector }); + + for (const extendedLog of extendedLogs) { + expect(extendedLog.log.selector.equals(targetSelector)).toBeTruthy(); + } + }); }); }); From 1a694d691e84a0a937ae37dc6933f4a8a2c8e01c Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 15:36:16 +0000 Subject: [PATCH 45/60] test: contract address filter param --- .../src/archiver/archiver_store.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 9e42bb37c35..d052e8dbd87 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -205,6 +205,25 @@ describe('Archiver Memory Store', () => { } }); + it('contractAddress filter param is respected', async () => { + // Get a random contract address from the logs + const targetBlockIndex = Math.floor(Math.random() * numBlocks); + const targetTxIndex = Math.floor(Math.random() * txsPerBlock); + const targetFunctionLogIndex = Math.floor(Math.random() * numPublicFunctionCalls); + const targetLogIndex = Math.floor(Math.random() * numUnencryptedLogs); + const targetContractAddress = UnencryptedL2Log.fromBuffer( + blocks[targetBlockIndex].newUnencryptedLogs!.txLogs[targetTxIndex].functionLogs[targetFunctionLogIndex].logs[ + targetLogIndex + ], + ).contractAddress; + + const extendedLogs = await archiverStore.getUnencryptedLogs({ contractAddress: targetContractAddress }); + + for (const extendedLog of extendedLogs) { + expect(extendedLog.log.contractAddress.equals(targetContractAddress)).toBeTruthy(); + } + }); + it('selector filter param is respected', async () => { // Get a random selector from the logs const targetBlockIndex = Math.floor(Math.random() * numBlocks); From 6e3842bb753139cb0b7624c1f951fc717fe878b4 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 15:46:43 +0000 Subject: [PATCH 46/60] test: maxLogs --- .../src/archiver/archiver_store.test.ts | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index d052e8dbd87..6376a1a4eba 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -83,7 +83,7 @@ describe('Archiver Memory Store', () => { }, ); - describe('getUnencryptedLogs errors', () => { + describe('getUnencryptedLogs errors and config', () => { it('throws when log filter is invalid', async () => { const txHash = new TxHash(randomBytes(TxHash.SIZE)); const fromBlock = 1; @@ -125,9 +125,26 @@ describe('Archiver Memory Store', () => { }), ).rejects.toThrow(`smaller than genesis block number`); }); + + it('does not return more than `maxLogs` logs', async () => { + const maxLogs = 5; + archiverStore = new MemoryArchiverStore(maxLogs); + const blocks = Array(10) + .fill(0) + .map((_, index: number) => L2Block.random(index + 1, 4, 2, 3, 2, 2)); + + await archiverStore.addL2Blocks(blocks); + await archiverStore.addLogs( + blocks.map(block => block.newUnencryptedLogs!), + LogType.UNENCRYPTED, + ); + + const extendedLogs = await archiverStore.getUnencryptedLogs({}); + expect(extendedLogs.length).toEqual(maxLogs); + }); }); - describe('getUnencryptedLogs filter', () => { + describe('getUnencryptedLogs filtering', () => { const txsPerBlock = 4; const numPublicFunctionCalls = 3; const numUnencryptedLogs = 4; From ecde8e7ede383d994e1f4716e24a28d0e3351e4e Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 9 Oct 2023 16:02:50 +0000 Subject: [PATCH 47/60] docs: not mentioning LogFilter type in docs --- docs/docs/dev_docs/contracts/syntax/events.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/docs/dev_docs/contracts/syntax/events.md b/docs/docs/dev_docs/contracts/syntax/events.md index 3bbbb288305..97c24de0c42 100644 --- a/docs/docs/dev_docs/contracts/syntax/events.md +++ b/docs/docs/dev_docs/contracts/syntax/events.md @@ -129,8 +129,6 @@ To display them run: aztec-cli get-logs --help ``` -or check the definition of `LogFilter` type. - ## Costs All event data is pushed to Ethereum as calldata by the sequencer and for this reason the cost of emitting an event is non-trivial. From 04f8555cbdf82eeba440974fedd1125ba8bb2841 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 10 Oct 2023 06:11:42 +0000 Subject: [PATCH 48/60] tsconfig cleanup --- yarn-project/cli/tsconfig.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/yarn-project/cli/tsconfig.json b/yarn-project/cli/tsconfig.json index f99c5e7e8c4..7bd5491149a 100644 --- a/yarn-project/cli/tsconfig.json +++ b/yarn-project/cli/tsconfig.json @@ -9,9 +9,6 @@ { "path": "../aztec.js" }, - { - "path": "../circuits.js" - }, { "path": "../ethereum" }, From 02e7f90b80fa075719ab77bb8ddd19e633650007 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 10 Oct 2023 06:32:40 +0000 Subject: [PATCH 49/60] feat: improved log id check --- yarn-project/types/src/logs/log_id.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yarn-project/types/src/logs/log_id.ts b/yarn-project/types/src/logs/log_id.ts index cfde8a0680d..00ab59c2c52 100644 --- a/yarn-project/types/src/logs/log_id.ts +++ b/yarn-project/types/src/logs/log_id.ts @@ -1,6 +1,8 @@ import { toBufferBE } from '@aztec/foundation/bigint-buffer'; import { BufferReader } from '@aztec/foundation/serialize'; +import { INITIAL_L2_BLOCK_NUM } from '../constants.js'; + /** A globally unique log id. */ export class LogId { /** @@ -17,7 +19,7 @@ export class LogId { /** The index of a log the tx was emitted in. */ public readonly logIndex: number, ) { - if (!Number.isInteger(blockNumber)) { + if (!Number.isInteger(blockNumber) || blockNumber < INITIAL_L2_BLOCK_NUM) { throw new Error(`Invalid block number: ${blockNumber}`); } if (!Number.isInteger(txIndex)) { From 24204d19b1786021025b50ca9ffdd142e769129e Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 10 Oct 2023 15:57:33 +0000 Subject: [PATCH 50/60] WIP on returning limit hit info --- .../archiver/src/archiver/archiver.ts | 4 +-- .../src/archiver/archiver_store.test.ts | 19 +++++++------- .../archiver/src/archiver/archiver_store.ts | 25 ++++++++++++++----- .../aztec-node/src/aztec-node/server.ts | 4 +-- yarn-project/aztec.js/src/contract/sent_tx.ts | 4 +-- .../aztec.js/src/wallet/base_wallet.ts | 4 +-- yarn-project/cli/src/index.ts | 13 +++++----- .../src/e2e_nested_contract.test.ts | 8 +++--- .../end-to-end/src/e2e_ordering.test.ts | 2 +- yarn-project/end-to-end/src/fixtures/utils.ts | 4 +-- .../src/guides/dapp_testing.test.ts | 2 +- .../pxe/src/pxe_service/pxe_service.ts | 4 +-- .../types/src/interfaces/aztec-node.ts | 4 +-- yarn-project/types/src/interfaces/pxe.ts | 4 +-- .../src/logs/get_unencrypted_logs_response.ts | 16 ++++++++++++ yarn-project/types/src/logs/index.ts | 1 + yarn-project/types/src/logs/l2_logs_source.ts | 4 +-- yarn-project/types/src/tx/tx.ts | 5 ++-- 18 files changed, 81 insertions(+), 46 deletions(-) create mode 100644 yarn-project/types/src/logs/get_unencrypted_logs_response.ts diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 823b7b9d515..d45f96193b5 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -10,7 +10,7 @@ import { ContractDataSource, EncodedContractFunction, ExtendedContractData, - ExtendedUnencryptedL2Log, + GetsUnencryptedLogsResponse, INITIAL_L2_BLOCK_NUM, L1ToL2Message, L1ToL2MessageSource, @@ -396,7 +396,7 @@ export class Archiver implements L2BlockSource, L2LogsSource, ContractDataSource * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise { + getUnencryptedLogs(filter: LogFilter): Promise { return this.store.getUnencryptedLogs(filter); } diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 6376a1a4eba..a5c6216d65f 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -139,8 +139,9 @@ describe('Archiver Memory Store', () => { LogType.UNENCRYPTED, ); - const extendedLogs = await archiverStore.getUnencryptedLogs({}); - expect(extendedLogs.length).toEqual(maxLogs); + const logsResponse = await archiverStore.getUnencryptedLogs({}); + expect(logsResponse.maxLogsHit).toBeTruthy(); + expect(logsResponse.logs.length).toEqual(maxLogs); }); }); @@ -171,7 +172,7 @@ describe('Archiver Memory Store', () => { const targetTxIndex = Math.floor(Math.random() * txsPerBlock); const targetTxHash = new L2BlockContext(blocks[targetBlockIndex]).getTxHash(targetTxIndex); - const logs = await archiverStore.getUnencryptedLogs({ txHash: targetTxHash }); + const logs = (await archiverStore.getUnencryptedLogs({ txHash: targetTxHash })).logs; const expectedNumLogs = numPublicFunctionCalls * numUnencryptedLogs; expect(logs.length).toEqual(expectedNumLogs); @@ -188,7 +189,7 @@ describe('Archiver Memory Store', () => { const fromBlock = 3; const toBlock = 7; - const logs = await archiverStore.getUnencryptedLogs({ fromBlock, toBlock }); + const logs = (await archiverStore.getUnencryptedLogs({ fromBlock, toBlock })).logs; const expectedNumLogs = txsPerBlock * numPublicFunctionCalls * numUnencryptedLogs * (toBlock - fromBlock); expect(logs.length).toEqual(expectedNumLogs); @@ -208,7 +209,7 @@ describe('Archiver Memory Store', () => { const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex); - const logs = await archiverStore.getUnencryptedLogs({ afterLog }); + const logs = (await archiverStore.getUnencryptedLogs({ afterLog })).logs; for (const log of logs) { const logId = log.id; @@ -234,9 +235,9 @@ describe('Archiver Memory Store', () => { ], ).contractAddress; - const extendedLogs = await archiverStore.getUnencryptedLogs({ contractAddress: targetContractAddress }); + const logsResponse = await archiverStore.getUnencryptedLogs({ contractAddress: targetContractAddress }); - for (const extendedLog of extendedLogs) { + for (const extendedLog of logsResponse.logs) { expect(extendedLog.log.contractAddress.equals(targetContractAddress)).toBeTruthy(); } }); @@ -253,9 +254,9 @@ describe('Archiver Memory Store', () => { ], ).selector; - const extendedLogs = await archiverStore.getUnencryptedLogs({ selector: targetSelector }); + const logsResponse = await archiverStore.getUnencryptedLogs({ selector: targetSelector }); - for (const extendedLog of extendedLogs) { + for (const extendedLog of logsResponse.logs) { expect(extendedLog.log.selector.equals(targetSelector)).toBeTruthy(); } }); diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index c354fda6793..6bc4907ef27 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -4,6 +4,7 @@ import { ContractData, ExtendedContractData, ExtendedUnencryptedL2Log, + GetsUnencryptedLogsResponse, INITIAL_L2_BLOCK_NUM, L1ToL2Message, L2Block, @@ -105,7 +106,7 @@ export interface ArchiverDataStore { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Add new extended contract data from an L2 block to the store's list. @@ -371,7 +372,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns The requested logs. * @throws If filter is invalid. */ - getUnencryptedLogs(filter: LogFilter): Promise { + getUnencryptedLogs(filter: LogFilter): Promise { validateLogFilter(filter); const txHash = filter.txHash; @@ -387,13 +388,19 @@ export class MemoryArchiverStore implements ArchiverDataStore { throw new Error(`"fromBlock" (${filter.fromBlock}) smaller than genesis block number (${INITIAL_L2_BLOCK_NUM}).`); } if (fromBlockIndex > this.unencryptedLogsPerBlock.length) { - return Promise.resolve([]); + return Promise.resolve({ + logs: [], + maxLogsHit: false, + }); } const toBlockIndex = (filter.toBlock || this.unencryptedLogsPerBlock.length + INITIAL_L2_BLOCK_NUM) - INITIAL_L2_BLOCK_NUM; if (toBlockIndex < fromBlockIndex) { - return Promise.resolve([]); + return Promise.resolve({ + logs: [], + maxLogsHit: false, + }); } const contractAddress = filter.contractAddress; @@ -424,7 +431,10 @@ export class MemoryArchiverStore implements ArchiverDataStore { new ExtendedUnencryptedL2Log(new LogId(blockContext.block.number, txIndexInBlock, logIndexInTx), log), ); if (logs.length === this.maxLogs) { - return Promise.resolve(logs); + return Promise.resolve({ + logs, + maxLogsHit: true, + }); } } } @@ -433,7 +443,10 @@ export class MemoryArchiverStore implements ArchiverDataStore { txIndexInBlock = 0; } - return Promise.resolve(logs); + return Promise.resolve({ + logs, + maxLogsHit: false, + }); } /** diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index fb3344b1ada..ac583e5d6d6 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -24,7 +24,7 @@ import { ContractData, ContractDataSource, ExtendedContractData, - ExtendedUnencryptedL2Log, + GetsUnencryptedLogsResponse, L1ToL2MessageAndIndex, L1ToL2MessageSource, L2Block, @@ -232,7 +232,7 @@ export class AztecNodeService implements AztecNode { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise { + getUnencryptedLogs(filter: LogFilter): Promise { return this.unencryptedLogsSource.getUnencryptedLogs(filter); } diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts index 82d08a58518..adb868a75aa 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -1,6 +1,6 @@ import { FieldsOf } from '@aztec/circuits.js'; import { retryUntil } from '@aztec/foundation/retry'; -import { ExtendedUnencryptedL2Log, PXE, TxHash, TxReceipt, TxStatus } from '@aztec/types'; +import { GetsUnencryptedLogsResponse, PXE, TxHash, TxReceipt, TxStatus } from '@aztec/types'; import every from 'lodash.every'; @@ -85,7 +85,7 @@ export class SentTx { * @remarks This function will wait for the tx to be mined if it hasn't been already. * @returns The requested logs. */ - public async getUnencryptedLogs(): Promise { + public async getUnencryptedLogs(): Promise { await this.wait(); return this.pxe.getUnencryptedLogs({ txHash: await this.getTxHash() }); } diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index b32c1eb4fd3..00ec07fac7c 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -4,8 +4,8 @@ import { ContractData, DeployedContract, ExtendedContractData, - ExtendedUnencryptedL2Log, FunctionCall, + GetsUnencryptedLogsResponse, L2Tx, LogFilter, NodeInfo, @@ -97,7 +97,7 @@ export abstract class BaseWallet implements Wallet { getContractData(contractAddress: AztecAddress): Promise { return this.pxe.getContractData(contractAddress); } - getUnencryptedLogs(filter: LogFilter): Promise { + getUnencryptedLogs(filter: LogFilter): Promise { return this.pxe.getUnencryptedLogs(filter); } getBlockNumber(): Promise { diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 7735fc88ebb..ca0d8e1e6de 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -320,7 +320,8 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { validateLogFilter(filter); const fetchLogs = async () => { - const logs = await pxe.getUnencryptedLogs(filter); + const response = await pxe.getUnencryptedLogs(filter); + const logs = response.logs; if (!logs.length) { const filterOptions = Object.entries(filter) @@ -335,18 +336,18 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { filter.fromBlock = undefined; filter.afterLog = logs[logs.length - 1].id; } + return response.maxLogsHit; }; if (follow) { log('Fetching logs...'); while (true) { - await fetchLogs(); - await sleep(1000); + const maxLogsHit = await fetchLogs(); + if (!maxLogsHit) await sleep(1000); } } else { - await fetchLogs(); - if (!txHash) { - log('\nTo continue fetching logs after the latest one set the --after-log param to ' + filter.afterLog); + while (await fetchLogs()) { + // Keep fetching logs until we reach the end. } } }); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts index b229aab85dc..0abd5912844 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts @@ -114,9 +114,11 @@ describe('e2e_nested_contract', () => { ]; const tx = await new BatchCall(wallet, actions).send().wait(); - const extendedLogs = await wallet.getUnencryptedLogs({ - fromBlock: tx.blockNumber!, - }); + const extendedLogs = ( + await wallet.getUnencryptedLogs({ + fromBlock: tx.blockNumber!, + }) + ).logs; const processedLogs = extendedLogs.map(extendedLog => toBigIntBE(extendedLog.log.data)); expect(processedLogs).toEqual([20n, 40n]); expect(await getChildStoredValue(childContract)).toEqual(40n); diff --git a/yarn-project/end-to-end/src/e2e_ordering.test.ts b/yarn-project/end-to-end/src/e2e_ordering.test.ts index bbdda1e38ca..7f3b722125c 100644 --- a/yarn-project/end-to-end/src/e2e_ordering.test.ts +++ b/yarn-project/end-to-end/src/e2e_ordering.test.ts @@ -21,7 +21,7 @@ describe('e2e_ordering', () => { fromBlock, toBlock: fromBlock + 1, }; - const unencryptedLogs = await pxe.getUnencryptedLogs(logFilter); + const unencryptedLogs = (await pxe.getUnencryptedLogs(logFilter)).logs; const bigintLogs = unencryptedLogs.map(extendedLog => toBigIntBE(extendedLog.log.data)); expect(bigintLogs).toStrictEqual(logMessages); diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index ebfd625105b..db7cfde63df 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -519,7 +519,7 @@ export const expectsNumOfEncryptedLogsInTheLastBlockToBe = async ( * @param logMessages - The set of expected log messages. */ export const expectUnencryptedLogsInTxToBe = async (tx: SentTx, logMessages: string[]) => { - const unencryptedLogs = await tx.getUnencryptedLogs(); + const unencryptedLogs = (await tx.getUnencryptedLogs()).logs; const asciiLogs = unencryptedLogs.map(extendedLog => extendedLog.log.data.toString('ascii')); expect(asciiLogs).toStrictEqual(logMessages); @@ -538,7 +538,7 @@ export const expectUnencryptedLogsFromLastBlockToBe = async (pxe: PXE, logMessag fromBlock, toBlock: fromBlock + 1, }; - const unencryptedLogs = await pxe.getUnencryptedLogs(logFilter); + const unencryptedLogs = (await pxe.getUnencryptedLogs(logFilter)).logs; // docs:end:get_logs const asciiLogs = unencryptedLogs.map(extendedLog => extendedLog.log.data.toString('ascii')); diff --git a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts index a779be2cbae..fcc21d8a756 100644 --- a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts +++ b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts @@ -210,7 +210,7 @@ describe('guides/dapp/testing', () => { fromBlock: tx.blockNumber!, limit: 1, // 1 log expected }; - const logs = await pxe.getUnencryptedLogs(filter); + const logs = (await pxe.getUnencryptedLogs(filter)).logs; expect(Fr.fromBuffer(logs[0].log.data)).toEqual(value); // docs:end:unencrypted-logs }); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index e217fcec912..01d7a3466c4 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -31,8 +31,8 @@ import { ContractData, DeployedContract, ExtendedContractData, - ExtendedUnencryptedL2Log, FunctionCall, + GetsUnencryptedLogsResponse, KeyStore, L2Block, L2Tx, @@ -389,7 +389,7 @@ export class PXEService implements PXE { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - public getUnencryptedLogs(filter: LogFilter): Promise { + public getUnencryptedLogs(filter: LogFilter): Promise { return this.node.getUnencryptedLogs(filter); } diff --git a/yarn-project/types/src/interfaces/aztec-node.ts b/yarn-project/types/src/interfaces/aztec-node.ts index a1e21798f46..c63cf45a636 100644 --- a/yarn-project/types/src/interfaces/aztec-node.ts +++ b/yarn-project/types/src/interfaces/aztec-node.ts @@ -6,7 +6,7 @@ import { Fr } from '@aztec/foundation/fields'; import { ContractData, ExtendedContractData, - ExtendedUnencryptedL2Log, + GetsUnencryptedLogsResponse, L2Block, L2BlockL2Logs, L2Tx, @@ -97,7 +97,7 @@ export interface AztecNode extends StateInfoProvider { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Method to submit a transaction to the p2p pool. diff --git a/yarn-project/types/src/interfaces/pxe.ts b/yarn-project/types/src/interfaces/pxe.ts index 4c0fdd0bc1b..020b3436b76 100644 --- a/yarn-project/types/src/interfaces/pxe.ts +++ b/yarn-project/types/src/interfaces/pxe.ts @@ -4,7 +4,7 @@ import { CompleteAddress, ContractData, ExtendedContractData, - ExtendedUnencryptedL2Log, + GetsUnencryptedLogsResponse, L2Tx, LogFilter, NotePreimage, @@ -236,7 +236,7 @@ export interface PXE { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Fetches the current block number. diff --git a/yarn-project/types/src/logs/get_unencrypted_logs_response.ts b/yarn-project/types/src/logs/get_unencrypted_logs_response.ts new file mode 100644 index 00000000000..936b2d3f4b5 --- /dev/null +++ b/yarn-project/types/src/logs/get_unencrypted_logs_response.ts @@ -0,0 +1,16 @@ +import { ExtendedUnencryptedL2Log } from './extended_unencrypted_l2_log.js'; + +/** + * It provides documentation for the GetsUnencryptedLogsResponse type. + */ +export type GetsUnencryptedLogsResponse = { + /** + * An array of ExtendedUnencryptedL2Log elements. + */ + logs: ExtendedUnencryptedL2Log[]; + + /** + * Indicates if a limit has been reached. + */ + maxLogsHit: boolean; +}; diff --git a/yarn-project/types/src/logs/index.ts b/yarn-project/types/src/logs/index.ts index d34c300eb27..a495dfb6a7b 100644 --- a/yarn-project/types/src/logs/index.ts +++ b/yarn-project/types/src/logs/index.ts @@ -1,3 +1,4 @@ +export * from './get_unencrypted_logs_response.js'; export * from './function_l2_logs.js'; export * from './l2_block_l2_logs.js'; export * from './l2_logs_source.js'; diff --git a/yarn-project/types/src/logs/l2_logs_source.ts b/yarn-project/types/src/logs/l2_logs_source.ts index 4e606baad32..997f522ea85 100644 --- a/yarn-project/types/src/logs/l2_logs_source.ts +++ b/yarn-project/types/src/logs/l2_logs_source.ts @@ -1,4 +1,4 @@ -import { ExtendedUnencryptedL2Log } from './extended_unencrypted_l2_log.js'; +import { GetsUnencryptedLogsResponse } from './get_unencrypted_logs_response.js'; import { L2BlockL2Logs } from './l2_block_l2_logs.js'; import { LogFilter } from './log_filter.js'; import { LogType } from './log_type.js'; @@ -21,7 +21,7 @@ export interface L2LogsSource { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Gets the number of the latest L2 block processed by the implementation. diff --git a/yarn-project/types/src/tx/tx.ts b/yarn-project/types/src/tx/tx.ts index cd90356b2aa..a59e8126398 100644 --- a/yarn-project/types/src/tx/tx.ts +++ b/yarn-project/types/src/tx/tx.ts @@ -10,7 +10,8 @@ import { arrayNonEmptyLength } from '@aztec/foundation/collection'; import { BufferReader, Tuple } from '@aztec/foundation/serialize'; import { ExtendedContractData } from '../contract_data.js'; -import { ExtendedUnencryptedL2Log, L2LogsSource } from '../index.js'; +import { L2LogsSource } from '../index.js'; +import { GetsUnencryptedLogsResponse } from '../logs/get_unencrypted_logs_response.js'; import { TxL2Logs } from '../logs/tx_l2_logs.js'; import { TxHash } from './tx_hash.js'; @@ -118,7 +119,7 @@ export class Tx { * @param logsSource - An instance of `L2LogsSource` which can be used to obtain the logs. * @returns The requested logs. */ - public async getUnencryptedLogs(logsSource: L2LogsSource): Promise { + public async getUnencryptedLogs(logsSource: L2LogsSource): Promise { return logsSource.getUnencryptedLogs({ txHash: await this.getTxHash() }); } From f01177332b53f20f6933bdca4ef0fbb6cba5b3b6 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 07:44:18 +0000 Subject: [PATCH 51/60] testing maxLogs --- .../src/archiver/archiver_store.test.ts | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index a5c6216d65f..4edafea3f90 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -139,9 +139,10 @@ describe('Archiver Memory Store', () => { LogType.UNENCRYPTED, ); - const logsResponse = await archiverStore.getUnencryptedLogs({}); - expect(logsResponse.maxLogsHit).toBeTruthy(); - expect(logsResponse.logs.length).toEqual(maxLogs); + const response = await archiverStore.getUnencryptedLogs({}); + + expect(response.maxLogsHit).toBeTruthy(); + expect(response.logs.length).toEqual(maxLogs); }); }); @@ -172,7 +173,10 @@ describe('Archiver Memory Store', () => { const targetTxIndex = Math.floor(Math.random() * txsPerBlock); const targetTxHash = new L2BlockContext(blocks[targetBlockIndex]).getTxHash(targetTxIndex); - const logs = (await archiverStore.getUnencryptedLogs({ txHash: targetTxHash })).logs; + const response = await archiverStore.getUnencryptedLogs({ txHash: targetTxHash }); + const logs = response.logs; + + expect(response.maxLogsHit).toBeFalsy(); const expectedNumLogs = numPublicFunctionCalls * numUnencryptedLogs; expect(logs.length).toEqual(expectedNumLogs); @@ -189,7 +193,10 @@ describe('Archiver Memory Store', () => { const fromBlock = 3; const toBlock = 7; - const logs = (await archiverStore.getUnencryptedLogs({ fromBlock, toBlock })).logs; + const response = await archiverStore.getUnencryptedLogs({ fromBlock, toBlock }); + const logs = response.logs; + + expect(response.maxLogsHit).toBeFalsy(); const expectedNumLogs = txsPerBlock * numPublicFunctionCalls * numUnencryptedLogs * (toBlock - fromBlock); expect(logs.length).toEqual(expectedNumLogs); @@ -209,7 +216,10 @@ describe('Archiver Memory Store', () => { const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex); - const logs = (await archiverStore.getUnencryptedLogs({ afterLog })).logs; + const response = await archiverStore.getUnencryptedLogs({ afterLog }); + const logs = response.logs; + + expect(response.maxLogsHit).toBeFalsy(); for (const log of logs) { const logId = log.id; @@ -235,9 +245,11 @@ describe('Archiver Memory Store', () => { ], ).contractAddress; - const logsResponse = await archiverStore.getUnencryptedLogs({ contractAddress: targetContractAddress }); + const response = await archiverStore.getUnencryptedLogs({ contractAddress: targetContractAddress }); + + expect(response.maxLogsHit).toBeFalsy(); - for (const extendedLog of logsResponse.logs) { + for (const extendedLog of response.logs) { expect(extendedLog.log.contractAddress.equals(targetContractAddress)).toBeTruthy(); } }); @@ -254,9 +266,11 @@ describe('Archiver Memory Store', () => { ], ).selector; - const logsResponse = await archiverStore.getUnencryptedLogs({ selector: targetSelector }); + const response = await archiverStore.getUnencryptedLogs({ selector: targetSelector }); + + expect(response.maxLogsHit).toBeFalsy(); - for (const extendedLog of logsResponse.logs) { + for (const extendedLog of response.logs) { expect(extendedLog.log.selector.equals(targetSelector)).toBeTruthy(); } }); From e5d40034d2f4061188bbc55b374e3dba1313f53a Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 08:09:21 +0000 Subject: [PATCH 52/60] afterLog taking precedence --- .../src/archiver/archiver_store.test.ts | 51 ++++++++++------ .../archiver/src/archiver/archiver_store.ts | 58 +++++++++---------- yarn-project/types/src/logs/log_filter.ts | 19 +++--- 3 files changed, 69 insertions(+), 59 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 4edafea3f90..054315e7353 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -86,36 +86,49 @@ describe('Archiver Memory Store', () => { describe('getUnencryptedLogs errors and config', () => { it('throws when log filter is invalid', async () => { const txHash = new TxHash(randomBytes(TxHash.SIZE)); - const fromBlock = 1; + const fromBlock = 2; const toBlock = 2; - const afterLog = new LogId(1, 2, 3); + // First invalid case - txHash and "fromBlock" are set const filter1 = { txHash, fromBlock, }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter1)).rejects.toThrow(`If txHash is set`); + await expect(async () => await archiverStore.getUnencryptedLogs(filter1)).rejects.toThrow( + 'Invalid filter: "txHash" is set along', + ); + // Second invalid case - "txHash" and "toBlock" are set const filter2 = { txHash, toBlock, }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter2)).rejects.toThrow(`If txHash is set`); + await expect(async () => await archiverStore.getUnencryptedLogs(filter2)).rejects.toThrow( + 'Invalid filter: "txHash" is set along', + ); + }); - const filter3 = { - txHash, - afterLog, - }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter3)).rejects.toThrow(`If txHash is set`); + it('does not throw when both "fromBlock" and "txHash" are set with afterLog', async () => { + // this case should not throw because "afterLog" should take precedence + const txHash = new TxHash(randomBytes(TxHash.SIZE)); + const fromBlock = 2; + const toBlock = 3; + const afterLog = new LogId(1, 2, 3); - const filter4 = { + // First invalid case - "txHash" and "fromBlock" are set + const filter1 = { + txHash, fromBlock, + toBlock, afterLog, }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter4)).rejects.toThrow(`If fromBlock is set`); + const response = await archiverStore.getUnencryptedLogs(filter1); + + expect(response.logs.length).toEqual(0); + expect(response.maxLogsHit).toEqual(false); }); - it('throws fromBlock is smaller than genesis block', async () => { + it('throws when "fromBlock" is smaller than genesis block', async () => { const fromBlock = INITIAL_L2_BLOCK_NUM - 1; await expect( @@ -126,7 +139,7 @@ describe('Archiver Memory Store', () => { ).rejects.toThrow(`smaller than genesis block number`); }); - it('does not return more than `maxLogs` logs', async () => { + it('does not return more than "maxLogs" logs', async () => { const maxLogs = 5; archiverStore = new MemoryArchiverStore(maxLogs); const blocks = Array(10) @@ -167,7 +180,7 @@ describe('Archiver Memory Store', () => { ); }); - it('txHash filter param is respected', async () => { + it('"txHash" filter param is respected', async () => { // get random tx const targetBlockIndex = Math.floor(Math.random() * numBlocks); const targetTxIndex = Math.floor(Math.random() * txsPerBlock); @@ -188,8 +201,8 @@ describe('Archiver Memory Store', () => { } }); - it('fromBlock and toBlock filter params are respected', async () => { - // Set fromBlock and toBlock + it('"fromBlock" and "toBlock" filter params are respected', async () => { + // Set "fromBlock" and "toBlock" const fromBlock = 3; const toBlock = 7; @@ -208,7 +221,7 @@ describe('Archiver Memory Store', () => { } }); - it('afterLog filter param is respected', async () => { + it('"afterLog" filter param is respected', async () => { // Get a random log as reference const targetBlockIndex = Math.floor(Math.random() * numBlocks); const targetTxIndex = Math.floor(Math.random() * txsPerBlock); @@ -233,7 +246,7 @@ describe('Archiver Memory Store', () => { } }); - it('contractAddress filter param is respected', async () => { + it('"contractAddress" filter param is respected', async () => { // Get a random contract address from the logs const targetBlockIndex = Math.floor(Math.random() * numBlocks); const targetTxIndex = Math.floor(Math.random() * txsPerBlock); @@ -254,7 +267,7 @@ describe('Archiver Memory Store', () => { } }); - it('selector filter param is respected', async () => { + it('"selector" filter param is respected', async () => { // Get a random selector from the logs const targetBlockIndex = Math.floor(Math.random() * numBlocks); const targetTxIndex = Math.floor(Math.random() * txsPerBlock); diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 6bc4907ef27..2811af67287 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -375,49 +375,43 @@ export class MemoryArchiverStore implements ArchiverDataStore { getUnencryptedLogs(filter: LogFilter): Promise { validateLogFilter(filter); - const txHash = filter.txHash; - + let txHash: TxHash | undefined; let fromBlockIndex = 0; - if (filter.fromBlock !== undefined) { - fromBlockIndex = filter.fromBlock - INITIAL_L2_BLOCK_NUM; - } else if (filter.afterLog !== undefined) { + let toBlockIndex = this.unencryptedLogsPerBlock.length; + let txIndexInBlock = 0; + let logIndexInTx = 0; + + if (filter.afterLog) { + // Continuation parameter is set: "txHash", "fromBlock" and "toBlock" are ignored. fromBlockIndex = filter.afterLog.blockNumber - INITIAL_L2_BLOCK_NUM; - } + txIndexInBlock = filter.afterLog.txIndex; + logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log + } else { + txHash = filter.txHash; - if (fromBlockIndex < 0) { - throw new Error(`"fromBlock" (${filter.fromBlock}) smaller than genesis block number (${INITIAL_L2_BLOCK_NUM}).`); - } - if (fromBlockIndex > this.unencryptedLogsPerBlock.length) { - return Promise.resolve({ - logs: [], - maxLogsHit: false, - }); - } + if (filter.fromBlock !== undefined) { + fromBlockIndex = filter.fromBlock - INITIAL_L2_BLOCK_NUM; + } + if (filter.toBlock !== undefined) { + toBlockIndex = filter.toBlock - INITIAL_L2_BLOCK_NUM; + } - const toBlockIndex = - (filter.toBlock || this.unencryptedLogsPerBlock.length + INITIAL_L2_BLOCK_NUM) - INITIAL_L2_BLOCK_NUM; - if (toBlockIndex < fromBlockIndex) { - return Promise.resolve({ - logs: [], - maxLogsHit: false, - }); + if (fromBlockIndex > this.unencryptedLogsPerBlock.length || toBlockIndex < fromBlockIndex) { + return Promise.resolve({ + logs: [], + maxLogsHit: false, + }); + } } const contractAddress = filter.contractAddress; const selector = filter.selector; - let txIndexInBlock = 0; - let logIndexInTx = 0; - if (filter.afterLog !== undefined) { - txIndexInBlock = filter.afterLog.txIndex; - logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log - } - const logs: ExtendedUnencryptedL2Log[] = []; - for (let i = fromBlockIndex; i < toBlockIndex; i++) { - const blockContext = this.l2BlockContexts[i]; - const blockLogs = this.unencryptedLogsPerBlock[i]; + for (; fromBlockIndex < toBlockIndex; fromBlockIndex++) { + const blockContext = this.l2BlockContexts[fromBlockIndex]; + const blockLogs = this.unencryptedLogsPerBlock[fromBlockIndex]; for (; txIndexInBlock < blockLogs.txLogs.length; txIndexInBlock++) { const txLogs = blockLogs.txLogs[txIndexInBlock].unrollLogs().map(log => UnencryptedL2Log.fromBuffer(log)); for (; logIndexInTx < txLogs.length; logIndexInTx++) { diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index 6867547c667..27dad535978 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -1,6 +1,6 @@ import { AztecAddress, FunctionSelector } from '@aztec/circuits.js'; -import { LogId, TxHash } from '../index.js'; +import { INITIAL_L2_BLOCK_NUM, LogId, TxHash } from '../index.js'; /** * Log filter used to fetch L2 logs. @@ -13,14 +13,14 @@ export type LogFilter = { txHash?: TxHash; /** * The block number from which to start fetching logs (inclusive). - * @remarks If this is set, `txHash` and `fromLog` can't be defined. + * @remarks If this is set, `txHash` can't be defined. */ fromBlock?: number; /** The block number until which to fetch logs (not inclusive). */ toBlock?: number; /** * Log id after which to start fetching logs . - * @remarks If this is set, `fromBlock` and `txHash` can't be defined. + * @remarks This is a continuation parameter and when it is set, txHash and fromBlock and toBlock are ignored. */ afterLog?: LogId; /** The contract address to filter logs by. */ @@ -38,11 +38,14 @@ export type LogFilter = { * @throws If the filter is invalid. */ export function validateLogFilter(filter: LogFilter) { - if (filter.txHash && (filter.fromBlock || filter.toBlock || filter.afterLog)) { - throw new Error("If txHash is set, fromBlock, toBlock, and fromLog can't be defined."); + if (filter.afterLog) { + // afterLog is a continuation parameter and when it is set, txHash and fromBlock and toBlock are ignored. + return; } - - if (filter.fromBlock !== undefined && filter.afterLog) { - throw new Error("If fromBlock is set, fromLog can't be defined."); + if (filter.txHash && (filter.fromBlock || filter.toBlock)) { + throw new Error('Invalid filter: "txHash" is set along with "fromBlock" and or "toBlock".'); + } + if (filter.fromBlock !== undefined && filter.fromBlock < INITIAL_L2_BLOCK_NUM) { + throw new Error(`"fromBlock" (${filter.fromBlock}) smaller than genesis block number (${INITIAL_L2_BLOCK_NUM}).`); } } From da21014977d63e5a7837286d65c030d53f9eb286 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 08:50:13 +0000 Subject: [PATCH 53/60] test fix --- yarn-project/end-to-end/src/sample-dapp/index.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/sample-dapp/index.mjs b/yarn-project/end-to-end/src/sample-dapp/index.mjs index 449eedace47..dc6ba0c08be 100644 --- a/yarn-project/end-to-end/src/sample-dapp/index.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/index.mjs @@ -98,7 +98,7 @@ async function mintPublicFunds(pxe) { // docs:start:showLogs const blockNumber = await pxe.getBlockNumber(); - const logs = await pxe.getUnencryptedLogs(blockNumber, 1); + const logs = (await pxe.getUnencryptedLogs(blockNumber, 1)).logs; const textLogs = L2BlockL2Logs.unrollLogs(logs).map(log => log.toString('ascii')); for (const log of textLogs) console.log(`Log emitted: ${log}`); // docs:end:showLogs From 72ee854c5cbccbe3ab2e707a38691de40e985ad7 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 09:20:37 +0000 Subject: [PATCH 54/60] nicer cli output --- yarn-project/cli/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index ca0d8e1e6de..8f2e8fc3d16 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -330,7 +330,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { .join(', '); if (!follow) log(`No logs found for filter: {${filterOptions}}`); } else { - if (!follow) log('Logs found: \n'); + if (!follow && !filter.afterLog) log('Logs found: \n'); logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); // Disable `fromBlock` and continue using the `afterLog` filter. filter.fromBlock = undefined; From 74fd2e147a7d763c174d17d224fa7fdbdd37658e Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 13:50:42 +0000 Subject: [PATCH 55/60] intersecting --- .../src/archiver/archiver_store.test.ts | 11 --------- .../archiver/src/archiver/archiver_store.ts | 24 +++++++++++-------- yarn-project/types/src/logs/log_filter.ts | 6 ++--- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 054315e7353..a46e24b78ad 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -128,17 +128,6 @@ describe('Archiver Memory Store', () => { expect(response.maxLogsHit).toEqual(false); }); - it('throws when "fromBlock" is smaller than genesis block', async () => { - const fromBlock = INITIAL_L2_BLOCK_NUM - 1; - - await expect( - async () => - await archiverStore.getUnencryptedLogs({ - fromBlock, - }), - ).rejects.toThrow(`smaller than genesis block number`); - }); - it('does not return more than "maxLogs" logs', async () => { const maxLogs = 5; archiverStore = new MemoryArchiverStore(maxLogs); diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 2811af67287..4b8fd2d6ec2 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -382,10 +382,14 @@ export class MemoryArchiverStore implements ArchiverDataStore { let logIndexInTx = 0; if (filter.afterLog) { - // Continuation parameter is set: "txHash", "fromBlock" and "toBlock" are ignored. - fromBlockIndex = filter.afterLog.blockNumber - INITIAL_L2_BLOCK_NUM; - txIndexInBlock = filter.afterLog.txIndex; - logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log + // Continuation parameter is set --> tx hash is ignored + if (filter.fromBlock == undefined || filter.fromBlock <= filter.afterLog.blockNumber) { + fromBlockIndex = filter.afterLog.blockNumber - INITIAL_L2_BLOCK_NUM; + txIndexInBlock = filter.afterLog.txIndex; + logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log + } else { + fromBlockIndex = filter.fromBlock - INITIAL_L2_BLOCK_NUM; + } } else { txHash = filter.txHash; @@ -395,13 +399,13 @@ export class MemoryArchiverStore implements ArchiverDataStore { if (filter.toBlock !== undefined) { toBlockIndex = filter.toBlock - INITIAL_L2_BLOCK_NUM; } + } - if (fromBlockIndex > this.unencryptedLogsPerBlock.length || toBlockIndex < fromBlockIndex) { - return Promise.resolve({ - logs: [], - maxLogsHit: false, - }); - } + if (fromBlockIndex > this.unencryptedLogsPerBlock.length || toBlockIndex < fromBlockIndex || toBlockIndex <= 0) { + return Promise.resolve({ + logs: [], + maxLogsHit: false, + }); } const contractAddress = filter.contractAddress; diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index 27dad535978..b36e1574d05 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -39,13 +39,11 @@ export type LogFilter = { */ export function validateLogFilter(filter: LogFilter) { if (filter.afterLog) { - // afterLog is a continuation parameter and when it is set, txHash and fromBlock and toBlock are ignored. + // afterLog is a continuation parameter and when it is set, "txHash" is ignored and "fromBlock" and "toBlock" are + // intersected with. return; } if (filter.txHash && (filter.fromBlock || filter.toBlock)) { throw new Error('Invalid filter: "txHash" is set along with "fromBlock" and or "toBlock".'); } - if (filter.fromBlock !== undefined && filter.fromBlock < INITIAL_L2_BLOCK_NUM) { - throw new Error(`"fromBlock" (${filter.fromBlock}) smaller than genesis block number (${INITIAL_L2_BLOCK_NUM}).`); - } } From 0a5b4dbc9ee4b94ef172dae3e1858ef69ced4d41 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 14:46:08 +0000 Subject: [PATCH 56/60] more tests --- .../src/archiver/archiver_store.test.ts | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index a46e24b78ad..26458e02011 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -276,5 +276,74 @@ describe('Archiver Memory Store', () => { expect(extendedLog.log.selector.equals(targetSelector)).toBeTruthy(); } }); + + it('"txHash" filter param is ignored when "afterLog" is set', async () => { + // Get random txHash + const txHash = new TxHash(randomBytes(TxHash.SIZE)); + const afterLog = new LogId(1, 0, 0); + + const response = await archiverStore.getUnencryptedLogs({ txHash, afterLog }); + expect(response.logs.length).toBeGreaterThan(1); + }); + + it.only('intersecting works', async () => { + let logs = (await archiverStore.getUnencryptedLogs({ fromBlock: -10, toBlock: -5 })).logs; + expect(logs.length).toBe(0); + + // "fromBlock" gets correctly trimmed to range and "toBlock" is exclusive + logs = (await archiverStore.getUnencryptedLogs({ fromBlock: -10, toBlock: 5 })).logs; + let blockNumbers = new Set(logs.map(log => log.id.blockNumber)); + expect(blockNumbers).toEqual(new Set([1, 2, 3, 4])); + + // "toBlock" should be exclusive + logs = (await archiverStore.getUnencryptedLogs({ fromBlock: 1, toBlock: 1 })).logs; + expect(logs.length).toBe(0); + + logs = (await archiverStore.getUnencryptedLogs({ fromBlock: 10, toBlock: 5 })).logs; + expect(logs.length).toBe(0); + + // both "fromBlock" and "toBlock" get correctly capped to range and logs from all blocks are returned + logs = (await archiverStore.getUnencryptedLogs({ fromBlock: -100, toBlock: +100 })).logs; + blockNumbers = new Set(logs.map(log => log.id.blockNumber)); + expect(blockNumbers.size).toBe(numBlocks); + + // intersecting with "afterLog" works + logs = (await archiverStore.getUnencryptedLogs({ fromBlock: 2, toBlock: 5, afterLog: new LogId(4, 0, 0) })).logs; + blockNumbers = new Set(logs.map(log => log.id.blockNumber)); + // Check that blockNumbers contain only 4 + expect(blockNumbers).toEqual(new Set([4])); + + logs = (await archiverStore.getUnencryptedLogs({ toBlock: 5, afterLog: new LogId(5, 1, 0) })).logs; + expect(logs.length).toBe(0); + + logs = (await archiverStore.getUnencryptedLogs({ fromBlock: 2, toBlock: 5, afterLog: new LogId(100, 0, 0) })) + .logs; + expect(logs.length).toBe(0); + }); + + it('"txIndex" and "logIndex" are respected when "afterLog.blockNumber" is equal to "fromBlock"', async () => { + // Get a random log as reference + const targetBlockIndex = Math.floor(Math.random() * numBlocks); + const targetTxIndex = Math.floor(Math.random() * txsPerBlock); + const targetLogIndex = Math.floor(Math.random() * numUnencryptedLogs); + + const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex); + + const response = await archiverStore.getUnencryptedLogs({ afterLog, fromBlock: afterLog.blockNumber }); + const logs = response.logs; + + expect(response.maxLogsHit).toBeFalsy(); + + for (const log of logs) { + const logId = log.id; + expect(logId.blockNumber).toBeGreaterThanOrEqual(afterLog.blockNumber); + if (logId.blockNumber === afterLog.blockNumber) { + expect(logId.txIndex).toBeGreaterThanOrEqual(afterLog.txIndex); + if (logId.txIndex === afterLog.txIndex) { + expect(logId.logIndex).toBeGreaterThan(afterLog.logIndex); + } + } + } + }); }); }); From 743e9f6d27caf9339e034a1beb786461f18c6dcf Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 14:49:38 +0000 Subject: [PATCH 57/60] final touches --- .../src/archiver/archiver_store.test.ts | 49 +------------------ .../archiver/src/archiver/archiver_store.ts | 14 +++--- yarn-project/cli/src/index.ts | 4 +- yarn-project/types/src/logs/log_filter.ts | 18 +------ 4 files changed, 12 insertions(+), 73 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.test.ts b/yarn-project/archiver/src/archiver/archiver_store.test.ts index 26458e02011..d97a813650f 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.test.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.test.ts @@ -83,51 +83,7 @@ describe('Archiver Memory Store', () => { }, ); - describe('getUnencryptedLogs errors and config', () => { - it('throws when log filter is invalid', async () => { - const txHash = new TxHash(randomBytes(TxHash.SIZE)); - const fromBlock = 2; - const toBlock = 2; - - // First invalid case - txHash and "fromBlock" are set - const filter1 = { - txHash, - fromBlock, - }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter1)).rejects.toThrow( - 'Invalid filter: "txHash" is set along', - ); - - // Second invalid case - "txHash" and "toBlock" are set - const filter2 = { - txHash, - toBlock, - }; - await expect(async () => await archiverStore.getUnencryptedLogs(filter2)).rejects.toThrow( - 'Invalid filter: "txHash" is set along', - ); - }); - - it('does not throw when both "fromBlock" and "txHash" are set with afterLog', async () => { - // this case should not throw because "afterLog" should take precedence - const txHash = new TxHash(randomBytes(TxHash.SIZE)); - const fromBlock = 2; - const toBlock = 3; - const afterLog = new LogId(1, 2, 3); - - // First invalid case - "txHash" and "fromBlock" are set - const filter1 = { - txHash, - fromBlock, - toBlock, - afterLog, - }; - const response = await archiverStore.getUnencryptedLogs(filter1); - - expect(response.logs.length).toEqual(0); - expect(response.maxLogsHit).toEqual(false); - }); - + describe('getUnencryptedLogs config', () => { it('does not return more than "maxLogs" logs', async () => { const maxLogs = 5; archiverStore = new MemoryArchiverStore(maxLogs); @@ -286,7 +242,7 @@ describe('Archiver Memory Store', () => { expect(response.logs.length).toBeGreaterThan(1); }); - it.only('intersecting works', async () => { + it('intersecting works', async () => { let logs = (await archiverStore.getUnencryptedLogs({ fromBlock: -10, toBlock: -5 })).logs; expect(logs.length).toBe(0); @@ -310,7 +266,6 @@ describe('Archiver Memory Store', () => { // intersecting with "afterLog" works logs = (await archiverStore.getUnencryptedLogs({ fromBlock: 2, toBlock: 5, afterLog: new LogId(4, 0, 0) })).logs; blockNumbers = new Set(logs.map(log => log.id.blockNumber)); - // Check that blockNumbers contain only 4 expect(blockNumbers).toEqual(new Set([4])); logs = (await archiverStore.getUnencryptedLogs({ toBlock: 5, afterLog: new LogId(5, 1, 0) })).logs; diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 4b8fd2d6ec2..75fd80cd961 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -16,7 +16,6 @@ import { LogType, TxHash, UnencryptedL2Log, - validateLogFilter, } from '@aztec/types'; import { L1ToL2MessageStore, PendingL1ToL2MessageStore } from './l1_to_l2_message_store.js'; @@ -373,8 +372,6 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @throws If filter is invalid. */ getUnencryptedLogs(filter: LogFilter): Promise { - validateLogFilter(filter); - let txHash: TxHash | undefined; let fromBlockIndex = 0; let toBlockIndex = this.unencryptedLogsPerBlock.length; @@ -396,11 +393,16 @@ export class MemoryArchiverStore implements ArchiverDataStore { if (filter.fromBlock !== undefined) { fromBlockIndex = filter.fromBlock - INITIAL_L2_BLOCK_NUM; } - if (filter.toBlock !== undefined) { - toBlockIndex = filter.toBlock - INITIAL_L2_BLOCK_NUM; - } } + if (filter.toBlock !== undefined) { + toBlockIndex = filter.toBlock - INITIAL_L2_BLOCK_NUM; + } + + // Ensure the indices are within block array bounds + fromBlockIndex = Math.max(fromBlockIndex, 0); + toBlockIndex = Math.min(toBlockIndex, this.unencryptedLogsPerBlock.length); + if (fromBlockIndex > this.unencryptedLogsPerBlock.length || toBlockIndex < fromBlockIndex || toBlockIndex <= 0) { return Promise.resolve({ logs: [], diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 8f2e8fc3d16..379d46dc869 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -14,7 +14,7 @@ import { DebugLogger, LogFn } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; import { fileURLToPath } from '@aztec/foundation/url'; import { compileContract, generateNoirInterface, generateTypescriptInterface } from '@aztec/noir-compiler/cli'; -import { CompleteAddress, ContractData, LogFilter, validateLogFilter } from '@aztec/types'; +import { CompleteAddress, ContractData, LogFilter } from '@aztec/types'; import { createSecp256k1PeerId } from '@libp2p/peer-id-factory'; import { Command, Option } from 'commander'; @@ -317,8 +317,6 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { const filter: LogFilter = { txHash, fromBlock, toBlock, afterLog, contractAddress, selector }; - validateLogFilter(filter); - const fetchLogs = async () => { const response = await pxe.getUnencryptedLogs(filter); const logs = response.logs; diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index b36e1574d05..3dd0c223a23 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -1,6 +1,6 @@ import { AztecAddress, FunctionSelector } from '@aztec/circuits.js'; -import { INITIAL_L2_BLOCK_NUM, LogId, TxHash } from '../index.js'; +import { LogId, TxHash } from '../index.js'; /** * Log filter used to fetch L2 logs. @@ -31,19 +31,3 @@ export type LogFilter = { */ selector?: FunctionSelector; }; - -/** - * Validates a log filter. - * @param filter - Log filter to validate. - * @throws If the filter is invalid. - */ -export function validateLogFilter(filter: LogFilter) { - if (filter.afterLog) { - // afterLog is a continuation parameter and when it is set, "txHash" is ignored and "fromBlock" and "toBlock" are - // intersected with. - return; - } - if (filter.txHash && (filter.fromBlock || filter.toBlock)) { - throw new Error('Invalid filter: "txHash" is set along with "fromBlock" and or "toBlock".'); - } -} From 5c0d510c9735139a9f5a7be9e5808e9817d72bcd Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 14:56:15 +0000 Subject: [PATCH 58/60] updated docs and comments --- yarn-project/archiver/src/archiver/archiver_store.ts | 2 +- yarn-project/cli/README.md | 3 ++- yarn-project/cli/src/index.ts | 2 +- yarn-project/types/src/logs/log_filter.ts | 6 ++---- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 75fd80cd961..3b6d907a410 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -369,7 +369,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { * Gets unencrypted logs based on the provided filter. * @param filter - The filter to apply to the logs. * @returns The requested logs. - * @throws If filter is invalid. + * @remarks Works by doing an intersection of all params in the filter. */ getUnencryptedLogs(filter: LogFilter): Promise { let txHash: TxHash | undefined; diff --git a/yarn-project/cli/README.md b/yarn-project/cli/README.md index aa5aec84b79..70007f28da5 100644 --- a/yarn-project/cli/README.md +++ b/yarn-project/cli/README.md @@ -387,7 +387,8 @@ aztec-cli parse-parameter-struct 0xabcdef1234567890abcdef1234567890abcdef1234567 ### get-logs -Gets all the unencrypted logs from L2 blocks in the specified range. +Applies filter and returns the resulting unencrypted logs. +The filter is applied by doing an intersection of all its params. Syntax: diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 379d46dc869..d6098cc8231 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -294,7 +294,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { program .command('get-logs') - .description('Gets all the unencrypted logs from L2 blocks in the range specified.') + .description('Gets all the unencrypted logs from an intersection of all the filter params.') .option('-tx, --tx-hash ', 'A transaction hash to get the receipt for.', parseOptionalTxHash) .option( '-fb, --from-block ', diff --git a/yarn-project/types/src/logs/log_filter.ts b/yarn-project/types/src/logs/log_filter.ts index 3dd0c223a23..34dca97343e 100644 --- a/yarn-project/types/src/logs/log_filter.ts +++ b/yarn-project/types/src/logs/log_filter.ts @@ -4,23 +4,21 @@ import { LogId, TxHash } from '../index.js'; /** * Log filter used to fetch L2 logs. + * @remarks This filter is applied as an intersection of all it's params. */ export type LogFilter = { /** * Hash of a transaction from which to fetch the logs. - * @remarks If this is set, `fromBlock` and `toBlock` can't be defined. */ txHash?: TxHash; /** * The block number from which to start fetching logs (inclusive). - * @remarks If this is set, `txHash` can't be defined. */ fromBlock?: number; /** The block number until which to fetch logs (not inclusive). */ toBlock?: number; /** - * Log id after which to start fetching logs . - * @remarks This is a continuation parameter and when it is set, txHash and fromBlock and toBlock are ignored. + * Log id after which to start fetching logs. */ afterLog?: LogId; /** The contract address to filter logs by. */ From efcec421ce1f729f5a76a2485a4f725e71eb6daf Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 17:38:28 +0000 Subject: [PATCH 59/60] GetsUnencryptedLogsResponse -> GetUnencryptedLogsResponse --- yarn-project/archiver/src/archiver/archiver.ts | 4 ++-- yarn-project/archiver/src/archiver/archiver_store.ts | 6 +++--- yarn-project/aztec-node/src/aztec-node/server.ts | 4 ++-- yarn-project/aztec.js/src/contract/sent_tx.ts | 4 ++-- yarn-project/aztec.js/src/wallet/base_wallet.ts | 4 ++-- yarn-project/canary/tsconfig.json | 2 +- yarn-project/pxe/src/pxe_service/pxe_service.ts | 4 ++-- yarn-project/types/src/interfaces/aztec-node.ts | 4 ++-- yarn-project/types/src/interfaces/pxe.ts | 4 ++-- .../types/src/logs/get_unencrypted_logs_response.ts | 4 ++-- yarn-project/types/src/logs/l2_logs_source.ts | 4 ++-- yarn-project/types/src/tx/tx.ts | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index d45f96193b5..82087dc9fa9 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -10,7 +10,7 @@ import { ContractDataSource, EncodedContractFunction, ExtendedContractData, - GetsUnencryptedLogsResponse, + GetUnencryptedLogsResponse, INITIAL_L2_BLOCK_NUM, L1ToL2Message, L1ToL2MessageSource, @@ -396,7 +396,7 @@ export class Archiver implements L2BlockSource, L2LogsSource, ContractDataSource * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise { + getUnencryptedLogs(filter: LogFilter): Promise { return this.store.getUnencryptedLogs(filter); } diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 3b6d907a410..f24db5057f8 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -4,7 +4,7 @@ import { ContractData, ExtendedContractData, ExtendedUnencryptedL2Log, - GetsUnencryptedLogsResponse, + GetUnencryptedLogsResponse, INITIAL_L2_BLOCK_NUM, L1ToL2Message, L2Block, @@ -105,7 +105,7 @@ export interface ArchiverDataStore { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Add new extended contract data from an L2 block to the store's list. @@ -371,7 +371,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns The requested logs. * @remarks Works by doing an intersection of all params in the filter. */ - getUnencryptedLogs(filter: LogFilter): Promise { + getUnencryptedLogs(filter: LogFilter): Promise { let txHash: TxHash | undefined; let fromBlockIndex = 0; let toBlockIndex = this.unencryptedLogsPerBlock.length; diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index ac583e5d6d6..08bab77942a 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -24,7 +24,7 @@ import { ContractData, ContractDataSource, ExtendedContractData, - GetsUnencryptedLogsResponse, + GetUnencryptedLogsResponse, L1ToL2MessageAndIndex, L1ToL2MessageSource, L2Block, @@ -232,7 +232,7 @@ export class AztecNodeService implements AztecNode { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise { + getUnencryptedLogs(filter: LogFilter): Promise { return this.unencryptedLogsSource.getUnencryptedLogs(filter); } diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts index adb868a75aa..8f920177d28 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -1,6 +1,6 @@ import { FieldsOf } from '@aztec/circuits.js'; import { retryUntil } from '@aztec/foundation/retry'; -import { GetsUnencryptedLogsResponse, PXE, TxHash, TxReceipt, TxStatus } from '@aztec/types'; +import { GetUnencryptedLogsResponse, PXE, TxHash, TxReceipt, TxStatus } from '@aztec/types'; import every from 'lodash.every'; @@ -85,7 +85,7 @@ export class SentTx { * @remarks This function will wait for the tx to be mined if it hasn't been already. * @returns The requested logs. */ - public async getUnencryptedLogs(): Promise { + public async getUnencryptedLogs(): Promise { await this.wait(); return this.pxe.getUnencryptedLogs({ txHash: await this.getTxHash() }); } diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 00ec07fac7c..6b215ee3ea6 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -5,7 +5,7 @@ import { DeployedContract, ExtendedContractData, FunctionCall, - GetsUnencryptedLogsResponse, + GetUnencryptedLogsResponse, L2Tx, LogFilter, NodeInfo, @@ -97,7 +97,7 @@ export abstract class BaseWallet implements Wallet { getContractData(contractAddress: AztecAddress): Promise { return this.pxe.getContractData(contractAddress); } - getUnencryptedLogs(filter: LogFilter): Promise { + getUnencryptedLogs(filter: LogFilter): Promise { return this.pxe.getUnencryptedLogs(filter); } getBlockNumber(): Promise { diff --git a/yarn-project/canary/tsconfig.json b/yarn-project/canary/tsconfig.json index 7621a947004..2e42dbb2f9a 100644 --- a/yarn-project/canary/tsconfig.json +++ b/yarn-project/canary/tsconfig.json @@ -24,7 +24,7 @@ }, { "path": "../end-to-end" - }, + } ], "include": ["src"] } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 01d7a3466c4..e911469fe8f 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -32,7 +32,7 @@ import { DeployedContract, ExtendedContractData, FunctionCall, - GetsUnencryptedLogsResponse, + GetUnencryptedLogsResponse, KeyStore, L2Block, L2Tx, @@ -389,7 +389,7 @@ export class PXEService implements PXE { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - public getUnencryptedLogs(filter: LogFilter): Promise { + public getUnencryptedLogs(filter: LogFilter): Promise { return this.node.getUnencryptedLogs(filter); } diff --git a/yarn-project/types/src/interfaces/aztec-node.ts b/yarn-project/types/src/interfaces/aztec-node.ts index c63cf45a636..287e4df2f53 100644 --- a/yarn-project/types/src/interfaces/aztec-node.ts +++ b/yarn-project/types/src/interfaces/aztec-node.ts @@ -6,7 +6,7 @@ import { Fr } from '@aztec/foundation/fields'; import { ContractData, ExtendedContractData, - GetsUnencryptedLogsResponse, + GetUnencryptedLogsResponse, L2Block, L2BlockL2Logs, L2Tx, @@ -97,7 +97,7 @@ export interface AztecNode extends StateInfoProvider { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Method to submit a transaction to the p2p pool. diff --git a/yarn-project/types/src/interfaces/pxe.ts b/yarn-project/types/src/interfaces/pxe.ts index 020b3436b76..6f733a4116f 100644 --- a/yarn-project/types/src/interfaces/pxe.ts +++ b/yarn-project/types/src/interfaces/pxe.ts @@ -4,7 +4,7 @@ import { CompleteAddress, ContractData, ExtendedContractData, - GetsUnencryptedLogsResponse, + GetUnencryptedLogsResponse, L2Tx, LogFilter, NotePreimage, @@ -236,7 +236,7 @@ export interface PXE { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Fetches the current block number. diff --git a/yarn-project/types/src/logs/get_unencrypted_logs_response.ts b/yarn-project/types/src/logs/get_unencrypted_logs_response.ts index 936b2d3f4b5..d50c7280a9b 100644 --- a/yarn-project/types/src/logs/get_unencrypted_logs_response.ts +++ b/yarn-project/types/src/logs/get_unencrypted_logs_response.ts @@ -1,9 +1,9 @@ import { ExtendedUnencryptedL2Log } from './extended_unencrypted_l2_log.js'; /** - * It provides documentation for the GetsUnencryptedLogsResponse type. + * It provides documentation for the GetUnencryptedLogsResponse type. */ -export type GetsUnencryptedLogsResponse = { +export type GetUnencryptedLogsResponse = { /** * An array of ExtendedUnencryptedL2Log elements. */ diff --git a/yarn-project/types/src/logs/l2_logs_source.ts b/yarn-project/types/src/logs/l2_logs_source.ts index 997f522ea85..a3566a803fc 100644 --- a/yarn-project/types/src/logs/l2_logs_source.ts +++ b/yarn-project/types/src/logs/l2_logs_source.ts @@ -1,4 +1,4 @@ -import { GetsUnencryptedLogsResponse } from './get_unencrypted_logs_response.js'; +import { GetUnencryptedLogsResponse } from './get_unencrypted_logs_response.js'; import { L2BlockL2Logs } from './l2_block_l2_logs.js'; import { LogFilter } from './log_filter.js'; import { LogType } from './log_type.js'; @@ -21,7 +21,7 @@ export interface L2LogsSource { * @param filter - The filter to apply to the logs. * @returns The requested logs. */ - getUnencryptedLogs(filter: LogFilter): Promise; + getUnencryptedLogs(filter: LogFilter): Promise; /** * Gets the number of the latest L2 block processed by the implementation. diff --git a/yarn-project/types/src/tx/tx.ts b/yarn-project/types/src/tx/tx.ts index a59e8126398..253fcddc68d 100644 --- a/yarn-project/types/src/tx/tx.ts +++ b/yarn-project/types/src/tx/tx.ts @@ -11,7 +11,7 @@ import { BufferReader, Tuple } from '@aztec/foundation/serialize'; import { ExtendedContractData } from '../contract_data.js'; import { L2LogsSource } from '../index.js'; -import { GetsUnencryptedLogsResponse } from '../logs/get_unencrypted_logs_response.js'; +import { GetUnencryptedLogsResponse } from '../logs/get_unencrypted_logs_response.js'; import { TxL2Logs } from '../logs/tx_l2_logs.js'; import { TxHash } from './tx_hash.js'; @@ -119,7 +119,7 @@ export class Tx { * @param logsSource - An instance of `L2LogsSource` which can be used to obtain the logs. * @returns The requested logs. */ - public async getUnencryptedLogs(logsSource: L2LogsSource): Promise { + public async getUnencryptedLogs(logsSource: L2LogsSource): Promise { return logsSource.getUnencryptedLogs({ txHash: await this.getTxHash() }); } From abfa181ea7c61c371b027b4dd6f672fa0b2b2caa Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 11 Oct 2023 17:38:54 +0000 Subject: [PATCH 60/60] cleanup --- yarn-project/cli/src/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index d6098cc8231..6ac81cd4af2 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -330,8 +330,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { } else { if (!follow && !filter.afterLog) log('Logs found: \n'); logs.forEach(unencryptedLog => log(unencryptedLog.toHumanReadable())); - // Disable `fromBlock` and continue using the `afterLog` filter. - filter.fromBlock = undefined; + // Set the continuation parameter for the following requests filter.afterLog = logs[logs.length - 1].id; } return response.maxLogsHit;