@aztec/archiver 0.0.1-commit.b655e406 → 0.0.1-commit.fce3e4f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dest/archiver/archiver.d.ts +30 -20
  2. package/dest/archiver/archiver.d.ts.map +1 -1
  3. package/dest/archiver/archiver.js +294 -208
  4. package/dest/archiver/archiver_store.d.ts +1 -1
  5. package/dest/archiver/archiver_store_test_suite.d.ts +1 -1
  6. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  7. package/dest/archiver/archiver_store_test_suite.js +5 -4
  8. package/dest/archiver/config.d.ts +1 -1
  9. package/dest/archiver/config.d.ts.map +1 -1
  10. package/dest/archiver/config.js +5 -0
  11. package/dest/archiver/data_retrieval.d.ts +17 -17
  12. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  13. package/dest/archiver/data_retrieval.js +110 -86
  14. package/dest/archiver/errors.d.ts +1 -1
  15. package/dest/archiver/errors.d.ts.map +1 -1
  16. package/dest/archiver/index.d.ts +1 -1
  17. package/dest/archiver/instrumentation.d.ts +3 -3
  18. package/dest/archiver/instrumentation.d.ts.map +1 -1
  19. package/dest/archiver/kv_archiver_store/block_store.d.ts +1 -1
  20. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  21. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +1 -1
  22. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
  23. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +1 -1
  24. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
  25. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +2 -2
  26. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  27. package/dest/archiver/kv_archiver_store/log_store.d.ts +1 -1
  28. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  29. package/dest/archiver/kv_archiver_store/message_store.d.ts +1 -1
  30. package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
  31. package/dest/archiver/structs/data_retrieval.d.ts +1 -1
  32. package/dest/archiver/structs/inbox_message.d.ts +1 -1
  33. package/dest/archiver/structs/published.d.ts +3 -2
  34. package/dest/archiver/structs/published.d.ts.map +1 -1
  35. package/dest/archiver/validation.d.ts +10 -4
  36. package/dest/archiver/validation.d.ts.map +1 -1
  37. package/dest/archiver/validation.js +29 -21
  38. package/dest/factory.d.ts +1 -1
  39. package/dest/index.d.ts +2 -2
  40. package/dest/index.d.ts.map +1 -1
  41. package/dest/index.js +1 -1
  42. package/dest/rpc/index.d.ts +2 -2
  43. package/dest/test/index.d.ts +1 -1
  44. package/dest/test/mock_archiver.d.ts +1 -1
  45. package/dest/test/mock_archiver.d.ts.map +1 -1
  46. package/dest/test/mock_l1_to_l2_message_source.d.ts +1 -1
  47. package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
  48. package/dest/test/mock_l2_block_source.d.ts +7 -6
  49. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  50. package/dest/test/mock_l2_block_source.js +1 -1
  51. package/dest/test/mock_structs.d.ts +1 -1
  52. package/package.json +17 -17
  53. package/src/archiver/archiver.ts +380 -244
  54. package/src/archiver/archiver_store_test_suite.ts +5 -4
  55. package/src/archiver/config.ts +5 -0
  56. package/src/archiver/data_retrieval.ts +156 -125
  57. package/src/archiver/instrumentation.ts +2 -2
  58. package/src/archiver/structs/published.ts +2 -1
  59. package/src/archiver/validation.ts +52 -27
  60. package/src/index.ts +1 -1
  61. package/src/test/mock_l2_block_source.ts +7 -6
@@ -4,6 +4,7 @@ import {
4
4
  PRIVATE_LOG_SIZE_IN_FIELDS,
5
5
  } from '@aztec/constants';
6
6
  import { makeTuple } from '@aztec/foundation/array';
7
+ import { EpochNumber } from '@aztec/foundation/branded-types';
7
8
  import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
8
9
  import { times, timesParallel } from '@aztec/foundation/collection';
9
10
  import { randomInt } from '@aztec/foundation/crypto';
@@ -1189,7 +1190,7 @@ export function describeArchiverDataStore(
1189
1190
  valid: false,
1190
1191
  block: randomBlockInfo(1),
1191
1192
  committee: [EthAddress.random(), EthAddress.random()],
1192
- epoch: 123n,
1193
+ epoch: EpochNumber(123),
1193
1194
  seed: 456n,
1194
1195
  attestors: [EthAddress.random()],
1195
1196
  attestations: [CommitteeAttestation.random()],
@@ -1208,7 +1209,7 @@ export function describeArchiverDataStore(
1208
1209
  block: randomBlockInfo(2),
1209
1210
  committee: [EthAddress.random()],
1210
1211
  attestors: [EthAddress.random()],
1211
- epoch: 789n,
1212
+ epoch: EpochNumber(789),
1212
1213
  seed: 101n,
1213
1214
  attestations: [CommitteeAttestation.random()],
1214
1215
  reason: 'invalid-attestation',
@@ -1227,7 +1228,7 @@ export function describeArchiverDataStore(
1227
1228
  valid: false,
1228
1229
  block: randomBlockInfo(3),
1229
1230
  committee: [EthAddress.random()],
1230
- epoch: 999n,
1231
+ epoch: EpochNumber(999),
1231
1232
  seed: 888n,
1232
1233
  attestors: [EthAddress.random()],
1233
1234
  attestations: [CommitteeAttestation.random()],
@@ -1246,7 +1247,7 @@ export function describeArchiverDataStore(
1246
1247
  valid: false,
1247
1248
  block: randomBlockInfo(4),
1248
1249
  committee: [],
1249
- epoch: 0n,
1250
+ epoch: EpochNumber(0),
1250
1251
  seed: 0n,
1251
1252
  attestors: [],
1252
1253
  attestations: [],
@@ -50,6 +50,11 @@ export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
50
50
  description: 'Whether to skip validating block attestations (use only for testing).',
51
51
  ...booleanConfigHelper(false),
52
52
  },
53
+ maxAllowedEthClientDriftSeconds: {
54
+ env: 'MAX_ALLOWED_ETH_CLIENT_DRIFT_SECONDS',
55
+ description: 'Maximum allowed drift in seconds between the Ethereum client and current time.',
56
+ ...numberConfigHelper(300),
57
+ },
53
58
  ...chainConfigMappings,
54
59
  ...l1ReaderConfigMappings,
55
60
  viemPollingIntervalMS: {
@@ -1,4 +1,10 @@
1
- import { BlobDeserializationError, SpongeBlob, getBlobFieldsInCheckpoint } from '@aztec/blob-lib';
1
+ import {
2
+ BlobDeserializationError,
3
+ type CheckpointBlobData,
4
+ SpongeBlob,
5
+ decodeCheckpointBlobDataFromBlobs,
6
+ encodeBlockBlobData,
7
+ } from '@aztec/blob-lib';
2
8
  import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
3
9
  import type {
4
10
  EpochProofPublicInputArgs,
@@ -6,7 +12,6 @@ import type {
6
12
  ViemCommitteeAttestations,
7
13
  ViemHeader,
8
14
  ViemPublicClient,
9
- ViemStateReference,
10
15
  } from '@aztec/ethereum';
11
16
  import { asyncPool } from '@aztec/foundation/async-pool';
12
17
  import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
@@ -15,11 +20,12 @@ import type { ViemSignature } from '@aztec/foundation/eth-signature';
15
20
  import { Fr } from '@aztec/foundation/fields';
16
21
  import { type Logger, createLogger } from '@aztec/foundation/log';
17
22
  import { type InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
18
- import { Body, CommitteeAttestation, L2Block, L2BlockHeader, PublishedL2Block } from '@aztec/stdlib/block';
23
+ import { Body, CommitteeAttestation, L2BlockNew } from '@aztec/stdlib/block';
24
+ import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
19
25
  import { Proof } from '@aztec/stdlib/proofs';
20
26
  import { CheckpointHeader } from '@aztec/stdlib/rollup';
21
27
  import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
22
- import { GlobalVariables, StateReference } from '@aztec/stdlib/tx';
28
+ import { BlockHeader, GlobalVariables, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
23
29
 
24
30
  import {
25
31
  type GetContractEventsReturnType,
@@ -36,75 +42,106 @@ import type { DataRetrieval } from './structs/data_retrieval.js';
36
42
  import type { InboxMessage } from './structs/inbox_message.js';
37
43
  import type { L1PublishedData } from './structs/published.js';
38
44
 
39
- export type RetrievedL2Block = {
40
- l2BlockNumber: number;
45
+ export type RetrievedCheckpoint = {
46
+ checkpointNumber: number;
41
47
  archiveRoot: Fr;
42
- stateReference: StateReference;
43
48
  header: CheckpointHeader;
44
- blobFields: Fr[];
49
+ checkpointBlobData: CheckpointBlobData;
45
50
  l1: L1PublishedData;
46
51
  chainId: Fr;
47
52
  version: Fr;
48
53
  attestations: CommitteeAttestation[];
49
54
  };
50
55
 
51
- export async function retrievedBlockToPublishedL2Block(retrievedBlock: RetrievedL2Block): Promise<PublishedL2Block> {
52
- const {
53
- l2BlockNumber,
54
- archiveRoot,
55
- stateReference,
56
- header: checkpointHeader,
57
- blobFields,
58
- l1,
59
- chainId,
60
- version,
61
- attestations,
62
- } = retrievedBlock;
63
-
64
- const archive = new AppendOnlyTreeSnapshot(
65
- archiveRoot,
66
- l2BlockNumber + 1, // nextAvailableLeafIndex
67
- );
68
-
69
- const globalVariables = GlobalVariables.from({
70
- chainId,
71
- version,
72
- blockNumber: l2BlockNumber,
73
- slotNumber: checkpointHeader.slotNumber,
74
- timestamp: checkpointHeader.timestamp,
75
- coinbase: checkpointHeader.coinbase,
76
- feeRecipient: checkpointHeader.feeRecipient,
77
- gasFees: checkpointHeader.gasFees,
78
- });
56
+ export async function retrievedToPublishedCheckpoint({
57
+ checkpointNumber,
58
+ archiveRoot,
59
+ header: checkpointHeader,
60
+ checkpointBlobData,
61
+ l1,
62
+ chainId,
63
+ version,
64
+ attestations,
65
+ }: RetrievedCheckpoint): Promise<PublishedCheckpoint> {
66
+ const { blocks: blocksBlobData } = checkpointBlobData;
67
+
68
+ // The lastArchiveRoot of a block is the new archive for the previous block.
69
+ const newArchiveRoots = blocksBlobData
70
+ .map(b => b.lastArchiveRoot)
71
+ .slice(1)
72
+ .concat([archiveRoot]);
73
+
74
+ // `blocksBlobData` is created from `decodeCheckpointBlobDataFromBlobs`. An error will be thrown if it can't read a
75
+ // field for the `l1ToL2MessageRoot` of the first block. So below we can safely assume it exists:
76
+ const l1toL2MessageTreeRoot = blocksBlobData[0].l1ToL2MessageRoot!;
77
+
78
+ const spongeBlob = SpongeBlob.init();
79
+ const l2Blocks: L2BlockNew[] = [];
80
+ for (let i = 0; i < blocksBlobData.length; i++) {
81
+ const blockBlobData = blocksBlobData[i];
82
+ const { blockEndMarker, blockEndStateField, lastArchiveRoot, noteHashRoot, nullifierRoot, publicDataRoot } =
83
+ blockBlobData;
84
+
85
+ const l2BlockNumber = blockEndMarker.blockNumber;
86
+
87
+ const globalVariables = GlobalVariables.from({
88
+ chainId,
89
+ version,
90
+ blockNumber: l2BlockNumber,
91
+ slotNumber: checkpointHeader.slotNumber,
92
+ timestamp: blockEndMarker.timestamp,
93
+ coinbase: checkpointHeader.coinbase,
94
+ feeRecipient: checkpointHeader.feeRecipient,
95
+ gasFees: checkpointHeader.gasFees,
96
+ });
97
+
98
+ const state = StateReference.from({
99
+ l1ToL2MessageTree: new AppendOnlyTreeSnapshot(
100
+ l1toL2MessageTreeRoot,
101
+ blockEndStateField.l1ToL2MessageNextAvailableLeafIndex,
102
+ ),
103
+ partial: PartialStateReference.from({
104
+ noteHashTree: new AppendOnlyTreeSnapshot(noteHashRoot, blockEndStateField.noteHashNextAvailableLeafIndex),
105
+ nullifierTree: new AppendOnlyTreeSnapshot(nullifierRoot, blockEndStateField.nullifierNextAvailableLeafIndex),
106
+ publicDataTree: new AppendOnlyTreeSnapshot(publicDataRoot, blockEndStateField.publicDataNextAvailableLeafIndex),
107
+ }),
108
+ });
109
+
110
+ const body = Body.fromTxBlobData(checkpointBlobData.blocks[0].txs);
111
+
112
+ const blobFields = encodeBlockBlobData(blockBlobData);
113
+ await spongeBlob.absorb(blobFields);
114
+
115
+ const clonedSpongeBlob = spongeBlob.clone();
116
+ const spongeBlobHash = await clonedSpongeBlob.squeeze();
117
+
118
+ const header = BlockHeader.from({
119
+ lastArchive: new AppendOnlyTreeSnapshot(lastArchiveRoot, l2BlockNumber),
120
+ state,
121
+ spongeBlobHash,
122
+ globalVariables,
123
+ totalFees: body.txEffects.reduce((accum, txEffect) => accum.add(txEffect.transactionFee), Fr.ZERO),
124
+ totalManaUsed: new Fr(blockEndStateField.totalManaUsed),
125
+ });
126
+
127
+ const newArchive = new AppendOnlyTreeSnapshot(newArchiveRoots[i], l2BlockNumber + 1);
128
+
129
+ l2Blocks.push(new L2BlockNew(newArchive, header, body));
130
+ }
79
131
 
80
- // TODO(#17027)
81
- // This works when there's only one block in the checkpoint.
82
- // If there's more than one block, we need to build the spongeBlob from the endSpongeBlob of the previous block.
83
- const spongeBlob = await SpongeBlob.init(blobFields.length);
84
- // Skip the first field which is the checkpoint prefix indicating the number of total blob fields in a checkpoint.
85
- const blockBlobFields = blobFields.slice(1);
86
- await spongeBlob.absorb(blockBlobFields);
87
- const spongeBlobHash = await spongeBlob.squeeze();
88
-
89
- const body = Body.fromBlobFields(blockBlobFields);
90
-
91
- const header = L2BlockHeader.from({
92
- lastArchive: new AppendOnlyTreeSnapshot(checkpointHeader.lastArchiveRoot, l2BlockNumber),
93
- contentCommitment: checkpointHeader.contentCommitment,
94
- state: stateReference,
95
- globalVariables,
96
- totalFees: body.txEffects.reduce((accum, txEffect) => accum.add(txEffect.transactionFee), Fr.ZERO),
97
- totalManaUsed: checkpointHeader.totalManaUsed,
98
- spongeBlobHash,
132
+ const lastBlock = l2Blocks.at(-1)!;
133
+ const checkpoint = Checkpoint.from({
134
+ archive: new AppendOnlyTreeSnapshot(archiveRoot, lastBlock.number + 1),
135
+ header: checkpointHeader,
136
+ blocks: l2Blocks,
137
+ number: checkpointNumber,
99
138
  });
100
139
 
101
- const block = new L2Block(archive, header, body);
102
-
103
- return PublishedL2Block.fromFields({ block, l1, attestations });
140
+ return PublishedCheckpoint.from({ checkpoint, l1, attestations });
104
141
  }
105
142
 
106
143
  /**
107
- * Fetches new L2 blocks.
144
+ * Fetches new checkpoints.
108
145
  * @param publicClient - The viem public client to use for transaction retrieval.
109
146
  * @param rollupAddress - The address of the rollup contract.
110
147
  * @param searchStartBlock - The block number to use for starting the search.
@@ -112,15 +149,15 @@ export async function retrievedBlockToPublishedL2Block(retrievedBlock: Retrieved
112
149
  * @param expectedNextL2BlockNum - The next L2 block number that we expect to find.
113
150
  * @returns An array of block; as well as the next eth block to search from.
114
151
  */
115
- export async function retrieveBlocksFromRollup(
152
+ export async function retrieveCheckpointsFromRollup(
116
153
  rollup: GetContractReturnType<typeof RollupAbi, ViemPublicClient>,
117
154
  publicClient: ViemPublicClient,
118
155
  blobSinkClient: BlobSinkClientInterface,
119
156
  searchStartBlock: bigint,
120
157
  searchEndBlock: bigint,
121
158
  logger: Logger = createLogger('archiver'),
122
- ): Promise<RetrievedL2Block[]> {
123
- const retrievedBlocks: RetrievedL2Block[] = [];
159
+ ): Promise<RetrievedCheckpoint[]> {
160
+ const retrievedCheckpoints: RetrievedCheckpoint[] = [];
124
161
 
125
162
  let rollupConstants: { chainId: Fr; version: Fr; targetCommitteeSize: number } | undefined;
126
163
 
@@ -128,8 +165,8 @@ export async function retrieveBlocksFromRollup(
128
165
  if (searchStartBlock > searchEndBlock) {
129
166
  break;
130
167
  }
131
- const l2BlockProposedLogs = (
132
- await rollup.getEvents.L2BlockProposed(
168
+ const checkpointProposedLogs = (
169
+ await rollup.getEvents.CheckpointProposed(
133
170
  {},
134
171
  {
135
172
  fromBlock: searchStartBlock,
@@ -138,13 +175,13 @@ export async function retrieveBlocksFromRollup(
138
175
  )
139
176
  ).filter(log => log.blockNumber! >= searchStartBlock && log.blockNumber! <= searchEndBlock);
140
177
 
141
- if (l2BlockProposedLogs.length === 0) {
178
+ if (checkpointProposedLogs.length === 0) {
142
179
  break;
143
180
  }
144
181
 
145
- const lastLog = l2BlockProposedLogs[l2BlockProposedLogs.length - 1];
182
+ const lastLog = checkpointProposedLogs.at(-1)!;
146
183
  logger.debug(
147
- `Got ${l2BlockProposedLogs.length} L2 block processed logs for L2 blocks ${l2BlockProposedLogs[0].args.blockNumber}-${lastLog.args.blockNumber} between L1 blocks ${searchStartBlock}-${searchEndBlock}`,
184
+ `Got ${checkpointProposedLogs.length} processed logs for checkpoints ${checkpointProposedLogs[0].args.checkpointNumber}-${lastLog.args.checkpointNumber} between L1 blocks ${searchStartBlock}-${searchEndBlock}`,
148
185
  );
149
186
 
150
187
  if (rollupConstants === undefined) {
@@ -160,52 +197,52 @@ export async function retrieveBlocksFromRollup(
160
197
  };
161
198
  }
162
199
 
163
- const newBlocks = await processL2BlockProposedLogs(
200
+ const newCheckpoints = await processCheckpointProposedLogs(
164
201
  rollup,
165
202
  publicClient,
166
203
  blobSinkClient,
167
- l2BlockProposedLogs,
204
+ checkpointProposedLogs,
168
205
  rollupConstants,
169
206
  logger,
170
207
  );
171
- retrievedBlocks.push(...newBlocks);
208
+ retrievedCheckpoints.push(...newCheckpoints);
172
209
  searchStartBlock = lastLog.blockNumber! + 1n;
173
210
  } while (searchStartBlock <= searchEndBlock);
174
211
 
175
- // The asyncpool from processL2BlockProposedLogs will not necessarily return the blocks in order, so we sort them before returning.
176
- return retrievedBlocks.sort((a, b) => Number(a.l1.blockNumber - b.l1.blockNumber));
212
+ // The asyncPool from processCheckpointProposedLogs will not necessarily return the checkpoints in order, so we sort them before returning.
213
+ return retrievedCheckpoints.sort((a, b) => Number(a.l1.blockNumber - b.l1.blockNumber));
177
214
  }
178
215
 
179
216
  /**
180
- * Processes newly received L2BlockProposed logs.
217
+ * Processes newly received CheckpointProposed logs.
181
218
  * @param rollup - The rollup contract
182
219
  * @param publicClient - The viem public client to use for transaction retrieval.
183
- * @param logs - L2BlockProposed logs.
184
- * @returns - An array blocks.
220
+ * @param logs - CheckpointProposed logs.
221
+ * @returns - An array of checkpoints.
185
222
  */
186
- async function processL2BlockProposedLogs(
223
+ async function processCheckpointProposedLogs(
187
224
  rollup: GetContractReturnType<typeof RollupAbi, ViemPublicClient>,
188
225
  publicClient: ViemPublicClient,
189
226
  blobSinkClient: BlobSinkClientInterface,
190
- logs: GetContractEventsReturnType<typeof RollupAbi, 'L2BlockProposed'>,
227
+ logs: GetContractEventsReturnType<typeof RollupAbi, 'CheckpointProposed'>,
191
228
  { chainId, version, targetCommitteeSize }: { chainId: Fr; version: Fr; targetCommitteeSize: number },
192
229
  logger: Logger,
193
- ): Promise<RetrievedL2Block[]> {
194
- const retrievedBlocks: RetrievedL2Block[] = [];
230
+ ): Promise<RetrievedCheckpoint[]> {
231
+ const retrievedCheckpoints: RetrievedCheckpoint[] = [];
195
232
  await asyncPool(10, logs, async log => {
196
- const l2BlockNumber = Number(log.args.blockNumber!);
233
+ const checkpointNumber = Number(log.args.checkpointNumber!);
197
234
  const archive = log.args.archive!;
198
- const archiveFromChain = await rollup.read.archiveAt([BigInt(l2BlockNumber)]);
235
+ const archiveFromChain = await rollup.read.archiveAt([BigInt(checkpointNumber)]);
199
236
  const blobHashes = log.args.versionedBlobHashes!.map(blobHash => Buffer.from(blobHash.slice(2), 'hex'));
200
237
 
201
- // The value from the event and contract will match only if the block is in the chain.
238
+ // The value from the event and contract will match only if the checkpoint is in the chain.
202
239
  if (archive === archiveFromChain) {
203
- const block = await getBlockFromRollupTx(
240
+ const checkpoint = await getCheckpointFromRollupTx(
204
241
  publicClient,
205
242
  blobSinkClient,
206
243
  log.transactionHash!,
207
244
  blobHashes,
208
- l2BlockNumber,
245
+ checkpointNumber,
209
246
  rollup.address,
210
247
  targetCommitteeSize,
211
248
  logger,
@@ -217,22 +254,22 @@ async function processL2BlockProposedLogs(
217
254
  timestamp: await getL1BlockTime(publicClient, log.blockNumber),
218
255
  };
219
256
 
220
- retrievedBlocks.push({ ...block, l1, chainId, version });
221
- logger.trace(`Retrieved L2 block ${l2BlockNumber} from L1 tx ${log.transactionHash}`, {
257
+ retrievedCheckpoints.push({ ...checkpoint, l1, chainId, version });
258
+ logger.trace(`Retrieved checkpoint ${checkpointNumber} from L1 tx ${log.transactionHash}`, {
222
259
  l1BlockNumber: log.blockNumber,
223
- l2BlockNumber,
260
+ checkpointNumber,
224
261
  archive: archive.toString(),
225
- attestations: block.attestations,
262
+ attestations: checkpoint.attestations,
226
263
  });
227
264
  } else {
228
- logger.warn(`Ignoring L2 block ${l2BlockNumber} due to archive root mismatch`, {
265
+ logger.warn(`Ignoring checkpoint ${checkpointNumber} due to archive root mismatch`, {
229
266
  actual: archive,
230
267
  expected: archiveFromChain,
231
268
  });
232
269
  }
233
270
  });
234
271
 
235
- return retrievedBlocks;
272
+ return retrievedCheckpoints;
236
273
  }
237
274
 
238
275
  export async function getL1BlockTime(publicClient: ViemPublicClient, blockNumber: bigint): Promise<bigint> {
@@ -291,24 +328,25 @@ function extractRollupProposeCalldata(multicall3Data: Hex, rollupAddress: Hex):
291
328
  }
292
329
 
293
330
  /**
294
- * Gets block from the calldata of an L1 transaction.
295
- * Assumes that the block was published from an EOA.
331
+ * Gets checkpoint from the calldata of an L1 transaction.
332
+ * Assumes that the checkpoint was published from an EOA.
296
333
  * TODO: Add retries and error management.
297
334
  * @param publicClient - The viem public client to use for transaction retrieval.
298
335
  * @param txHash - Hash of the tx that published it.
299
- * @param l2BlockNumber - L2 block number.
300
- * @returns L2 block from the calldata, deserialized
336
+ * @param checkpointNumber - Checkpoint number.
337
+ * @returns Checkpoint from the calldata, deserialized
301
338
  */
302
- async function getBlockFromRollupTx(
339
+ async function getCheckpointFromRollupTx(
303
340
  publicClient: ViemPublicClient,
304
341
  blobSinkClient: BlobSinkClientInterface,
305
342
  txHash: `0x${string}`,
306
343
  blobHashes: Buffer[], // TODO(md): buffer32?
307
- l2BlockNumber: number,
344
+ checkpointNumber: number,
308
345
  rollupAddress: Hex,
309
346
  targetCommitteeSize: number,
310
347
  logger: Logger,
311
- ): Promise<Omit<RetrievedL2Block, 'l1' | 'chainId' | 'version'>> {
348
+ ): Promise<Omit<RetrievedCheckpoint, 'l1' | 'chainId' | 'version'>> {
349
+ logger.trace(`Fetching checkpoint ${checkpointNumber} from rollup tx ${txHash}`);
312
350
  const { input: forwarderData, blockHash } = await publicClient.getTransaction({ hash: txHash });
313
351
 
314
352
  const rollupData = extractRollupProposeCalldata(forwarderData, rollupAddress);
@@ -324,7 +362,6 @@ async function getBlockFromRollupTx(
324
362
  const [decodedArgs, packedAttestations, _signers, _blobInput] = rollupArgs! as readonly [
325
363
  {
326
364
  archive: Hex;
327
- stateReference: ViemStateReference;
328
365
  oracleInput: {
329
366
  feeAssetPriceModifier: bigint;
330
367
  };
@@ -340,10 +377,10 @@ async function getBlockFromRollupTx(
340
377
  const attestations = CommitteeAttestation.fromPacked(packedAttestations, targetCommitteeSize);
341
378
 
342
379
  logger.trace(`Recovered propose calldata from tx ${txHash}`, {
343
- l2BlockNumber,
380
+ checkpointNumber,
344
381
  archive: decodedArgs.archive,
345
- stateReference: decodedArgs.stateReference,
346
382
  header: decodedArgs.header,
383
+ l1BlockHash: blockHash,
347
384
  blobHashes,
348
385
  attestations,
349
386
  packedAttestations,
@@ -353,16 +390,13 @@ async function getBlockFromRollupTx(
353
390
  const header = CheckpointHeader.fromViem(decodedArgs.header);
354
391
  const blobBodies = await blobSinkClient.getBlobSidecar(blockHash, blobHashes);
355
392
  if (blobBodies.length === 0) {
356
- throw new NoBlobBodiesFoundError(l2BlockNumber);
393
+ throw new NoBlobBodiesFoundError(checkpointNumber);
357
394
  }
358
395
 
359
- let blobFields: Fr[];
396
+ let checkpointBlobData: CheckpointBlobData;
360
397
  try {
361
- // Get the fields that were actually added in the checkpoint. And check the encoding of the fields.
362
- blobFields = getBlobFieldsInCheckpoint(
363
- blobBodies.map(b => b.blob),
364
- true /* checkEncoding */,
365
- );
398
+ // Attempt to decode the checkpoint blob data.
399
+ checkpointBlobData = decodeCheckpointBlobDataFromBlobs(blobBodies.map(b => b.blob));
366
400
  } catch (err: any) {
367
401
  if (err instanceof BlobDeserializationError) {
368
402
  logger.fatal(err.message);
@@ -374,14 +408,11 @@ async function getBlockFromRollupTx(
374
408
 
375
409
  const archiveRoot = new Fr(Buffer.from(hexToBytes(decodedArgs.archive)));
376
410
 
377
- const stateReference = StateReference.fromViem(decodedArgs.stateReference);
378
-
379
411
  return {
380
- l2BlockNumber,
412
+ checkpointNumber,
381
413
  archiveRoot,
382
- stateReference,
383
414
  header,
384
- blobFields,
415
+ checkpointBlobData,
385
416
  attestations,
386
417
  };
387
418
  }
@@ -432,13 +463,13 @@ export async function retrieveL1ToL2Messages(
432
463
 
433
464
  function mapLogsInboxMessage(logs: GetContractEventsReturnType<typeof InboxAbi, 'MessageSent'>): InboxMessage[] {
434
465
  return logs.map(log => {
435
- const { index, hash, l2BlockNumber, rollingHash } = log.args;
466
+ const { index, hash, checkpointNumber, rollingHash } = log.args;
436
467
  return {
437
468
  index: index!,
438
469
  leaf: Fr.fromHexString(hash!),
439
470
  l1BlockNumber: log.blockNumber,
440
471
  l1BlockHash: Buffer32.fromString(log.blockHash),
441
- l2BlockNumber: Number(l2BlockNumber!),
472
+ l2BlockNumber: Number(checkpointNumber!),
442
473
  rollingHash: Buffer16.fromString(rollingHash!),
443
474
  };
444
475
  });
@@ -450,7 +481,7 @@ export async function retrieveL2ProofVerifiedEvents(
450
481
  rollupAddress: EthAddress,
451
482
  searchStartBlock: bigint,
452
483
  searchEndBlock?: bigint,
453
- ): Promise<{ l1BlockNumber: bigint; l2BlockNumber: number; proverId: Fr; txHash: Hex }[]> {
484
+ ): Promise<{ l1BlockNumber: bigint; checkpointNumber: number; proverId: Fr; txHash: Hex }[]> {
454
485
  const logs = await publicClient.getLogs({
455
486
  address: rollupAddress.toString(),
456
487
  fromBlock: searchStartBlock,
@@ -461,7 +492,7 @@ export async function retrieveL2ProofVerifiedEvents(
461
492
 
462
493
  return logs.map(log => ({
463
494
  l1BlockNumber: log.blockNumber,
464
- l2BlockNumber: Number(log.args.blockNumber),
495
+ checkpointNumber: Number(log.args.checkpointNumber),
465
496
  proverId: Fr.fromHexString(log.args.proverId),
466
497
  txHash: log.transactionHash,
467
498
  }));
@@ -473,14 +504,14 @@ export async function retrieveL2ProofsFromRollup(
473
504
  rollupAddress: EthAddress,
474
505
  searchStartBlock: bigint,
475
506
  searchEndBlock?: bigint,
476
- ): Promise<DataRetrieval<{ proof: Proof; proverId: Fr; l2BlockNumber: number; txHash: `0x${string}` }>> {
507
+ ): Promise<DataRetrieval<{ proof: Proof; proverId: Fr; checkpointNumber: number; txHash: `0x${string}` }>> {
477
508
  const logs = await retrieveL2ProofVerifiedEvents(publicClient, rollupAddress, searchStartBlock, searchEndBlock);
478
- const retrievedData: { proof: Proof; proverId: Fr; l2BlockNumber: number; txHash: `0x${string}` }[] = [];
509
+ const retrievedData: { proof: Proof; proverId: Fr; checkpointNumber: number; txHash: `0x${string}` }[] = [];
479
510
  const lastProcessedL1BlockNumber = logs.length > 0 ? logs.at(-1)!.l1BlockNumber : searchStartBlock - 1n;
480
511
 
481
- for (const { txHash, proverId, l2BlockNumber } of logs) {
512
+ for (const { txHash, proverId, checkpointNumber } of logs) {
482
513
  const proofData = await getProofFromSubmitProofTx(publicClient, txHash, proverId);
483
- retrievedData.push({ proof: proofData.proof, proverId: proofData.proverId, l2BlockNumber, txHash });
514
+ retrievedData.push({ proof: proofData.proof, proverId: proofData.proverId, checkpointNumber, txHash });
484
515
  }
485
516
  return {
486
517
  retrievedData,
@@ -488,26 +519,26 @@ export async function retrieveL2ProofsFromRollup(
488
519
  };
489
520
  }
490
521
 
491
- export type SubmitBlockProof = {
522
+ export type SubmitEpochProof = {
492
523
  archiveRoot: Fr;
493
524
  proverId: Fr;
494
525
  proof: Proof;
495
526
  };
496
527
 
497
528
  /**
498
- * Gets block metadata (header and archive snapshot) from the calldata of an L1 transaction.
529
+ * Gets epoch proof metadata (archive root and proof) from the calldata of an L1 transaction.
499
530
  * Assumes that the block was published from an EOA.
500
531
  * TODO: Add retries and error management.
501
532
  * @param publicClient - The viem public client to use for transaction retrieval.
502
533
  * @param txHash - Hash of the tx that published it.
503
- * @param l2BlockNum - L2 block number.
504
- * @returns L2 block metadata (header and archive) from the calldata, deserialized
534
+ * @param expectedProverId - Expected prover ID.
535
+ * @returns Epoch proof metadata from the calldata, deserialized.
505
536
  */
506
537
  export async function getProofFromSubmitProofTx(
507
538
  publicClient: ViemPublicClient,
508
539
  txHash: `0x${string}`,
509
540
  expectedProverId: Fr,
510
- ): Promise<SubmitBlockProof> {
541
+ ): Promise<SubmitEpochProof> {
511
542
  const { input: data } = await publicClient.getTransaction({ hash: txHash });
512
543
  const { functionName, args } = decodeFunctionData({ abi: RollupAbi, data });
513
544
 
@@ -1,5 +1,5 @@
1
1
  import { createLogger } from '@aztec/foundation/log';
2
- import type { L2Block } from '@aztec/stdlib/block';
2
+ import type { L2BlockNew } from '@aztec/stdlib/block';
3
3
  import {
4
4
  Attributes,
5
5
  type Gauge,
@@ -139,7 +139,7 @@ export class ArchiverInstrumentation {
139
139
  return this.telemetry.isEnabled();
140
140
  }
141
141
 
142
- public processNewBlocks(syncTimePerBlock: number, blocks: L2Block[]) {
142
+ public processNewBlocks(syncTimePerBlock: number, blocks: L2BlockNew[]) {
143
143
  this.syncDurationPerBlock.record(Math.ceil(syncTimePerBlock));
144
144
  this.blockHeight.record(Math.max(...blocks.map(b => b.number)));
145
145
  this.syncBlockCount.add(blocks.length);
@@ -1 +1,2 @@
1
- export type { PublishedL2Block, L1PublishedData } from '@aztec/stdlib/block';
1
+ export type { PublishedL2Block } from '@aztec/stdlib/block';
2
+ export type { L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';