From 6737f46e1eb55afc2e7ae7c3ecdd4dfca982079e Mon Sep 17 00:00:00 2001 From: ludamad Date: Fri, 13 Dec 2024 15:34:14 -0500 Subject: [PATCH] Revert "refactor: tagging cleanup (#10675)" This reverts commit 52b541ab4e6295aea199a2181575208f20eaa7fc. --- cspell.json | 9 +- .../aztec/src/encrypted_logs/payload.nr | 2 +- .../aztec-nr/aztec/src/oracle/notes.nr | 14 +- .../types/src/indexed_tagging_secret.nr | 6 +- .../circuits.js/src/keys/derivation.ts | 3 +- yarn-project/circuits.js/src/structs/index.ts | 2 +- .../src/structs/indexed_tagging_secret.ts | 40 ----- .../circuits.js/src/structs/tagging_secret.ts | 24 +++ .../pxe/src/database/kv_pxe_database.ts | 4 +- .../pxe/src/simulator_oracle/index.ts | 152 +++++++++--------- .../simulator_oracle/simulator_oracle.test.ts | 36 ++--- .../pxe/src/simulator_oracle/tagging_utils.ts | 54 ------- .../simulator/src/acvm/oracle/oracle.ts | 4 +- .../simulator/src/acvm/oracle/typed_oracle.ts | 4 +- .../simulator/src/client/db_oracle.ts | 6 +- .../src/client/private_execution.test.ts | 2 +- .../simulator/src/client/view_data_oracle.ts | 6 +- yarn-project/txe/src/oracle/txe_oracle.ts | 16 +- .../txe/src/txe_service/txe_service.ts | 4 +- 19 files changed, 157 insertions(+), 231 deletions(-) delete mode 100644 yarn-project/circuits.js/src/structs/indexed_tagging_secret.ts create mode 100644 yarn-project/circuits.js/src/structs/tagging_secret.ts delete mode 100644 yarn-project/pxe/src/simulator_oracle/tagging_utils.ts diff --git a/cspell.json b/cspell.json index 0b8d2a27549..3059335afc2 100644 --- a/cspell.json +++ b/cspell.json @@ -275,12 +275,11 @@ "unexcluded", "unfinalised", "unprefixed", - "unshift", - "unshifted", - "unsynched", "unzipit", "updateable", "upperfirst", + "unshift", + "unshifted", "usecase", "usecases", "utxo", @@ -324,7 +323,5 @@ "lib", "*.cmake" ], - "flagWords": [ - "anonymous" - ] + "flagWords": ["anonymous"] } diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index 1b396ef7b65..751d3c2d718 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -260,7 +260,7 @@ mod test { 0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c, ); - let _ = OracleMock::mock("getIndexedTaggingSecretAsSender").returns([69420, 1337]); + let _ = OracleMock::mock("getAppTaggingSecretAsSender").returns([69420, 1337]); let _ = OracleMock::mock("incrementAppTaggingSecretIndexAsSender").returns(()); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr index e7534b14fb9..6d2cdab8f83 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr @@ -205,25 +205,25 @@ pub unconstrained fn check_nullifier_exists(inner_nullifier: Field) -> bool { #[oracle(checkNullifierExists)] unconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {} -/// Same as `get_indexed_tagging_secret_as_sender`, except it returns the derived tag, ready to be included in a log. +/// Same as `get_app_tagging_secret_as_sender`, except it returns the derived tag, ready to be included in a log. pub unconstrained fn get_app_tag_as_sender(sender: AztecAddress, recipient: AztecAddress) -> Field { - get_indexed_tagging_secret_as_sender(sender, recipient).compute_tag(recipient) + get_app_tagging_secret_as_sender(sender, recipient).compute_tag(recipient) } /// Returns the tagging secret for a given sender and recipient pair, siloed for the current contract address. /// Includes the last known index used to send a note tagged with this secret. -/// For this to work, PXE must know the ivsk_m of the sender. +/// For this to work, PXE must know the ivpsk_m of the sender. /// For the recipient's side, only the address is needed. -pub unconstrained fn get_indexed_tagging_secret_as_sender( +pub unconstrained fn get_app_tagging_secret_as_sender( sender: AztecAddress, recipient: AztecAddress, ) -> IndexedTaggingSecret { - let result = get_indexed_tagging_secret_as_sender_oracle(sender, recipient); + let result = get_app_tagging_secret_as_sender_oracle(sender, recipient); IndexedTaggingSecret::deserialize(result) } -#[oracle(getIndexedTaggingSecretAsSender)] -unconstrained fn get_indexed_tagging_secret_as_sender_oracle( +#[oracle(getAppTaggingSecretAsSender)] +unconstrained fn get_app_tagging_secret_as_sender_oracle( _sender: AztecAddress, _recipient: AztecAddress, ) -> [Field; INDEXED_TAGGING_SECRET_LENGTH] {} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/indexed_tagging_secret.nr b/noir-projects/noir-protocol-circuits/crates/types/src/indexed_tagging_secret.nr index 4781bd87560..89837964cff 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/indexed_tagging_secret.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/indexed_tagging_secret.nr @@ -6,14 +6,12 @@ pub global INDEXED_TAGGING_SECRET_LENGTH: u32 = 2; #[derive(Serialize, Deserialize)] pub struct IndexedTaggingSecret { - app_tagging_secret: Field, + secret: Field, index: u32, } impl IndexedTaggingSecret { pub fn compute_tag(self, recipient: AztecAddress) -> Field { - poseidon2_hash( - [self.app_tagging_secret, recipient.to_field(), self.index as Field], - ) + poseidon2_hash([self.secret, recipient.to_field(), self.index as Field]) } } diff --git a/yarn-project/circuits.js/src/keys/derivation.ts b/yarn-project/circuits.js/src/keys/derivation.ts index 032141f9842..495ea964cf8 100644 --- a/yarn-project/circuits.js/src/keys/derivation.ts +++ b/yarn-project/circuits.js/src/keys/derivation.ts @@ -123,8 +123,7 @@ export function deriveKeys(secretKey: Fr) { }; } -// Returns shared tagging secret computed with Diffie-Hellman key exchange. -export function computeTaggingSecretPoint(knownAddress: CompleteAddress, ivsk: Fq, externalAddress: AztecAddress) { +export function computeTaggingSecret(knownAddress: CompleteAddress, ivsk: Fq, externalAddress: AztecAddress) { const knownPreaddress = computePreaddress(knownAddress.publicKeys.hash(), knownAddress.partialAddress); // TODO: #8970 - Computation of address point from x coordinate might fail const externalAddressPoint = externalAddress.toAddressPoint(); diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 9160f7cfe06..4959a0fb048 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -15,7 +15,7 @@ export * from './gas_fees.js'; export * from './gas_settings.js'; export * from './global_variables.js'; export * from './block_header.js'; -export * from './indexed_tagging_secret.js'; +export * from './tagging_secret.js'; export * from './kernel/combined_accumulated_data.js'; export * from './kernel/combined_constant_data.js'; export * from './kernel/private_kernel_empty_inputs.js'; diff --git a/yarn-project/circuits.js/src/structs/indexed_tagging_secret.ts b/yarn-project/circuits.js/src/structs/indexed_tagging_secret.ts deleted file mode 100644 index 4a884180eb8..00000000000 --- a/yarn-project/circuits.js/src/structs/indexed_tagging_secret.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { poseidon2Hash } from '@aztec/foundation/crypto'; -import { Fr } from '@aztec/foundation/fields'; - -export class IndexedTaggingSecret { - constructor(public appTaggingSecret: Fr, public index: number) {} - - toFields(): Fr[] { - return [this.appTaggingSecret, new Fr(this.index)]; - } - - static fromFields(serialized: Fr[]) { - return new this(serialized[0], serialized[1].toNumber()); - } - - /** - * Computes the tag based on the app tagging secret, recipient and index. - * @dev By including the recipient we achieve "directionality" of the tag (when sending a note in the other - * direction, the tag will be different). - * @param recipient The recipient of the note - * @returns The tag. - */ - computeTag(recipient: AztecAddress) { - return poseidon2Hash([this.appTaggingSecret, recipient, this.index]); - } - - /** - * Computes the tag as it is submitted on-chain. - * @dev We do this second layer of siloing (one was already done as the tagging secret is app-siloed) because kernels - * do that to protect against contract impersonation attacks. This extra layer of siloing in kernels ensures that - * a malicious contract cannot emit a note with a tag corresponding to another contract. - * @param recipient The recipient of the note - * @param app The app address - * @returns The tag as it is submitted on-chain in a log. - */ - computeSiloedTag(recipient: AztecAddress, app: AztecAddress) { - const tag = this.computeTag(recipient); - return poseidon2Hash([app, tag]); - } -} diff --git a/yarn-project/circuits.js/src/structs/tagging_secret.ts b/yarn-project/circuits.js/src/structs/tagging_secret.ts new file mode 100644 index 00000000000..97371fe7a8b --- /dev/null +++ b/yarn-project/circuits.js/src/structs/tagging_secret.ts @@ -0,0 +1,24 @@ +import { type AztecAddress } from '@aztec/foundation/aztec-address'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; + +export class IndexedTaggingSecret { + constructor(public secret: Fr, public index: number) {} + + toFields(): Fr[] { + return [this.secret, new Fr(this.index)]; + } + + static fromFields(serialized: Fr[]) { + return new this(serialized[0], serialized[1].toNumber()); + } + + computeTag(recipient: AztecAddress) { + return poseidon2Hash([this.secret, recipient, this.index]); + } + + computeSiloedTag(recipient: AztecAddress, contractAddress: AztecAddress) { + const tag = this.computeTag(recipient); + return poseidon2Hash([contractAddress, tag]); + } +} diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 7ff1f19062b..5439afa717b 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -585,9 +585,7 @@ export class KVPxeDatabase implements PxeDatabase { async #setTaggingSecretsIndexes(indexedSecrets: IndexedTaggingSecret[], storageMap: AztecAsyncMap) { await Promise.all( - indexedSecrets.map(indexedSecret => - storageMap.set(indexedSecret.appTaggingSecret.toString(), indexedSecret.index), - ), + indexedSecrets.map(indexedSecret => storageMap.set(indexedSecret.secret.toString(), indexedSecret.index)), ); } diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 160947e25c1..0d88946a5ea 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -24,7 +24,7 @@ import { type L1_TO_L2_MSG_TREE_HEIGHT, PrivateLog, computeAddressSecret, - computeTaggingSecretPoint, + computeTaggingSecret, } from '@aztec/circuits.js'; import { type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/abi'; import { poseidon2Hash } from '@aztec/foundation/crypto'; @@ -38,7 +38,6 @@ import { type IncomingNoteDao } from '../database/incoming_note_dao.js'; import { type PxeDatabase } from '../database/index.js'; import { produceNoteDaos } from '../note_decryption_utils/produce_note_daos.js'; import { getAcirSimulator } from '../simulator/index.js'; -import { getInitialIndexes, getLeftMostIndexedTaggingSecrets, getRightMostIndexes } from './tagging_utils.js'; /** * A data oracle that provides information needed for simulating a transaction. @@ -258,28 +257,28 @@ export class SimulatorOracle implements DBOracle { } /** - * Returns the tagging secret for a given sender and recipient pair. For this to work, the ivsk_m of the sender must be known. + * Returns the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known. * Includes the next index to be used used for tagging with this secret. * @param contractAddress - The contract address to silo the secret for * @param sender - The address sending the note * @param recipient - The address receiving the note - * @returns An indexed tagging secret that can be used to tag notes. + * @returns A siloed tagging secret that can be used to tag notes. */ - public async getIndexedTaggingSecretAsSender( + public async getAppTaggingSecretAsSender( contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress, ): Promise { await this.syncTaggedLogsAsSender(contractAddress, sender, recipient); - const appTaggingSecret = await this.#calculateAppTaggingSecret(contractAddress, sender, recipient); - const [index] = await this.db.getTaggingSecretsIndexesAsSender([appTaggingSecret]); + const secret = await this.#calculateTaggingSecret(contractAddress, sender, recipient); + const [index] = await this.db.getTaggingSecretsIndexesAsSender([secret]); - return new IndexedTaggingSecret(appTaggingSecret, index); + return new IndexedTaggingSecret(secret, index); } /** - * Increments the tagging secret for a given sender and recipient pair. For this to work, the ivsk_m of the sender must be known. + * Increments the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known. * @param contractAddress - The contract address to silo the secret for * @param sender - The address sending the note * @param recipient - The address receiving the note @@ -289,7 +288,7 @@ export class SimulatorOracle implements DBOracle { sender: AztecAddress, recipient: AztecAddress, ): Promise { - const secret = await this.#calculateAppTaggingSecret(contractAddress, sender, recipient); + const secret = await this.#calculateTaggingSecret(contractAddress, sender, recipient); const contractName = await this.contractDataOracle.getDebugContractName(contractAddress); this.log.debug(`Incrementing app tagging secret at ${contractName}(${contractAddress})`, { secret, @@ -303,25 +302,25 @@ export class SimulatorOracle implements DBOracle { await this.db.setTaggingSecretsIndexesAsSender([new IndexedTaggingSecret(secret, index + 1)]); } - async #calculateAppTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) { + async #calculateTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) { const senderCompleteAddress = await this.getCompleteAddress(sender); const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender); - const secretPoint = computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient); - // Silo the secret so it can't be used to track other app's notes - const appSecret = poseidon2Hash([secretPoint.x, secretPoint.y, contractAddress]); - return appSecret; + const sharedSecret = computeTaggingSecret(senderCompleteAddress, senderIvsk, recipient); + // Silo the secret to the app so it can't be used to track other app's notes + const siloedSecret = poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]); + return siloedSecret; } /** - * Returns the indexed tagging secrets for a given recipient and all the senders in the address book + * Returns the siloed tagging secrets for a given recipient and all the senders in the address book * This method should be exposed as an oracle call to allow aztec.nr to perform the orchestration * of the syncTaggedLogs and processTaggedLogs methods. However, it is not possible to do so at the moment, * so we're keeping it private for now. * @param contractAddress - The contract address to silo the secret for * @param recipient - The address receiving the notes - * @returns A list of indexed tagging secrets + * @returns A list of siloed tagging secrets */ - async #getIndexedTaggingSecretsForContacts( + async #getAppTaggingSecretsForContacts( contractAddress: AztecAddress, recipient: AztecAddress, ): Promise { @@ -333,7 +332,7 @@ export class SimulatorOracle implements DBOracle { (address, index, self) => index === self.findIndex(otherAddress => otherAddress.equals(address)), ); const appTaggingSecrets = contacts.map(contact => { - const sharedSecret = computeTaggingSecretPoint(recipientCompleteAddress, recipientIvsk, contact); + const sharedSecret = computeTaggingSecret(recipientCompleteAddress, recipientIvsk, contact); return poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]); }); const indexes = await this.db.getTaggingSecretsIndexesAsRecipient(appTaggingSecrets); @@ -352,7 +351,7 @@ export class SimulatorOracle implements DBOracle { sender: AztecAddress, recipient: AztecAddress, ): Promise { - const appTaggingSecret = await this.#calculateAppTaggingSecret(contractAddress, sender, recipient); + const appTaggingSecret = await this.#calculateTaggingSecret(contractAddress, sender, recipient); let [currentIndex] = await this.db.getTaggingSecretsIndexesAsSender([appTaggingSecret]); const INDEX_OFFSET = 10; @@ -410,8 +409,7 @@ export class SimulatorOracle implements DBOracle { /** * Synchronizes the logs tagged with scoped addresses and all the senders in the address book. - * Returns the unsynched logs and updates the indexes of the secrets used to tag them until there are no more logs - * to sync. + * Returns the unsynched logs and updates the indexes of the secrets used to tag them until there are no more logs to sync. * @param contractAddress - The address of the contract that the logs are tagged for * @param recipient - The address of the recipient * @returns A list of encrypted logs tagged with the recipient's address @@ -421,12 +419,8 @@ export class SimulatorOracle implements DBOracle { maxBlockNumber: number, scopes?: AztecAddress[], ): Promise> { - // Half the size of the window we slide over the tagging secret indexes. - const WINDOW_HALF_SIZE = 10; - const recipients = scopes ? scopes : await this.keyStore.getAccounts(); - // A map of never-before-seen logs going from recipient address to logs - const newLogsMap = new Map(); + const result = new Map(); const contractName = await this.contractDataOracle.getDebugContractName(contractAddress); for (const recipient of recipients) { const logs: TxScopedL2Log[] = []; @@ -437,40 +431,56 @@ export class SimulatorOracle implements DBOracle { // length, since we don't really know the note they correspond to until we decrypt them. // 1. Get all the secrets for the recipient and sender pairs (#9365) - const indexedTaggingSecrets = await this.#getIndexedTaggingSecretsForContacts(contractAddress, recipient); + const appTaggingSecrets = await this.#getAppTaggingSecretsForContacts(contractAddress, recipient); // 1.1 Set up a sliding window with an offset. Chances are the sender might have messed up - // and inadvertently incremented their index without us getting any logs (for example, in case - // of a revert). If we stopped looking for logs the first time we don't receive any logs for a tag, - // we might never receive anything from that sender again. - // Also there's a possibility that we have advanced our index, but the sender has reused it, - // so we might have missed some logs. For these reasons, we have to look both back and ahead of - // the stored index. - - // App tagging secrets along with an index in a window to check in the current iteration. Called current because - // this value will be updated as we iterate through the window. - let currentSecrets = getLeftMostIndexedTaggingSecrets(indexedTaggingSecrets, WINDOW_HALF_SIZE); - // Right-most indexes in a window to check stored in a key-value map where key is the app tagging secret - // and value is the index to check (the right-most index in the window). - const rightMostIndexesMap = getRightMostIndexes(indexedTaggingSecrets, WINDOW_HALF_SIZE); - // The initial/unmodified indexes of the secrets stored in a key-value map where key is the app tagging secret. - const initialIndexesMap = getInitialIndexes(indexedTaggingSecrets); - // A map of indexes to increment for secrets for which we have found logs with an index higher than the one - // stored. - const indexesToIncrementMap: { [k: string]: number } = {}; - - while (currentSecrets.length > 0) { + // and inadvertently incremented their index without use getting any logs (for example, in case + // of a revert). If we stopped looking for logs the first time + // we receive 0 for a tag, we might never receive anything from that sender again. + // Also there's a possibility that we have advanced our index, but the sender has reused it, so + // we might have missed some logs. For these reasons, we have to look both back and ahead of the + // stored index + const INDEX_OFFSET = 10; + type SearchState = { + currentTagggingSecrets: IndexedTaggingSecret[]; + maxIndexesToCheck: { [k: string]: number }; + initialSecretIndexes: { [k: string]: number }; + secretsToIncrement: { [k: string]: number }; + }; + const searchState = appTaggingSecrets.reduce( + (acc, appTaggingSecret) => ({ + // Start looking for logs before the stored index + currentTagggingSecrets: acc.currentTagggingSecrets.concat([ + new IndexedTaggingSecret(appTaggingSecret.secret, Math.max(0, appTaggingSecret.index - INDEX_OFFSET)), + ]), + // Keep looking for logs beyond the stored index + maxIndexesToCheck: { + ...acc.maxIndexesToCheck, + ...{ [appTaggingSecret.secret.toString()]: appTaggingSecret.index + INDEX_OFFSET }, + }, + // Keeps track of the secrets we have to increment in the database + secretsToIncrement: {}, + // Store the initial set of indexes for the secrets + initialSecretIndexes: { + ...acc.initialSecretIndexes, + ...{ [appTaggingSecret.secret.toString()]: appTaggingSecret.index }, + }, + }), + { currentTagggingSecrets: [], maxIndexesToCheck: {}, secretsToIncrement: {}, initialSecretIndexes: {} }, + ); + + let { currentTagggingSecrets } = searchState; + const { maxIndexesToCheck, secretsToIncrement, initialSecretIndexes } = searchState; + + while (currentTagggingSecrets.length > 0) { // 2. Compute tags using the secrets, recipient and index. Obtain logs for each tag (#9380) - const currentTags = currentSecrets.map(secret => - // We compute the siloed tags since we need the tags as they appear in the log. - secret.computeSiloedTag(recipient, contractAddress), + const currentTags = currentTagggingSecrets.map(taggingSecret => + taggingSecret.computeSiloedTag(recipient, contractAddress), ); - - // Fetch the logs for the tags and iterate over them const logsByTags = await this.aztecNode.getLogsByTags(currentTags); - const secretsWithNewIndex: IndexedTaggingSecret[] = []; + const newTaggingSecrets: IndexedTaggingSecret[] = []; logsByTags.forEach((logsByTag, logIndex) => { - const { appTaggingSecret: currentSecret, index: currentIndex } = currentSecrets[logIndex]; + const { secret: currentSecret, index: currentIndex } = currentTagggingSecrets[logIndex]; const currentSecretAsStr = currentSecret.toString(); this.log.debug(`Syncing logs for recipient ${recipient} at contract ${contractName}(${contractAddress})`, { recipient, @@ -494,46 +504,40 @@ export class SimulatorOracle implements DBOracle { ); logs.push(...logsByTag); - if (currentIndex >= initialIndexesMap[currentSecretAsStr]) { - // 3.2. We found an index higher than the stored/initial one so we update it in the db later on (#9380) - indexesToIncrementMap[currentSecretAsStr] = newIndex; - // 3.3. We found an index higher than the initial one so we slide the window. - rightMostIndexesMap[currentSecretAsStr] = currentIndex + WINDOW_HALF_SIZE; + if (currentIndex >= initialSecretIndexes[currentSecretAsStr]) { + // 3.2. Increment the index for the tags that have logs, provided they're higher than the one + // we have stored in the db (#9380) + secretsToIncrement[currentSecretAsStr] = newIndex; + // 3.3. Slide the window forwards if we have found logs beyond the initial index + maxIndexesToCheck[currentSecretAsStr] = currentIndex + INDEX_OFFSET; } } // 3.4 Keep increasing the index (inside the window) temporarily for the tags that have no logs // There's a chance the sender missed some and we want to catch up - if (currentIndex < rightMostIndexesMap[currentSecretAsStr]) { + if (currentIndex < maxIndexesToCheck[currentSecretAsStr]) { const newTaggingSecret = new IndexedTaggingSecret(currentSecret, currentIndex + 1); - secretsWithNewIndex.push(newTaggingSecret); + newTaggingSecrets.push(newTaggingSecret); } }); - - // We store the new indexes for the secrets that have logs with an index higher than the one stored. await this.db.setTaggingSecretsIndexesAsRecipient( - Object.keys(indexesToIncrementMap).map( - secret => new IndexedTaggingSecret(Fr.fromHexString(secret), indexesToIncrementMap[secret]), + Object.keys(secretsToIncrement).map( + secret => new IndexedTaggingSecret(Fr.fromHexString(secret), secretsToIncrement[secret]), ), ); - - // We've processed all the current secret-index pairs so we proceed to the next iteration. - currentSecrets = secretsWithNewIndex; + currentTagggingSecrets = newTaggingSecrets; } - newLogsMap.set( + result.set( recipient.toString(), // Remove logs with a block number higher than the max block number // Duplicates are likely to happen due to the sliding window, so we also filter them out logs.filter( (log, index, self) => - // The following condition is true if the log has small enough block number and is unique - // --> the right side of the && is true if the index of the current log is the first occurrence - // of the log in the array --> that way we ensure uniqueness. log.blockNumber <= maxBlockNumber && index === self.findIndex(otherLog => otherLog.equals(log)), ), ); } - return newLogsMap; + return result; } /** diff --git a/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts b/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts index 1e88eaab363..930d586681d 100644 --- a/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts +++ b/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts @@ -18,7 +18,7 @@ import { IndexedTaggingSecret, MAX_NOTE_HASHES_PER_TX, computeAddress, - computeTaggingSecretPoint, + computeTaggingSecret, deriveKeys, } from '@aztec/circuits.js'; import { pedersenHash, poseidon2Hash } from '@aztec/foundation/crypto'; @@ -103,9 +103,9 @@ function computeSiloedTagForIndex( contractAddress: AztecAddress, index: number, ) { - const secretPoint = computeTaggingSecretPoint(sender.completeAddress, sender.ivsk, recipient); - const appSecret = poseidon2Hash([secretPoint.x, secretPoint.y, contractAddress]); - const tag = poseidon2Hash([appSecret, recipient, index]); + const sharedSecret = computeTaggingSecret(sender.completeAddress, sender.ivsk, recipient); + const siloedSecret = poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]); + const tag = poseidon2Hash([siloedSecret, recipient, index]); return poseidon2Hash([contractAddress, tag]); } @@ -240,12 +240,12 @@ describe('Simulator oracle', () => { const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + const firstSenderSharedSecret = computeTaggingSecret(recipient, ivsk, sender.completeAddress.address); + return poseidon2Hash([firstSenderSharedSecret.x, firstSenderSharedSecret.y, contractAddress]); }); // First sender should have 2 logs, but keep index 1 since they were built using the same tag - // Next 4 senders should also have index 1 = offset + 1 + // Next 4 senders hould also have index 1 = offset + 1 // Last 5 senders should have index 2 = offset + 2 const indexes = await database.getTaggingSecretsIndexesAsRecipient(secrets); @@ -269,8 +269,8 @@ describe('Simulator oracle', () => { // Recompute the secrets (as recipient) to ensure indexes are updated const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + const firstSenderSharedSecret = computeTaggingSecret(recipient, ivsk, sender.completeAddress.address); + return poseidon2Hash([firstSenderSharedSecret.x, firstSenderSharedSecret.y, contractAddress]); }); const indexesAsSender = await database.getTaggingSecretsIndexesAsSender(secrets); @@ -320,12 +320,12 @@ describe('Simulator oracle', () => { // Recompute the secrets (as recipient) to ensure indexes are updated const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + const firstSenderSharedSecret = computeTaggingSecret(recipient, ivsk, sender.completeAddress.address); + return poseidon2Hash([firstSenderSharedSecret.x, firstSenderSharedSecret.y, contractAddress]); }); // First sender should have 2 logs, but keep index 1 since they were built using the same tag - // Next 4 senders should also have index 6 = offset + 1 + // Next 4 senders hould also have index 6 = offset + 1 // Last 5 senders should have index 7 = offset + 2 const indexes = await database.getTaggingSecretsIndexesAsRecipient(secrets); @@ -344,8 +344,8 @@ describe('Simulator oracle', () => { // Recompute the secrets (as recipient) to update indexes const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + const firstSenderSharedSecret = computeTaggingSecret(recipient, ivsk, sender.completeAddress.address); + return poseidon2Hash([firstSenderSharedSecret.x, firstSenderSharedSecret.y, contractAddress]); }); // Increase our indexes to 2 @@ -377,8 +377,8 @@ describe('Simulator oracle', () => { // Recompute the secrets (as recipient) to update indexes const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + const firstSenderSharedSecret = computeTaggingSecret(recipient, ivsk, sender.completeAddress.address); + return poseidon2Hash([firstSenderSharedSecret.x, firstSenderSharedSecret.y, contractAddress]); }); await database.setTaggingSecretsIndexesAsRecipient( @@ -408,8 +408,8 @@ describe('Simulator oracle', () => { // Recompute the secrets (as recipient) to update indexes const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address); const secrets = senders.map(sender => { - const firstSenderSecretPoint = computeTaggingSecretPoint(recipient, ivsk, sender.completeAddress.address); - return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]); + const firstSenderSharedSecret = computeTaggingSecret(recipient, ivsk, sender.completeAddress.address); + return poseidon2Hash([firstSenderSharedSecret.x, firstSenderSharedSecret.y, contractAddress]); }); await database.setTaggingSecretsIndexesAsRecipient( diff --git a/yarn-project/pxe/src/simulator_oracle/tagging_utils.ts b/yarn-project/pxe/src/simulator_oracle/tagging_utils.ts deleted file mode 100644 index 52ed10a1cfc..00000000000 --- a/yarn-project/pxe/src/simulator_oracle/tagging_utils.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { IndexedTaggingSecret } from '@aztec/circuits.js'; - -/** - * Gets indexed tagging secrets with leftmost indexes. - * @param indexedTaggingSecrets - The indexed tagging secrets to get the leftmost indexed tagging secrets from. - * @param windowHalfSize- The half size of the window to slide over the tagging secret indexes. - * @returns The leftmost indexed tagging secrets. - */ -export function getLeftMostIndexedTaggingSecrets( - indexedTaggingSecrets: IndexedTaggingSecret[], - windowHalfSize: number, -): IndexedTaggingSecret[] { - return indexedTaggingSecrets.map( - indexedTaggingSecret => - new IndexedTaggingSecret( - indexedTaggingSecret.appTaggingSecret, - Math.max(0, indexedTaggingSecret.index - windowHalfSize), - ), - ); -} - -/** - * Creates a map from app tagging secret to rightmost index. - * @param indexedTaggingSecrets - The indexed tagging secrets to get the rightmost indexes from. - * @param windowHalfSize- The half size of the window to slide over the tagging secret indexes. - * @returns The map from app tagging secret to rightmost index. - */ -export function getRightMostIndexes( - indexedTaggingSecrets: IndexedTaggingSecret[], - windowHalfSize: number, -): { [k: string]: number } { - const rightMostIndexes: { [k: string]: number } = {}; - - for (const indexedTaggingSecret of indexedTaggingSecrets) { - rightMostIndexes[indexedTaggingSecret.appTaggingSecret.toString()] = indexedTaggingSecret.index + windowHalfSize; - } - - return rightMostIndexes; -} - -/** - * Creates a map from app tagging secret to initial index. - * @param indexedTaggingSecrets - The indexed tagging secrets to get the initial indexes from. - * @returns The map from app tagging secret to initial index. - */ -export function getInitialIndexes(indexedTaggingSecrets: IndexedTaggingSecret[]): { [k: string]: number } { - const initialIndexes: { [k: string]: number } = {}; - - for (const indexedTaggingSecret of indexedTaggingSecrets) { - initialIndexes[indexedTaggingSecret.appTaggingSecret.toString()] = indexedTaggingSecret.index; - } - - return initialIndexes; -} diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 254b91fb3ab..99d5d5f29f2 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -375,8 +375,8 @@ export class Oracle { this.typedOracle.notifySetMinRevertibleSideEffectCounter(frToNumber(fromACVMField(minRevertibleSideEffectCounter))); } - async getIndexedTaggingSecretAsSender([sender]: ACVMField[], [recipient]: ACVMField[]): Promise { - const taggingSecret = await this.typedOracle.getIndexedTaggingSecretAsSender( + async getAppTaggingSecretAsSender([sender]: ACVMField[], [recipient]: ACVMField[]): Promise { + const taggingSecret = await this.typedOracle.getAppTaggingSecretAsSender( AztecAddress.fromString(sender), AztecAddress.fromString(recipient), ); diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index d5c461bd3c2..2505a0478b0 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -237,8 +237,8 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('debugLog'); } - getIndexedTaggingSecretAsSender(_sender: AztecAddress, _recipient: AztecAddress): Promise { - throw new OracleMethodNotAvailableError('getIndexedTaggingSecretAsSender'); + getAppTaggingSecretAsSender(_sender: AztecAddress, _recipient: AztecAddress): Promise { + throw new OracleMethodNotAvailableError('getAppTaggingSecretAsSender'); } incrementAppTaggingSecretIndexAsSender(_sender: AztecAddress, _recipient: AztecAddress): Promise { diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 9472148257a..6702810c86a 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -198,21 +198,21 @@ export interface DBOracle extends CommitmentsDB { getBlockNumber(): Promise; /** - * Returns the tagging secret for a given sender and recipient pair. For this to work, the ivsk_m of the sender must be known. + * Returns the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known. * Includes the next index to be used used for tagging with this secret. * @param contractAddress - The contract address to silo the secret for * @param sender - The address sending the note * @param recipient - The address receiving the note * @returns A tagging secret that can be used to tag notes. */ - getIndexedTaggingSecretAsSender( + getAppTaggingSecretAsSender( contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress, ): Promise; /** - * Increments the tagging secret for a given sender and recipient pair. For this to work, the ivsk_m of the sender must be known. + * Increments the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known. * @param contractAddress - The contract address to silo the secret for * @param sender - The address sending the note * @param recipient - The address receiving the note diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 19d96f8b043..4d225f58d57 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -233,7 +233,7 @@ describe('Private Execution test suite', () => { throw new Error(`Unknown address: ${address}. Recipient: ${recipient}, Owner: ${owner}`); }); - oracle.getIndexedTaggingSecretAsSender.mockImplementation( + oracle.getAppTaggingSecretAsSender.mockImplementation( (_contractAddress: AztecAddress, _sender: AztecAddress, _recipient: AztecAddress) => { const secret = Fr.random(); return Promise.resolve(new IndexedTaggingSecret(secret, 0)); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index bfd870760b1..358a3271186 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -296,16 +296,16 @@ export class ViewDataOracle extends TypedOracle { /** * Returns the tagging secret for a given sender and recipient pair, siloed to the current contract address. * Includes the next index to be used used for tagging with this secret. - * For this to work, the ivsk_m of the sender must be known. + * For this to work, the ivpsk_m of the sender must be known. * @param sender - The address sending the note * @param recipient - The address receiving the note * @returns A tagging secret that can be used to tag notes. */ - public override async getIndexedTaggingSecretAsSender( + public override async getAppTaggingSecretAsSender( sender: AztecAddress, recipient: AztecAddress, ): Promise { - return await this.db.getIndexedTaggingSecretAsSender(this.contractAddress, sender, recipient); + return await this.db.getAppTaggingSecretAsSender(this.contractAddress, sender, recipient); } public override async syncNotes() { diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 03928a58a30..a455373b83c 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -36,7 +36,7 @@ import { type PublicDataTreeLeafPreimage, type PublicDataWrite, computeContractClassId, - computeTaggingSecretPoint, + computeTaggingSecret, deriveKeys, getContractClassFromArtifact, } from '@aztec/circuits.js'; @@ -890,24 +890,24 @@ export class TXE implements TypedOracle { } async incrementAppTaggingSecretIndexAsSender(sender: AztecAddress, recipient: AztecAddress): Promise { - const appSecret = await this.#calculateAppTaggingSecret(this.contractAddress, sender, recipient); + const appSecret = await this.#calculateTaggingSecret(this.contractAddress, sender, recipient); const [index] = await this.txeDatabase.getTaggingSecretsIndexesAsSender([appSecret]); await this.txeDatabase.setTaggingSecretsIndexesAsSender([new IndexedTaggingSecret(appSecret, index + 1)]); } - async getIndexedTaggingSecretAsSender(sender: AztecAddress, recipient: AztecAddress): Promise { - const secret = await this.#calculateAppTaggingSecret(this.contractAddress, sender, recipient); + async getAppTaggingSecretAsSender(sender: AztecAddress, recipient: AztecAddress): Promise { + const secret = await this.#calculateTaggingSecret(this.contractAddress, sender, recipient); const [index] = await this.txeDatabase.getTaggingSecretsIndexesAsSender([secret]); return new IndexedTaggingSecret(secret, index); } - async #calculateAppTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) { + async #calculateTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) { const senderCompleteAddress = await this.getCompleteAddress(sender); const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender); - const secretPoint = computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient); + const sharedSecret = computeTaggingSecret(senderCompleteAddress, senderIvsk, recipient); // Silo the secret to the app so it can't be used to track other app's notes - const appSecret = poseidon2Hash([secretPoint.x, secretPoint.y, contractAddress]); - return appSecret; + const siloedSecret = poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]); + return siloedSecret; } async syncNotes() { diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 9d87db3c1b4..de5c041d1c1 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -584,8 +584,8 @@ export class TXEService { return toForeignCallResult([toArray(witness.toFields())]); } - async getIndexedTaggingSecretAsSender(sender: ForeignCallSingle, recipient: ForeignCallSingle) { - const secret = await this.typedOracle.getIndexedTaggingSecretAsSender( + async getAppTaggingSecretAsSender(sender: ForeignCallSingle, recipient: ForeignCallSingle) { + const secret = await this.typedOracle.getAppTaggingSecretAsSender( AztecAddress.fromField(fromSingle(sender)), AztecAddress.fromField(fromSingle(recipient)), );