From fe817365c443525c9f27007c45fdf10db497f3f4 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 22 May 2025 09:21:27 +0000 Subject: [PATCH 01/14] refactor: separating getLogsByTags to public and private versions --- .../src/messages/discovery/partial_notes.nr | 4 +-- .../aztec/src/oracle/message_discovery.nr | 12 ++++----- .../aztec-node/src/aztec-node/server.ts | 10 +++++++ .../pxe_oracle_interface.test.ts | 12 ++++----- .../pxe_oracle_interface.ts | 26 +++++++------------ .../src/private/acvm/oracle/oracle.ts | 8 +++--- .../src/private/acvm/oracle/typed_oracle.ts | 6 ++--- .../src/private/execution_data_provider.ts | 4 +-- .../src/private/utility_execution_oracle.ts | 6 ++--- .../stdlib/src/interfaces/aztec-node.test.ts | 10 +++++++ .../stdlib/src/interfaces/aztec-node.ts | 13 ++++++++++ .../stdlib/src/logs/log_with_tx_data.ts | 9 +++---- yarn-project/txe/src/oracle/txe_oracle.ts | 12 ++++++--- .../txe/src/txe_service/txe_service.ts | 13 ++++++---- 14 files changed, 89 insertions(+), 56 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr b/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr index ad7aa6defaa1..d13c921c5703 100644 --- a/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr +++ b/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr @@ -4,7 +4,7 @@ use crate::{ discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery}, encoding::MAX_MESSAGE_CONTENT_LEN, }, - oracle::message_discovery::{deliver_note, get_log_by_tag}, + oracle::message_discovery::{deliver_note, get_public_log_by_tag}, utils::array, }; @@ -93,7 +93,7 @@ pub unconstrained fn fetch_and_process_public_partial_note_completion_logs( ); pending_partial_notes.for_each(|i, pending_partial_note: DeliveredPendingPartialNote| { - let maybe_log = get_log_by_tag(pending_partial_note.note_completion_log_tag); + let maybe_log = get_public_log_by_tag(pending_partial_note.note_completion_log_tag); if maybe_log.is_none() { debug_log_format( "Found no completion logs for partial note with tag {}", diff --git a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr index eaa049a915bc..042efc82b7f2 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr @@ -50,9 +50,7 @@ pub unconstrained fn deliver_note( /// The contents of a public log, plus contextual information about the transaction in which the log was emitted. This /// is the data required in order to discover notes that are being delivered in a log. -// TODO(#11639): this could also be used to fetch private logs, but the `BoundedVec` maximum length is that of a public -// log. -pub struct LogWithTxData { +pub struct PublicLogWithTxData { // The log fields length is PUBLIC_LOG_SIZE_IN_FIELDS. + 1 because the contract address is prepended to the content. pub log_content: BoundedVec, pub tx_hash: Field, @@ -68,8 +66,8 @@ pub struct LogWithTxData { /// Public logs have an extra field included at the beginning with the address of the contract that emitted them. // TODO(#11627): handle multiple logs with the same tag. // TODO(#10273): improve contract siloing of logs, don't introduce an extra field. -pub unconstrained fn get_log_by_tag(tag: Field) -> Option { - get_log_by_tag_oracle(tag) +pub unconstrained fn get_public_log_by_tag(tag: Field) -> Option { + get_public_log_by_tag_oracle(tag) } #[oracle(deliverNote)] @@ -84,5 +82,5 @@ unconstrained fn deliver_note_oracle( recipient: AztecAddress, ) -> bool {} -#[oracle(getLogByTag)] -unconstrained fn get_log_by_tag_oracle(tag: Field) -> Option {} +#[oracle(getPublicLogByTag)] +unconstrained fn get_public_log_by_tag_oracle(tag: Field) -> Option {} diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 892636635282..96376d3cd4a8 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -476,6 +476,16 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { return this.logsSource.getLogsByTags(tags); } + public async getPrivateLogsByTags(tags: Fr[]): Promise { + const allLogs = await this.logsSource.getLogsByTags(tags); + return allLogs.map(logs => logs.filter(log => !log.isFromPublic)); + } + + public async getPublicLogsByTags(tags: Fr[]): Promise { + const allLogs = await this.logsSource.getLogsByTags(tags); + return allLogs.map(logs => logs.filter(log => log.isFromPublic)); + } + /** * Gets public logs based on the provided filter. * @param filter - The filter to apply to the logs. diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts index 4dd8c2406b40..56205209f797 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts @@ -635,7 +635,7 @@ describe('PXEOracleInterface', () => { }); }); - describe('getLogByTag', () => { + describe('getPublicLogByTag', () => { const tag = Fr.random(); beforeEach(() => { @@ -646,7 +646,7 @@ describe('PXEOracleInterface', () => { it('returns null if no logs found for tag', async () => { aztecNode.getLogsByTags.mockResolvedValue([[]]); - const result = await pxeOracleInterface.getLogByTag(tag); + const result = await pxeOracleInterface.getPublicLogByTag(tag); expect(result).toBeNull(); }); @@ -662,7 +662,7 @@ describe('PXEOracleInterface', () => { txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), ); - const result = (await pxeOracleInterface.getLogByTag(tag))!; + const result = (await pxeOracleInterface.getPublicLogByTag(tag))!; if (isFromPublic) { expect(result.logContent).toEqual( @@ -683,7 +683,7 @@ describe('PXEOracleInterface', () => { const scopedLog = await TxScopedL2Log.random(); aztecNode.getLogsByTags.mockResolvedValue([[scopedLog, scopedLog]]); - await expect(pxeOracleInterface.getLogByTag(tag)).rejects.toThrow(/Got 2 logs for tag/); + await expect(pxeOracleInterface.getPublicLogByTag(tag)).rejects.toThrow(/Got 2 logs for tag/); }); it('throws if tx effect not found', async () => { @@ -691,7 +691,7 @@ describe('PXEOracleInterface', () => { aztecNode.getLogsByTags.mockResolvedValue([[scopedLog]]); aztecNode.getTxEffect.mockResolvedValue(undefined); - await expect(pxeOracleInterface.getLogByTag(tag)).rejects.toThrow(/failed to retrieve tx effects/); + await expect(pxeOracleInterface.getPublicLogByTag(tag)).rejects.toThrow(/failed to retrieve tx effects/); }); it('returns log fields that are actually emitted', async () => { @@ -709,7 +709,7 @@ describe('PXEOracleInterface', () => { aztecNode.getLogsByTags.mockResolvedValue([[scopedLogWithPadding]]); aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); - const result = await pxeOracleInterface.getLogByTag(tag); + const result = await pxeOracleInterface.getPublicLogByTag(tag); expect(result?.logContent).toEqual(logContent); }); diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts index e06d5e35ebd3..f5bc8ab094a5 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts @@ -19,9 +19,9 @@ import type { KeyValidationRequest } from '@aztec/stdlib/kernel'; import { computeAddressSecret, computeAppTaggingSecret } from '@aztec/stdlib/keys'; import { IndexedTaggingSecret, - LogWithTxData, PendingTaggedLog, PublicLog, + PublicLogWithTxData, TxScopedL2Log, deriveEcdhSharedSecret, } from '@aztec/stdlib/logs'; @@ -392,7 +392,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { }); // We fetch the logs for the tags - const possibleLogs = await this.aztecNode.getLogsByTags(currentTags); + const possibleLogs = await this.aztecNode.getPrivateLogsByTags(currentTags); // We find the index of the last log in the window that is not empty const indexOfLastLog = possibleLogs.findLastIndex(possibleLog => possibleLog.length !== 0); @@ -490,20 +490,14 @@ export class PXEOracleInterface implements ExecutionDataProvider { // a new set of secrets and windows to fetch logs for. const newLargestIndexMapForIteration: { [k: string]: number } = {}; - // Fetch the logs for the tags and iterate over them - const logsByTags = await this.aztecNode.getLogsByTags(tagsForTheWholeWindow); + // Fetch the private logs for the tags and iterate over them + const logsByTags = await this.aztecNode.getPrivateLogsByTags(tagsForTheWholeWindow); for (let logIndex = 0; logIndex < logsByTags.length; logIndex++) { const logsByTag = logsByTags[logIndex]; if (logsByTag.length > 0) { - // Discard public logs - const filteredLogsByTag = logsByTag.filter(l => !l.isFromPublic); - if (filteredLogsByTag.length < logsByTag.length) { - this.log.warn(`Discarded ${logsByTag.filter(l => l.isFromPublic).length} public logs with matching tags`); - } - // We filter out the logs that are newer than the historical block number of the tx currently being constructed - const filteredLogsByBlockNumber = filteredLogsByTag.filter(l => l.blockNumber <= maxBlockNumber); + const filteredLogsByBlockNumber = logsByTag.filter(l => l.blockNumber <= maxBlockNumber); // We store the logs in capsules (to later be obtained in Noir) await this.#storePendingTaggedLogs( @@ -518,7 +512,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { const secretCorrespondingToLog = secretsForTheWholeWindow[logIndex]; const initialIndex = initialIndexesMap[secretCorrespondingToLog.appTaggingSecret.toString()]; - this.log.debug(`Found ${filteredLogsByTag.length} logs as recipient ${recipient}`, { + this.log.debug(`Found ${logsByTags.length} logs as recipient ${recipient}`, { recipient, secret: secretCorrespondingToLog.appTaggingSecret, contractName, @@ -700,8 +694,8 @@ export class PXEOracleInterface implements ExecutionDataProvider { } } - public async getLogByTag(tag: Fr): Promise { - const logs = await this.aztecNode.getLogsByTags([tag]); + public async getPublicLogByTag(tag: Fr): Promise { + const logs = await this.aztecNode.getPublicLogsByTags([tag]); const logsForTag = logs[0]; this.log.debug(`Got ${logsForTag.length} logs for tag ${tag}`); @@ -711,7 +705,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { } else if (logsForTag.length > 1) { // TODO(#11627): handle this case throw new Error( - `Got ${logsForTag.length} logs for tag ${tag}. getLogByTag currently only supports a single log per tag`, + `Got ${logsForTag.length} logs for tag ${tag}. getPublicLogByTag currently only supports a single log per tag`, ); } @@ -729,7 +723,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { scopedLog.log.getEmittedFields(), ); - return new LogWithTxData(logContent, scopedLog.txHash, txEffect.data.noteHashes, txEffect.data.nullifiers[0]); + return new PublicLogWithTxData(logContent, scopedLog.txHash, txEffect.data.noteHashes, txEffect.data.nullifiers[0]); } public async removeNullifiedNotes(contractAddress: AztecAddress) { diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index 0d71f2c7bca8..440ac4f16abc 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts @@ -1,7 +1,7 @@ import { Fr, Point } from '@aztec/foundation/fields'; import { EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; -import { ContractClassLog, ContractClassLogFields, LogWithTxData } from '@aztec/stdlib/logs'; +import { ContractClassLog, ContractClassLogFields, PublicLogWithTxData } from '@aztec/stdlib/logs'; import { MerkleTreeId } from '@aztec/stdlib/trees'; import { TxHash } from '@aztec/stdlib/tx'; @@ -412,11 +412,11 @@ export class Oracle { return [toACVMField(true)]; } - async getLogByTag([tag]: ACVMField[]): Promise<(ACVMField | ACVMField[])[]> { - const log = await this.typedOracle.getLogByTag(Fr.fromString(tag)); + async getPublicLogByTag([tag]: ACVMField[]): Promise<(ACVMField | ACVMField[])[]> { + const log = await this.typedOracle.getPublicLogByTag(Fr.fromString(tag)); if (log == null) { - return [toACVMField(0), ...LogWithTxData.noirSerializationOfEmpty().map(toACVMFieldSingleOrArray)]; + return [toACVMField(0), ...PublicLogWithTxData.noirSerializationOfEmpty().map(toACVMFieldSingleOrArray)]; } else { return [toACVMField(1), ...log.toNoirSerialization().map(toACVMFieldSingleOrArray)]; } diff --git a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts index acc110a02ba5..c65cdf0f2498 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts @@ -4,7 +4,7 @@ import type { EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdli import type { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract'; import type { KeyValidationRequest } from '@aztec/stdlib/kernel'; -import type { ContractClassLog, IndexedTaggingSecret, LogWithTxData } from '@aztec/stdlib/logs'; +import type { ContractClassLog, IndexedTaggingSecret, PublicLogWithTxData } from '@aztec/stdlib/logs'; import type { Note, NoteStatus } from '@aztec/stdlib/note'; import { type MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees'; import type { BlockHeader, TxHash } from '@aztec/stdlib/tx'; @@ -231,8 +231,8 @@ export abstract class TypedOracle { return Promise.reject(new OracleMethodNotAvailableError('deliverNote')); } - getLogByTag(_tag: Fr): Promise { - throw new OracleMethodNotAvailableError('getLogByTag'); + getPublicLogByTag(_tag: Fr): Promise { + throw new OracleMethodNotAvailableError('getPublicLogByTag'); } storeCapsule(_contractAddress: AztecAddress, _key: Fr, _capsule: Fr[]): Promise { diff --git a/yarn-project/simulator/src/private/execution_data_provider.ts b/yarn-project/simulator/src/private/execution_data_provider.ts index 791329c90f1b..c5f580f75ff8 100644 --- a/yarn-project/simulator/src/private/execution_data_provider.ts +++ b/yarn-project/simulator/src/private/execution_data_provider.ts @@ -10,7 +10,7 @@ import type { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { L2Block } from '@aztec/stdlib/block'; import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract'; import type { KeyValidationRequest } from '@aztec/stdlib/kernel'; -import { IndexedTaggingSecret, LogWithTxData } from '@aztec/stdlib/logs'; +import { IndexedTaggingSecret, PublicLogWithTxData } from '@aztec/stdlib/logs'; import type { NoteStatus } from '@aztec/stdlib/note'; import { type MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees'; import type { BlockHeader, TxHash } from '@aztec/stdlib/tx'; @@ -311,7 +311,7 @@ export interface ExecutionDataProvider { * * @param tag - The log tag to search for. */ - getLogByTag(tag: Fr): Promise; + getPublicLogByTag(tag: Fr): Promise; /** * Removes all of a contract's notes that have been nullified from the note database. diff --git a/yarn-project/simulator/src/private/utility_execution_oracle.ts b/yarn-project/simulator/src/private/utility_execution_oracle.ts index 39b9080925d2..a6d9924c6476 100644 --- a/yarn-project/simulator/src/private/utility_execution_oracle.ts +++ b/yarn-project/simulator/src/private/utility_execution_oracle.ts @@ -7,7 +7,7 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract'; import { siloNullifier } from '@aztec/stdlib/hash'; import type { KeyValidationRequest } from '@aztec/stdlib/kernel'; -import { IndexedTaggingSecret, LogWithTxData } from '@aztec/stdlib/logs'; +import { IndexedTaggingSecret, PublicLogWithTxData } from '@aztec/stdlib/logs'; import type { NoteStatus } from '@aztec/stdlib/note'; import { type MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees'; import type { BlockHeader, Capsule, TxHash } from '@aztec/stdlib/tx'; @@ -307,8 +307,8 @@ export class UtilityExecutionOracle extends TypedOracle { ); } - public override getLogByTag(tag: Fr): Promise { - return this.executionDataProvider.getLogByTag(tag); + public override getPublicLogByTag(tag: Fr): Promise { + return this.executionDataProvider.getPublicLogByTag(tag); } public override storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise { diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts index c7b0f7b3d6c5..a399f7c7b8aa 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts @@ -582,6 +582,16 @@ class MockAztecNode implements AztecNode { expect(tags[0]).toBeInstanceOf(Fr); return [[await TxScopedL2Log.random()]]; } + async getPrivateLogsByTags(tags: Fr[]): Promise { + expect(tags).toHaveLength(1); + expect(tags[0]).toBeInstanceOf(Fr); + return [[await TxScopedL2Log.random(false)]]; + } + async getPublicLogsByTags(tags: Fr[]): Promise { + expect(tags).toHaveLength(1); + expect(tags[0]).toBeInstanceOf(Fr); + return [[await TxScopedL2Log.random(true)]]; + } sendTx(tx: Tx): Promise { expect(tx).toBeInstanceOf(Tx); return Promise.resolve(); diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.ts b/yarn-project/stdlib/src/interfaces/aztec-node.ts index eaaa1af90ba7..79e22025539a 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.ts @@ -311,6 +311,9 @@ export interface AztecNode */ getLogsByTags(tags: Fr[]): Promise; + getPrivateLogsByTags(tags: Fr[]): Promise; + getPublicLogsByTags(tags: Fr[]): Promise; + /** * Method to submit a transaction to the p2p pool. * @param tx - The transaction to be submitted. @@ -511,6 +514,16 @@ export const AztecNodeApiSchema: ApiSchemaFor = { .args(z.array(schemas.Fr)) .returns(z.array(z.array(TxScopedL2Log.schema))), + getPrivateLogsByTags: z + .function() + .args(z.array(schemas.Fr)) + .returns(z.array(z.array(TxScopedL2Log.schema))), + + getPublicLogsByTags: z + .function() + .args(z.array(schemas.Fr)) + .returns(z.array(z.array(TxScopedL2Log.schema))), + sendTx: z.function().args(Tx.schema).returns(z.void()), getTxReceipt: z.function().args(TxHash.schema).returns(TxReceipt.schema), diff --git a/yarn-project/stdlib/src/logs/log_with_tx_data.ts b/yarn-project/stdlib/src/logs/log_with_tx_data.ts index bab5655e1044..b5fa2e15f948 100644 --- a/yarn-project/stdlib/src/logs/log_with_tx_data.ts +++ b/yarn-project/stdlib/src/logs/log_with_tx_data.ts @@ -2,9 +2,9 @@ import { MAX_NOTE_HASHES_PER_TX, PUBLIC_LOG_SIZE_IN_FIELDS } from '@aztec/consta import { Fr } from '@aztec/foundation/fields'; import { TxHash } from '@aztec/stdlib/tx'; -// TypeScript representation of the Noir aztec::oracle::message_discovery::LogWithTxData struct. This is used as a -// response for PXE's custom getLogByTag oracle. -export class LogWithTxData { +// TypeScript representation of the Noir aztec::oracle::message_discovery::PublicLogWithTxData struct. This is used as a +// response for PXE's custom getPublicLogByTag oracle. +export class PublicLogWithTxData { constructor( // The emitted fields of a log. // For public logs, the contract address is prepended to the content. @@ -18,7 +18,6 @@ export class LogWithTxData { return [ // The log fields length is PUBLIC_LOG_SIZE_IN_FIELDS. + 1 because the contract address is prepended to the content. // This is only used for public logs currently, so the maxLength is PUBLIC_LOG_SIZE_IN_FIELDS + 1. - // TODO(#11639): this could also be used for private logs. ...toBoundedVecSerialization(this.logContent, PUBLIC_LOG_SIZE_IN_FIELDS + 1), this.txHash.hash, ...toBoundedVecSerialization(this.uniqueNoteHashesInTx, MAX_NOTE_HASHES_PER_TX), @@ -27,7 +26,7 @@ export class LogWithTxData { } static noirSerializationOfEmpty(): (Fr | Fr[])[] { - return new LogWithTxData([], TxHash.zero(), [], new Fr(0)).toNoirSerialization(); + return new PublicLogWithTxData([], TxHash.zero(), [], new Fr(0)).toNoirSerialization(); } } diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 2a7f976dd976..3b8fea1ba4c9 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -99,7 +99,13 @@ import { ScopedLogHash, } from '@aztec/stdlib/kernel'; import { deriveKeys } from '@aztec/stdlib/keys'; -import { ContractClassLog, IndexedTaggingSecret, LogWithTxData, PrivateLog, type PublicLog } from '@aztec/stdlib/logs'; +import { + ContractClassLog, + IndexedTaggingSecret, + PrivateLog, + type PublicLog, + PublicLogWithTxData, +} from '@aztec/stdlib/logs'; import { ScopedL2ToL1Message } from '@aztec/stdlib/messaging'; import type { NoteStatus } from '@aztec/stdlib/note'; import { ClientIvcProof } from '@aztec/stdlib/proofs'; @@ -1191,8 +1197,8 @@ export class TXE implements TypedOracle { ); } - async getLogByTag(tag: Fr): Promise { - return await this.pxeOracleInterface.getLogByTag(tag); + async getPublicLogByTag(tag: Fr): Promise { + return await this.pxeOracleInterface.getPublicLogByTag(tag); } // AVM oracles diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 8026c13beef0..35167a16b2fc 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -11,7 +11,7 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address'; import { computePartialAddress } from '@aztec/stdlib/contract'; import { SimulationError } from '@aztec/stdlib/errors'; import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash'; -import { LogWithTxData } from '@aztec/stdlib/logs'; +import { PublicLogWithTxData } from '@aztec/stdlib/logs'; import { MerkleTreeId } from '@aztec/stdlib/trees'; import { TXE } from '../oracle/txe_oracle.js'; @@ -731,18 +731,21 @@ export class TXEService { return toForeignCallResult([toSingle(Fr.ONE)]); } - async getLogByTag(tag: ForeignCallSingle) { + async getPublicLogByTag(tag: ForeignCallSingle) { if (!this.oraclesEnabled) { throw new Error( 'Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.', ); } - // TODO(AD): this was warning that getLogByTag did not return a promise. - const log = await Promise.resolve(this.typedOracle.getLogByTag(fromSingle(tag))); + // TODO(AD): this was warning that getPublicLogByTag did not return a promise. + const log = await Promise.resolve(this.typedOracle.getPublicLogByTag(fromSingle(tag))); if (log == null) { - return toForeignCallResult([toSingle(Fr.ZERO), ...LogWithTxData.noirSerializationOfEmpty().map(toSingleOrArray)]); + return toForeignCallResult([ + toSingle(Fr.ZERO), + ...PublicLogWithTxData.noirSerializationOfEmpty().map(toSingleOrArray), + ]); } else { return toForeignCallResult([toSingle(Fr.ONE), ...log.toNoirSerialization().map(toSingleOrArray)]); } From 3f8147191f9737d001cf8436b9db290bbf84cee8 Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 22 May 2025 09:42:59 +0000 Subject: [PATCH 02/14] nuking getLogsByTags --- .../aztec-node/src/aztec-node/server.ts | 12 +-- .../pxe_oracle_interface.test.ts | 94 +++++++------------ .../stdlib/src/interfaces/aztec-node.test.ts | 14 +-- .../stdlib/src/interfaces/aztec-node.ts | 7 -- .../stdlib/src/logs/tx_scoped_l2_log.ts | 1 + 5 files changed, 44 insertions(+), 84 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 96376d3cd4a8..239fd1454638 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -466,23 +466,15 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { return this.logsSource.getPrivateLogs(from, limit); } - /** - * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag). - * @param tags - The tags to filter the logs by. - * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match - * that tag. - */ - public getLogsByTags(tags: Fr[]): Promise { - return this.logsSource.getLogsByTags(tags); - } - public async getPrivateLogsByTags(tags: Fr[]): Promise { const allLogs = await this.logsSource.getLogsByTags(tags); + // TODO(#14460): Have logSource implement getPrivateLogsByTags and skip the filter here. return allLogs.map(logs => logs.filter(log => !log.isFromPublic)); } public async getPublicLogsByTags(tags: Fr[]): Promise { const allLogs = await this.logsSource.getLogsByTags(tags); + // TODO(#14460): Have logSource implement getPrivateLogsByTags and skip the filter here. return allLogs.map(logs => logs.filter(log => log.isFromPublic)); } diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts index 56205209f797..7ee57666a131 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts @@ -1,8 +1,7 @@ -import { PRIVATE_LOG_SIZE_IN_FIELDS, PUBLIC_LOG_SIZE_IN_FIELDS } from '@aztec/constants'; +import { PUBLIC_LOG_SIZE_IN_FIELDS } from '@aztec/constants'; import { padArrayEnd, timesParallel } from '@aztec/foundation/collection'; import { randomInt } from '@aztec/foundation/crypto'; import { Fq, Fr } from '@aztec/foundation/fields'; -import type { Tuple } from '@aztec/foundation/serialize'; import { KeyStore } from '@aztec/key-store'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; @@ -148,7 +147,7 @@ describe('PXEOracleInterface', () => { // Accumulated logs intended for recipient: NUM_SENDERS + 1 + NUM_SENDERS / 2 // Set up the getTaggedLogs mock - aztecNode.getLogsByTags.mockImplementation(tags => { + aztecNode.getPrivateLogsByTags.mockImplementation(tags => { return Promise.resolve(tags.map(tag => logs[tag.toString()] ?? [])); }); } @@ -168,7 +167,7 @@ describe('PXEOracleInterface', () => { for (const sender of senders) { await taggingDataProvider.addSenderAddress(sender.completeAddress.address); } - aztecNode.getLogsByTags.mockReset(); + aztecNode.getPrivateLogsByTags.mockReset(); aztecNode.getTxEffect.mockResolvedValue({ ...randomInBlock(await TxEffect.random()), txIndexInBlock: 0, @@ -203,7 +202,7 @@ describe('PXEOracleInterface', () => { // We should have called the node 2 times: // 2 times: first time during initial request, second time after pushing the edge of the window once - expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2); + expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(2); }); it('should sync tagged logs as senders', async () => { @@ -237,7 +236,7 @@ describe('PXEOracleInterface', () => { const indexesAsSender = await getTaggingSecretsIndexesAsSenderForSenders(); expect(indexesAsSender).toStrictEqual([[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]); - expect(aztecNode.getLogsByTags.mock.calls.length).toBe(0); + expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(0); for (let i = 0; i < senders.length; i++) { await pxeOracleInterface.syncTaggedLogsAsSender( @@ -251,8 +250,8 @@ describe('PXEOracleInterface', () => { expect(indexesAsSenderAfterSync).toStrictEqual([[1], [1], [1], [1], [1], [2], [2], [2], [2], [2]]); // Only 1 window is obtained for each sender - expect(aztecNode.getLogsByTags.mock.calls.length).toBe(NUM_SENDERS); - aztecNode.getLogsByTags.mockReset(); + expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(NUM_SENDERS); + aztecNode.getPrivateLogsByTags.mockReset(); // We add more logs to the second half of the window to test that a second iteration in `syncTaggedLogsAsSender` // is handled correctly. @@ -269,7 +268,7 @@ describe('PXEOracleInterface', () => { indexesAsSenderAfterSync = await getTaggingSecretsIndexesAsSenderForSenders(); expect(indexesAsSenderAfterSync).toStrictEqual([[12], [12], [12], [12], [12], [13], [13], [13], [13], [13]]); - expect(aztecNode.getLogsByTags.mock.calls.length).toBe(NUM_SENDERS * 2); + expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(NUM_SENDERS * 2); }); it('should sync tagged logs with a sender index offset', async () => { @@ -299,7 +298,7 @@ describe('PXEOracleInterface', () => { // We should have called the node 2 times: // 2 times: first time during initial request, second time after pushing the edge of the window once - expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2); + expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(2); }); it("should sync tagged logs for which indexes are not updated if they're inside the window", async () => { @@ -336,7 +335,7 @@ describe('PXEOracleInterface', () => { // We should have called the node 2 times: // first time during initial request, second time after pushing the edge of the window once - expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2); + expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(2); }); it("should not sync tagged logs for which indexes are not updated if they're outside the window", async () => { @@ -372,7 +371,7 @@ describe('PXEOracleInterface', () => { expect(indexes).toEqual([index, index, index, index, index, index, index, index, index, index]); // We should have called the node once and that is only for the first window - expect(aztecNode.getLogsByTags.mock.calls.length).toBe(1); + expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(1); }); it('should sync tagged logs from scratch after a DB wipe', async () => { @@ -399,9 +398,9 @@ describe('PXEOracleInterface', () => { // Since no logs were synced, window edge hash not been pushed and for this reason we should have called // the node only once for the initial window - expect(aztecNode.getLogsByTags.mock.calls.length).toBe(1); + expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(1); - aztecNode.getLogsByTags.mockClear(); + aztecNode.getPrivateLogsByTags.mockClear(); // Wipe the database await taggingDataProvider.resetNoteSyncData(); @@ -418,7 +417,7 @@ describe('PXEOracleInterface', () => { // We should have called the node 2 times: // first time during initial request, second time after pushing the edge of the window once - expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2); + expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(2); }); it('should not sync tagged logs with a blockNumber larger than the block number to which PXE is synced', async () => { @@ -434,28 +433,6 @@ describe('PXEOracleInterface', () => { await expectPendingTaggedLogArrayLengthToBe(contractAddress, NUM_SENDERS + 1); }); - it('should not sync public tagged logs', async () => { - const logs: { [k: string]: TxScopedL2Log[] } = {}; - const tag = await computeSiloedTagForIndex(senders[0], recipient.address, contractAddress, 0); - - // Create a public log with the correct tag - const logContent = [Fr.ONE, tag, ...Array(PUBLIC_LOG_SIZE_IN_FIELDS - 2).fill(Fr.random())] as Tuple< - Fr, - typeof PUBLIC_LOG_SIZE_IN_FIELDS - >; - const log = new PublicLog(await AztecAddress.random(), logContent, PUBLIC_LOG_SIZE_IN_FIELDS); - const scopedLog = new TxScopedL2Log(TxHash.random(), 1, 0, 0, log); - - logs[tag.toString()] = [scopedLog]; - aztecNode.getLogsByTags.mockImplementation(tags => { - return Promise.resolve(tags.map(tag => logs[tag.toString()] ?? [])); - }); - await pxeOracleInterface.syncTaggedLogs(contractAddress, PENDING_TAGGED_LOG_ARRAY_BASE_SLOT); - - // We expect the above log to be discarded, and so none to be synced - await expectPendingTaggedLogArrayLengthToBe(contractAddress, 0); - }); - const expectPendingTaggedLogArrayLengthToBe = async (contractAddress: AztecAddress, expectedLength: number) => { // Capsule array length is stored in the array base slot. const capsule = await capsuleDataProvider.loadCapsule(contractAddress, PENDING_TAGGED_LOG_ARRAY_BASE_SLOT); @@ -639,24 +616,21 @@ describe('PXEOracleInterface', () => { const tag = Fr.random(); beforeEach(() => { - aztecNode.getLogsByTags.mockReset(); + aztecNode.getPublicLogsByTags.mockReset(); aztecNode.getTxEffect.mockReset(); }); it('returns null if no logs found for tag', async () => { - aztecNode.getLogsByTags.mockResolvedValue([[]]); + aztecNode.getPublicLogsByTags.mockResolvedValue([[]]); const result = await pxeOracleInterface.getPublicLogByTag(tag); expect(result).toBeNull(); }); - it.each<[string, boolean]>([ - ['public log', true], - ['private log', false], - ])('returns log data for %s when single log found', async (_, isFromPublic) => { - const scopedLog = await TxScopedL2Log.random(isFromPublic); + it('returns log data when single log found', async () => { + const scopedLog = await TxScopedL2Log.random(true); - aztecNode.getLogsByTags.mockResolvedValue([[scopedLog]]); + aztecNode.getPublicLogsByTags.mockResolvedValue([[scopedLog]]); const indexedTxEffect = await randomIndexedTxEffect(); aztecNode.getTxEffect.mockImplementation((txHash: TxHash) => txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), @@ -664,31 +638,27 @@ describe('PXEOracleInterface', () => { const result = (await pxeOracleInterface.getPublicLogByTag(tag))!; - if (isFromPublic) { - expect(result.logContent).toEqual( - [(scopedLog.log as PublicLog).contractAddress.toField()].concat(scopedLog.log.getEmittedFields()), - ); - } else { - expect(result.logContent).toEqual(scopedLog.log.getEmittedFields()); - } + expect(result.logContent).toEqual( + [(scopedLog.log as PublicLog).contractAddress.toField()].concat(scopedLog.log.getEmittedFields()), + ); expect(result.uniqueNoteHashesInTx).toEqual(indexedTxEffect.data.noteHashes); expect(result.txHash).toEqual(scopedLog.txHash); expect(result.firstNullifierInTx).toEqual(indexedTxEffect.data.nullifiers[0]); - expect(aztecNode.getLogsByTags).toHaveBeenCalledWith([tag]); + expect(aztecNode.getPublicLogsByTags).toHaveBeenCalledWith([tag]); expect(aztecNode.getTxEffect).toHaveBeenCalledWith(scopedLog.txHash); }); it('throws if multiple logs found for tag', async () => { - const scopedLog = await TxScopedL2Log.random(); - aztecNode.getLogsByTags.mockResolvedValue([[scopedLog, scopedLog]]); + const scopedLog = await TxScopedL2Log.random(true); + aztecNode.getPublicLogsByTags.mockResolvedValue([[scopedLog, scopedLog]]); await expect(pxeOracleInterface.getPublicLogByTag(tag)).rejects.toThrow(/Got 2 logs for tag/); }); it('throws if tx effect not found', async () => { - const scopedLog = await TxScopedL2Log.random(); - aztecNode.getLogsByTags.mockResolvedValue([[scopedLog]]); + const scopedLog = await TxScopedL2Log.random(true); + aztecNode.getPublicLogsByTags.mockResolvedValue([[scopedLog]]); aztecNode.getTxEffect.mockResolvedValue(undefined); await expect(pxeOracleInterface.getPublicLogByTag(tag)).rejects.toThrow(/failed to retrieve tx effects/); @@ -697,7 +667,11 @@ describe('PXEOracleInterface', () => { it('returns log fields that are actually emitted', async () => { const logContent = [Fr.random(), Fr.random()]; - const log = new PrivateLog(padArrayEnd(logContent, Fr.ZERO, PRIVATE_LOG_SIZE_IN_FIELDS), logContent.length); + const log = PublicLog.from({ + contractAddress: await AztecAddress.random(), + fields: padArrayEnd(logContent, Fr.ZERO, PUBLIC_LOG_SIZE_IN_FIELDS), + emittedLength: logContent.length, + }); const scopedLogWithPadding = new TxScopedL2Log( TxHash.random(), randomInt(100), @@ -706,12 +680,12 @@ describe('PXEOracleInterface', () => { log, ); - aztecNode.getLogsByTags.mockResolvedValue([[scopedLogWithPadding]]); + aztecNode.getPublicLogsByTags.mockResolvedValue([[scopedLogWithPadding]]); aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); const result = await pxeOracleInterface.getPublicLogByTag(tag); - expect(result?.logContent).toEqual(logContent); + expect(result?.logContent).toEqual([log.contractAddress.toField(), ...logContent]); }); }); diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts index a399f7c7b8aa..fe789d2c894c 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts @@ -243,8 +243,13 @@ describe('AztecNodeApiSchema', () => { expect(response).toEqual({ logs: [expect.any(ExtendedContractClassLog)], maxLogsHit: true }); }); - it('getLogsByTags', async () => { - const response = await context.client.getLogsByTags([Fr.random()]); + it('getPrivateLogsByTags', async () => { + const response = await context.client.getPrivateLogsByTags([Fr.random()]); + expect(response).toEqual([[expect.any(TxScopedL2Log)]]); + }); + + it('getPublicLogsByTags', async () => { + const response = await context.client.getPublicLogsByTags([Fr.random()]); expect(response).toEqual([[expect.any(TxScopedL2Log)]]); }); @@ -577,11 +582,6 @@ class MockAztecNode implements AztecNode { expect(filter.contractAddress).toBeInstanceOf(AztecAddress); return Promise.resolve({ logs: [await ExtendedContractClassLog.random()], maxLogsHit: true }); } - async getLogsByTags(tags: Fr[]): Promise { - expect(tags).toHaveLength(1); - expect(tags[0]).toBeInstanceOf(Fr); - return [[await TxScopedL2Log.random()]]; - } async getPrivateLogsByTags(tags: Fr[]): Promise { expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(Fr); diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.ts b/yarn-project/stdlib/src/interfaces/aztec-node.ts index 79e22025539a..834e4aa6c657 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.ts @@ -309,8 +309,6 @@ export interface AztecNode * array implies no logs match that tag. There can be multiple logs for 1 tag because tag reuse can happen * --> e.g. when sending a note from multiple unsynched devices. */ - getLogsByTags(tags: Fr[]): Promise; - getPrivateLogsByTags(tags: Fr[]): Promise; getPublicLogsByTags(tags: Fr[]): Promise; @@ -509,11 +507,6 @@ export const AztecNodeApiSchema: ApiSchemaFor = { getContractClassLogs: z.function().args(LogFilterSchema).returns(GetContractClassLogsResponseSchema), - getLogsByTags: z - .function() - .args(z.array(schemas.Fr)) - .returns(z.array(z.array(TxScopedL2Log.schema))), - getPrivateLogsByTags: z .function() .args(z.array(schemas.Fr)) diff --git a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts index 5fa4d937a7f3..1dd8c874d555 100644 --- a/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts +++ b/yarn-project/stdlib/src/logs/tx_scoped_l2_log.ts @@ -6,6 +6,7 @@ import { TxHash } from '../tx/tx_hash.js'; import { PrivateLog } from './private_log.js'; import { PublicLog } from './public_log.js'; +// TODO(#14460): Split to private and public versions instead of having this weird mix. export class TxScopedL2Log { constructor( /* From 71ad6d6a0eb50930b481be924c2f3155eba96edb Mon Sep 17 00:00:00 2001 From: benesjan Date: Thu, 22 May 2025 09:53:15 +0000 Subject: [PATCH 03/14] docs fixes --- .../aztec-nr/aztec/src/oracle/message_discovery.nr | 6 ++---- yarn-project/aztec-node/src/aztec-node/server.ts | 2 +- .../pxe_oracle_interface/pxe_oracle_interface.test.ts | 2 +- .../src/pxe_oracle_interface/pxe_oracle_interface.ts | 4 ++-- .../simulator/src/private/execution_data_provider.ts | 10 ++++++---- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr index 042efc82b7f2..9739c0d4e07b 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr @@ -60,10 +60,8 @@ pub struct PublicLogWithTxData { pub first_nullifier_in_tx: Field, } -/// Fetches a log from the node that has the corresponding `tag`. The log can be either a public or a private log, and -/// the tag is the first field in the log's content. Returns `Option::none` if no such log exists. Throws if more than -/// one log with that tag exists. -/// Public logs have an extra field included at the beginning with the address of the contract that emitted them. +/// Fetches a public log from the node that has the corresponding `tag`. The tag is the first field in the log's content. +/// Returns `Option::none` if no such log exists. Throws if more than one log with that tag exists. // TODO(#11627): handle multiple logs with the same tag. // TODO(#10273): improve contract siloing of logs, don't introduce an extra field. pub unconstrained fn get_public_log_by_tag(tag: Field) -> Option { diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 239fd1454638..262957c65b00 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -474,7 +474,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { public async getPublicLogsByTags(tags: Fr[]): Promise { const allLogs = await this.logsSource.getLogsByTags(tags); - // TODO(#14460): Have logSource implement getPrivateLogsByTags and skip the filter here. + // TODO(#14460): Have logSource implement getPublicLogsByTags and skip the filter here. return allLogs.map(logs => logs.filter(log => log.isFromPublic)); } diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts index 7ee57666a131..50a2283484b3 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts @@ -146,7 +146,7 @@ describe('PXEOracleInterface', () => { } // Accumulated logs intended for recipient: NUM_SENDERS + 1 + NUM_SENDERS / 2 - // Set up the getTaggedLogs mock + // Set up the getPrivateLogsByTags mock aztecNode.getPrivateLogsByTags.mockImplementation(tags => { return Promise.resolve(tags.map(tag => logs[tag.toString()] ?? [])); }); diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts index f5bc8ab094a5..be9bb95cda1b 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts @@ -429,8 +429,8 @@ export class PXEOracleInterface implements ExecutionDataProvider { } /** - * Synchronizes the logs tagged with scoped addresses and all the senders in the address book. Stores the found logs - * in CapsuleArray ready for a later retrieval in Aztec.nr. + * Synchronizes the private logs tagged with scoped addresses and all the senders in the address book. Stores the found + * logs in CapsuleArray ready for a later retrieval in Aztec.nr. * @param contractAddress - The address of the contract that the logs are tagged for. * @param pendingTaggedLogArrayBaseSlot - The base slot of the pending tagged logs capsule array in which * found logs will be stored. diff --git a/yarn-project/simulator/src/private/execution_data_provider.ts b/yarn-project/simulator/src/private/execution_data_provider.ts index c5f580f75ff8..cb1e5b2acce5 100644 --- a/yarn-project/simulator/src/private/execution_data_provider.ts +++ b/yarn-project/simulator/src/private/execution_data_provider.ts @@ -261,8 +261,8 @@ export interface ExecutionDataProvider { ): Promise; /** - * Synchronizes the logs tagged with scoped addresses and all the senders in the address book. Stores the found logs - * in CapsuleArray ready for a later retrieval in Aztec.nr. + * Synchronizes the private logs tagged with scoped addresses and all the senders in the address book. Stores the found + * logs in CapsuleArray ready for a later retrieval in Aztec.nr. * @param contractAddress - The address of the contract that the logs are tagged for. * @param pendingTaggedLogArrayBaseSlot - The base slot of the pending tagged log capsule array in which found logs will be stored. * @param scopes - The scoped addresses to sync logs for. If not provided, all accounts in the address book will be @@ -306,10 +306,12 @@ export interface ExecutionDataProvider { getNoteHash(leafIndex: bigint): Promise; /** - * Searches for a log with the corresponding `tag` and returns it along with contextual transaction information. - * Returns null if no such log exists, and throws if more than one exists. + * Searches for a public log with the corresponding `tag` and returns it along with contextual transaction + * information. * * @param tag - The log tag to search for. + * @returns The public log with transaction data if found, null otherwise. + * @throws If more than one log with that tag exists. */ getPublicLogByTag(tag: Fr): Promise; From a890caec46c0fa638c0ebb969a591127af52446d Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 23 May 2025 07:51:35 +0000 Subject: [PATCH 04/14] contract arg in get_public_log_by_tag --- .../src/messages/discovery/partial_notes.nr | 7 ++-- .../aztec/src/oracle/message_discovery.nr | 14 +++++--- .../aztec-node/src/aztec-node/server.ts | 11 +++--- .../pxe_oracle_interface.test.ts | 35 ++++++++++--------- .../pxe_oracle_interface.ts | 9 +++-- .../src/private/acvm/oracle/oracle.ts | 10 ++++-- .../src/private/acvm/oracle/typed_oracle.ts | 4 +-- .../src/private/execution_data_provider.ts | 3 +- .../src/private/utility_execution_oracle.ts | 7 ++-- .../stdlib/src/interfaces/aztec-node.test.ts | 6 ++-- .../stdlib/src/interfaces/aztec-node.ts | 18 +++++++--- .../stdlib/src/logs/log_with_tx_data.ts | 2 +- yarn-project/txe/src/oracle/txe_oracle.ts | 4 +-- .../txe/src/txe_service/txe_service.ts | 11 ++++-- 14 files changed, 92 insertions(+), 49 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr b/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr index d13c921c5703..875d49962f8a 100644 --- a/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr +++ b/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr @@ -4,7 +4,7 @@ use crate::{ discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery}, encoding::MAX_MESSAGE_CONTENT_LEN, }, - oracle::message_discovery::{deliver_note, get_public_log_by_tag}, + oracle::message_discovery::{deliver_note, get_public_log_by_tag_for_contract}, utils::array, }; @@ -93,7 +93,10 @@ pub unconstrained fn fetch_and_process_public_partial_note_completion_logs( ); pending_partial_notes.for_each(|i, pending_partial_note: DeliveredPendingPartialNote| { - let maybe_log = get_public_log_by_tag(pending_partial_note.note_completion_log_tag); + let maybe_log = get_public_log_by_tag_for_contract( + pending_partial_note.note_completion_log_tag, + contract_address, + ); if maybe_log.is_none() { debug_log_format( "Found no completion logs for partial note with tag {}", diff --git a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr index 9739c0d4e07b..2cce16de85b4 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr @@ -64,8 +64,11 @@ pub struct PublicLogWithTxData { /// Returns `Option::none` if no such log exists. Throws if more than one log with that tag exists. // TODO(#11627): handle multiple logs with the same tag. // TODO(#10273): improve contract siloing of logs, don't introduce an extra field. -pub unconstrained fn get_public_log_by_tag(tag: Field) -> Option { - get_public_log_by_tag_oracle(tag) +pub unconstrained fn get_public_log_by_tag_for_contract( + tag: Field, + contract_address: AztecAddress, +) -> Option { + get_public_log_by_tag_for_contract_oracle(tag, contract_address) } #[oracle(deliverNote)] @@ -80,5 +83,8 @@ unconstrained fn deliver_note_oracle( recipient: AztecAddress, ) -> bool {} -#[oracle(getPublicLogByTag)] -unconstrained fn get_public_log_by_tag_oracle(tag: Field) -> Option {} +#[oracle(getPublicLogByTagForContract)] +unconstrained fn get_public_log_by_tag_for_contract_oracle( + tag: Field, + contract_address: AztecAddress, +) -> Option {} diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 262957c65b00..7dc29bb76672 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -67,7 +67,7 @@ import { type WorldStateSynchronizer, tryStop, } from '@aztec/stdlib/interfaces/server'; -import type { LogFilter, PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs'; +import type { LogFilter, PrivateLog, PublicLog, TxScopedL2Log } from '@aztec/stdlib/logs'; import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging'; import { P2PClientType } from '@aztec/stdlib/p2p'; import type { NullifierLeafPreimage, PublicDataTreeLeaf, PublicDataTreeLeafPreimage } from '@aztec/stdlib/trees'; @@ -472,10 +472,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { return allLogs.map(logs => logs.filter(log => !log.isFromPublic)); } - public async getPublicLogsByTags(tags: Fr[]): Promise { + public async getPublicLogsByTagsForContract(tags: Fr[], contractAddress: AztecAddress): Promise { const allLogs = await this.logsSource.getLogsByTags(tags); - // TODO(#14460): Have logSource implement getPublicLogsByTags and skip the filter here. - return allLogs.map(logs => logs.filter(log => log.isFromPublic)); + // TODO(#14460): Have logSource implement getPublicLogsByTagsForContract and skip the filtering here. + const allPublicLogs = allLogs.map(logs => logs.filter(log => log.isFromPublic)); + return allPublicLogs.filter(logs => + logs.some(log => (log.log as PublicLog).contractAddress.equals(contractAddress)), + ); } /** diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts index 50a2283484b3..ab2f077b864c 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts @@ -612,56 +612,59 @@ describe('PXEOracleInterface', () => { }); }); - describe('getPublicLogByTag', () => { + describe('getPublicLogByTagForContract', () => { const tag = Fr.random(); beforeEach(() => { - aztecNode.getPublicLogsByTags.mockReset(); + aztecNode.getPublicLogsByTagsForContract.mockReset(); aztecNode.getTxEffect.mockReset(); }); it('returns null if no logs found for tag', async () => { - aztecNode.getPublicLogsByTags.mockResolvedValue([[]]); + aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[]]); - const result = await pxeOracleInterface.getPublicLogByTag(tag); + const result = await pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress); expect(result).toBeNull(); }); it('returns log data when single log found', async () => { const scopedLog = await TxScopedL2Log.random(true); + const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - aztecNode.getPublicLogsByTags.mockResolvedValue([[scopedLog]]); + aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLog]]); const indexedTxEffect = await randomIndexedTxEffect(); aztecNode.getTxEffect.mockImplementation((txHash: TxHash) => txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), ); - const result = (await pxeOracleInterface.getPublicLogByTag(tag))!; + const result = (await pxeOracleInterface.getPublicLogByTagForContract(tag, logContractAddress))!; - expect(result.logContent).toEqual( - [(scopedLog.log as PublicLog).contractAddress.toField()].concat(scopedLog.log.getEmittedFields()), - ); + expect(result.logContent).toEqual([logContractAddress.toField()].concat(scopedLog.log.getEmittedFields())); expect(result.uniqueNoteHashesInTx).toEqual(indexedTxEffect.data.noteHashes); expect(result.txHash).toEqual(scopedLog.txHash); expect(result.firstNullifierInTx).toEqual(indexedTxEffect.data.nullifiers[0]); - expect(aztecNode.getPublicLogsByTags).toHaveBeenCalledWith([tag]); + expect(aztecNode.getPublicLogsByTagsForContract).toHaveBeenCalledWith([tag], logContractAddress); expect(aztecNode.getTxEffect).toHaveBeenCalledWith(scopedLog.txHash); }); it('throws if multiple logs found for tag', async () => { const scopedLog = await TxScopedL2Log.random(true); - aztecNode.getPublicLogsByTags.mockResolvedValue([[scopedLog, scopedLog]]); + aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLog, scopedLog]]); - await expect(pxeOracleInterface.getPublicLogByTag(tag)).rejects.toThrow(/Got 2 logs for tag/); + await expect(pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress)).rejects.toThrow( + /Got 2 logs for tag/, + ); }); it('throws if tx effect not found', async () => { const scopedLog = await TxScopedL2Log.random(true); - aztecNode.getPublicLogsByTags.mockResolvedValue([[scopedLog]]); + aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLog]]); aztecNode.getTxEffect.mockResolvedValue(undefined); - await expect(pxeOracleInterface.getPublicLogByTag(tag)).rejects.toThrow(/failed to retrieve tx effects/); + await expect(pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress)).rejects.toThrow( + /failed to retrieve tx effects/, + ); }); it('returns log fields that are actually emitted', async () => { @@ -680,10 +683,10 @@ describe('PXEOracleInterface', () => { log, ); - aztecNode.getPublicLogsByTags.mockResolvedValue([[scopedLogWithPadding]]); + aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLogWithPadding]]); aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); - const result = await pxeOracleInterface.getPublicLogByTag(tag); + const result = await pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress); expect(result?.logContent).toEqual([log.contractAddress.toField(), ...logContent]); }); diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts index be9bb95cda1b..aef728b9f4a8 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts @@ -694,8 +694,11 @@ export class PXEOracleInterface implements ExecutionDataProvider { } } - public async getPublicLogByTag(tag: Fr): Promise { - const logs = await this.aztecNode.getPublicLogsByTags([tag]); + public async getPublicLogByTagForContract( + tag: Fr, + contractAddress: AztecAddress, + ): Promise { + const logs = await this.aztecNode.getPublicLogsByTagsForContract([tag], contractAddress); const logsForTag = logs[0]; this.log.debug(`Got ${logsForTag.length} logs for tag ${tag}`); @@ -705,7 +708,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { } else if (logsForTag.length > 1) { // TODO(#11627): handle this case throw new Error( - `Got ${logsForTag.length} logs for tag ${tag}. getPublicLogByTag currently only supports a single log per tag`, + `Got ${logsForTag.length} logs for tag ${tag} and contract ${contractAddress.toString()}. getPublicLogByTagForContract currently only supports a single log per tag`, ); } diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index 440ac4f16abc..96eec32d1047 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts @@ -412,8 +412,14 @@ export class Oracle { return [toACVMField(true)]; } - async getPublicLogByTag([tag]: ACVMField[]): Promise<(ACVMField | ACVMField[])[]> { - const log = await this.typedOracle.getPublicLogByTag(Fr.fromString(tag)); + async getPublicLogByTagForContract( + [tag]: ACVMField[], + [contractAddress]: ACVMField[], + ): Promise<(ACVMField | ACVMField[])[]> { + const log = await this.typedOracle.getPublicLogByTagForContract( + Fr.fromString(tag), + AztecAddress.fromString(contractAddress), + ); if (log == null) { return [toACVMField(0), ...PublicLogWithTxData.noirSerializationOfEmpty().map(toACVMFieldSingleOrArray)]; diff --git a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts index c65cdf0f2498..f50a6fd23be9 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts @@ -231,8 +231,8 @@ export abstract class TypedOracle { return Promise.reject(new OracleMethodNotAvailableError('deliverNote')); } - getPublicLogByTag(_tag: Fr): Promise { - throw new OracleMethodNotAvailableError('getPublicLogByTag'); + getPublicLogByTagForContract(_tag: Fr, _contractAddress: AztecAddress): Promise { + throw new OracleMethodNotAvailableError('getPublicLogByTagForContract'); } storeCapsule(_contractAddress: AztecAddress, _key: Fr, _capsule: Fr[]): Promise { diff --git a/yarn-project/simulator/src/private/execution_data_provider.ts b/yarn-project/simulator/src/private/execution_data_provider.ts index cb1e5b2acce5..e74e4e06662b 100644 --- a/yarn-project/simulator/src/private/execution_data_provider.ts +++ b/yarn-project/simulator/src/private/execution_data_provider.ts @@ -310,10 +310,11 @@ export interface ExecutionDataProvider { * information. * * @param tag - The log tag to search for. + * @param contractAddress - The contract address to search for the log in. * @returns The public log with transaction data if found, null otherwise. * @throws If more than one log with that tag exists. */ - getPublicLogByTag(tag: Fr): Promise; + getPublicLogByTagForContract(tag: Fr, contractAddress: AztecAddress): Promise; /** * Removes all of a contract's notes that have been nullified from the note database. diff --git a/yarn-project/simulator/src/private/utility_execution_oracle.ts b/yarn-project/simulator/src/private/utility_execution_oracle.ts index a6d9924c6476..1ffe2eddba07 100644 --- a/yarn-project/simulator/src/private/utility_execution_oracle.ts +++ b/yarn-project/simulator/src/private/utility_execution_oracle.ts @@ -307,8 +307,11 @@ export class UtilityExecutionOracle extends TypedOracle { ); } - public override getPublicLogByTag(tag: Fr): Promise { - return this.executionDataProvider.getPublicLogByTag(tag); + public override getPublicLogByTagForContract( + tag: Fr, + contractAddress: AztecAddress, + ): Promise { + return this.executionDataProvider.getPublicLogByTagForContract(tag, contractAddress); } public override storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise { diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts index fe789d2c894c..68008d712416 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts @@ -248,8 +248,8 @@ describe('AztecNodeApiSchema', () => { expect(response).toEqual([[expect.any(TxScopedL2Log)]]); }); - it('getPublicLogsByTags', async () => { - const response = await context.client.getPublicLogsByTags([Fr.random()]); + it('getPublicLogsByTagsForContract', async () => { + const response = await context.client.getPublicLogsByTagsForContract([Fr.random()], await AztecAddress.random()); expect(response).toEqual([[expect.any(TxScopedL2Log)]]); }); @@ -587,7 +587,7 @@ class MockAztecNode implements AztecNode { expect(tags[0]).toBeInstanceOf(Fr); return [[await TxScopedL2Log.random(false)]]; } - async getPublicLogsByTags(tags: Fr[]): Promise { + async getPublicLogsByTagsForContract(tags: Fr[]): Promise { expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(Fr); return [[await TxScopedL2Log.random(true)]]; diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.ts b/yarn-project/stdlib/src/interfaces/aztec-node.ts index 834e4aa6c657..dc73680ef4b9 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.ts @@ -303,14 +303,24 @@ export interface AztecNode getContractClassLogs(filter: LogFilter): Promise; /** - * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag). + * Gets all private logs that match any of the received tags (i.e. logs with their first field equal to a tag). * @param tags - The tags to filter the logs by. * @returns For each received tag, an array of matching logs and metadata (e.g. tx hash) is returned. An empty * array implies no logs match that tag. There can be multiple logs for 1 tag because tag reuse can happen * --> e.g. when sending a note from multiple unsynched devices. */ getPrivateLogsByTags(tags: Fr[]): Promise; - getPublicLogsByTags(tags: Fr[]): Promise; + + /** + * Gets all public logs that match any of the received tags (i.e. logs with their first field equal to a tag) for + * a given contract. + * @param tags - The tags to filter the logs by. + * @param contractAddress - The address of the contract to filter the logs by. + * @returns For each received tag, an array of matching logs and metadata (e.g. tx hash) is returned. An empty + * array implies no logs match that tag. There can be multiple logs for 1 tag because tag reuse can happen + * --> e.g. when sending a note from multiple unsynched devices. + */ + getPublicLogsByTagsForContract(tags: Fr[], contractAddress: AztecAddress): Promise; /** * Method to submit a transaction to the p2p pool. @@ -512,9 +522,9 @@ export const AztecNodeApiSchema: ApiSchemaFor = { .args(z.array(schemas.Fr)) .returns(z.array(z.array(TxScopedL2Log.schema))), - getPublicLogsByTags: z + getPublicLogsByTagsForContract: z .function() - .args(z.array(schemas.Fr)) + .args(z.array(schemas.Fr), schemas.AztecAddress) .returns(z.array(z.array(TxScopedL2Log.schema))), sendTx: z.function().args(Tx.schema).returns(z.void()), diff --git a/yarn-project/stdlib/src/logs/log_with_tx_data.ts b/yarn-project/stdlib/src/logs/log_with_tx_data.ts index b5fa2e15f948..be1652a540a1 100644 --- a/yarn-project/stdlib/src/logs/log_with_tx_data.ts +++ b/yarn-project/stdlib/src/logs/log_with_tx_data.ts @@ -3,7 +3,7 @@ import { Fr } from '@aztec/foundation/fields'; import { TxHash } from '@aztec/stdlib/tx'; // TypeScript representation of the Noir aztec::oracle::message_discovery::PublicLogWithTxData struct. This is used as a -// response for PXE's custom getPublicLogByTag oracle. +// response for PXE's custom getPublicLogByTagForContract oracle. export class PublicLogWithTxData { constructor( // The emitted fields of a log. diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 3b8fea1ba4c9..cc5bc8403690 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -1197,8 +1197,8 @@ export class TXE implements TypedOracle { ); } - async getPublicLogByTag(tag: Fr): Promise { - return await this.pxeOracleInterface.getPublicLogByTag(tag); + async getPublicLogByTagForContract(tag: Fr, contractAddress: AztecAddress): Promise { + return await this.pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress); } // AVM oracles diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 35167a16b2fc..5cb51e47906c 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -731,15 +731,20 @@ export class TXEService { return toForeignCallResult([toSingle(Fr.ONE)]); } - async getPublicLogByTag(tag: ForeignCallSingle) { + async getPublicLogByTagForContract(tag: ForeignCallSingle, contractAddress: ForeignCallSingle) { if (!this.oraclesEnabled) { throw new Error( 'Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.', ); } - // TODO(AD): this was warning that getPublicLogByTag did not return a promise. - const log = await Promise.resolve(this.typedOracle.getPublicLogByTag(fromSingle(tag))); + // TODO(AD): this was warning that getPublicLogByTagForContract did not return a promise. + const log = await Promise.resolve( + this.typedOracle.getPublicLogByTagForContract( + fromSingle(tag), + AztecAddress.fromField(fromSingle(contractAddress)), + ), + ); if (log == null) { return toForeignCallResult([ From 5061c5ea4a7fcab497df28e77456a5459ce583f8 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 23 May 2025 10:07:02 +0000 Subject: [PATCH 05/14] fix --- yarn-project/aztec-node/src/aztec-node/server.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 7dc29bb76672..915d136e60f1 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -476,8 +476,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { const allLogs = await this.logsSource.getLogsByTags(tags); // TODO(#14460): Have logSource implement getPublicLogsByTagsForContract and skip the filtering here. const allPublicLogs = allLogs.map(logs => logs.filter(log => log.isFromPublic)); - return allPublicLogs.filter(logs => - logs.some(log => (log.log as PublicLog).contractAddress.equals(contractAddress)), + return allPublicLogs.map(logs => + logs.filter(log => (log.log as PublicLog).contractAddress.equals(contractAddress)), ); } From 7ab61b29820f6884654e4f7d8a51a0bd151db80b Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 23 May 2025 13:40:15 +0000 Subject: [PATCH 06/14] getPublicLogByTagForContract --> getPublicLogByTagFromContract --- .../aztec/src/messages/discovery/partial_notes.nr | 4 ++-- .../aztec-nr/aztec/src/oracle/message_discovery.nr | 8 ++++---- .../pxe_oracle_interface.test.ts | 12 ++++++------ .../src/pxe_oracle_interface/pxe_oracle_interface.ts | 4 ++-- .../simulator/src/private/acvm/oracle/oracle.ts | 4 ++-- .../src/private/acvm/oracle/typed_oracle.ts | 4 ++-- .../simulator/src/private/execution_data_provider.ts | 2 +- .../src/private/utility_execution_oracle.ts | 4 ++-- yarn-project/stdlib/src/logs/log_with_tx_data.ts | 2 +- yarn-project/txe/src/oracle/txe_oracle.ts | 4 ++-- yarn-project/txe/src/txe_service/txe_service.ts | 6 +++--- 11 files changed, 27 insertions(+), 27 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr b/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr index 875d49962f8a..35aedf09331a 100644 --- a/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr +++ b/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr @@ -4,7 +4,7 @@ use crate::{ discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery}, encoding::MAX_MESSAGE_CONTENT_LEN, }, - oracle::message_discovery::{deliver_note, get_public_log_by_tag_for_contract}, + oracle::message_discovery::{deliver_note, get_public_log_by_tag_from_contract}, utils::array, }; @@ -93,7 +93,7 @@ pub unconstrained fn fetch_and_process_public_partial_note_completion_logs( ); pending_partial_notes.for_each(|i, pending_partial_note: DeliveredPendingPartialNote| { - let maybe_log = get_public_log_by_tag_for_contract( + let maybe_log = get_public_log_by_tag_from_contract( pending_partial_note.note_completion_log_tag, contract_address, ); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr index 2cce16de85b4..886f5562db6f 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr @@ -64,11 +64,11 @@ pub struct PublicLogWithTxData { /// Returns `Option::none` if no such log exists. Throws if more than one log with that tag exists. // TODO(#11627): handle multiple logs with the same tag. // TODO(#10273): improve contract siloing of logs, don't introduce an extra field. -pub unconstrained fn get_public_log_by_tag_for_contract( +pub unconstrained fn get_public_log_by_tag_from_contract( tag: Field, contract_address: AztecAddress, ) -> Option { - get_public_log_by_tag_for_contract_oracle(tag, contract_address) + get_public_log_by_tag_from_contract_oracle(tag, contract_address) } #[oracle(deliverNote)] @@ -83,8 +83,8 @@ unconstrained fn deliver_note_oracle( recipient: AztecAddress, ) -> bool {} -#[oracle(getPublicLogByTagForContract)] -unconstrained fn get_public_log_by_tag_for_contract_oracle( +#[oracle(getPublicLogByTagFromContract)] +unconstrained fn get_public_log_by_tag_from_contract_oracle( tag: Field, contract_address: AztecAddress, ) -> Option {} diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts index ab2f077b864c..af36bc795367 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts @@ -612,7 +612,7 @@ describe('PXEOracleInterface', () => { }); }); - describe('getPublicLogByTagForContract', () => { + describe('getPublicLogByTagFromContract', () => { const tag = Fr.random(); beforeEach(() => { @@ -623,7 +623,7 @@ describe('PXEOracleInterface', () => { it('returns null if no logs found for tag', async () => { aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[]]); - const result = await pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress); + const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); expect(result).toBeNull(); }); @@ -637,7 +637,7 @@ describe('PXEOracleInterface', () => { txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), ); - const result = (await pxeOracleInterface.getPublicLogByTagForContract(tag, logContractAddress))!; + const result = (await pxeOracleInterface.getPublicLogByTagFromContract(tag, logContractAddress))!; expect(result.logContent).toEqual([logContractAddress.toField()].concat(scopedLog.log.getEmittedFields())); expect(result.uniqueNoteHashesInTx).toEqual(indexedTxEffect.data.noteHashes); @@ -652,7 +652,7 @@ describe('PXEOracleInterface', () => { const scopedLog = await TxScopedL2Log.random(true); aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLog, scopedLog]]); - await expect(pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress)).rejects.toThrow( + await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress)).rejects.toThrow( /Got 2 logs for tag/, ); }); @@ -662,7 +662,7 @@ describe('PXEOracleInterface', () => { aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLog]]); aztecNode.getTxEffect.mockResolvedValue(undefined); - await expect(pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress)).rejects.toThrow( + await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress)).rejects.toThrow( /failed to retrieve tx effects/, ); }); @@ -686,7 +686,7 @@ describe('PXEOracleInterface', () => { aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLogWithPadding]]); aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); - const result = await pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress); + const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); expect(result?.logContent).toEqual([log.contractAddress.toField(), ...logContent]); }); diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts index aef728b9f4a8..15590cf3397d 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts @@ -694,7 +694,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { } } - public async getPublicLogByTagForContract( + public async getPublicLogByTagFromContract( tag: Fr, contractAddress: AztecAddress, ): Promise { @@ -708,7 +708,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { } else if (logsForTag.length > 1) { // TODO(#11627): handle this case throw new Error( - `Got ${logsForTag.length} logs for tag ${tag} and contract ${contractAddress.toString()}. getPublicLogByTagForContract currently only supports a single log per tag`, + `Got ${logsForTag.length} logs for tag ${tag} and contract ${contractAddress.toString()}. getPublicLogByTagFromContract currently only supports a single log per tag`, ); } diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index 96eec32d1047..815821ed94dc 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts @@ -412,11 +412,11 @@ export class Oracle { return [toACVMField(true)]; } - async getPublicLogByTagForContract( + async getPublicLogByTagFromContract( [tag]: ACVMField[], [contractAddress]: ACVMField[], ): Promise<(ACVMField | ACVMField[])[]> { - const log = await this.typedOracle.getPublicLogByTagForContract( + const log = await this.typedOracle.getPublicLogByTagFromContract( Fr.fromString(tag), AztecAddress.fromString(contractAddress), ); diff --git a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts index f50a6fd23be9..fbac85a1e866 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts @@ -231,8 +231,8 @@ export abstract class TypedOracle { return Promise.reject(new OracleMethodNotAvailableError('deliverNote')); } - getPublicLogByTagForContract(_tag: Fr, _contractAddress: AztecAddress): Promise { - throw new OracleMethodNotAvailableError('getPublicLogByTagForContract'); + getPublicLogByTagFromContract(_tag: Fr, _contractAddress: AztecAddress): Promise { + throw new OracleMethodNotAvailableError('getPublicLogByTagFromContract'); } storeCapsule(_contractAddress: AztecAddress, _key: Fr, _capsule: Fr[]): Promise { diff --git a/yarn-project/simulator/src/private/execution_data_provider.ts b/yarn-project/simulator/src/private/execution_data_provider.ts index e74e4e06662b..bcc535d9b825 100644 --- a/yarn-project/simulator/src/private/execution_data_provider.ts +++ b/yarn-project/simulator/src/private/execution_data_provider.ts @@ -314,7 +314,7 @@ export interface ExecutionDataProvider { * @returns The public log with transaction data if found, null otherwise. * @throws If more than one log with that tag exists. */ - getPublicLogByTagForContract(tag: Fr, contractAddress: AztecAddress): Promise; + getPublicLogByTagFromContract(tag: Fr, contractAddress: AztecAddress): Promise; /** * Removes all of a contract's notes that have been nullified from the note database. diff --git a/yarn-project/simulator/src/private/utility_execution_oracle.ts b/yarn-project/simulator/src/private/utility_execution_oracle.ts index 1ffe2eddba07..5b219daa2b9d 100644 --- a/yarn-project/simulator/src/private/utility_execution_oracle.ts +++ b/yarn-project/simulator/src/private/utility_execution_oracle.ts @@ -307,11 +307,11 @@ export class UtilityExecutionOracle extends TypedOracle { ); } - public override getPublicLogByTagForContract( + public override getPublicLogByTagFromContract( tag: Fr, contractAddress: AztecAddress, ): Promise { - return this.executionDataProvider.getPublicLogByTagForContract(tag, contractAddress); + return this.executionDataProvider.getPublicLogByTagFromContract(tag, contractAddress); } public override storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise { diff --git a/yarn-project/stdlib/src/logs/log_with_tx_data.ts b/yarn-project/stdlib/src/logs/log_with_tx_data.ts index be1652a540a1..b7cebcc56a4b 100644 --- a/yarn-project/stdlib/src/logs/log_with_tx_data.ts +++ b/yarn-project/stdlib/src/logs/log_with_tx_data.ts @@ -3,7 +3,7 @@ import { Fr } from '@aztec/foundation/fields'; import { TxHash } from '@aztec/stdlib/tx'; // TypeScript representation of the Noir aztec::oracle::message_discovery::PublicLogWithTxData struct. This is used as a -// response for PXE's custom getPublicLogByTagForContract oracle. +// response for PXE's custom getPublicLogByTagFromContract oracle. export class PublicLogWithTxData { constructor( // The emitted fields of a log. diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index cc5bc8403690..5ff4c5fd839e 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -1197,8 +1197,8 @@ export class TXE implements TypedOracle { ); } - async getPublicLogByTagForContract(tag: Fr, contractAddress: AztecAddress): Promise { - return await this.pxeOracleInterface.getPublicLogByTagForContract(tag, contractAddress); + async getPublicLogByTagFromContract(tag: Fr, contractAddress: AztecAddress): Promise { + return await this.pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); } // AVM oracles diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 5cb51e47906c..834d7a5a9fe0 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -731,16 +731,16 @@ export class TXEService { return toForeignCallResult([toSingle(Fr.ONE)]); } - async getPublicLogByTagForContract(tag: ForeignCallSingle, contractAddress: ForeignCallSingle) { + async getPublicLogByTagFromContract(tag: ForeignCallSingle, contractAddress: ForeignCallSingle) { if (!this.oraclesEnabled) { throw new Error( 'Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.', ); } - // TODO(AD): this was warning that getPublicLogByTagForContract did not return a promise. + // TODO(AD): this was warning that getPublicLogByTagFromContract did not return a promise. const log = await Promise.resolve( - this.typedOracle.getPublicLogByTagForContract( + this.typedOracle.getPublicLogByTagFromContract( fromSingle(tag), AztecAddress.fromField(fromSingle(contractAddress)), ), From 2ae1d68f28bb14edf6344bb0a2dc21a63e9476d5 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 23 May 2025 14:08:56 +0000 Subject: [PATCH 07/14] getPublicLogsByTagsForContract --> getPublicLogsByTagsFromContract --- yarn-project/aztec-node/src/aztec-node/server.ts | 4 ++-- .../pxe_oracle_interface.test.ts | 14 +++++++------- .../pxe_oracle_interface/pxe_oracle_interface.ts | 2 +- .../stdlib/src/interfaces/aztec-node.test.ts | 6 +++--- yarn-project/stdlib/src/interfaces/aztec-node.ts | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 915d136e60f1..d7f11de41046 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -472,9 +472,9 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { return allLogs.map(logs => logs.filter(log => !log.isFromPublic)); } - public async getPublicLogsByTagsForContract(tags: Fr[], contractAddress: AztecAddress): Promise { + public async getPublicLogsByTagsFromContract(tags: Fr[], contractAddress: AztecAddress): Promise { const allLogs = await this.logsSource.getLogsByTags(tags); - // TODO(#14460): Have logSource implement getPublicLogsByTagsForContract and skip the filtering here. + // TODO(#14460): Have logSource implement getPublicLogsByTagsFromContract and skip the filtering here. const allPublicLogs = allLogs.map(logs => logs.filter(log => log.isFromPublic)); return allPublicLogs.map(logs => logs.filter(log => (log.log as PublicLog).contractAddress.equals(contractAddress)), diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts index af36bc795367..e001dc6992c5 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts @@ -616,12 +616,12 @@ describe('PXEOracleInterface', () => { const tag = Fr.random(); beforeEach(() => { - aztecNode.getPublicLogsByTagsForContract.mockReset(); + aztecNode.getPublicLogsByTagsFromContract.mockReset(); aztecNode.getTxEffect.mockReset(); }); it('returns null if no logs found for tag', async () => { - aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[]]); + aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[]]); const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); expect(result).toBeNull(); @@ -631,7 +631,7 @@ describe('PXEOracleInterface', () => { const scopedLog = await TxScopedL2Log.random(true); const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLog]]); + aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); const indexedTxEffect = await randomIndexedTxEffect(); aztecNode.getTxEffect.mockImplementation((txHash: TxHash) => txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), @@ -644,13 +644,13 @@ describe('PXEOracleInterface', () => { expect(result.txHash).toEqual(scopedLog.txHash); expect(result.firstNullifierInTx).toEqual(indexedTxEffect.data.nullifiers[0]); - expect(aztecNode.getPublicLogsByTagsForContract).toHaveBeenCalledWith([tag], logContractAddress); + expect(aztecNode.getPublicLogsByTagsFromContract).toHaveBeenCalledWith([tag], logContractAddress); expect(aztecNode.getTxEffect).toHaveBeenCalledWith(scopedLog.txHash); }); it('throws if multiple logs found for tag', async () => { const scopedLog = await TxScopedL2Log.random(true); - aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLog, scopedLog]]); + aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog, scopedLog]]); await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress)).rejects.toThrow( /Got 2 logs for tag/, @@ -659,7 +659,7 @@ describe('PXEOracleInterface', () => { it('throws if tx effect not found', async () => { const scopedLog = await TxScopedL2Log.random(true); - aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLog]]); + aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); aztecNode.getTxEffect.mockResolvedValue(undefined); await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress)).rejects.toThrow( @@ -683,7 +683,7 @@ describe('PXEOracleInterface', () => { log, ); - aztecNode.getPublicLogsByTagsForContract.mockResolvedValue([[scopedLogWithPadding]]); + aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLogWithPadding]]); aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts index 15590cf3397d..2bcef23f246b 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts @@ -698,7 +698,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { tag: Fr, contractAddress: AztecAddress, ): Promise { - const logs = await this.aztecNode.getPublicLogsByTagsForContract([tag], contractAddress); + const logs = await this.aztecNode.getPublicLogsByTagsFromContract([tag], contractAddress); const logsForTag = logs[0]; this.log.debug(`Got ${logsForTag.length} logs for tag ${tag}`); diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts index 68008d712416..632dfc1ca7a2 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts @@ -248,8 +248,8 @@ describe('AztecNodeApiSchema', () => { expect(response).toEqual([[expect.any(TxScopedL2Log)]]); }); - it('getPublicLogsByTagsForContract', async () => { - const response = await context.client.getPublicLogsByTagsForContract([Fr.random()], await AztecAddress.random()); + it('getPublicLogsByTagsFromContract', async () => { + const response = await context.client.getPublicLogsByTagsFromContract([Fr.random()], await AztecAddress.random()); expect(response).toEqual([[expect.any(TxScopedL2Log)]]); }); @@ -587,7 +587,7 @@ class MockAztecNode implements AztecNode { expect(tags[0]).toBeInstanceOf(Fr); return [[await TxScopedL2Log.random(false)]]; } - async getPublicLogsByTagsForContract(tags: Fr[]): Promise { + async getPublicLogsByTagsFromContract(tags: Fr[]): Promise { expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(Fr); return [[await TxScopedL2Log.random(true)]]; diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.ts b/yarn-project/stdlib/src/interfaces/aztec-node.ts index dc73680ef4b9..f9a6a68f2fc9 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.ts @@ -320,7 +320,7 @@ export interface AztecNode * array implies no logs match that tag. There can be multiple logs for 1 tag because tag reuse can happen * --> e.g. when sending a note from multiple unsynched devices. */ - getPublicLogsByTagsForContract(tags: Fr[], contractAddress: AztecAddress): Promise; + getPublicLogsByTagsFromContract(tags: Fr[], contractAddress: AztecAddress): Promise; /** * Method to submit a transaction to the p2p pool. @@ -522,7 +522,7 @@ export const AztecNodeApiSchema: ApiSchemaFor = { .args(z.array(schemas.Fr)) .returns(z.array(z.array(TxScopedL2Log.schema))), - getPublicLogsByTagsForContract: z + getPublicLogsByTagsFromContract: z .function() .args(z.array(schemas.Fr), schemas.AztecAddress) .returns(z.array(z.array(TxScopedL2Log.schema))), From dc809953a68fe6b08e87b4783dfbcd98f2453746 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 23 May 2025 14:48:48 +0000 Subject: [PATCH 08/14] reverting changes to AztecNode --- .../aztec-node/src/aztec-node/server.ts | 21 ++++------ .../pxe_oracle_interface.test.ts | 40 +++++++++---------- .../pxe_oracle_interface.ts | 23 +++++++++-- .../stdlib/src/interfaces/aztec-node.test.ts | 18 ++------- .../stdlib/src/interfaces/aztec-node.ts | 22 ++-------- 5 files changed, 55 insertions(+), 69 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index d7f11de41046..0ffc5c8d2986 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -466,19 +466,14 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { return this.logsSource.getPrivateLogs(from, limit); } - public async getPrivateLogsByTags(tags: Fr[]): Promise { - const allLogs = await this.logsSource.getLogsByTags(tags); - // TODO(#14460): Have logSource implement getPrivateLogsByTags and skip the filter here. - return allLogs.map(logs => logs.filter(log => !log.isFromPublic)); - } - - public async getPublicLogsByTagsFromContract(tags: Fr[], contractAddress: AztecAddress): Promise { - const allLogs = await this.logsSource.getLogsByTags(tags); - // TODO(#14460): Have logSource implement getPublicLogsByTagsFromContract and skip the filtering here. - const allPublicLogs = allLogs.map(logs => logs.filter(log => log.isFromPublic)); - return allPublicLogs.map(logs => - logs.filter(log => (log.log as PublicLog).contractAddress.equals(contractAddress)), - ); + /** + * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag). + * @param tags - The tags to filter the logs by. + * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match + * that tag. + */ + public getLogsByTags(tags: Fr[]): Promise { + return this.logsSource.getLogsByTags(tags); } /** diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts index e001dc6992c5..f842c8c3df6e 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts @@ -147,7 +147,7 @@ describe('PXEOracleInterface', () => { // Accumulated logs intended for recipient: NUM_SENDERS + 1 + NUM_SENDERS / 2 // Set up the getPrivateLogsByTags mock - aztecNode.getPrivateLogsByTags.mockImplementation(tags => { + aztecNode.getLogsByTags.mockImplementation(tags => { return Promise.resolve(tags.map(tag => logs[tag.toString()] ?? [])); }); } @@ -167,7 +167,7 @@ describe('PXEOracleInterface', () => { for (const sender of senders) { await taggingDataProvider.addSenderAddress(sender.completeAddress.address); } - aztecNode.getPrivateLogsByTags.mockReset(); + aztecNode.getLogsByTags.mockReset(); aztecNode.getTxEffect.mockResolvedValue({ ...randomInBlock(await TxEffect.random()), txIndexInBlock: 0, @@ -202,7 +202,7 @@ describe('PXEOracleInterface', () => { // We should have called the node 2 times: // 2 times: first time during initial request, second time after pushing the edge of the window once - expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(2); + expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2); }); it('should sync tagged logs as senders', async () => { @@ -236,7 +236,7 @@ describe('PXEOracleInterface', () => { const indexesAsSender = await getTaggingSecretsIndexesAsSenderForSenders(); expect(indexesAsSender).toStrictEqual([[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]); - expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(0); + expect(aztecNode.getLogsByTags.mock.calls.length).toBe(0); for (let i = 0; i < senders.length; i++) { await pxeOracleInterface.syncTaggedLogsAsSender( @@ -250,8 +250,8 @@ describe('PXEOracleInterface', () => { expect(indexesAsSenderAfterSync).toStrictEqual([[1], [1], [1], [1], [1], [2], [2], [2], [2], [2]]); // Only 1 window is obtained for each sender - expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(NUM_SENDERS); - aztecNode.getPrivateLogsByTags.mockReset(); + expect(aztecNode.getLogsByTags.mock.calls.length).toBe(NUM_SENDERS); + aztecNode.getLogsByTags.mockReset(); // We add more logs to the second half of the window to test that a second iteration in `syncTaggedLogsAsSender` // is handled correctly. @@ -268,7 +268,7 @@ describe('PXEOracleInterface', () => { indexesAsSenderAfterSync = await getTaggingSecretsIndexesAsSenderForSenders(); expect(indexesAsSenderAfterSync).toStrictEqual([[12], [12], [12], [12], [12], [13], [13], [13], [13], [13]]); - expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(NUM_SENDERS * 2); + expect(aztecNode.getLogsByTags.mock.calls.length).toBe(NUM_SENDERS * 2); }); it('should sync tagged logs with a sender index offset', async () => { @@ -298,7 +298,7 @@ describe('PXEOracleInterface', () => { // We should have called the node 2 times: // 2 times: first time during initial request, second time after pushing the edge of the window once - expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(2); + expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2); }); it("should sync tagged logs for which indexes are not updated if they're inside the window", async () => { @@ -335,7 +335,7 @@ describe('PXEOracleInterface', () => { // We should have called the node 2 times: // first time during initial request, second time after pushing the edge of the window once - expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(2); + expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2); }); it("should not sync tagged logs for which indexes are not updated if they're outside the window", async () => { @@ -371,7 +371,7 @@ describe('PXEOracleInterface', () => { expect(indexes).toEqual([index, index, index, index, index, index, index, index, index, index]); // We should have called the node once and that is only for the first window - expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(1); + expect(aztecNode.getLogsByTags.mock.calls.length).toBe(1); }); it('should sync tagged logs from scratch after a DB wipe', async () => { @@ -398,9 +398,9 @@ describe('PXEOracleInterface', () => { // Since no logs were synced, window edge hash not been pushed and for this reason we should have called // the node only once for the initial window - expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(1); + expect(aztecNode.getLogsByTags.mock.calls.length).toBe(1); - aztecNode.getPrivateLogsByTags.mockClear(); + aztecNode.getLogsByTags.mockClear(); // Wipe the database await taggingDataProvider.resetNoteSyncData(); @@ -417,7 +417,7 @@ describe('PXEOracleInterface', () => { // We should have called the node 2 times: // first time during initial request, second time after pushing the edge of the window once - expect(aztecNode.getPrivateLogsByTags.mock.calls.length).toBe(2); + expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2); }); it('should not sync tagged logs with a blockNumber larger than the block number to which PXE is synced', async () => { @@ -616,12 +616,12 @@ describe('PXEOracleInterface', () => { const tag = Fr.random(); beforeEach(() => { - aztecNode.getPublicLogsByTagsFromContract.mockReset(); + aztecNode.getLogsByTags.mockReset(); aztecNode.getTxEffect.mockReset(); }); it('returns null if no logs found for tag', async () => { - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[]]); + aztecNode.getLogsByTags.mockResolvedValue([[]]); const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); expect(result).toBeNull(); @@ -631,7 +631,7 @@ describe('PXEOracleInterface', () => { const scopedLog = await TxScopedL2Log.random(true); const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); + aztecNode.getLogsByTags.mockResolvedValue([[scopedLog]]); const indexedTxEffect = await randomIndexedTxEffect(); aztecNode.getTxEffect.mockImplementation((txHash: TxHash) => txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), @@ -644,13 +644,13 @@ describe('PXEOracleInterface', () => { expect(result.txHash).toEqual(scopedLog.txHash); expect(result.firstNullifierInTx).toEqual(indexedTxEffect.data.nullifiers[0]); - expect(aztecNode.getPublicLogsByTagsFromContract).toHaveBeenCalledWith([tag], logContractAddress); + expect(aztecNode.getLogsByTags).toHaveBeenCalledWith([tag]); expect(aztecNode.getTxEffect).toHaveBeenCalledWith(scopedLog.txHash); }); it('throws if multiple logs found for tag', async () => { const scopedLog = await TxScopedL2Log.random(true); - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog, scopedLog]]); + aztecNode.getLogsByTags.mockResolvedValue([[scopedLog, scopedLog]]); await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress)).rejects.toThrow( /Got 2 logs for tag/, @@ -659,7 +659,7 @@ describe('PXEOracleInterface', () => { it('throws if tx effect not found', async () => { const scopedLog = await TxScopedL2Log.random(true); - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLog]]); + aztecNode.getLogsByTags.mockResolvedValue([[scopedLog]]); aztecNode.getTxEffect.mockResolvedValue(undefined); await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress)).rejects.toThrow( @@ -683,7 +683,7 @@ describe('PXEOracleInterface', () => { log, ); - aztecNode.getPublicLogsByTagsFromContract.mockResolvedValue([[scopedLogWithPadding]]); + aztecNode.getLogsByTags.mockResolvedValue([[scopedLogWithPadding]]); aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts index 2bcef23f246b..37898a5f7ee4 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts @@ -392,7 +392,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { }); // We fetch the logs for the tags - const possibleLogs = await this.aztecNode.getPrivateLogsByTags(currentTags); + const possibleLogs = await this.#getPrivateLogsByTags(currentTags); // We find the index of the last log in the window that is not empty const indexOfLastLog = possibleLogs.findLastIndex(possibleLog => possibleLog.length !== 0); @@ -491,7 +491,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { const newLargestIndexMapForIteration: { [k: string]: number } = {}; // Fetch the private logs for the tags and iterate over them - const logsByTags = await this.aztecNode.getPrivateLogsByTags(tagsForTheWholeWindow); + const logsByTags = await this.#getPrivateLogsByTags(tagsForTheWholeWindow); for (let logIndex = 0; logIndex < logsByTags.length; logIndex++) { const logsByTag = logsByTags[logIndex]; @@ -698,7 +698,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { tag: Fr, contractAddress: AztecAddress, ): Promise { - const logs = await this.aztecNode.getPublicLogsByTagsFromContract([tag], contractAddress); + const logs = await this.#getPublicLogsByTagsFromContract([tag], contractAddress); const logsForTag = logs[0]; this.log.debug(`Got ${logsForTag.length} logs for tag ${tag}`); @@ -829,4 +829,21 @@ export class PXEOracleInterface implements ExecutionDataProvider { blockNumber, ); } + + // TODO: Make this a public function on the AztecNode interface and remove the original getLogsByTags. This was not + // done yet as we were unsure about the API and we didn't want to introduce a breaking change. + async #getPrivateLogsByTags(tags: Fr[]): Promise { + const allLogs = await this.aztecNode.getLogsByTags(tags); + return allLogs.map(logs => logs.filter(log => !log.isFromPublic)); + } + + // TODO: Make this a public function on the AztecNode interface and remove the original getLogsByTags. This was not + // done yet as we were unsure about the API and we didn't want to introduce a breaking change. + async #getPublicLogsByTagsFromContract(tags: Fr[], contractAddress: AztecAddress): Promise { + const allLogs = await this.aztecNode.getLogsByTags(tags); + const allPublicLogs = allLogs.map(logs => logs.filter(log => log.isFromPublic)); + return allPublicLogs.map(logs => + logs.filter(log => (log.log as PublicLog).contractAddress.equals(contractAddress)), + ); + } } diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts index 632dfc1ca7a2..c7b0f7b3d6c5 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts @@ -243,13 +243,8 @@ describe('AztecNodeApiSchema', () => { expect(response).toEqual({ logs: [expect.any(ExtendedContractClassLog)], maxLogsHit: true }); }); - it('getPrivateLogsByTags', async () => { - const response = await context.client.getPrivateLogsByTags([Fr.random()]); - expect(response).toEqual([[expect.any(TxScopedL2Log)]]); - }); - - it('getPublicLogsByTagsFromContract', async () => { - const response = await context.client.getPublicLogsByTagsFromContract([Fr.random()], await AztecAddress.random()); + it('getLogsByTags', async () => { + const response = await context.client.getLogsByTags([Fr.random()]); expect(response).toEqual([[expect.any(TxScopedL2Log)]]); }); @@ -582,15 +577,10 @@ class MockAztecNode implements AztecNode { expect(filter.contractAddress).toBeInstanceOf(AztecAddress); return Promise.resolve({ logs: [await ExtendedContractClassLog.random()], maxLogsHit: true }); } - async getPrivateLogsByTags(tags: Fr[]): Promise { - expect(tags).toHaveLength(1); - expect(tags[0]).toBeInstanceOf(Fr); - return [[await TxScopedL2Log.random(false)]]; - } - async getPublicLogsByTagsFromContract(tags: Fr[]): Promise { + async getLogsByTags(tags: Fr[]): Promise { expect(tags).toHaveLength(1); expect(tags[0]).toBeInstanceOf(Fr); - return [[await TxScopedL2Log.random(true)]]; + return [[await TxScopedL2Log.random()]]; } sendTx(tx: Tx): Promise { expect(tx).toBeInstanceOf(Tx); diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.ts b/yarn-project/stdlib/src/interfaces/aztec-node.ts index f9a6a68f2fc9..eaaa1af90ba7 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.ts @@ -303,24 +303,13 @@ export interface AztecNode getContractClassLogs(filter: LogFilter): Promise; /** - * Gets all private logs that match any of the received tags (i.e. logs with their first field equal to a tag). + * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag). * @param tags - The tags to filter the logs by. * @returns For each received tag, an array of matching logs and metadata (e.g. tx hash) is returned. An empty * array implies no logs match that tag. There can be multiple logs for 1 tag because tag reuse can happen * --> e.g. when sending a note from multiple unsynched devices. */ - getPrivateLogsByTags(tags: Fr[]): Promise; - - /** - * Gets all public logs that match any of the received tags (i.e. logs with their first field equal to a tag) for - * a given contract. - * @param tags - The tags to filter the logs by. - * @param contractAddress - The address of the contract to filter the logs by. - * @returns For each received tag, an array of matching logs and metadata (e.g. tx hash) is returned. An empty - * array implies no logs match that tag. There can be multiple logs for 1 tag because tag reuse can happen - * --> e.g. when sending a note from multiple unsynched devices. - */ - getPublicLogsByTagsFromContract(tags: Fr[], contractAddress: AztecAddress): Promise; + getLogsByTags(tags: Fr[]): Promise; /** * Method to submit a transaction to the p2p pool. @@ -517,16 +506,11 @@ export const AztecNodeApiSchema: ApiSchemaFor = { getContractClassLogs: z.function().args(LogFilterSchema).returns(GetContractClassLogsResponseSchema), - getPrivateLogsByTags: z + getLogsByTags: z .function() .args(z.array(schemas.Fr)) .returns(z.array(z.array(TxScopedL2Log.schema))), - getPublicLogsByTagsFromContract: z - .function() - .args(z.array(schemas.Fr), schemas.AztecAddress) - .returns(z.array(z.array(TxScopedL2Log.schema))), - sendTx: z.function().args(Tx.schema).returns(z.void()), getTxReceipt: z.function().args(TxHash.schema).returns(TxReceipt.schema), From af731aa7b2285036a6a70f00222ee130035339c0 Mon Sep 17 00:00:00 2001 From: benesjan Date: Fri, 23 May 2025 14:53:13 +0000 Subject: [PATCH 09/14] test fix --- yarn-project/aztec-node/src/aztec-node/server.ts | 2 +- .../pxe_oracle_interface/pxe_oracle_interface.test.ts | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 0ffc5c8d2986..892636635282 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -67,7 +67,7 @@ import { type WorldStateSynchronizer, tryStop, } from '@aztec/stdlib/interfaces/server'; -import type { LogFilter, PrivateLog, PublicLog, TxScopedL2Log } from '@aztec/stdlib/logs'; +import type { LogFilter, PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs'; import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging'; import { P2PClientType } from '@aztec/stdlib/p2p'; import type { NullifierLeafPreimage, PublicDataTreeLeaf, PublicDataTreeLeafPreimage } from '@aztec/stdlib/trees'; diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts index f842c8c3df6e..e066a55b92e8 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts @@ -651,8 +651,9 @@ describe('PXEOracleInterface', () => { it('throws if multiple logs found for tag', async () => { const scopedLog = await TxScopedL2Log.random(true); aztecNode.getLogsByTags.mockResolvedValue([[scopedLog, scopedLog]]); + const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress)).rejects.toThrow( + await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, logContractAddress)).rejects.toThrow( /Got 2 logs for tag/, ); }); @@ -661,17 +662,19 @@ describe('PXEOracleInterface', () => { const scopedLog = await TxScopedL2Log.random(true); aztecNode.getLogsByTags.mockResolvedValue([[scopedLog]]); aztecNode.getTxEffect.mockResolvedValue(undefined); + const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress)).rejects.toThrow( + await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, logContractAddress)).rejects.toThrow( /failed to retrieve tx effects/, ); }); it('returns log fields that are actually emitted', async () => { const logContent = [Fr.random(), Fr.random()]; + const logContractAddress = await AztecAddress.random(); const log = PublicLog.from({ - contractAddress: await AztecAddress.random(), + contractAddress: logContractAddress, fields: padArrayEnd(logContent, Fr.ZERO, PUBLIC_LOG_SIZE_IN_FIELDS), emittedLength: logContent.length, }); @@ -686,7 +689,7 @@ describe('PXEOracleInterface', () => { aztecNode.getLogsByTags.mockResolvedValue([[scopedLogWithPadding]]); aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); - const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); + const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, logContractAddress); expect(result?.logContent).toEqual([log.contractAddress.toField(), ...logContent]); }); From 969768cb3648d6ba88a72504dcb7556a56985c3e Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 26 May 2025 06:43:59 +0000 Subject: [PATCH 10/14] migration notes --- docs/docs/migration_notes.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index f4f03705e83a..a12649647dcf 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -7,6 +7,17 @@ tags: [migration, updating, sandbox] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. +## TBD + +## [Aztec.nr] Modified `getLogByTag` oracle + +`getLogByTag` oracle has been renamed to `getPublicLogByTagFromContract` and now it accepts contract address along with a tag as input: + +```diff +- let maybe_log = get_log_by_tag(pending_partial_note.note_completion_log_tag); ++ let maybe_log = get_public_log_by_tag_from_contract(pending_partial_note.note_completion_log_tag, contract_address); +``` + ## 0.87.0 ## [Aztec.js/TS libraries] From 4532d208a5c28c7b5d2e5a3f9093115fe7c76b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Tue, 27 May 2025 15:26:06 +0200 Subject: [PATCH 11/14] Update noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolás Venturo --- noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr index 886f5562db6f..559e2d8e9348 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr @@ -60,7 +60,7 @@ pub struct PublicLogWithTxData { pub first_nullifier_in_tx: Field, } -/// Fetches a public log from the node that has the corresponding `tag`. The tag is the first field in the log's content. +/// Fetches a public log emitted by `contract_address` that has the corresponding `tag`. The tag is the first field in the log's content. /// Returns `Option::none` if no such log exists. Throws if more than one log with that tag exists. // TODO(#11627): handle multiple logs with the same tag. // TODO(#10273): improve contract siloing of logs, don't introduce an extra field. From 24e86ff41e5e1bbfd4aea72f507179241d55ed7a Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 27 May 2025 13:33:29 +0000 Subject: [PATCH 12/14] updated migration notes --- docs/docs/migration_notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index a12649647dcf..83793286594d 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -9,9 +9,9 @@ Aztec is in full-speed development. Literally every version breaks compatibility ## TBD -## [Aztec.nr] Modified `getLogByTag` oracle +## [Aztec.nr] Modified `get_log_by_tag` function -`getLogByTag` oracle has been renamed to `getPublicLogByTagFromContract` and now it accepts contract address along with a tag as input: +`get_log_by_tag` oracle has been renamed to `get_public_log_by_tag_from_contract` and now it accepts contract address along with a tag as input: ```diff - let maybe_log = get_log_by_tag(pending_partial_note.note_completion_log_tag); From 7ab99353a00ae448444c289ecaa15eeadf3d801b Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 27 May 2025 13:37:37 +0000 Subject: [PATCH 13/14] linking issue --- .../pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts index 37898a5f7ee4..9d8d90d319c9 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts @@ -830,15 +830,15 @@ export class PXEOracleInterface implements ExecutionDataProvider { ); } - // TODO: Make this a public function on the AztecNode interface and remove the original getLogsByTags. This was not - // done yet as we were unsure about the API and we didn't want to introduce a breaking change. + // TODO(#12656): Make this a public function on the AztecNode interface and remove the original getLogsByTags. This + // was not done yet as we were unsure about the API and we didn't want to introduce a breaking change. async #getPrivateLogsByTags(tags: Fr[]): Promise { const allLogs = await this.aztecNode.getLogsByTags(tags); return allLogs.map(logs => logs.filter(log => !log.isFromPublic)); } - // TODO: Make this a public function on the AztecNode interface and remove the original getLogsByTags. This was not - // done yet as we were unsure about the API and we didn't want to introduce a breaking change. + // TODO(#12656): Make this a public function on the AztecNode interface and remove the original getLogsByTags. This + // was not done yet as we were unsure about the API and we didn't want to introduce a breaking change. async #getPublicLogsByTagsFromContract(tags: Fr[], contractAddress: AztecAddress): Promise { const allLogs = await this.aztecNode.getLogsByTags(tags); const allPublicLogs = allLogs.map(logs => logs.filter(log => log.isFromPublic)); From 3fd0d199d3b5413a1e43bc86f7827c46a8be35f4 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 27 May 2025 14:43:56 +0000 Subject: [PATCH 14/14] get_public_log_by_tag_from_contract --> get_public_log_by_tag --- docs/docs/migration_notes.md | 4 ++-- .../aztec/src/messages/discovery/partial_notes.nr | 4 ++-- .../aztec-nr/aztec/src/oracle/message_discovery.nr | 8 ++++---- .../pxe_oracle_interface.test.ts | 14 ++++++-------- .../pxe_oracle_interface/pxe_oracle_interface.ts | 7 ++----- .../simulator/src/private/acvm/oracle/oracle.ts | 10 ++-------- .../src/private/acvm/oracle/typed_oracle.ts | 4 ++-- .../src/private/execution_data_provider.ts | 2 +- .../src/private/utility_execution_oracle.ts | 7 ++----- yarn-project/stdlib/src/logs/log_with_tx_data.ts | 2 +- yarn-project/txe/src/oracle/txe_oracle.ts | 4 ++-- yarn-project/txe/src/txe_service/txe_service.ts | 9 +++------ 12 files changed, 29 insertions(+), 46 deletions(-) diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 83793286594d..c2501f8201b2 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -11,11 +11,11 @@ Aztec is in full-speed development. Literally every version breaks compatibility ## [Aztec.nr] Modified `get_log_by_tag` function -`get_log_by_tag` oracle has been renamed to `get_public_log_by_tag_from_contract` and now it accepts contract address along with a tag as input: +`get_log_by_tag` function has been renamed to `get_public_log_by_tag` and now it accepts contract address along with a tag as input and it only returns public logs: ```diff - let maybe_log = get_log_by_tag(pending_partial_note.note_completion_log_tag); -+ let maybe_log = get_public_log_by_tag_from_contract(pending_partial_note.note_completion_log_tag, contract_address); ++ let maybe_log = get_public_log_by_tag(pending_partial_note.note_completion_log_tag, contract_address); ``` ## 0.87.0 diff --git a/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr b/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr index 35aedf09331a..0298748136f1 100644 --- a/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr +++ b/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr @@ -4,7 +4,7 @@ use crate::{ discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery}, encoding::MAX_MESSAGE_CONTENT_LEN, }, - oracle::message_discovery::{deliver_note, get_public_log_by_tag_from_contract}, + oracle::message_discovery::{deliver_note, get_public_log_by_tag}, utils::array, }; @@ -93,7 +93,7 @@ pub unconstrained fn fetch_and_process_public_partial_note_completion_logs( ); pending_partial_notes.for_each(|i, pending_partial_note: DeliveredPendingPartialNote| { - let maybe_log = get_public_log_by_tag_from_contract( + let maybe_log = get_public_log_by_tag( pending_partial_note.note_completion_log_tag, contract_address, ); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr index 559e2d8e9348..5a4ae812df2e 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr @@ -64,11 +64,11 @@ pub struct PublicLogWithTxData { /// Returns `Option::none` if no such log exists. Throws if more than one log with that tag exists. // TODO(#11627): handle multiple logs with the same tag. // TODO(#10273): improve contract siloing of logs, don't introduce an extra field. -pub unconstrained fn get_public_log_by_tag_from_contract( +pub unconstrained fn get_public_log_by_tag( tag: Field, contract_address: AztecAddress, ) -> Option { - get_public_log_by_tag_from_contract_oracle(tag, contract_address) + get_public_log_by_tag_oracle(tag, contract_address) } #[oracle(deliverNote)] @@ -83,8 +83,8 @@ unconstrained fn deliver_note_oracle( recipient: AztecAddress, ) -> bool {} -#[oracle(getPublicLogByTagFromContract)] -unconstrained fn get_public_log_by_tag_from_contract_oracle( +#[oracle(getPublicLogByTag)] +unconstrained fn get_public_log_by_tag_oracle( tag: Field, contract_address: AztecAddress, ) -> Option {} diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts index e066a55b92e8..9effc3f239ab 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.test.ts @@ -612,7 +612,7 @@ describe('PXEOracleInterface', () => { }); }); - describe('getPublicLogByTagFromContract', () => { + describe('getPublicLogByTag', () => { const tag = Fr.random(); beforeEach(() => { @@ -623,7 +623,7 @@ describe('PXEOracleInterface', () => { it('returns null if no logs found for tag', async () => { aztecNode.getLogsByTags.mockResolvedValue([[]]); - const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); + const result = await pxeOracleInterface.getPublicLogByTag(tag, contractAddress); expect(result).toBeNull(); }); @@ -637,7 +637,7 @@ describe('PXEOracleInterface', () => { txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), ); - const result = (await pxeOracleInterface.getPublicLogByTagFromContract(tag, logContractAddress))!; + const result = (await pxeOracleInterface.getPublicLogByTag(tag, logContractAddress))!; expect(result.logContent).toEqual([logContractAddress.toField()].concat(scopedLog.log.getEmittedFields())); expect(result.uniqueNoteHashesInTx).toEqual(indexedTxEffect.data.noteHashes); @@ -653,9 +653,7 @@ describe('PXEOracleInterface', () => { aztecNode.getLogsByTags.mockResolvedValue([[scopedLog, scopedLog]]); const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, logContractAddress)).rejects.toThrow( - /Got 2 logs for tag/, - ); + await expect(pxeOracleInterface.getPublicLogByTag(tag, logContractAddress)).rejects.toThrow(/Got 2 logs for tag/); }); it('throws if tx effect not found', async () => { @@ -664,7 +662,7 @@ describe('PXEOracleInterface', () => { aztecNode.getTxEffect.mockResolvedValue(undefined); const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - await expect(pxeOracleInterface.getPublicLogByTagFromContract(tag, logContractAddress)).rejects.toThrow( + await expect(pxeOracleInterface.getPublicLogByTag(tag, logContractAddress)).rejects.toThrow( /failed to retrieve tx effects/, ); }); @@ -689,7 +687,7 @@ describe('PXEOracleInterface', () => { aztecNode.getLogsByTags.mockResolvedValue([[scopedLogWithPadding]]); aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); - const result = await pxeOracleInterface.getPublicLogByTagFromContract(tag, logContractAddress); + const result = await pxeOracleInterface.getPublicLogByTag(tag, logContractAddress); expect(result?.logContent).toEqual([log.contractAddress.toField(), ...logContent]); }); diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts index 9d8d90d319c9..48ff18828437 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts @@ -694,10 +694,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { } } - public async getPublicLogByTagFromContract( - tag: Fr, - contractAddress: AztecAddress, - ): Promise { + public async getPublicLogByTag(tag: Fr, contractAddress: AztecAddress): Promise { const logs = await this.#getPublicLogsByTagsFromContract([tag], contractAddress); const logsForTag = logs[0]; @@ -708,7 +705,7 @@ export class PXEOracleInterface implements ExecutionDataProvider { } else if (logsForTag.length > 1) { // TODO(#11627): handle this case throw new Error( - `Got ${logsForTag.length} logs for tag ${tag} and contract ${contractAddress.toString()}. getPublicLogByTagFromContract currently only supports a single log per tag`, + `Got ${logsForTag.length} logs for tag ${tag} and contract ${contractAddress.toString()}. getPublicLogByTag currently only supports a single log per tag`, ); } diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index 815821ed94dc..35b5da6aca74 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts @@ -412,14 +412,8 @@ export class Oracle { return [toACVMField(true)]; } - async getPublicLogByTagFromContract( - [tag]: ACVMField[], - [contractAddress]: ACVMField[], - ): Promise<(ACVMField | ACVMField[])[]> { - const log = await this.typedOracle.getPublicLogByTagFromContract( - Fr.fromString(tag), - AztecAddress.fromString(contractAddress), - ); + async getPublicLogByTag([tag]: ACVMField[], [contractAddress]: ACVMField[]): Promise<(ACVMField | ACVMField[])[]> { + const log = await this.typedOracle.getPublicLogByTag(Fr.fromString(tag), AztecAddress.fromString(contractAddress)); if (log == null) { return [toACVMField(0), ...PublicLogWithTxData.noirSerializationOfEmpty().map(toACVMFieldSingleOrArray)]; diff --git a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts index fbac85a1e866..f1a6d77e58e0 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts @@ -231,8 +231,8 @@ export abstract class TypedOracle { return Promise.reject(new OracleMethodNotAvailableError('deliverNote')); } - getPublicLogByTagFromContract(_tag: Fr, _contractAddress: AztecAddress): Promise { - throw new OracleMethodNotAvailableError('getPublicLogByTagFromContract'); + getPublicLogByTag(_tag: Fr, _contractAddress: AztecAddress): Promise { + throw new OracleMethodNotAvailableError('getPublicLogByTag'); } storeCapsule(_contractAddress: AztecAddress, _key: Fr, _capsule: Fr[]): Promise { diff --git a/yarn-project/simulator/src/private/execution_data_provider.ts b/yarn-project/simulator/src/private/execution_data_provider.ts index bcc535d9b825..ce1fd99ec328 100644 --- a/yarn-project/simulator/src/private/execution_data_provider.ts +++ b/yarn-project/simulator/src/private/execution_data_provider.ts @@ -314,7 +314,7 @@ export interface ExecutionDataProvider { * @returns The public log with transaction data if found, null otherwise. * @throws If more than one log with that tag exists. */ - getPublicLogByTagFromContract(tag: Fr, contractAddress: AztecAddress): Promise; + getPublicLogByTag(tag: Fr, contractAddress: AztecAddress): Promise; /** * Removes all of a contract's notes that have been nullified from the note database. diff --git a/yarn-project/simulator/src/private/utility_execution_oracle.ts b/yarn-project/simulator/src/private/utility_execution_oracle.ts index 5b219daa2b9d..ce10987e5f80 100644 --- a/yarn-project/simulator/src/private/utility_execution_oracle.ts +++ b/yarn-project/simulator/src/private/utility_execution_oracle.ts @@ -307,11 +307,8 @@ export class UtilityExecutionOracle extends TypedOracle { ); } - public override getPublicLogByTagFromContract( - tag: Fr, - contractAddress: AztecAddress, - ): Promise { - return this.executionDataProvider.getPublicLogByTagFromContract(tag, contractAddress); + public override getPublicLogByTag(tag: Fr, contractAddress: AztecAddress): Promise { + return this.executionDataProvider.getPublicLogByTag(tag, contractAddress); } public override storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise { diff --git a/yarn-project/stdlib/src/logs/log_with_tx_data.ts b/yarn-project/stdlib/src/logs/log_with_tx_data.ts index b7cebcc56a4b..b5fa2e15f948 100644 --- a/yarn-project/stdlib/src/logs/log_with_tx_data.ts +++ b/yarn-project/stdlib/src/logs/log_with_tx_data.ts @@ -3,7 +3,7 @@ import { Fr } from '@aztec/foundation/fields'; import { TxHash } from '@aztec/stdlib/tx'; // TypeScript representation of the Noir aztec::oracle::message_discovery::PublicLogWithTxData struct. This is used as a -// response for PXE's custom getPublicLogByTagFromContract oracle. +// response for PXE's custom getPublicLogByTag oracle. export class PublicLogWithTxData { constructor( // The emitted fields of a log. diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 5ff4c5fd839e..2128a2984e0a 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -1197,8 +1197,8 @@ export class TXE implements TypedOracle { ); } - async getPublicLogByTagFromContract(tag: Fr, contractAddress: AztecAddress): Promise { - return await this.pxeOracleInterface.getPublicLogByTagFromContract(tag, contractAddress); + async getPublicLogByTag(tag: Fr, contractAddress: AztecAddress): Promise { + return await this.pxeOracleInterface.getPublicLogByTag(tag, contractAddress); } // AVM oracles diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 834d7a5a9fe0..fe48d70b7d7f 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -731,19 +731,16 @@ export class TXEService { return toForeignCallResult([toSingle(Fr.ONE)]); } - async getPublicLogByTagFromContract(tag: ForeignCallSingle, contractAddress: ForeignCallSingle) { + async getPublicLogByTag(tag: ForeignCallSingle, contractAddress: ForeignCallSingle) { if (!this.oraclesEnabled) { throw new Error( 'Oracle access from the root of a TXe test are not enabled. Please use env._ to interact with the oracles.', ); } - // TODO(AD): this was warning that getPublicLogByTagFromContract did not return a promise. + // TODO(AD): this was warning that getPublicLogByTag did not return a promise. const log = await Promise.resolve( - this.typedOracle.getPublicLogByTagFromContract( - fromSingle(tag), - AztecAddress.fromField(fromSingle(contractAddress)), - ), + this.typedOracle.getPublicLogByTag(fromSingle(tag), AztecAddress.fromField(fromSingle(contractAddress))), ); if (log == null) {