Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { PUBLIC_LOG_DATA_SIZE_IN_FIELDS } from '@aztec/constants';
import { timesParallel } from '@aztec/foundation/collection';
import { poseidon2Hash } from '@aztec/foundation/crypto';
import { Fq, Fr } from '@aztec/foundation/fields';
import type { Tuple } from '@aztec/foundation/serialize';
import { KeyStore } from '@aztec/key-store';
Expand All @@ -11,7 +10,7 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
import { randomInBlock } from '@aztec/stdlib/block';
import { CompleteAddress } from '@aztec/stdlib/contract';
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
import { computeAddress, computeTaggingSecretPoint, deriveKeys } from '@aztec/stdlib/keys';
import { computeAddress, computeAppTaggingSecret, deriveKeys } from '@aztec/stdlib/keys';
import { IndexedTaggingSecret, PrivateLog, PublicLog, TxScopedL2Log } from '@aztec/stdlib/logs';
import { randomContractArtifact, randomContractInstanceWithAddress } from '@aztec/stdlib/testing';
import { TxEffect, TxHash } from '@aztec/stdlib/tx';
Expand All @@ -37,10 +36,9 @@ async function computeSiloedTagForIndex(
contractAddress: AztecAddress,
index: number,
) {
const secretPoint = await computeTaggingSecretPoint(sender.completeAddress, sender.ivsk, recipient);
const appSecret = await poseidon2Hash([secretPoint.x, secretPoint.y, contractAddress]);
const tag = await poseidon2Hash([appSecret, recipient, index]);
return poseidon2Hash([contractAddress, tag]);
const appSecret = await computeAppTaggingSecret(sender.completeAddress, sender.ivsk, recipient, contractAddress);
const indexedTaggingSecret = new IndexedTaggingSecret(appSecret, index);
return indexedTaggingSecret.computeSiloedTag(recipient, contractAddress);
}

describe('PXEOracleInterface', () => {
Expand Down Expand Up @@ -175,14 +173,9 @@ describe('PXEOracleInterface', () => {

const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address);
const secrets = await Promise.all(
senders.map(async sender => {
const firstSenderSecretPoint = await computeTaggingSecretPoint(
recipient,
ivsk,
sender.completeAddress.address,
);
return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]);
}),
senders.map(sender =>
computeAppTaggingSecret(recipient, ivsk, sender.completeAddress.address, contractAddress),
),
);

// First sender should have 2 logs, but keep index 1 since they were built using the same tag
Expand Down Expand Up @@ -210,14 +203,9 @@ describe('PXEOracleInterface', () => {
// Recompute the secrets (as recipient) to ensure indexes are updated
const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address);
const secrets = await Promise.all(
senders.map(async sender => {
const firstSenderSecretPoint = await computeTaggingSecretPoint(
recipient,
ivsk,
sender.completeAddress.address,
);
return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]);
}),
senders.map(sender =>
computeAppTaggingSecret(recipient, ivsk, sender.completeAddress.address, contractAddress),
),
);

const indexesAsSender = await taggingDataProvider.getTaggingSecretsIndexesAsSender(secrets);
Expand Down Expand Up @@ -268,14 +256,9 @@ describe('PXEOracleInterface', () => {
// Recompute the secrets (as recipient) to ensure indexes are updated
const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address);
const secrets = await Promise.all(
senders.map(async sender => {
const firstSenderSecretPoint = await computeTaggingSecretPoint(
recipient,
ivsk,
sender.completeAddress.address,
);
return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]);
}),
senders.map(sender =>
computeAppTaggingSecret(recipient, ivsk, sender.completeAddress.address, contractAddress),
),
);

// First sender should have 2 logs, but keep index 1 since they were built using the same tag
Expand All @@ -298,14 +281,9 @@ describe('PXEOracleInterface', () => {
// Recompute the secrets (as recipient) to update indexes
const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address);
const secrets = await Promise.all(
senders.map(async sender => {
const firstSenderSecretPoint = await computeTaggingSecretPoint(
recipient,
ivsk,
sender.completeAddress.address,
);
return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]);
}),
senders.map(sender =>
computeAppTaggingSecret(recipient, ivsk, sender.completeAddress.address, contractAddress),
),
);

// Increase our indexes to 2
Expand Down Expand Up @@ -339,14 +317,9 @@ describe('PXEOracleInterface', () => {
// Recompute the secrets (as recipient) to update indexes
const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address);
const secrets = await Promise.all(
senders.map(async sender => {
const firstSenderSecretPoint = await computeTaggingSecretPoint(
recipient,
ivsk,
sender.completeAddress.address,
);
return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]);
}),
senders.map(sender =>
computeAppTaggingSecret(recipient, ivsk, sender.completeAddress.address, contractAddress),
),
);

// We set the indexes to WINDOW_HALF_SIZE + 1 so that it's outside the window and for this reason no updates
Expand Down Expand Up @@ -377,14 +350,9 @@ describe('PXEOracleInterface', () => {
// Recompute the secrets (as recipient) to update indexes
const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address);
const secrets = await Promise.all(
senders.map(async sender => {
const firstSenderSecretPoint = await computeTaggingSecretPoint(
recipient,
ivsk,
sender.completeAddress.address,
);
return poseidon2Hash([firstSenderSecretPoint.x, firstSenderSecretPoint.y, contractAddress]);
}),
senders.map(sender =>
computeAppTaggingSecret(recipient, ivsk, sender.completeAddress.address, contractAddress),
),
);

await taggingDataProvider.setTaggingSecretsIndexesAsRecipient(
Expand Down
16 changes: 6 additions & 10 deletions yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type L1_TO_L2_MSG_TREE_HEIGHT, MAX_NOTE_HASHES_PER_TX, PRIVATE_LOG_SIZE_IN_FIELDS } from '@aztec/constants';
import { timesParallel } from '@aztec/foundation/collection';
import { poseidon2Hash, randomInt } from '@aztec/foundation/crypto';
import { randomInt } from '@aztec/foundation/crypto';
import { Fr, Point } from '@aztec/foundation/fields';
import { createLogger } from '@aztec/foundation/log';
import type { KeyStore } from '@aztec/key-store';
Expand All @@ -26,7 +26,7 @@ import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract';
import { computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/stdlib/hash';
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
import { computeAddressSecret, computeTaggingSecretPoint } from '@aztec/stdlib/keys';
import { computeAddressSecret, computeAppTaggingSecret } from '@aztec/stdlib/keys';
import {
IndexedTaggingSecret,
LogWithTxData,
Expand Down Expand Up @@ -333,10 +333,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
async #calculateAppTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) {
const senderCompleteAddress = await this.getCompleteAddress(sender);
const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
const secretPoint = await 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;
return computeAppTaggingSecret(senderCompleteAddress, senderIvsk, recipient, contractAddress);
}

/**
Expand All @@ -362,10 +359,9 @@ export class PXEOracleInterface implements ExecutionDataProvider {
...(await this.keyStore.getAccounts()),
].filter((address, index, self) => index === self.findIndex(otherAddress => otherAddress.equals(address)));
const appTaggingSecrets = await Promise.all(
senders.map(async contact => {
const sharedSecret = await computeTaggingSecretPoint(recipientCompleteAddress, recipientIvsk, contact);
return poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]);
}),
senders.map(contact =>
computeAppTaggingSecret(recipientCompleteAddress, recipientIvsk, contact, contractAddress),
),
);
const indexes = await this.taggingDataProvider.getTaggingSecretsIndexesAsRecipient(appTaggingSecrets);
return appTaggingSecrets.map((secret, i) => new IndexedTaggingSecret(secret, indexes[i]));
Expand Down
18 changes: 12 additions & 6 deletions yarn-project/stdlib/src/keys/derivation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GeneratorIndex } from '@aztec/constants';
import { Grumpkin, poseidon2HashWithSeparator, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto';
import { Grumpkin, poseidon2Hash, poseidon2HashWithSeparator, sha512ToGrumpkinScalar } from '@aztec/foundation/crypto';
import { Fq, Fr, GrumpkinScalar } from '@aztec/foundation/fields';

import { AztecAddress } from '../aztec-address/index.js';
Expand Down Expand Up @@ -123,11 +123,7 @@ export async function deriveKeys(secretKey: Fr) {
}

// Returns shared tagging secret computed with Diffie-Hellman key exchange.
export async function computeTaggingSecretPoint(
knownAddress: CompleteAddress,
ivsk: Fq,
externalAddress: AztecAddress,
) {
async function computeTaggingSecretPoint(knownAddress: CompleteAddress, ivsk: Fq, externalAddress: AztecAddress) {
const knownPreaddress = await computePreaddress(await knownAddress.publicKeys.hash(), knownAddress.partialAddress);
// TODO: #8970 - Computation of address point from x coordinate might fail
const externalAddressPoint = await externalAddress.toAddressPoint();
Expand All @@ -139,3 +135,13 @@ export async function computeTaggingSecretPoint(
// computeAddressSecret takes care of selecting the one that leads to a positive y-coordinate, which is the only valid address point
return curve.mul(externalAddressPoint, await computeAddressSecret(knownPreaddress, ivsk));
}

export async function computeAppTaggingSecret(
knownAddress: CompleteAddress,
ivsk: Fq,
externalAddress: AztecAddress,
app: AztecAddress,
) {
const taggingSecretPoint = await computeTaggingSecretPoint(knownAddress, ivsk, externalAddress);
return poseidon2Hash([taggingSecretPoint.x, taggingSecretPoint.y, app]);
}
Loading