Skip to content
Open
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
Expand Up @@ -9,15 +9,15 @@ import { randomPublishedL2Block } from '@aztec/stdlib/testing';
import { jest } from '@jest/globals';
import { type MockProxy, mock } from 'jest-mock-extended';

import { AnchorBlockDataProvider } from '../storage/anchor_block_data_provider/anchor_block_data_provider.js';
import { NoteDataProvider } from '../storage/note_data_provider/note_data_provider.js';
import { AnchorBlockStore } from '../storage/anchor_block_store/anchor_block_store.js';
import { NoteStore } from '../storage/note_store/note_store.js';
import { BlockSynchronizer } from './block_synchronizer.js';

describe('BlockSynchronizer', () => {
let synchronizer: BlockSynchronizer;
let tipsStore: L2TipsKVStore;
let anchorBlockDataProvider: AnchorBlockDataProvider;
let noteDataProvider: NoteDataProvider;
let anchorBlockStore: AnchorBlockStore;
let noteStore: NoteStore;
let aztecNode: MockProxy<AztecNode>;
let blockStream: MockProxy<L2BlockStream>;

Expand All @@ -32,22 +32,22 @@ describe('BlockSynchronizer', () => {
blockStream = mock<L2BlockStream>();
aztecNode = mock<AztecNode>();
tipsStore = new L2TipsKVStore(store, 'pxe');
anchorBlockDataProvider = new AnchorBlockDataProvider(store);
noteDataProvider = await NoteDataProvider.create(store);
synchronizer = new TestSynchronizer(aztecNode, anchorBlockDataProvider, noteDataProvider, tipsStore);
anchorBlockStore = new AnchorBlockStore(store);
noteStore = await NoteStore.create(store);
synchronizer = new TestSynchronizer(aztecNode, anchorBlockStore, noteStore, tipsStore);
});

it('sets header from latest block', async () => {
const block = await randomPublishedL2Block(1);
await synchronizer.handleBlockStreamEvent({ type: 'blocks-added', blocks: [block] });

const obtainedHeader = await anchorBlockDataProvider.getBlockHeader();
const obtainedHeader = await anchorBlockStore.getBlockHeader();
expect(obtainedHeader).toEqual(block.block.getBlockHeader());
});

it('removes notes from db on a reorg', async () => {
const rollbackNotesAndNullifiers = jest
.spyOn(noteDataProvider, 'rollbackNotesAndNullifiers')
.spyOn(noteStore, 'rollbackNotesAndNullifiers')
.mockImplementation(() => Promise.resolve());
aztecNode.getBlockHeader.mockImplementation(async blockNumber =>
(await L2Block.random(BlockNumber(blockNumber as number))).getBlockHeader(),
Expand Down
20 changes: 10 additions & 10 deletions yarn-project/pxe/src/block_synchronizer/block_synchronizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { L2BlockStream, type L2BlockStreamEvent, type L2BlockStreamEventHandler
import type { AztecNode } from '@aztec/stdlib/interfaces/client';

import type { PXEConfig } from '../config/index.js';
import type { AnchorBlockDataProvider } from '../storage/anchor_block_data_provider/anchor_block_data_provider.js';
import type { NoteDataProvider } from '../storage/note_data_provider/note_data_provider.js';
import type { AnchorBlockStore } from '../storage/anchor_block_store/anchor_block_store.js';
import type { NoteStore } from '../storage/note_store/note_store.js';

/**
* The BlockSynchronizer class orchestrates synchronization between PXE and Aztec node, maintaining an up-to-date
Expand All @@ -20,8 +20,8 @@ export class BlockSynchronizer implements L2BlockStreamEventHandler {

constructor(
private node: AztecNode,
private anchorBlockDataProvider: AnchorBlockDataProvider,
private noteDataProvider: NoteDataProvider,
private anchorBlockStore: AnchorBlockStore,
private noteStore: NoteStore,
private l2TipsStore: L2TipsKVStore,
config: Partial<Pick<PXEConfig, 'l2BlockBatchSize'>> = {},
loggerOrSuffix?: string | Logger,
Expand Down Expand Up @@ -54,20 +54,20 @@ export class BlockSynchronizer implements L2BlockStreamEventHandler {
archive: lastBlock.archive.root.toString(),
header: lastBlock.header.toInspect(),
});
await this.anchorBlockDataProvider.setHeader(lastBlock.getBlockHeader());
await this.anchorBlockStore.setHeader(lastBlock.getBlockHeader());
break;
}
case 'chain-pruned': {
this.log.warn(`Pruning data after block ${event.block.number} due to reorg`);
// We first unnullify and then remove so that unnullified notes that were created after the block number end up deleted.
const lastSynchedBlockNumber = (await this.anchorBlockDataProvider.getBlockHeader()).getBlockNumber();
await this.noteDataProvider.rollbackNotesAndNullifiers(event.block.number, lastSynchedBlockNumber);
const lastSynchedBlockNumber = (await this.anchorBlockStore.getBlockHeader()).getBlockNumber();
await this.noteStore.rollbackNotesAndNullifiers(event.block.number, lastSynchedBlockNumber);
// Update the header to the last block.
const newHeader = await this.node.getBlockHeader(event.block.number);
if (!newHeader) {
this.log.error(`Block header not found for block number ${event.block.number} during chain prune`);
} else {
await this.anchorBlockDataProvider.setHeader(newHeader);
await this.anchorBlockStore.setHeader(newHeader);
}
break;
}
Expand Down Expand Up @@ -104,13 +104,13 @@ export class BlockSynchronizer implements L2BlockStreamEventHandler {
let currentHeader;

try {
currentHeader = await this.anchorBlockDataProvider.getBlockHeader();
currentHeader = await this.anchorBlockStore.getBlockHeader();
} catch {
this.log.debug('Header is not set, requesting from the node');
}
if (!currentHeader) {
// REFACTOR: We should know the header of the genesis block without having to request it from the node.
await this.anchorBlockDataProvider.setHeader((await this.node.getBlockHeader(BlockNumber.ZERO))!);
await this.anchorBlockStore.setHeader((await this.node.getBlockHeader(BlockNumber.ZERO))!);
}
await this.blockStream.sync();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ import {
getFinalMinRevertibleSideEffectCounter,
} from '@aztec/stdlib/tx';

import type { AddressDataProvider } from '../storage/address_data_provider/address_data_provider.js';
import type { AnchorBlockDataProvider } from '../storage/anchor_block_data_provider/anchor_block_data_provider.js';
import type { CapsuleDataProvider } from '../storage/capsule_data_provider/capsule_data_provider.js';
import type { ContractDataProvider } from '../storage/contract_data_provider/contract_data_provider.js';
import type { NoteDataProvider } from '../storage/note_data_provider/note_data_provider.js';
import type { PrivateEventDataProvider } from '../storage/private_event_data_provider/private_event_data_provider.js';
import type { RecipientTaggingDataProvider } from '../storage/tagging_data_provider/recipient_tagging_data_provider.js';
import type { SenderAddressBook } from '../storage/tagging_data_provider/sender_address_book.js';
import type { SenderTaggingDataProvider } from '../storage/tagging_data_provider/sender_tagging_data_provider.js';
import type { AddressStore } from '../storage/address_store/address_store.js';
import type { AnchorBlockStore } from '../storage/anchor_block_store/anchor_block_store.js';
import type { CapsuleStore } from '../storage/capsule_store/capsule_store.js';
import type { ContractStore } from '../storage/contract_store/contract_store.js';
import type { NoteStore } from '../storage/note_store/note_store.js';
import type { PrivateEventStore } from '../storage/private_event_store/private_event_store.js';
import type { RecipientTaggingStore } from '../storage/tagging_store/recipient_tagging_store.js';
import type { SenderAddressBookStore } from '../storage/tagging_store/sender_address_book_store.js';
import type { SenderTaggingStore } from '../storage/tagging_store/sender_tagging_store.js';
import { ExecutionNoteCache } from './execution_note_cache.js';
import { ExecutionTaggingIndexCache } from './execution_tagging_index_cache.js';
import { HashedValuesCache } from './hashed_values_cache.js';
Expand All @@ -96,17 +96,17 @@ export class ContractFunctionSimulator {
private log: Logger;

constructor(
private contractDataProvider: ContractDataProvider,
private noteDataProvider: NoteDataProvider,
private contractStore: ContractStore,
private noteStore: NoteStore,
private keyStore: KeyStore,
private addressDataProvider: AddressDataProvider,
private addressStore: AddressStore,
private aztecNode: AztecNode,
private anchorBlockDataProvider: AnchorBlockDataProvider,
private senderTaggingDataProvider: SenderTaggingDataProvider,
private recipientTaggingDataProvider: RecipientTaggingDataProvider,
private senderAddressBook: SenderAddressBook,
private capsuleDataProvider: CapsuleDataProvider,
private privateEventDataProvider: PrivateEventDataProvider,
private anchorBlockStore: AnchorBlockStore,
private senderTaggingStore: SenderTaggingStore,
private recipientTaggingStore: RecipientTaggingStore,
private senderAddressBookStore: SenderAddressBookStore,
private capsuleStore: CapsuleStore,
private privateEventStore: PrivateEventStore,
private simulator: CircuitSimulator,
) {
this.log = createLogger('simulator');
Expand Down Expand Up @@ -136,12 +136,9 @@ export class ContractFunctionSimulator {
): Promise<PrivateExecutionResult> {
const simulatorSetupTimer = new Timer();

await verifyCurrentClassId(contractAddress, this.aztecNode, this.contractDataProvider, anchorBlockHeader);
await verifyCurrentClassId(contractAddress, this.aztecNode, this.contractStore, anchorBlockHeader);

const entryPointArtifact = await this.contractDataProvider.getFunctionArtifactWithDebugMetadata(
contractAddress,
selector,
);
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(contractAddress, selector);

if (entryPointArtifact.functionType !== FunctionType.PRIVATE) {
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as private`);
Expand Down Expand Up @@ -177,17 +174,17 @@ export class ContractFunctionSimulator {
HashedValuesCache.create(request.argsOfCalls),
noteCache,
taggingIndexCache,
this.contractDataProvider,
this.noteDataProvider,
this.contractStore,
this.noteStore,
this.keyStore,
this.addressDataProvider,
this.addressStore,
this.aztecNode,
this.anchorBlockDataProvider,
this.senderTaggingDataProvider,
this.recipientTaggingDataProvider,
this.senderAddressBook,
this.capsuleDataProvider,
this.privateEventDataProvider,
this.anchorBlockStore,
this.senderTaggingStore,
this.recipientTaggingStore,
this.senderAddressBookStore,
this.capsuleStore,
this.privateEventStore,
0, // totalPublicArgsCount
startSideEffectCounter,
undefined, // log
Expand Down Expand Up @@ -259,12 +256,9 @@ export class ContractFunctionSimulator {
anchorBlockHeader: BlockHeader,
scopes?: AztecAddress[],
): Promise<Fr[]> {
await verifyCurrentClassId(call.to, this.aztecNode, this.contractDataProvider, anchorBlockHeader);
await verifyCurrentClassId(call.to, this.aztecNode, this.contractStore, anchorBlockHeader);

const entryPointArtifact = await this.contractDataProvider.getFunctionArtifactWithDebugMetadata(
call.to,
call.selector,
);
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);

if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
Expand All @@ -275,16 +269,16 @@ export class ContractFunctionSimulator {
authwits,
[],
anchorBlockHeader,
this.contractDataProvider,
this.noteDataProvider,
this.contractStore,
this.noteStore,
this.keyStore,
this.addressDataProvider,
this.addressStore,
this.aztecNode,
this.anchorBlockDataProvider,
this.recipientTaggingDataProvider,
this.senderAddressBook,
this.capsuleDataProvider,
this.privateEventDataProvider,
this.anchorBlockStore,
this.recipientTaggingStore,
this.senderAddressBookStore,
this.capsuleStore,
this.privateEventStore,
undefined,
scopes,
);
Expand Down Expand Up @@ -350,13 +344,13 @@ class OrderedSideEffect<T> {
* @param privateExecutionResult - The result of the private execution.
* @param nonceGenerator - A nonce generator for note hashes. According to the protocol rules,
* it can either be the first nullifier in the tx or the hash of the initial tx request if there are none.
* @param contractDataProvider - A provider for contract data in order to get function names and debug info.
* @param contractStore - A provider for contract data in order to get function names and debug info.
* @returns The simulated proving result.
*/
export async function generateSimulatedProvingResult(
privateExecutionResult: PrivateExecutionResult,
nonceGenerator: Fr,
contractDataProvider: ContractDataProvider,
contractStore: ContractStore,
): Promise<PrivateKernelExecutionProofOutput<PrivateKernelTailCircuitPublicInputs>> {
const siloedNoteHashes: OrderedSideEffect<Fr>[] = [];
const nullifiers: OrderedSideEffect<Fr>[] = [];
Expand Down Expand Up @@ -433,7 +427,7 @@ export async function generateSimulatedProvingResult(
: execution.publicInputs.publicTeardownCallRequest;

executionSteps.push({
functionName: await contractDataProvider.getDebugFunctionName(
functionName: await contractStore.getDebugFunctionName(
execution.publicInputs.callContext.contractAddress,
execution.publicInputs.callContext.functionSelector,
),
Expand Down
Loading