Skip to content

Commit

Permalink
feat: only download non-pruned blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
LHerskind committed Sep 16, 2024
1 parent bc8d461 commit 1db58f1
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 58 deletions.
7 changes: 5 additions & 2 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
header.globalVariables.blockNumber, header.contentCommitment.outHash, l2ToL1TreeMinHeight
);

emit L2BlockProposed(header.globalVariables.blockNumber);
emit L2BlockProposed(header.globalVariables.blockNumber, _archive);

// Automatically flag the block as proven if we have cheated and set assumeProvenUntilBlockNumber.
if (header.globalVariables.blockNumber < assumeProvenUntilBlockNumber) {
Expand Down Expand Up @@ -399,7 +399,10 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
* @return bytes32 - The archive root of the block
*/
function archiveAt(uint256 _blockNumber) external view override(IRollup) returns (bytes32) {
return blocks[_blockNumber].archive;
if (_blockNumber < pendingBlockCount) {
return blocks[_blockNumber].archive;
}
return bytes32(0);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/src/core/interfaces/IRollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface ITestRollup {
}

interface IRollup {
event L2BlockProposed(uint256 indexed blockNumber);
event L2BlockProposed(uint256 indexed blockNumber, bytes32 indexed archive);
event L2ProofVerified(uint256 indexed blockNumber, bytes32 indexed proverId);
event PrunedPending(uint256 provenBlockCount, uint256 pendingBlockCount);

Expand Down
26 changes: 19 additions & 7 deletions yarn-project/archiver/src/archiver/archiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,15 @@ import {
} from '@aztec/types/contracts';

import groupBy from 'lodash.groupby';
import { type Chain, type HttpTransport, type PublicClient, createPublicClient, getContract, http } from 'viem';
import {
type Chain,
type GetContractReturnType,
type HttpTransport,
type PublicClient,
createPublicClient,
getContract,
http,
} from 'viem';

import { type ArchiverDataStore } from './archiver_store.js';
import { type ArchiverConfig } from './config.js';
Expand All @@ -68,6 +76,8 @@ export class Archiver implements ArchiveSource {
*/
private runningPromise?: RunningPromise;

private rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>;

/**
* Creates a new instance of the Archiver.
* @param publicClient - A client for interacting with the Ethereum node.
Expand All @@ -88,7 +98,13 @@ export class Archiver implements ArchiveSource {
private readonly instrumentation: ArchiverInstrumentation,
private readonly l1StartBlock: bigint = 0n,
private readonly log: DebugLogger = createDebugLogger('aztec:archiver'),
) {}
) {
this.rollup = getContract({
address: rollupAddress.toString(),
abi: RollupAbi,
client: publicClient,
});
}

/**
* Creates a new instance of the Archiver and blocks until it syncs from chain.
Expand Down Expand Up @@ -245,17 +261,13 @@ export class Archiver implements ArchiveSource {

await this.store.addL1ToL2Messages(retrievedL1ToL2Messages);

// Read all data from chain and then write to our stores at the end
const nextExpectedL2BlockNum = BigInt((await this.store.getSynchedL2BlockNumber()) + 1);

this.log.debug(`Retrieving blocks from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
const retrievedBlocks = await retrieveBlockFromRollup(
this.rollup,
this.publicClient,
this.rollupAddress,
blockUntilSynced,
blocksSynchedTo + 1n,
currentL1BlockNumber,
nextExpectedL2BlockNum,
);

// Add the body
Expand Down
28 changes: 17 additions & 11 deletions yarn-project/archiver/src/archiver/data_retrieval.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { type InboxLeaf, type L2Block } from '@aztec/circuit-types';
import { Fr, type Proof } from '@aztec/circuits.js';
import { type EthAddress } from '@aztec/foundation/eth-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
import { RollupAbi } from '@aztec/l1-artifacts';

import { type Hex, type PublicClient, getAbiItem } from 'viem';
import {
type Chain,
type GetContractReturnType,
type Hex,
type HttpTransport,
type PublicClient,
getAbiItem,
} from 'viem';

import {
getBlockProofFromSubmitProofTx,
Expand All @@ -27,38 +34,37 @@ import { type L1Published } from './structs/published.js';
* @returns An array of block; as well as the next eth block to search from.
*/
export async function retrieveBlockFromRollup(
rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>,
publicClient: PublicClient,
rollupAddress: EthAddress,
blockUntilSynced: boolean,
searchStartBlock: bigint,
searchEndBlock: bigint,
expectedNextL2BlockNum: bigint,
logger: DebugLogger = createDebugLogger('aztec:archiver'),
): Promise<L1Published<L2Block>[]> {
const retrievedBlocks: L1Published<L2Block>[] = [];
do {
if (searchStartBlock > searchEndBlock) {
break;
}
const L2BlockProposedLogs = await getL2BlockProposedLogs(
const l2BlockProposedLogs = await getL2BlockProposedLogs(
publicClient,
rollupAddress,
EthAddress.fromString(rollup.address),
searchStartBlock,
searchEndBlock,
);
if (L2BlockProposedLogs.length === 0) {

if (l2BlockProposedLogs.length === 0) {
break;
}

const lastLog = L2BlockProposedLogs[L2BlockProposedLogs.length - 1];
const lastLog = l2BlockProposedLogs[l2BlockProposedLogs.length - 1];
logger.debug(
`Got L2 block processed logs for ${L2BlockProposedLogs[0].blockNumber}-${lastLog.blockNumber} between ${searchStartBlock}-${searchEndBlock} L1 blocks`,
`Got L2 block processed logs for ${l2BlockProposedLogs[0].blockNumber}-${lastLog.blockNumber} between ${searchStartBlock}-${searchEndBlock} L1 blocks`,
);

const newBlocks = await processL2BlockProposedLogs(publicClient, expectedNextL2BlockNum, L2BlockProposedLogs);
const newBlocks = await processL2BlockProposedLogs(rollup, publicClient, l2BlockProposedLogs);
retrievedBlocks.push(...newBlocks);
searchStartBlock = lastLog.blockNumber! + 1n;
expectedNextL2BlockNum += BigInt(newBlocks.length);
} while (blockUntilSynced && searchStartBlock <= searchEndBlock);
return retrievedBlocks;
}
Expand Down
49 changes: 31 additions & 18 deletions yarn-project/archiver/src/archiver/eth_log_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,18 @@ import { Fr } from '@aztec/foundation/fields';
import { numToUInt32BE } from '@aztec/foundation/serialize';
import { InboxAbi, RollupAbi } from '@aztec/l1-artifacts';

import { type Hex, type Log, type PublicClient, decodeFunctionData, getAbiItem, getAddress, hexToBytes } from 'viem';
import {
type Chain,
type GetContractReturnType,
type Hex,
type HttpTransport,
type Log,
type PublicClient,
decodeFunctionData,
getAbiItem,
getAddress,
hexToBytes,
} from 'viem';

import { type L1Published, type L1PublishedData } from './structs/published.js';

Expand All @@ -27,33 +38,35 @@ export function processMessageSentLogs(

/**
* Processes newly received L2BlockProposed logs.
* @param rollup - The rollup contract
* @param publicClient - The viem public client to use for transaction retrieval.
* @param expectedL2BlockNumber - The next expected L2 block number.
* @param logs - L2BlockProposed logs.
* @returns - An array blocks.
*/
export async function processL2BlockProposedLogs(
rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>,
publicClient: PublicClient,
expectedL2BlockNumber: bigint,
logs: Log<bigint, number, false, undefined, true, typeof RollupAbi, 'L2BlockProposed'>[],
): Promise<L1Published<L2Block>[]> {
const retrievedBlocks: L1Published<L2Block>[] = [];
for (const log of logs) {
const blockNum = log.args.blockNumber;
if (blockNum !== expectedL2BlockNumber) {
throw new Error('Block number mismatch. Expected: ' + expectedL2BlockNumber + ' but got: ' + blockNum + '.');
const blockNum = log.args.blockNumber!;
const archive = log.args.archive!;
const archiveFromChain = await rollup.read.archiveAt([blockNum]);

// The value from the event and contract will match only if the block is in the chain.
if (archive === archiveFromChain) {
// TODO: Fetch blocks from calldata in parallel
const block = await getBlockFromRollupTx(publicClient, log.transactionHash!, blockNum);

const l1: L1PublishedData = {
blockNumber: log.blockNumber,
blockHash: log.blockHash,
timestamp: await getL1BlockTime(publicClient, log.blockNumber),
};

retrievedBlocks.push({ data: block, l1 });
}
// TODO: Fetch blocks from calldata in parallel
const block = await getBlockFromRollupTx(publicClient, log.transactionHash!, log.args.blockNumber);

const l1: L1PublishedData = {
blockNumber: log.blockNumber,
blockHash: log.blockHash,
timestamp: await getL1BlockTime(publicClient, log.blockNumber),
};

retrievedBlocks.push({ data: block, l1 });
expectedL2BlockNumber++;
}

return retrievedBlocks;
Expand Down Expand Up @@ -101,7 +114,7 @@ async function getBlockFromRollupTx(
const archive = AppendOnlyTreeSnapshot.fromBuffer(
Buffer.concat([
Buffer.from(hexToBytes(archiveRootHex)), // L2Block.archive.root
numToUInt32BE(Number(l2BlockNum)), // L2Block.archive.nextAvailableLeafIndex
numToUInt32BE(Number(l2BlockNum + 1n)), // L2Block.archive.nextAvailableLeafIndex
]),
);

Expand Down
Loading

0 comments on commit 1db58f1

Please sign in to comment.