Skip to content

Commit

Permalink
refactor: nuking L2BlockContext (#5569)
Browse files Browse the repository at this point in the history
Fixes
[#5534](#5534)
  • Loading branch information
benesjan authored Apr 4, 2024
1 parent 59799f2 commit 1299190
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 124 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { InboxLeaf, L2Block, L2BlockContext, LogId, LogType, TxHash } from '@aztec/circuit-types';
import { InboxLeaf, L2Block, LogId, LogType, TxHash } from '@aztec/circuit-types';
import '@aztec/circuit-types/jest';
import { AztecAddress, Fr, INITIAL_L2_BLOCK_NUM, L1_TO_L2_MSG_SUBTREE_HEIGHT } from '@aztec/circuits.js';
import {
Expand Down Expand Up @@ -328,7 +328,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch
// get random tx
const targetBlockIndex = randomInt(numBlocks);
const targetTxIndex = randomInt(txsPerBlock);
const targetTxHash = new L2BlockContext(blocks.retrievedData[targetBlockIndex]).getTxHash(targetTxIndex);
const targetTxHash = blocks.retrievedData[targetBlockIndex].body.txEffects[targetTxIndex].txHash;

const response = await store.getUnencryptedLogs({ txHash: targetTxHash });
const logs = response.logs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
type GetUnencryptedLogsResponse,
type InboxLeaf,
type L2Block,
L2BlockContext,
type L2BlockL2Logs,
type LogFilter,
LogId,
Expand Down Expand Up @@ -37,7 +36,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
/**
* An array containing all the L2 blocks that have been fetched so far.
*/
private l2BlockContexts: L2BlockContext[] = [];
private l2Blocks: L2Block[] = [];

/**
* A mapping of body hash to body
Expand Down Expand Up @@ -144,7 +143,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
*/
public addBlocks(blocks: DataRetrieval<L2Block>): Promise<boolean> {
this.lastL1BlockNewBlocks = blocks.lastProcessedL1BlockNumber;
this.l2BlockContexts.push(...blocks.retrievedData.map(block => new L2BlockContext(block)));
this.l2Blocks.push(...blocks.retrievedData);
this.txEffects.push(...blocks.retrievedData.flatMap(b => b.body.txEffects));
return Promise.resolve(true);
}
Expand Down Expand Up @@ -242,12 +241,12 @@ export class MemoryArchiverStore implements ArchiverDataStore {
}

const fromIndex = Math.max(from - INITIAL_L2_BLOCK_NUM, 0);
if (fromIndex >= this.l2BlockContexts.length) {
if (fromIndex >= this.l2Blocks.length) {
return Promise.resolve([]);
}

const toIndex = fromIndex + limit;
return Promise.resolve(this.l2BlockContexts.slice(fromIndex, toIndex).map(blockContext => blockContext.block));
return Promise.resolve(this.l2Blocks.slice(fromIndex, toIndex));
}

/**
Expand All @@ -266,12 +265,11 @@ export class MemoryArchiverStore implements ArchiverDataStore {
* @returns The requested tx receipt (or undefined if not found).
*/
public getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
for (const blockContext of this.l2BlockContexts) {
for (const currentTxHash of blockContext.getTxHashes()) {
for (const block of this.l2Blocks) {
const txHashes = block.body.txEffects.map(txEffect => txEffect.txHash);
for (const currentTxHash of txHashes) {
if (currentTxHash.equals(txHash)) {
return Promise.resolve(
new TxReceipt(txHash, TxStatus.MINED, '', blockContext.block.hash().toBuffer(), blockContext.block.number),
);
return Promise.resolve(new TxReceipt(txHash, TxStatus.MINED, '', block.hash().toBuffer(), block.number));
}
}
}
Expand Down Expand Up @@ -364,20 +362,18 @@ export class MemoryArchiverStore implements ArchiverDataStore {
const logs: ExtendedUnencryptedL2Log[] = [];

for (; fromBlockIndex < toBlockIndex; fromBlockIndex++) {
const blockContext = this.l2BlockContexts[fromBlockIndex];
const block = this.l2Blocks[fromBlockIndex];
const blockLogs = this.unencryptedLogsPerBlock[fromBlockIndex];
for (; txIndexInBlock < blockLogs.txLogs.length; txIndexInBlock++) {
const txLogs = blockLogs.txLogs[txIndexInBlock].unrollLogs();
for (; logIndexInTx < txLogs.length; logIndexInTx++) {
const log = txLogs[logIndexInTx];
if (
(!txHash || blockContext.getTxHash(txIndexInBlock).equals(txHash)) &&
(!txHash || block.body.txEffects[txIndexInBlock].txHash.equals(txHash)) &&
(!contractAddress || log.contractAddress.equals(contractAddress)) &&
(!selector || log.selector.equals(selector))
) {
logs.push(
new ExtendedUnencryptedL2Log(new LogId(blockContext.block.number, txIndexInBlock, logIndexInTx), log),
);
logs.push(new ExtendedUnencryptedL2Log(new LogId(block.number, txIndexInBlock, logIndexInTx), log));
if (logs.length === this.maxLogs) {
return Promise.resolve({
logs,
Expand All @@ -402,10 +398,10 @@ export class MemoryArchiverStore implements ArchiverDataStore {
* @returns The number of the latest L2 block processed.
*/
public getSynchedL2BlockNumber(): Promise<number> {
if (this.l2BlockContexts.length === 0) {
if (this.l2Blocks.length === 0) {
return Promise.resolve(INITIAL_L2_BLOCK_NUM - 1);
}
return Promise.resolve(this.l2BlockContexts[this.l2BlockContexts.length - 1].block.number);
return Promise.resolve(this.l2Blocks[this.l2Blocks.length - 1].number);
}

public getSynchPoint(): Promise<ArchiverL1SynchPoint> {
Expand Down
1 change: 0 additions & 1 deletion yarn-project/circuit-types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export * from './notes/index.js';
export * from './messaging/index.js';
export * from './l2_block.js';
export * from './body.js';
export * from './l2_block_context.js';
export * from './l2_block_downloader/index.js';
export * from './l2_block_source.js';
export * from './tx_effect.js';
Expand Down
37 changes: 0 additions & 37 deletions yarn-project/circuit-types/src/l2_block_context.ts

This file was deleted.

14 changes: 3 additions & 11 deletions yarn-project/p2p/src/client/p2p_client.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import {
type L2Block,
L2BlockContext,
L2BlockDownloader,
type L2BlockSource,
type Tx,
type TxHash,
} from '@aztec/circuit-types';
import { type L2Block, L2BlockDownloader, type L2BlockSource, type Tx, type TxHash } from '@aztec/circuit-types';
import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants';
import { createDebugLogger } from '@aztec/foundation/log';
import { type AztecKVStore, type AztecSingleton } from '@aztec/kv-store';
Expand Down Expand Up @@ -280,9 +273,8 @@ export class P2PClient implements P2P {
* @returns Empty promise.
*/
private async reconcileTxPool(blocks: L2Block[]): Promise<void> {
for (let i = 0; i < blocks.length; i++) {
const blockContext = new L2BlockContext(blocks[i]);
const txHashes = blockContext.getTxHashes();
for (const block of blocks) {
const txHashes = block.body.txEffects.map(txEffect => txEffect.txHash);
await this.txPool.deleteTxs(txHashes);
this.p2pService.settledTxs(txHashes);
}
Expand Down
34 changes: 16 additions & 18 deletions yarn-project/pxe/src/note_processor/note_processor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
type KeyStore,
type L1NotePayload,
L2Block,
L2BlockContext,
TaggedNote,
} from '@aztec/circuit-types';
import { Fr, INITIAL_L2_BLOCK_NUM, MAX_NEW_NOTE_HASHES_PER_TX } from '@aztec/circuits.js';
Expand Down Expand Up @@ -87,7 +86,7 @@ describe('Note Processor', () => {
throw new Error(`Tx size should be less than ${TXS_PER_BLOCK}.`);
}

const blockContexts: L2BlockContext[] = [];
const blocks: L2Block[] = [];
const encryptedLogsArr: EncryptedL2BlockL2Logs[] = [];
const ownedL1NotePayloads: L1NotePayload[] = [];
const numberOfBlocks = prependedBlocks + appendedBlocks + 1;
Expand All @@ -109,10 +108,9 @@ describe('Note Processor', () => {
block.body.txEffects[i].noteHashes = txEffectNotes.map(n => pedersenHash(n.notePayload.note.items));
}

const randomBlockContext = new L2BlockContext(block);
blockContexts.push(randomBlockContext);
blocks.push(block);
}
return { blockContexts, encryptedLogsArr, ownedL1NotePayloads };
return { blocks, encryptedLogsArr, ownedL1NotePayloads };
};

beforeAll(() => {
Expand Down Expand Up @@ -152,8 +150,8 @@ describe('Note Processor', () => {
});

it('should store a note that belongs to us', async () => {
const { blockContexts, encryptedLogsArr, ownedL1NotePayloads } = mockData([[2]]);
await noteProcessor.process(blockContexts, encryptedLogsArr);
const { blocks, encryptedLogsArr, ownedL1NotePayloads } = mockData([[2]]);
await noteProcessor.process(blocks, encryptedLogsArr);

expect(addNotesSpy).toHaveBeenCalledTimes(1);
expect(addNotesSpy).toHaveBeenCalledWith([
Expand All @@ -169,12 +167,12 @@ describe('Note Processor', () => {
const appendedBlocks = 1;
const thisBlockDataStartIndex = firstBlockDataStartIndex + prependedBlocks * numCommitmentsPerBlock;

const { blockContexts, encryptedLogsArr, ownedL1NotePayloads } = mockData(
const { blocks, encryptedLogsArr, ownedL1NotePayloads } = mockData(
[[], [1], [], [0, 2]],
prependedBlocks,
appendedBlocks,
);
await noteProcessor.process(blockContexts, encryptedLogsArr);
await noteProcessor.process(blocks, encryptedLogsArr);

expect(addNotesSpy).toHaveBeenCalledTimes(1);
expect(addNotesSpy).toHaveBeenCalledWith([
Expand All @@ -197,17 +195,17 @@ describe('Note Processor', () => {
}, 30_000);

it('should not store notes that do not belong to us', async () => {
const { blockContexts, encryptedLogsArr } = mockData([]);
await noteProcessor.process(blockContexts, encryptedLogsArr);
const { blocks, encryptedLogsArr } = mockData([]);
await noteProcessor.process(blocks, encryptedLogsArr);
});

it('should be able to recover two note payloads with containing the same note', async () => {
const note = TaggedNote.random(); // L1NotePayload.random();
const note2 = TaggedNote.random(); // L1NotePayload.random();
// All note payloads except one have the same contract address, storage slot, and the actual note.
const notes = [note, note, note, note2, note];
const { blockContexts, encryptedLogsArr, ownedL1NotePayloads } = mockData([[0, 2], [], [0, 1, 3]], 0, 0, notes);
await noteProcessor.process(blockContexts, encryptedLogsArr);
const { blocks, encryptedLogsArr, ownedL1NotePayloads } = mockData([[0, 2], [], [0, 1, 3]], 0, 0, notes);
await noteProcessor.process(blocks, encryptedLogsArr);

const addedNoteDaos: NoteDao[] = addNotesSpy.mock.calls[0][0];
expect(addedNoteDaos.map(dao => dao)).toEqual([
Expand All @@ -229,14 +227,14 @@ describe('Note Processor', () => {
});

it('advances the block number', async () => {
const { blockContexts, encryptedLogsArr } = mockData([[2]]);
await noteProcessor.process(blockContexts, encryptedLogsArr);
expect(noteProcessor.status.syncedToBlock).toEqual(blockContexts.at(-1)?.block.number);
const { blocks, encryptedLogsArr } = mockData([[2]]);
await noteProcessor.process(blocks, encryptedLogsArr);
expect(noteProcessor.status.syncedToBlock).toEqual(blocks.at(-1)?.number);
});

it('should restore the last block number processed and ignore the starting block', async () => {
const { blockContexts, encryptedLogsArr } = mockData([[2]]);
await noteProcessor.process(blockContexts, encryptedLogsArr);
const { blocks, encryptedLogsArr } = mockData([[2]]);
await noteProcessor.process(blocks, encryptedLogsArr);

const newNoteProcessor = new NoteProcessor(
owner.getPublicKey(),
Expand Down
40 changes: 17 additions & 23 deletions yarn-project/pxe/src/note_processor/note_processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
type EncryptedL2BlockL2Logs,
type KeyStore,
L1NotePayload,
type L2BlockContext,
type L2Block,
TaggedNote,
} from '@aztec/circuit-types';
import { type NoteProcessorStats } from '@aztec/circuit-types/stats';
Expand All @@ -25,9 +25,9 @@ import { produceNoteDao } from './produce_note_dao.js';
*/
interface ProcessedData {
/**
* Holds L2 block and a cache of already requested tx hashes.
* Holds L2 block.
*/
blockContext: L2BlockContext;
block: L2Block;
/**
* DAOs of processed notes.
*/
Expand Down Expand Up @@ -82,25 +82,20 @@ export class NoteProcessor {
}

/**
* Process the given L2 block contexts and encrypted logs to update the note processor.
* It synchronizes the user's account by decrypting the encrypted logs and processing
* the transactions and auxiliary data associated with them.
* Throws an error if the number of block contexts and encrypted logs do not match.
* Extracts new user-relevant notes from the information contained in the provided L2 blocks and encrypted logs.
*
* @param l2BlockContexts - An array of L2 block contexts to be processed.
* @param encryptedL2BlockLogs - An array of encrypted logs associated with the L2 block contexts.
* @throws If the number of blocks and encrypted logs do not match.
* @param l2Blocks - L2 blocks to be processed.
* @param encryptedL2BlockLogs - Encrypted logs associated with the L2 blocks.
* @returns A promise that resolves once the processing is completed.
*/
public async process(
l2BlockContexts: L2BlockContext[],
encryptedL2BlockLogs: EncryptedL2BlockL2Logs[],
): Promise<void> {
if (l2BlockContexts.length !== encryptedL2BlockLogs.length) {
public async process(l2Blocks: L2Block[], encryptedL2BlockLogs: EncryptedL2BlockL2Logs[]): Promise<void> {
if (l2Blocks.length !== encryptedL2BlockLogs.length) {
throw new Error(
`Number of blocks and EncryptedLogs is not equal. Received ${l2BlockContexts.length} blocks, ${encryptedL2BlockLogs.length} encrypted logs.`,
`Number of blocks and EncryptedLogs is not equal. Received ${l2Blocks.length} blocks, ${encryptedL2BlockLogs.length} encrypted logs.`,
);
}
if (!l2BlockContexts.length) {
if (l2Blocks.length === 0) {
return;
}

Expand All @@ -113,8 +108,7 @@ export class NoteProcessor {
for (let blockIndex = 0; blockIndex < encryptedL2BlockLogs.length; ++blockIndex) {
this.stats.blocks++;
const { txLogs } = encryptedL2BlockLogs[blockIndex];
const blockContext = l2BlockContexts[blockIndex];
const block = blockContext.block;
const block = l2Blocks[blockIndex];
const dataStartIndexForBlock =
block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
block.body.numberOfTxsIncludingPadded * MAX_NEW_NOTE_HASHES_PER_TX;
Expand All @@ -140,7 +134,7 @@ export class NoteProcessor {
if (taggedNote?.notePayload) {
const { notePayload: payload } = taggedNote;
// We have successfully decrypted the data.
const txHash = blockContext.getTxHash(indexOfTxInABlock);
const txHash = block.body.txEffects[indexOfTxInABlock].txHash;
try {
const noteDao = await produceNoteDao(
this.simulator,
Expand Down Expand Up @@ -179,15 +173,15 @@ export class NoteProcessor {
}

blocksAndNotes.push({
blockContext: l2BlockContexts[blockIndex],
block: l2Blocks[blockIndex],
noteDaos,
});
}

await this.processBlocksAndNotes(blocksAndNotes);
await this.processDeferredNotes(deferredNoteDaos);

const syncedToBlock = l2BlockContexts[l2BlockContexts.length - 1].block.number;
const syncedToBlock = l2Blocks[l2Blocks.length - 1].number;
await this.db.setSynchedBlockNumberForPublicKey(this.publicKey, syncedToBlock);

this.log(`Synched block ${syncedToBlock}`);
Expand All @@ -200,7 +194,7 @@ export class NoteProcessor {
* transaction auxiliary data from the database. This function keeps track of new nullifiers
* and ensures all other transactions are updated with newly settled block information.
*
* @param blocksAndNotes - Array of objects containing L2BlockContexts, user-pertaining transaction indices, and NoteDaos.
* @param blocksAndNotes - Array of objects containing L2 blocks, user-pertaining transaction indices, and NoteDaos.
*/
private async processBlocksAndNotes(blocksAndNotes: ProcessedData[]) {
const noteDaos = blocksAndNotes.flatMap(b => b.noteDaos);
Expand All @@ -216,7 +210,7 @@ export class NoteProcessor {
}

const newNullifiers: Fr[] = blocksAndNotes.flatMap(b =>
b.blockContext.block.body.txEffects.flatMap(txEffect => txEffect.nullifiers),
b.block.body.txEffects.flatMap(txEffect => txEffect.nullifiers),
);
const removedNotes = await this.db.removeNullifiedNotes(newNullifiers, this.publicKey);
removedNotes.forEach(noteDao => {
Expand Down
Loading

0 comments on commit 1299190

Please sign in to comment.