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

refactor: nuking L2BlockContext #5569

Merged
merged 4 commits into from
Apr 4, 2024
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,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
Loading