diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index f4f03705e83a..c2501f8201b2 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 `get_log_by_tag` function + +`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(pending_partial_note.note_completion_log_tag, contract_address); +``` + ## 0.87.0 ## [Aztec.js/TS libraries] 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..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_log_by_tag}, + oracle::message_discovery::{deliver_note, get_public_log_by_tag}, 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_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, + 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 eaa049a915bc..5a4ae812df2e 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, @@ -62,14 +60,15 @@ pub struct LogWithTxData { 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 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. -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, + contract_address: AztecAddress, +) -> Option { + get_public_log_by_tag_oracle(tag, contract_address) } #[oracle(deliverNote)] @@ -84,5 +83,8 @@ 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, + 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 4dd8c2406b40..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 @@ -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'; @@ -147,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.getLogsByTags.mockImplementation(tags => { return Promise.resolve(tags.map(tag => logs[tag.toString()] ?? [])); }); @@ -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); @@ -635,7 +612,7 @@ describe('PXEOracleInterface', () => { }); }); - describe('getLogByTag', () => { + describe('getPublicLogByTag', () => { const tag = Fr.random(); beforeEach(() => { @@ -646,15 +623,13 @@ 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, contractAddress); 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); + const logContractAddress = (scopedLog.log as PublicLog).contractAddress; aztecNode.getLogsByTags.mockResolvedValue([[scopedLog]]); const indexedTxEffect = await randomIndexedTxEffect(); @@ -662,15 +637,9 @@ describe('PXEOracleInterface', () => { txHash.equals(scopedLog.txHash) ? Promise.resolve(indexedTxEffect) : Promise.resolve(undefined), ); - const result = (await pxeOracleInterface.getLogByTag(tag))!; + const result = (await pxeOracleInterface.getPublicLogByTag(tag, logContractAddress))!; - 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([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]); @@ -680,24 +649,33 @@ describe('PXEOracleInterface', () => { }); it('throws if multiple logs found for tag', async () => { - const scopedLog = await TxScopedL2Log.random(); + const scopedLog = await TxScopedL2Log.random(true); aztecNode.getLogsByTags.mockResolvedValue([[scopedLog, scopedLog]]); + const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - await expect(pxeOracleInterface.getLogByTag(tag)).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 () => { - const scopedLog = await TxScopedL2Log.random(); + const scopedLog = await TxScopedL2Log.random(true); aztecNode.getLogsByTags.mockResolvedValue([[scopedLog]]); aztecNode.getTxEffect.mockResolvedValue(undefined); + const logContractAddress = (scopedLog.log as PublicLog).contractAddress; - await expect(pxeOracleInterface.getLogByTag(tag)).rejects.toThrow(/failed to retrieve tx effects/); + await expect(pxeOracleInterface.getPublicLogByTag(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 = new PrivateLog(padArrayEnd(logContent, Fr.ZERO, PRIVATE_LOG_SIZE_IN_FIELDS), logContent.length); + const log = PublicLog.from({ + contractAddress: logContractAddress, + fields: padArrayEnd(logContent, Fr.ZERO, PUBLIC_LOG_SIZE_IN_FIELDS), + emittedLength: logContent.length, + }); const scopedLogWithPadding = new TxScopedL2Log( TxHash.random(), randomInt(100), @@ -709,9 +687,9 @@ describe('PXEOracleInterface', () => { aztecNode.getLogsByTags.mockResolvedValue([[scopedLogWithPadding]]); aztecNode.getTxEffect.mockResolvedValue(await randomIndexedTxEffect()); - const result = await pxeOracleInterface.getLogByTag(tag); + const result = await pxeOracleInterface.getPublicLogByTag(tag, logContractAddress); - expect(result?.logContent).toEqual(logContent); + 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 e06d5e35ebd3..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 @@ -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.#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); @@ -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. @@ -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.#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, contractAddress: AztecAddress): Promise { + const logs = await this.#getPublicLogsByTagsFromContract([tag], contractAddress); 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} and contract ${contractAddress.toString()}. 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) { @@ -832,4 +826,21 @@ export class PXEOracleInterface implements ExecutionDataProvider { blockNumber, ); } + + // 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(#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)); + return allPublicLogs.map(logs => + logs.filter(log => (log.log as PublicLog).contractAddress.equals(contractAddress)), + ); + } } diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index 0d71f2c7bca8..35b5da6aca74 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[], [contractAddress]: ACVMField[]): Promise<(ACVMField | ACVMField[])[]> { + const log = await this.typedOracle.getPublicLogByTag(Fr.fromString(tag), AztecAddress.fromString(contractAddress)); 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..f1a6d77e58e0 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, _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 791329c90f1b..ce1fd99ec328 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'; @@ -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,12 +306,15 @@ 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. + * @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. */ - getLogByTag(tag: Fr): 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 39b9080925d2..ce10987e5f80 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, 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 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/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( /* diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 2a7f976dd976..2128a2984e0a 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, 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 8026c13beef0..fe48d70b7d7f 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,23 @@ export class TXEService { return toForeignCallResult([toSingle(Fr.ONE)]); } - async getLogByTag(tag: 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 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), AztecAddress.fromField(fromSingle(contractAddress))), + ); 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)]); }