Skip to content

Commit

Permalink
better approach
Browse files Browse the repository at this point in the history
  • Loading branch information
sklppy88 committed Nov 21, 2024
1 parent 8b53b70 commit 621ffab
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 68 deletions.
13 changes: 6 additions & 7 deletions yarn-project/pxe/src/database/kv_pxe_database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -677,13 +677,12 @@ export class KVPxeDatabase implements PxeDatabase {
await this.#setTaggingSecretsIndexes(indexedSecrets, this.#taggingSecretIndexesForRecipients);
}

#setTaggingSecretsIndexes(
indexedSecrets: IndexedTaggingSecret[],
storageMap: AztecMap<string, number>,
): Promise<Promise<void>[]> {
return this.db.transaction(() =>
indexedSecrets.map(indexedSecret => storageMap.set(indexedSecret.secret.toString(), indexedSecret.index)),
);
#setTaggingSecretsIndexes(indexedSecrets: IndexedTaggingSecret[], storageMap: AztecMap<string, number>) {
return this.db.transaction(() => {
indexedSecrets.forEach(
indexedSecret => void storageMap.set(indexedSecret.secret.toString(), indexedSecret.index),
);
});
}

async getTaggingSecretsIndexesAsRecipient(appTaggingSecrets: Fr[]) {
Expand Down
5 changes: 5 additions & 0 deletions yarn-project/pxe/src/database/pxe_database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD
*/
getTaggingSecretsIndexesAsSender(appTaggingSecrets: Fr[]): Promise<number[]>;

/**
* Sets the index for the provided app siloed tagging secrets
* To be used when the generated tags have been "seen" as a sender
* @param appTaggingSecrets - The app siloed tagging secrets.
*/
setTaggingSecretsIndexesAsSender(indexedTaggingSecrets: IndexedTaggingSecret[]): Promise<void>;

/**
Expand Down
100 changes: 41 additions & 59 deletions yarn-project/pxe/src/simulator_oracle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ export class SimulatorOracle implements DBOracle {
);

const [index] = await this.db.getTaggingSecretsIndexesAsSender([secret]);
await this.db.setTaggingSecretsIndexesAsSender([new IndexedTaggingSecret(secret, index)]);
await this.db.setTaggingSecretsIndexesAsSender([new IndexedTaggingSecret(secret, index + 1)]);
}

async #calculateTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) {
Expand Down Expand Up @@ -335,19 +335,39 @@ export class SimulatorOracle implements DBOracle {
return appTaggingSecrets.map((secret, i) => new IndexedTaggingSecret(secret, indexes[i]));
}

async #getAppTaggingSecretAsSender(
/**
* Updates the local index of the shared tagging secret of a sender / recipient pair
* if a log with a larger index is found from the node.
* @param contractAddress - The address of the contract that the logs are tagged for
* @param sender - The address of the sender, we must know the sender's ivsk_m.
* @param recipient - The address of the recipient.
*/
public async syncTaggedLogsAsSender(
contractAddress: AztecAddress,
sender: AztecAddress,
recipient: AztecAddress,
): Promise<IndexedTaggingSecret> {
const senderCompleteAddress = await this.getCompleteAddress(sender);
const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
): Promise<void> {
const contractName = await this.contractDataOracle.getDebugContractName(contractAddress);
const appTaggingSecret = await this.#calculateTaggingSecret(contractAddress, sender, recipient);
let [currentIndex] = await this.db.getTaggingSecretsIndexesAsSender([appTaggingSecret]);

const sharedSecret = computeTaggingSecret(senderCompleteAddress, senderIvsk, recipient);
const appTaggingSecret = poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]);
const [index] = await this.db.getTaggingSecretsIndexesAsSender([appTaggingSecret]);
while (true) {
const currentIndexedAppTaggingSecret = new IndexedTaggingSecret(appTaggingSecret, currentIndex);
const currentTag = currentIndexedAppTaggingSecret.computeTag(recipient);

const [[possibleLog]] = await this.aztecNode.getLogsByTags([currentTag]);

return new IndexedTaggingSecret(appTaggingSecret, index);
if (possibleLog !== undefined) {
currentIndex++;
} else {
this.log.debug(
`Syncing logs for sender ${sender}, secret ${appTaggingSecret}:${currentIndex} at contract: ${contractName}(${contractAddress})`,
);

await this.db.setTaggingSecretsIndexesAsSender([new IndexedTaggingSecret(appTaggingSecret, currentIndex)]);
break;
}
}
}

/**
Expand All @@ -363,34 +383,6 @@ export class SimulatorOracle implements DBOracle {
scopes?: AztecAddress[],
): Promise<Map<string, TxScopedL2Log[]>> {
const recipients = scopes ? scopes : await this.keyStore.getAccounts();

const result = await this.#syncTaggedLogs(contractAddress, recipients);

for (const [key, value] of result) {
result.set(
key,
value.filter(log => log.blockNumber <= maxBlockNumber),
);
}

return result;
}

public async syncTaggedLogsAsSender(
contractAddress: AztecAddress,
sender: AztecAddress,
recipient: AztecAddress,
): Promise<Map<string, TxScopedL2Log[]>> {
const result = await this.#syncTaggedLogs(contractAddress, [recipient], sender);

return result;
}

async #syncTaggedLogs(
contractAddress: AztecAddress,
recipients: AztecAddress[],
asSender?: AztecAddress,
): Promise<Map<string, TxScopedL2Log[]>> {
const result = new Map<string, TxScopedL2Log[]>();
const contractName = await this.contractDataOracle.getDebugContractName(contractAddress);
for (const recipient of recipients) {
Expand All @@ -402,12 +394,7 @@ 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 appTaggingSecrets: IndexedTaggingSecret[] = [];
if (asSender === undefined) {
appTaggingSecrets.push(...(await this.#getAppTaggingSecretsForContacts(contractAddress, recipient)));
} else {
appTaggingSecrets.push(await this.#getAppTaggingSecretAsSender(contractAddress, asSender, 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 inadvertedly incremented their index without use getting any logs (for example, in case
Expand Down Expand Up @@ -485,27 +472,22 @@ export class SimulatorOracle implements DBOracle {
newTaggingSecrets.push(newTaggingSecret);
}
});
if (asSender === undefined) {
await this.db.setTaggingSecretsIndexesAsRecipient(
Object.keys(secretsToIncrement).map(
secret => new IndexedTaggingSecret(Fr.fromString(secret), secretsToIncrement[secret]),
),
);
} else {
await this.db.setTaggingSecretsIndexesAsSender(
Object.keys(secretsToIncrement).map(
secret => new IndexedTaggingSecret(Fr.fromString(secret), secretsToIncrement[secret]),
),
);
}

await this.db.setTaggingSecretsIndexesAsRecipient(
Object.keys(secretsToIncrement).map(
secret => new IndexedTaggingSecret(Fr.fromString(secret), secretsToIncrement[secret]),
),
);
currentTagggingSecrets = newTaggingSecrets;
}

result.set(
recipient.toString(),
// Duplicates are likely to happen due to the sliding window, so we filter them out
logs.filter((log, index, self) => index === self.findIndex(otherLog => otherLog.equals(log))),
// 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) =>
log.blockNumber <= maxBlockNumber && index === self.findIndex(otherLog => otherLog.equals(log)),
),
);
}
return result;
Expand Down
40 changes: 38 additions & 2 deletions yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ describe('Simulator oracle', () => {
describe('sync tagged logs', () => {
const NUM_SENDERS = 10;
const SENDER_OFFSET_WINDOW_SIZE = 10;
let senders: { completeAddress: CompleteAddress; ivsk: Fq }[];
let senders: { completeAddress: CompleteAddress; ivsk: Fq; secretKey: Fr }[];

function generateMockLogs(senderOffset: number) {
const logs: { [k: string]: TxScopedL2Log[] } = {};
Expand Down Expand Up @@ -232,7 +232,7 @@ describe('Simulator oracle', () => {
const partialAddress = Fr.random();
const address = computeAddress(keys.publicKeys, partialAddress);
const completeAddress = new CompleteAddress(address, keys.publicKeys, partialAddress);
return { completeAddress, ivsk: keys.masterIncomingViewingSecretKey };
return { completeAddress, ivsk: keys.masterIncomingViewingSecretKey, secretKey: new Fr(index) };
});
for (const sender of senders) {
await database.addContactAddress(sender.completeAddress.address);
Expand Down Expand Up @@ -268,6 +268,42 @@ describe('Simulator oracle', () => {
expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2 + SENDER_OFFSET_WINDOW_SIZE);
});

it('should sync tagged logs as senders', async () => {
for (const sender of senders) {
await database.addCompleteAddress(sender.completeAddress);
await keyStore.addAccount(sender.secretKey, sender.completeAddress.partialAddress);
}

const senderOffset = 0;
generateMockLogs(senderOffset);

// Recompute the secrets (as recipient) to ensure indexes are updated
const ivsk = await keyStore.getMasterIncomingViewingSecretKey(recipient.address);
const secrets = senders.map(sender => {
const firstSenderSharedSecret = computeTaggingSecret(recipient, ivsk, sender.completeAddress.address);
return poseidon2Hash([firstSenderSharedSecret.x, firstSenderSharedSecret.y, contractAddress]);
});

const indexesAsSender = await database.getTaggingSecretsIndexesAsSender(secrets);
expect(indexesAsSender).toStrictEqual([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);

expect(aztecNode.getLogsByTags.mock.calls.length).toBe(0);

for (let i = 0; i < senders.length; i++) {
await simulatorOracle.syncTaggedLogsAsSender(
contractAddress,
senders[i].completeAddress.address,
recipient.address,
);
}

const indexesAsSenderAfterSync = await database.getTaggingSecretsIndexesAsSender(secrets);
expect(indexesAsSenderAfterSync).toStrictEqual([1, 1, 1, 1, 1, 2, 2, 2, 2, 2]);

// We expect getLogsByTags to be called N + 1 times, where N is the index.
expect(aztecNode.getLogsByTags.mock.calls.length).toBe(2 * 5 + 3 * 5);
});

it('should sync tagged logs with a sender index offset', async () => {
const senderOffset = 5;
generateMockLogs(senderOffset);
Expand Down

0 comments on commit 621ffab

Please sign in to comment.