Skip to content
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
17 changes: 16 additions & 1 deletion yarn-project/archiver/src/modules/data_source_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ import type { EthAddress } from '@aztec/foundation/eth-address';
import { isDefined } from '@aztec/foundation/types';
import type { FunctionSelector } from '@aztec/stdlib/abi';
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
import { type BlockHash, CheckpointedL2Block, CommitteeAttestation, L2Block, type L2Tips } from '@aztec/stdlib/block';
import {
type BlockData,
type BlockHash,
CheckpointedL2Block,
CommitteeAttestation,
L2Block,
type L2Tips,
} from '@aztec/stdlib/block';
import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
import { type L1RollupConstants, getSlotRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
Expand Down Expand Up @@ -129,6 +136,14 @@ export abstract class ArchiverDataSourceBase
return this.store.getBlockHeaderByArchive(archive);
}

public getBlockData(number: BlockNumber): Promise<BlockData | undefined> {
return this.store.getBlockData(number);
}

public getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined> {
return this.store.getBlockDataByArchive(archive);
}

public async getL2Block(number: BlockNumber): Promise<L2Block | undefined> {
// If the number provided is -ve, then return the latest block.
if (number < 0) {
Expand Down
54 changes: 42 additions & 12 deletions yarn-project/archiver/src/store/block_store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { isDefined } from '@aztec/foundation/types';
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncSingleton, Range } from '@aztec/kv-store';
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
import {
type BlockData,
BlockHash,
Body,
CheckpointedL2Block,
Expand Down Expand Up @@ -655,6 +656,32 @@ export class BlockStore {
}
}

/**
* Gets block metadata (without tx data) by block number.
* @param blockNumber - The number of the block to return.
* @returns The requested block data.
*/
async getBlockData(blockNumber: BlockNumber): Promise<BlockData | undefined> {
const blockStorage = await this.#blocks.getAsync(blockNumber);
if (!blockStorage || !blockStorage.header) {
return undefined;
}
return this.getBlockDataFromBlockStorage(blockStorage);
}

/**
* Gets block metadata (without tx data) by archive root.
* @param archive - The archive root of the block to return.
* @returns The requested block data.
*/
async getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined> {
const blockNumber = await this.#blockArchiveIndex.getAsync(archive.toString());
if (blockNumber === undefined) {
return undefined;
}
return this.getBlockData(BlockNumber(blockNumber));
}

/**
* Gets an L2 block.
* @param blockNumber - The number of the block to return.
Expand Down Expand Up @@ -759,15 +786,24 @@ export class BlockStore {
}
}

private getBlockDataFromBlockStorage(blockStorage: BlockStorage): BlockData {
return {
header: BlockHeader.fromBuffer(blockStorage.header),
archive: AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive),
blockHash: Fr.fromBuffer(blockStorage.blockHash),
checkpointNumber: CheckpointNumber(blockStorage.checkpointNumber),
indexWithinCheckpoint: IndexWithinCheckpoint(blockStorage.indexWithinCheckpoint),
};
}

private async getBlockFromBlockStorage(
blockNumber: number,
blockStorage: BlockStorage,
): Promise<L2Block | undefined> {
const header = BlockHeader.fromBuffer(blockStorage.header);
const archive = AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive);
const blockHash = blockStorage.blockHash;
header.setHash(Fr.fromBuffer(blockHash));
const blockHashString = bufferToHex(blockHash);
const { header, archive, blockHash, checkpointNumber, indexWithinCheckpoint } =
this.getBlockDataFromBlockStorage(blockStorage);
header.setHash(blockHash);
const blockHashString = bufferToHex(blockStorage.blockHash);
const blockTxsBuffer = await this.#blockTxs.getAsync(blockHashString);
if (blockTxsBuffer === undefined) {
this.#log.warn(`Could not find body for block ${header.globalVariables.blockNumber} ${blockHash}`);
Expand All @@ -786,13 +822,7 @@ export class BlockStore {
txEffects.push(deserializeIndexedTxEffect(txEffect).data);
}
const body = new Body(txEffects);
const block = new L2Block(
archive,
header,
body,
CheckpointNumber(blockStorage.checkpointNumber!),
IndexWithinCheckpoint(blockStorage.indexWithinCheckpoint),
);
const block = new L2Block(archive, header, body, checkpointNumber, indexWithinCheckpoint);

if (block.number !== blockNumber) {
throw new Error(
Expand Down
24 changes: 23 additions & 1 deletion yarn-project/archiver/src/store/kv_archiver_store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import { createLogger } from '@aztec/foundation/log';
import type { AztecAsyncKVStore, CustomRange, StoreSize } from '@aztec/kv-store';
import { FunctionSelector } from '@aztec/stdlib/abi';
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
import { BlockHash, CheckpointedL2Block, L2Block, type ValidateCheckpointResult } from '@aztec/stdlib/block';
import {
type BlockData,
BlockHash,
CheckpointedL2Block,
L2Block,
type ValidateCheckpointResult,
} from '@aztec/stdlib/block';
import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
import type {
ContractClassPublic,
Expand Down Expand Up @@ -369,6 +375,22 @@ export class KVArchiverDataStore implements ContractDataSource {
return this.#blockStore.getBlockHeaderByArchive(archive);
}

/**
* Gets block metadata (without tx data) by block number.
* @param blockNumber - The block number to return.
*/
getBlockData(blockNumber: BlockNumber): Promise<BlockData | undefined> {
return this.#blockStore.getBlockData(blockNumber);
}

/**
* Gets block metadata (without tx data) by archive root.
* @param archive - The archive root to return.
*/
getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined> {
return this.#blockStore.getBlockDataByArchive(archive);
}

/**
* Gets a tx effect.
* @param txHash - The hash of the tx corresponding to the tx effect.
Expand Down
29 changes: 29 additions & 0 deletions yarn-project/archiver/src/test/mock_l2_block_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { createLogger } from '@aztec/foundation/log';
import type { FunctionSelector } from '@aztec/stdlib/abi';
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
import {
type BlockData,
BlockHash,
CheckpointedL2Block,
L2Block,
Expand Down Expand Up @@ -255,6 +256,34 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
return Promise.resolve(block?.header);
}

public async getBlockData(number: BlockNumber): Promise<BlockData | undefined> {
const block = this.l2Blocks[number - 1];
if (!block) {
return undefined;
}
return {
header: block.header,
archive: block.archive,
blockHash: await block.hash(),
checkpointNumber: block.checkpointNumber,
indexWithinCheckpoint: block.indexWithinCheckpoint,
};
}

public async getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined> {
const block = this.l2Blocks.find(b => b.archive.root.equals(archive));
if (!block) {
return undefined;
}
return {
header: block.header,
archive: block.archive,
blockHash: await block.hash(),
checkpointNumber: block.checkpointNumber,
indexWithinCheckpoint: block.indexWithinCheckpoint,
};
}

getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
return Promise.resolve(this.l2Blocks.at(typeof number === 'number' ? number - 1 : -1)?.header);
}
Expand Down
17 changes: 16 additions & 1 deletion yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@ import {
} from '@aztec/slasher';
import { CollectionLimitsConfig, PublicSimulatorConfig } from '@aztec/stdlib/avm';
import { AztecAddress } from '@aztec/stdlib/aztec-address';
import { BlockHash, type BlockParameter, type DataInBlock, L2Block, type L2BlockSource } from '@aztec/stdlib/block';
import {
type BlockData,
BlockHash,
type BlockParameter,
type DataInBlock,
L2Block,
type L2BlockSource,
} from '@aztec/stdlib/block';
import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
import type {
ContractClassPublic,
Expand Down Expand Up @@ -1106,6 +1113,14 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
return await this.blockSource.getBlockHeaderByArchive(archive);
}

public getBlockData(number: BlockNumber): Promise<BlockData | undefined> {
return this.blockSource.getBlockData(number);
}

public getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined> {
return this.blockSource.getBlockDataByArchive(archive);
}

/**
* Simulates the public part of a transaction with the current state.
* @param tx - The transaction to simulate.
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec-node/src/sentinel/sentinel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ describe('sentinel', () => {
ts,
nowMs: ts * 1000n,
});
archiver.getL2Block.calledWith(blockNumber).mockResolvedValue(mockBlock);
archiver.getBlockHeader.calledWith(blockNumber).mockResolvedValue(mockBlock.header);
archiver.getL1Constants.mockResolvedValue(l1Constants);
epochCache.getL1Constants.mockReturnValue(l1Constants);

Expand Down
8 changes: 4 additions & 4 deletions yarn-project/aztec-node/src/sentinel/sentinel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
return;
}
const blockNumber = event.block.number;
const block = await this.archiver.getL2Block(blockNumber);
if (!block) {
this.logger.error(`Failed to get block ${blockNumber}`, { block });
const header = await this.archiver.getBlockHeader(blockNumber);
if (!header) {
this.logger.error(`Failed to get block header ${blockNumber}`);
return;
}

// TODO(palla/slash): We should only be computing proven performance if this is
// a full proof epoch and not a partial one, otherwise we'll end up with skewed stats.
const epoch = getEpochAtSlot(block.header.getSlot(), this.epochCache.getL1Constants());
const epoch = getEpochAtSlot(header.getSlot(), this.epochCache.getL1Constants());
this.logger.debug(`Computing proven performance for epoch ${epoch}`);
const performance = await this.computeProvenPerformance(epoch);
this.logger.info(`Computed proven performance for epoch ${epoch}`, performance);
Expand Down
20 changes: 17 additions & 3 deletions yarn-project/sequencer-client/src/sequencer/sequencer.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
import type { EpochCache, EpochCommitteeInfo } from '@aztec/epoch-cache';
import type { RollupContract } from '@aztec/ethereum/contracts';
import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
import {
BlockNumber,
CheckpointNumber,
EpochNumber,
IndexWithinCheckpoint,
SlotNumber,
} from '@aztec/foundation/branded-types';
import { omit, times, timesParallel } from '@aztec/foundation/collection';
import { Secp256k1Signer } from '@aztec/foundation/crypto/secp256k1-signer';
import { Fr } from '@aztec/foundation/curves/bn254';
Expand All @@ -12,6 +18,7 @@ import type { P2P } from '@aztec/p2p';
import type { SlasherClientInterface } from '@aztec/slasher';
import { AztecAddress } from '@aztec/stdlib/aztec-address';
import {
type BlockData,
CommitteeAttestation,
CommitteeAttestationsAndSigners,
GENESIS_CHECKPOINT_HEADER_HASH,
Expand All @@ -31,7 +38,8 @@ import {
type WorldStateSynchronizerStatus,
} from '@aztec/stdlib/interfaces/server';
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
import { GlobalVariables, type Tx } from '@aztec/stdlib/tx';
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
import { BlockHeader, GlobalVariables, type Tx } from '@aztec/stdlib/tx';
import type { FullNodeCheckpointsBuilder, ValidatorClient } from '@aztec/validator-client';

import { expect } from '@jest/globals';
Expand Down Expand Up @@ -235,7 +243,13 @@ describe('sequencer', () => {
checkpointBuilder.setBlockProvider(() => block);

l2BlockSource = mock<L2BlockSource & L2BlockSink>({
getL2Block: mockFn().mockResolvedValue(L2Block.empty()),
getBlockData: mockFn().mockResolvedValue({
header: BlockHeader.empty(),
archive: AppendOnlyTreeSnapshot.empty(),
blockHash: Fr.ZERO,
checkpointNumber: CheckpointNumber(0),
indexWithinCheckpoint: IndexWithinCheckpoint(0),
} satisfies BlockData),
getBlockNumber: mockFn().mockResolvedValue(lastBlockNumber),
getL2Tips: mockFn().mockResolvedValue({
proposed: { number: lastBlockNumber, hash },
Expand Down
22 changes: 11 additions & 11 deletions yarn-project/sequencer-client/src/sequencer/sequencer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { DateProvider } from '@aztec/foundation/timer';
import type { TypedEventEmitter } from '@aztec/foundation/types';
import type { P2P } from '@aztec/p2p';
import type { SlasherClientInterface } from '@aztec/slasher';
import type { L2Block, L2BlockSink, L2BlockSource, ValidateCheckpointResult } from '@aztec/stdlib/block';
import type { BlockData, L2BlockSink, L2BlockSource, ValidateCheckpointResult } from '@aztec/stdlib/block';
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
import { getSlotAtTimestamp, getSlotStartBuildTimestamp } from '@aztec/stdlib/epoch-helpers';
import {
Expand Down Expand Up @@ -301,10 +301,10 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
}

// Check that the slot is not taken by a block already (should never happen, since only us can propose for this slot)
if (syncedTo.block && syncedTo.block.header.getSlot() >= slot) {
if (syncedTo.blockData && syncedTo.blockData.header.getSlot() >= slot) {
this.log.warn(
`Cannot propose block at next L2 slot ${slot} since that slot was taken by block ${syncedTo.blockNumber}`,
{ ...logCtx, block: syncedTo.block.header.toInspect() },
{ ...logCtx, block: syncedTo.blockData.header.toInspect() },
);
this.metrics.recordBlockProposalPrecheckFailed('slot_already_taken');
return undefined;
Expand Down Expand Up @@ -523,18 +523,18 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
};
}

const block = await this.l2BlockSource.getL2Block(blockNumber);
if (!block) {
const blockData = await this.l2BlockSource.getBlockData(blockNumber);
if (!blockData) {
// this shouldn't really happen because a moment ago we checked that all components were in sync
this.log.error(`Failed to get L2 block ${blockNumber} from the archiver with all components in sync`);
this.log.error(`Failed to get L2 block data ${blockNumber} from the archiver with all components in sync`);
return undefined;
}

return {
block,
blockNumber: block.number,
checkpointNumber: block.checkpointNumber,
archive: block.archive.root,
blockData,
blockNumber: blockData.header.getBlockNumber(),
checkpointNumber: blockData.checkpointNumber,
archive: blockData.archive.root,
l1Timestamp,
pendingChainValidationStatus,
};
Expand Down Expand Up @@ -867,7 +867,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
}

type SequencerSyncCheckResult = {
block?: L2Block;
blockData?: BlockData;
checkpointNumber: CheckpointNumber;
blockNumber: BlockNumber;
archive: Fr;
Expand Down
26 changes: 26 additions & 0 deletions yarn-project/stdlib/src/block/block_data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { CheckpointNumberSchema, IndexWithinCheckpointSchema } from '@aztec/foundation/branded-types';
import type { CheckpointNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
import type { Fr } from '@aztec/foundation/curves/bn254';
import { schemas } from '@aztec/foundation/schemas';

import { z } from 'zod';

import { AppendOnlyTreeSnapshot } from '../trees/append_only_tree_snapshot.js';
import { BlockHeader } from '../tx/block_header.js';

/** L2Block metadata. Equivalent to L2Block but without block body containing tx data. */
export type BlockData = {
header: BlockHeader;
archive: AppendOnlyTreeSnapshot;
blockHash: Fr;
checkpointNumber: CheckpointNumber;
indexWithinCheckpoint: IndexWithinCheckpoint;
};

export const BlockDataSchema = z.object({
header: BlockHeader.schema,
archive: AppendOnlyTreeSnapshot.schema,
blockHash: schemas.Fr,
checkpointNumber: CheckpointNumberSchema,
indexWithinCheckpoint: IndexWithinCheckpointSchema,
});
1 change: 1 addition & 0 deletions yarn-project/stdlib/src/block/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './block_data.js';
export * from './l2_block.js';
export * from './l2_block_stream/index.js';
export * from './in_block.js';
Expand Down
Loading
Loading