Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: process tagged logs #9623

Merged
merged 22 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 16 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
28 changes: 9 additions & 19 deletions noir-projects/aztec-nr/aztec/src/oracle/notes.nr
Original file line number Diff line number Diff line change
Expand Up @@ -231,25 +231,15 @@ unconstrained fn increment_app_tagging_secret_oracle(
_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.
/// For this to work, PXE must know the ivsk_m of the recipient.
pub unconstrained fn get_app_tagging_secrets_for_senders(
recipient: AztecAddress,
) -> [IndexedTaggingSecret] {
let results = get_app_tagging_secrets_for_senders_oracle(recipient);
let mut indexed_tagging_secrets = &[];
for i in 0..results.len() {
if i % 3 != 0 {
continue;
}
indexed_tagging_secrets = indexed_tagging_secrets.push_back(
IndexedTaggingSecret::deserialize([results[i], results[i + 1], results[i + 2]]),
);
pub fn sync_notes(recipient: AztecAddress) {
Thunkar marked this conversation as resolved.
Show resolved Hide resolved
unsafe {
sync_notes_oracle_wrapper(recipient);
Thunkar marked this conversation as resolved.
Show resolved Hide resolved
}
indexed_tagging_secrets
}

#[oracle(getAppTaggingSecretsForSenders)]
unconstrained fn get_app_tagging_secrets_for_senders_oracle(_recipient: AztecAddress) -> [Field] {}
unconstrained fn sync_notes_oracle_wrapper(recipient: AztecAddress) {
sync_notes_oracle(recipient);
}

#[oracle(syncNotes)]
unconstrained fn sync_notes_oracle(_recipient: AztecAddress) {}
6 changes: 3 additions & 3 deletions yarn-project/archiver/src/archiver/archiver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
type EncryptedL2NoteLog,
type FromLogType,
type GetUnencryptedLogsResponse,
type InboxLeaf,
Expand All @@ -15,6 +14,7 @@ import {
type TxEffect,
type TxHash,
type TxReceipt,
type TxScopedEncryptedL2NoteLog,
type UnencryptedL2Log,
} from '@aztec/circuit-types';
import {
Expand Down Expand Up @@ -634,7 +634,7 @@ export class Archiver implements ArchiveSource {
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
* that tag.
*/
getLogsByTags(tags: Fr[]): Promise<EncryptedL2NoteLog[][]> {
getLogsByTags(tags: Fr[]): Promise<TxScopedEncryptedL2NoteLog[][]> {
return this.store.getLogsByTags(tags);
}

Expand Down Expand Up @@ -934,7 +934,7 @@ class ArchiverStoreHelper
): Promise<L2BlockL2Logs<FromLogType<TLogType>>[]> {
return this.store.getLogs(from, limit, logType);
}
getLogsByTags(tags: Fr[]): Promise<EncryptedL2NoteLog[][]> {
getLogsByTags(tags: Fr[]): Promise<TxScopedEncryptedL2NoteLog[][]> {
return this.store.getLogsByTags(tags);
}
getUnencryptedLogs(filter: LogFilter): Promise<GetUnencryptedLogsResponse> {
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/archiver/src/archiver/archiver_store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
type EncryptedL2NoteLog,
type FromLogType,
type GetUnencryptedLogsResponse,
type InboxLeaf,
Expand All @@ -10,6 +9,7 @@ import {
type TxEffect,
type TxHash,
type TxReceipt,
type TxScopedEncryptedL2NoteLog,
} from '@aztec/circuit-types';
import {
type ContractClassPublic,
Expand Down Expand Up @@ -142,7 +142,7 @@ export interface ArchiverDataStore {
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
* that tag.
*/
getLogsByTags(tags: Fr[]): Promise<EncryptedL2NoteLog[][]>;
getLogsByTags(tags: Fr[]): Promise<TxScopedEncryptedL2NoteLog[][]>;

/**
* Gets unencrypted logs based on the provided filter.
Expand Down
12 changes: 7 additions & 5 deletions yarn-project/archiver/src/archiver/archiver_store_test_suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,9 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch

logsByTags.forEach((logsByTag, logIndex) => {
expect(logsByTag).toHaveLength(1);
const [log] = logsByTag;
expect(log).toEqual(
const [scopedLog] = logsByTag;
expect(scopedLog.txHash).toEqual(blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash);
expect(scopedLog.log).toEqual(
blocks[targetBlockIndex].data.body.noteEncryptedLogs.txLogs[targetTxIndex].unrollLogs()[logIndex],
);
});
Expand All @@ -427,7 +428,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch

logsByTags.forEach(logsByTag => {
expect(logsByTag).toHaveLength(2);
const [tag0, tag1] = logsByTag.map(log => new Fr(log.data.subarray(0, 32)));
const [tag0, tag1] = logsByTag.map(scopedLog => new Fr(scopedLog.log.data.subarray(0, 32)));
expect(tag0).toEqual(tag1);
});
});
Expand All @@ -450,8 +451,9 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch

populatedLogsByTags.forEach((logsByTag, logIndex) => {
expect(logsByTag).toHaveLength(1);
const [log] = logsByTag;
expect(log).toEqual(
const [scopedLog] = logsByTag;
expect(scopedLog.txHash).toEqual(blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash);
expect(scopedLog.log).toEqual(
blocks[targetBlockIndex].data.body.noteEncryptedLogs.txLogs[targetTxIndex].unrollLogs()[logIndex + 1],
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
type EncryptedL2NoteLog,
type FromLogType,
type GetUnencryptedLogsResponse,
type InboxLeaf,
Expand All @@ -10,6 +9,7 @@ import {
type TxEffect,
type TxHash,
type TxReceipt,
type TxScopedEncryptedL2NoteLog,
} from '@aztec/circuit-types';
import {
type ContractClassPublic,
Expand Down Expand Up @@ -245,7 +245,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
* that tag.
*/
getLogsByTags(tags: Fr[]): Promise<EncryptedL2NoteLog[][]> {
getLogsByTags(tags: Fr[]): Promise<TxScopedEncryptedL2NoteLog[][]> {
try {
return this.#logStore.getLogsByTags(tags);
} catch (err) {
Expand Down
22 changes: 15 additions & 7 deletions yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
EncryptedL2BlockL2Logs,
EncryptedL2NoteLog,
EncryptedNoteL2BlockL2Logs,
ExtendedUnencryptedL2Log,
type FromLogType,
Expand All @@ -10,11 +9,12 @@ import {
type LogFilter,
LogId,
LogType,
TxScopedEncryptedL2NoteLog,
UnencryptedL2BlockL2Logs,
type UnencryptedL2Log,
} from '@aztec/circuit-types';
import { Fr } from '@aztec/circuits.js';
import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants';
import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX } from '@aztec/circuits.js/constants';
import { createDebugLogger } from '@aztec/foundation/log';
import { type AztecKVStore, type AztecMap, type AztecMultiMap } from '@aztec/kv-store';

Expand Down Expand Up @@ -52,8 +52,13 @@ export class LogStore {
addLogs(blocks: L2Block[]): Promise<boolean> {
return this.db.transaction(() => {
blocks.forEach(block => {
const dataStartIndexForBlock =
block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX;
void this.#noteEncryptedLogsByBlock.set(block.number, block.body.noteEncryptedLogs.toBuffer());
block.body.noteEncryptedLogs.txLogs.forEach(txLogs => {
block.body.noteEncryptedLogs.txLogs.forEach((txLogs, txIndex) => {
const txHash = block.body.txEffects[txIndex].txHash;
const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
Thunkar marked this conversation as resolved.
Show resolved Hide resolved
const noteLogs = txLogs.unrollLogs();
noteLogs.forEach(noteLog => {
if (noteLog.data.length < 32) {
Expand All @@ -63,12 +68,15 @@ export class LogStore {
try {
const tag = new Fr(noteLog.data.subarray(0, 32));
const hexHash = noteLog.hash().toString('hex');
// Ideally we'd store all of the logs for a matching tag in an AztecMultiMap, but this type doesn't doesn't
// Ideally we'd store all of the logs for a matching tag in an AztecMultiMap, but this type doesn't
// handle storing buffers well. The 'ordered-binary' encoding returns an error trying to decode buffers
// ('the number <> cannot be converted to a BigInt because it is not an integer'). We therefore store
// instead the hashes of the logs.
void this.#noteEncryptedLogHashesByTag.set(tag.toString(), hexHash);
void this.#noteEncryptedLogsByHash.set(hexHash, noteLog.toBuffer());
void this.#noteEncryptedLogsByHash.set(
hexHash,
new TxScopedEncryptedL2NoteLog(txHash, dataStartIndexForTx, noteLog).toBuffer(),
);
void this.#noteEncryptedLogTagsByBlock.set(block.number, tag.toString());
} catch (err) {
this.#log.warn(`Failed to add tagged note log to store: ${err}`);
Expand Down Expand Up @@ -156,7 +164,7 @@ export class LogStore {
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
* that tag.
*/
getLogsByTags(tags: Fr[]): Promise<EncryptedL2NoteLog[][]> {
getLogsByTags(tags: Fr[]): Promise<TxScopedEncryptedL2NoteLog[][]> {
return this.db.transaction(() => {
return tags.map(tag => {
const logHashes = Array.from(this.#noteEncryptedLogHashesByTag.getValues(tag.toString()));
Expand All @@ -166,7 +174,7 @@ export class LogStore {
// addLogs should ensure that we never have undefined logs, but we filter them out regardless to protect
// ourselves from database corruption
.filter(noteLogBuffer => noteLogBuffer != undefined)
.map(noteLogBuffer => EncryptedL2NoteLog.fromBuffer(noteLogBuffer!))
.map(noteLogBuffer => TxScopedEncryptedL2NoteLog.fromBuffer(noteLogBuffer!))
);
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
type EncryptedL2BlockL2Logs,
type EncryptedL2NoteLog,
type EncryptedNoteL2BlockL2Logs,
ExtendedUnencryptedL2Log,
type FromLogType,
Expand All @@ -14,6 +13,7 @@ import {
type TxEffect,
type TxHash,
TxReceipt,
TxScopedEncryptedL2NoteLog,
type UnencryptedL2BlockL2Logs,
} from '@aztec/circuit-types';
import {
Expand All @@ -24,6 +24,7 @@ import {
Fr,
type Header,
INITIAL_L2_BLOCK_NUM,
MAX_NOTE_HASHES_PER_TX,
type UnconstrainedFunctionWithMembershipProof,
} from '@aztec/circuits.js';
import { type ContractArtifact } from '@aztec/foundation/abi';
Expand Down Expand Up @@ -51,7 +52,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {

private noteEncryptedLogsPerBlock: Map<number, EncryptedNoteL2BlockL2Logs> = new Map();

private taggedNoteEncryptedLogs: Map<string, EncryptedL2NoteLog[]> = new Map();
private taggedNoteEncryptedLogs: Map<string, TxScopedEncryptedL2NoteLog[]> = new Map();

private noteEncryptedLogTagsPerBlock: Map<number, Fr[]> = new Map();

Expand Down Expand Up @@ -213,8 +214,13 @@ export class MemoryArchiverStore implements ArchiverDataStore {
*/
addLogs(blocks: L2Block[]): Promise<boolean> {
blocks.forEach(block => {
const dataStartIndexForBlock =
block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX;
this.noteEncryptedLogsPerBlock.set(block.number, block.body.noteEncryptedLogs);
block.body.noteEncryptedLogs.txLogs.forEach(txLogs => {
block.body.noteEncryptedLogs.txLogs.forEach((txLogs, txIndex) => {
const txHash = block.body.txEffects[txIndex].txHash;
const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
const noteLogs = txLogs.unrollLogs();
noteLogs.forEach(noteLog => {
if (noteLog.data.length < 32) {
Expand All @@ -224,7 +230,10 @@ export class MemoryArchiverStore implements ArchiverDataStore {
try {
const tag = new Fr(noteLog.data.subarray(0, 32));
const currentNoteLogs = this.taggedNoteEncryptedLogs.get(tag.toString()) || [];
this.taggedNoteEncryptedLogs.set(tag.toString(), [...currentNoteLogs, noteLog]);
this.taggedNoteEncryptedLogs.set(tag.toString(), [
...currentNoteLogs,
new TxScopedEncryptedL2NoteLog(txHash, dataStartIndexForTx, noteLog),
]);
const currentTagsInBlock = this.noteEncryptedLogTagsPerBlock.get(block.number) || [];
this.noteEncryptedLogTagsPerBlock.set(block.number, [...currentTagsInBlock, tag]);
} catch (err) {
Expand Down Expand Up @@ -419,7 +428,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
* that tag.
*/
getLogsByTags(tags: Fr[]): Promise<EncryptedL2NoteLog[][]> {
getLogsByTags(tags: Fr[]): Promise<TxScopedEncryptedL2NoteLog[][]> {
const noteLogs = tags.map(tag => this.taggedNoteEncryptedLogs.get(tag.toString()) || []);
return Promise.resolve(noteLogs);
}
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover';
import {
type AztecNode,
type ClientProtocolCircuitVerifier,
type EncryptedL2NoteLog,
type EpochProofQuote,
type FromLogType,
type GetUnencryptedLogsResponse,
Expand All @@ -27,6 +26,7 @@ import {
type TxEffect,
type TxHash,
TxReceipt,
type TxScopedEncryptedL2NoteLog,
TxStatus,
type TxValidator,
type WorldStateSynchronizer,
Expand Down Expand Up @@ -313,7 +313,7 @@ export class AztecNodeService implements AztecNode {
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
* that tag.
*/
public getLogsByTags(tags: Fr[]): Promise<EncryptedL2NoteLog[][]> {
public getLogsByTags(tags: Fr[]): Promise<TxScopedEncryptedL2NoteLog[][]> {
return this.encryptedLogsSource.getLogsByTags(tags);
}

Expand Down
4 changes: 2 additions & 2 deletions yarn-project/circuit-types/src/interfaces/aztec-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ import type { Fr } from '@aztec/foundation/fields';

import type { L2Block } from '../l2_block.js';
import type {
EncryptedL2NoteLog,
FromLogType,
GetUnencryptedLogsResponse,
L2BlockL2Logs,
LogFilter,
LogType,
TxScopedEncryptedL2NoteLog,
} from '../logs/index.js';
import type { MerkleTreeId } from '../merkle_tree_id.js';
import type { EpochProofQuote } from '../prover_coordination/epoch_proof_quote.js';
Expand Down Expand Up @@ -258,7 +258,7 @@ export interface AztecNode extends ProverCoordination {
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
* that tag.
Thunkar marked this conversation as resolved.
Show resolved Hide resolved
*/
getLogsByTags(tags: Fr[]): Promise<EncryptedL2NoteLog[][]>;
getLogsByTags(tags: Fr[]): Promise<TxScopedEncryptedL2NoteLog[][]>;

/**
* Method to submit a transaction to the p2p pool.
Expand Down
37 changes: 37 additions & 0 deletions yarn-project/circuit-types/src/logs/get_logs_response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Fr } from '@aztec/circuits.js';
import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize';

import { EncryptedL2NoteLog, TxHash } from '../index.js';
import { type ExtendedUnencryptedL2Log } from './extended_unencrypted_l2_log.js';

/**
* It provides documentation for the GetUnencryptedLogsResponse type.
*/
export type GetUnencryptedLogsResponse = {
/**
* An array of ExtendedUnencryptedL2Log elements.
*/
logs: ExtendedUnencryptedL2Log[];

/**
* Indicates if a limit has been reached.
*/
maxLogsHit: boolean;
};

export class TxScopedEncryptedL2NoteLog {
constructor(public txHash: TxHash, public dataStartIndexForTx: number, public log: EncryptedL2NoteLog) {}

toBuffer() {
return Buffer.concat([this.txHash.toBuffer(), numToUInt32BE(this.dataStartIndexForTx), this.log.toBuffer()]);
}

static fromBuffer(buffer: Buffer) {
const reader = BufferReader.asReader(buffer);
return new TxScopedEncryptedL2NoteLog(
TxHash.fromField(reader.readObject(Fr)),
reader.readNumber(),
EncryptedL2NoteLog.fromBuffer(reader.readToEnd()),
);
}
}

This file was deleted.

2 changes: 1 addition & 1 deletion yarn-project/circuit-types/src/logs/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export * from './encrypted_l2_note_log.js';
export * from './encrypted_l2_log.js';
export * from './event_metadata.js';
export * from './get_unencrypted_logs_response.js';
export * from './get_logs_response.js';
export * from './function_l2_logs.js';
export * from './l2_block_l2_logs.js';
export * from './l2_logs_source.js';
Expand Down
Loading
Loading