From 97a4c0c4452f31e5c0dc776812242d2444348406 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:29:20 +0000 Subject: [PATCH] feat: add increment secret oracles (#9573) This PR adds the oracles to increment a tagging secret's index. --- .../aztec-nr/aztec/src/oracle/notes.nr | 10 ++++++++ .../types/src/indexed_tagging_secret.nr | 4 ++-- .../circuits.js/src/structs/tagging_secret.ts | 10 +++++++- .../pxe/src/database/kv_pxe_database.ts | 2 +- .../pxe/src/simulator_oracle/index.ts | 24 +++++++++++++++++-- .../simulator/src/acvm/oracle/oracle.ts | 7 ++++++ .../simulator/src/acvm/oracle/typed_oracle.ts | 4 ++++ .../src/client/client_execution_context.ts | 4 ++++ .../simulator/src/client/db_oracle.ts | 12 ++++++++++ yarn-project/txe/src/oracle/txe_oracle.ts | 18 +++++++++++--- 10 files changed, 86 insertions(+), 9 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr index 39ed994516f..c13d768425f 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr @@ -221,6 +221,16 @@ unconstrained fn get_app_tagging_secret_oracle( _recipient: AztecAddress, ) -> [Field; INDEXED_TAGGING_SECRET_LENGTH] {} +pub unconstrained fn increment_app_tagging_secret(sender: AztecAddress, recipient: AztecAddress) { + increment_app_tagging_secret_oracle(sender, recipient); +} + +#[oracle(incrementAppTaggingSecret)] +unconstrained fn increment_app_tagging_secret_oracle( + _sender: AztecAddress, + _recipient: AztecAddress, +) {} + /// Returns the tagging secrets for a given recipient and all the senders in PXE's address book, // siloed for the current contract address. /// Includes the last known index used for tagging with this secret. 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 c3191eb9e08..0d07468ae6b 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 @@ -1,10 +1,10 @@ -use crate::traits::Deserialize; +use crate::traits::{Deserialize, Serialize}; use super::address::aztec_address::AztecAddress; use std::meta::derive; pub global INDEXED_TAGGING_SECRET_LENGTH: u32 = 3; -#[derive(Deserialize)] +#[derive(Serialize, Deserialize)] pub struct IndexedTaggingSecret { secret: Field, recipient: AztecAddress, diff --git a/yarn-project/circuits.js/src/structs/tagging_secret.ts b/yarn-project/circuits.js/src/structs/tagging_secret.ts index b43e8cb8030..9dd550b232d 100644 --- a/yarn-project/circuits.js/src/structs/tagging_secret.ts +++ b/yarn-project/circuits.js/src/structs/tagging_secret.ts @@ -1,4 +1,4 @@ -import { type AztecAddress } from '@aztec/foundation/aztec-address'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; export class TaggingSecret { @@ -17,4 +17,12 @@ export class IndexedTaggingSecret extends TaggingSecret { override toFields(): Fr[] { return [this.secret, this.recipient, new Fr(this.index)]; } + + static fromFields(serialized: Fr[]) { + return new this(serialized[0], AztecAddress.fromField(serialized[1]), serialized[2].toNumber()); + } + + static fromTaggingSecret(directionalSecret: TaggingSecret, index: number) { + return new this(directionalSecret.secret, directionalSecret.recipient, index); + } } diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 0468c3c445d..d44ce292c6d 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -603,7 +603,7 @@ export class KVPxeDatabase implements PxeDatabase { const indexes = await this.getTaggingSecretsIndexes(appTaggingSecretsWithRecipient); await this.db.transaction(() => { indexes.forEach((taggingSecretIndex, listIndex) => { - const nextIndex = taggingSecretIndex ? taggingSecretIndex + 1 : 1; + const nextIndex = taggingSecretIndex + 1; const { secret, recipient } = appTaggingSecretsWithRecipient[listIndex]; const key = `${secret.toString()}-${recipient.toString()}`; void this.#taggingSecretIndexes.set(key, nextIndex); diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index b67a5dd2da1..607514942cf 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -255,6 +255,27 @@ export class SimulatorOracle implements DBOracle { sender: AztecAddress, recipient: AztecAddress, ): Promise { + const directionalSecret = await this.#calculateDirectionalSecret(contractAddress, sender, recipient); + const [index] = await this.db.getTaggingSecretsIndexes([directionalSecret]); + return IndexedTaggingSecret.fromTaggingSecret(directionalSecret, index); + } + + /** + * 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 + */ + public async incrementAppTaggingSecret( + contractAddress: AztecAddress, + sender: AztecAddress, + recipient: AztecAddress, + ): Promise { + const directionalSecret = await this.#calculateDirectionalSecret(contractAddress, sender, recipient); + await this.db.incrementTaggingSecretsIndexes([directionalSecret]); + } + + async #calculateDirectionalSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) { const senderCompleteAddress = await this.getCompleteAddress(sender); const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender); const sharedSecret = computeTaggingSecret(senderCompleteAddress, senderIvsk, recipient); @@ -262,8 +283,7 @@ export class SimulatorOracle implements DBOracle { const siloedSecret = poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]); // Get the index of the secret, ensuring the directionality (sender -> recipient) const directionalSecret = new TaggingSecret(siloedSecret, recipient); - const [index] = await this.db.getTaggingSecretsIndexes([directionalSecret]); - return new IndexedTaggingSecret(siloedSecret, recipient, index); + return directionalSecret; } /** diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index c8fdb5a18b2..00f41304842 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -417,6 +417,13 @@ export class Oracle { return taggingSecret.toFields().map(toACVMField); } + async incrementAppTaggingSecret([sender]: ACVMField[], [recipient]: ACVMField[]) { + await this.typedOracle.incrementAppTaggingSecret( + AztecAddress.fromString(sender), + AztecAddress.fromString(recipient), + ); + } + async getAppTaggingSecretsForSenders([recipient]: ACVMField[]): Promise { const taggingSecrets = await this.typedOracle.getAppTaggingSecretsForSenders(AztecAddress.fromString(recipient)); return taggingSecrets.flatMap(taggingSecret => taggingSecret.toFields().map(toACVMField)); diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 284b08f5e0f..83aec5ed0d3 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -258,6 +258,10 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getAppTaggingSecret'); } + incrementAppTaggingSecret(_sender: AztecAddress, _recipient: AztecAddress): Promise { + throw new OracleMethodNotAvailableError('incrementAppTaggingSecret'); + } + getAppTaggingSecretsForSenders(_recipient: AztecAddress): Promise { throw new OracleMethodNotAvailableError('getAppTaggingSecretsForSenders'); } diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 06c51c9b0bf..773c0449f75 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -609,4 +609,8 @@ export class ClientExecutionContext extends ViewDataOracle { public getDebugFunctionName() { return this.db.getDebugFunctionName(this.contractAddress, this.callContext.functionSelector); } + + public override async incrementAppTaggingSecret(sender: AztecAddress, recipient: AztecAddress) { + await this.db.incrementAppTaggingSecret(this.contractAddress, sender, recipient); + } } diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index c19a0b1636a..d94cc95d0b0 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -209,6 +209,18 @@ export interface DBOracle extends CommitmentsDB { recipient: AztecAddress, ): Promise; + /** + * 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 + */ + incrementAppTaggingSecret( + contractAddress: AztecAddress, + sender: AztecAddress, + recipient: AztecAddress, + ): Promise; + /** * Returns the siloed tagging secrets for a given recipient and all the senders in the address book * @param contractAddress - The contract address to silo the secret for diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 1754fa8e8c1..01c7dc312bb 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -756,14 +756,26 @@ export class TXE implements TypedOracle { return; } + async incrementAppTaggingSecret(sender: AztecAddress, recipient: AztecAddress): Promise { + const directionalSecret = await this.#calculateDirectionalSecret(this.contractAddress, sender, recipient); + await this.txeDatabase.incrementTaggingSecretsIndexes([directionalSecret]); + } + async getAppTaggingSecret(sender: AztecAddress, recipient: AztecAddress): Promise { + const directionalSecret = await this.#calculateDirectionalSecret(this.contractAddress, sender, recipient); + const [index] = await this.txeDatabase.getTaggingSecretsIndexes([directionalSecret]); + return IndexedTaggingSecret.fromTaggingSecret(directionalSecret, index); + } + + async #calculateDirectionalSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) { const senderCompleteAddress = await this.getCompleteAddress(sender); const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender); 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 secret = poseidon2Hash([sharedSecret.x, sharedSecret.y, this.contractAddress]); - const [index] = await this.txeDatabase.getTaggingSecretsIndexes([new TaggingSecret(secret, recipient)]); - return new IndexedTaggingSecret(secret, recipient, index); + const siloedSecret = poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]); + // Get the index of the secret, ensuring the directionality (sender -> recipient) + const directionalSecret = new TaggingSecret(siloedSecret, recipient); + return directionalSecret; } async getAppTaggingSecretsForSenders(recipient: AztecAddress): Promise {