@aztec/archiver 0.0.1-commit.5daedc8 → 0.0.1-commit.6201a7b05

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 (218) hide show
  1. package/README.md +162 -22
  2. package/dest/archiver.d.ts +147 -0
  3. package/dest/archiver.d.ts.map +1 -0
  4. package/dest/archiver.js +788 -0
  5. package/dest/config.d.ts +32 -0
  6. package/dest/config.d.ts.map +1 -0
  7. package/dest/config.js +83 -0
  8. package/dest/errors.d.ts +92 -0
  9. package/dest/errors.d.ts.map +1 -0
  10. package/dest/errors.js +136 -0
  11. package/dest/factory.d.ts +8 -7
  12. package/dest/factory.d.ts.map +1 -1
  13. package/dest/factory.js +100 -15
  14. package/dest/index.d.ts +12 -4
  15. package/dest/index.d.ts.map +1 -1
  16. package/dest/index.js +10 -3
  17. package/dest/interfaces.d.ts +9 -0
  18. package/dest/interfaces.d.ts.map +1 -0
  19. package/dest/interfaces.js +3 -0
  20. package/dest/l1/bin/retrieve-calldata.d.ts +3 -0
  21. package/dest/l1/bin/retrieve-calldata.d.ts.map +1 -0
  22. package/dest/l1/bin/retrieve-calldata.js +152 -0
  23. package/dest/l1/calldata_retriever.d.ts +136 -0
  24. package/dest/l1/calldata_retriever.d.ts.map +1 -0
  25. package/dest/l1/calldata_retriever.js +408 -0
  26. package/dest/l1/data_retrieval.d.ts +97 -0
  27. package/dest/l1/data_retrieval.d.ts.map +1 -0
  28. package/dest/{archiver → l1}/data_retrieval.js +86 -165
  29. package/dest/l1/debug_tx.d.ts +19 -0
  30. package/dest/l1/debug_tx.d.ts.map +1 -0
  31. package/dest/l1/debug_tx.js +73 -0
  32. package/dest/l1/spire_proposer.d.ts +70 -0
  33. package/dest/l1/spire_proposer.d.ts.map +1 -0
  34. package/dest/l1/spire_proposer.js +149 -0
  35. package/dest/l1/trace_tx.d.ts +97 -0
  36. package/dest/l1/trace_tx.d.ts.map +1 -0
  37. package/dest/l1/trace_tx.js +91 -0
  38. package/dest/l1/types.d.ts +12 -0
  39. package/dest/l1/types.d.ts.map +1 -0
  40. package/dest/l1/types.js +3 -0
  41. package/dest/l1/validate_historical_logs.d.ts +23 -0
  42. package/dest/l1/validate_historical_logs.d.ts.map +1 -0
  43. package/dest/l1/validate_historical_logs.js +108 -0
  44. package/dest/l1/validate_trace.d.ts +32 -0
  45. package/dest/l1/validate_trace.d.ts.map +1 -0
  46. package/dest/l1/validate_trace.js +154 -0
  47. package/dest/modules/data_source_base.d.ts +95 -0
  48. package/dest/modules/data_source_base.d.ts.map +1 -0
  49. package/dest/modules/data_source_base.js +234 -0
  50. package/dest/modules/data_store_updater.d.ts +93 -0
  51. package/dest/modules/data_store_updater.d.ts.map +1 -0
  52. package/dest/modules/data_store_updater.js +345 -0
  53. package/dest/modules/instrumentation.d.ts +55 -0
  54. package/dest/modules/instrumentation.d.ts.map +1 -0
  55. package/dest/modules/instrumentation.js +143 -0
  56. package/dest/modules/l1_synchronizer.d.ts +77 -0
  57. package/dest/modules/l1_synchronizer.d.ts.map +1 -0
  58. package/dest/modules/l1_synchronizer.js +1265 -0
  59. package/dest/modules/validation.d.ts +18 -0
  60. package/dest/modules/validation.d.ts.map +1 -0
  61. package/dest/{archiver → modules}/validation.js +13 -7
  62. package/dest/store/block_store.d.ts +262 -0
  63. package/dest/store/block_store.d.ts.map +1 -0
  64. package/dest/store/block_store.js +1048 -0
  65. package/dest/store/contract_class_store.d.ts +17 -0
  66. package/dest/store/contract_class_store.d.ts.map +1 -0
  67. package/dest/store/contract_class_store.js +64 -0
  68. package/dest/store/contract_instance_store.d.ts +24 -0
  69. package/dest/store/contract_instance_store.d.ts.map +1 -0
  70. package/dest/{archiver/kv_archiver_store → store}/contract_instance_store.js +7 -3
  71. package/dest/store/kv_archiver_store.d.ts +401 -0
  72. package/dest/store/kv_archiver_store.d.ts.map +1 -0
  73. package/dest/store/kv_archiver_store.js +525 -0
  74. package/dest/store/l2_tips_cache.d.ts +20 -0
  75. package/dest/store/l2_tips_cache.d.ts.map +1 -0
  76. package/dest/store/l2_tips_cache.js +109 -0
  77. package/dest/store/log_store.d.ts +57 -0
  78. package/dest/store/log_store.d.ts.map +1 -0
  79. package/dest/store/log_store.js +531 -0
  80. package/dest/store/message_store.d.ts +44 -0
  81. package/dest/store/message_store.d.ts.map +1 -0
  82. package/dest/{archiver/kv_archiver_store → store}/message_store.js +36 -23
  83. package/dest/{archiver/structs → structs}/data_retrieval.d.ts +1 -1
  84. package/dest/structs/data_retrieval.d.ts.map +1 -0
  85. package/dest/structs/inbox_message.d.ts +15 -0
  86. package/dest/structs/inbox_message.d.ts.map +1 -0
  87. package/dest/{archiver/structs → structs}/inbox_message.js +6 -5
  88. package/dest/structs/published.d.ts +2 -0
  89. package/dest/structs/published.d.ts.map +1 -0
  90. package/dest/test/fake_l1_state.d.ts +214 -0
  91. package/dest/test/fake_l1_state.d.ts.map +1 -0
  92. package/dest/test/fake_l1_state.js +517 -0
  93. package/dest/test/index.d.ts +2 -1
  94. package/dest/test/index.d.ts.map +1 -1
  95. package/dest/test/index.js +4 -1
  96. package/dest/test/mock_archiver.d.ts +16 -8
  97. package/dest/test/mock_archiver.d.ts.map +1 -1
  98. package/dest/test/mock_archiver.js +19 -14
  99. package/dest/test/mock_l1_to_l2_message_source.d.ts +7 -6
  100. package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
  101. package/dest/test/mock_l1_to_l2_message_source.js +23 -12
  102. package/dest/test/mock_l2_block_source.d.ts +68 -20
  103. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  104. package/dest/test/mock_l2_block_source.js +298 -85
  105. package/dest/test/mock_structs.d.ts +83 -4
  106. package/dest/test/mock_structs.d.ts.map +1 -1
  107. package/dest/test/mock_structs.js +157 -11
  108. package/dest/test/noop_l1_archiver.d.ts +26 -0
  109. package/dest/test/noop_l1_archiver.d.ts.map +1 -0
  110. package/dest/test/noop_l1_archiver.js +74 -0
  111. package/package.json +20 -20
  112. package/src/archiver.ts +566 -0
  113. package/src/{archiver/config.ts → config.ts} +51 -14
  114. package/src/errors.ts +213 -0
  115. package/src/factory.ts +155 -17
  116. package/src/index.ts +12 -3
  117. package/src/interfaces.ts +9 -0
  118. package/src/l1/README.md +55 -0
  119. package/src/l1/bin/retrieve-calldata.ts +194 -0
  120. package/src/l1/calldata_retriever.ts +523 -0
  121. package/src/{archiver → l1}/data_retrieval.ts +155 -247
  122. package/src/l1/debug_tx.ts +99 -0
  123. package/src/l1/spire_proposer.ts +152 -0
  124. package/src/l1/trace_tx.ts +128 -0
  125. package/src/l1/types.ts +13 -0
  126. package/src/l1/validate_historical_logs.ts +140 -0
  127. package/src/l1/validate_trace.ts +229 -0
  128. package/src/modules/data_source_base.ts +364 -0
  129. package/src/modules/data_store_updater.ts +465 -0
  130. package/src/modules/instrumentation.ts +204 -0
  131. package/src/modules/l1_synchronizer.ts +1126 -0
  132. package/src/{archiver → modules}/validation.ts +21 -15
  133. package/src/store/block_store.ts +1361 -0
  134. package/src/store/contract_class_store.ts +82 -0
  135. package/src/{archiver/kv_archiver_store → store}/contract_instance_store.ts +10 -7
  136. package/src/store/kv_archiver_store.ts +765 -0
  137. package/src/store/l2_tips_cache.ts +134 -0
  138. package/src/store/log_store.ts +733 -0
  139. package/src/{archiver/kv_archiver_store → store}/message_store.ts +48 -28
  140. package/src/{archiver/structs → structs}/inbox_message.ts +7 -7
  141. package/src/{archiver/structs → structs}/published.ts +0 -1
  142. package/src/test/fake_l1_state.ts +770 -0
  143. package/src/test/fixtures/debug_traceTransaction-multicall3.json +88 -0
  144. package/src/test/fixtures/debug_traceTransaction-multiplePropose.json +153 -0
  145. package/src/test/fixtures/debug_traceTransaction-proxied.json +122 -0
  146. package/src/test/fixtures/trace_transaction-multicall3.json +65 -0
  147. package/src/test/fixtures/trace_transaction-multiplePropose.json +319 -0
  148. package/src/test/fixtures/trace_transaction-proxied.json +128 -0
  149. package/src/test/fixtures/trace_transaction-randomRevert.json +216 -0
  150. package/src/test/index.ts +4 -0
  151. package/src/test/mock_archiver.ts +23 -16
  152. package/src/test/mock_l1_to_l2_message_source.ts +19 -11
  153. package/src/test/mock_l2_block_source.ts +367 -93
  154. package/src/test/mock_structs.ts +289 -13
  155. package/src/test/noop_l1_archiver.ts +117 -0
  156. package/dest/archiver/archiver.d.ts +0 -287
  157. package/dest/archiver/archiver.d.ts.map +0 -1
  158. package/dest/archiver/archiver.js +0 -1408
  159. package/dest/archiver/archiver_store.d.ts +0 -255
  160. package/dest/archiver/archiver_store.d.ts.map +0 -1
  161. package/dest/archiver/archiver_store.js +0 -4
  162. package/dest/archiver/archiver_store_test_suite.d.ts +0 -8
  163. package/dest/archiver/archiver_store_test_suite.d.ts.map +0 -1
  164. package/dest/archiver/archiver_store_test_suite.js +0 -1289
  165. package/dest/archiver/config.d.ts +0 -21
  166. package/dest/archiver/config.d.ts.map +0 -1
  167. package/dest/archiver/config.js +0 -55
  168. package/dest/archiver/data_retrieval.d.ts +0 -79
  169. package/dest/archiver/data_retrieval.d.ts.map +0 -1
  170. package/dest/archiver/errors.d.ts +0 -12
  171. package/dest/archiver/errors.d.ts.map +0 -1
  172. package/dest/archiver/errors.js +0 -17
  173. package/dest/archiver/index.d.ts +0 -7
  174. package/dest/archiver/index.d.ts.map +0 -1
  175. package/dest/archiver/index.js +0 -4
  176. package/dest/archiver/instrumentation.d.ts +0 -35
  177. package/dest/archiver/instrumentation.d.ts.map +0 -1
  178. package/dest/archiver/instrumentation.js +0 -140
  179. package/dest/archiver/kv_archiver_store/block_store.d.ts +0 -124
  180. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +0 -1
  181. package/dest/archiver/kv_archiver_store/block_store.js +0 -370
  182. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +0 -18
  183. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +0 -1
  184. package/dest/archiver/kv_archiver_store/contract_class_store.js +0 -120
  185. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +0 -24
  186. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +0 -1
  187. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +0 -168
  188. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +0 -1
  189. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +0 -296
  190. package/dest/archiver/kv_archiver_store/log_store.d.ts +0 -49
  191. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +0 -1
  192. package/dest/archiver/kv_archiver_store/log_store.js +0 -336
  193. package/dest/archiver/kv_archiver_store/message_store.d.ts +0 -39
  194. package/dest/archiver/kv_archiver_store/message_store.d.ts.map +0 -1
  195. package/dest/archiver/structs/data_retrieval.d.ts.map +0 -1
  196. package/dest/archiver/structs/inbox_message.d.ts +0 -15
  197. package/dest/archiver/structs/inbox_message.d.ts.map +0 -1
  198. package/dest/archiver/structs/published.d.ts +0 -3
  199. package/dest/archiver/structs/published.d.ts.map +0 -1
  200. package/dest/archiver/validation.d.ts +0 -17
  201. package/dest/archiver/validation.d.ts.map +0 -1
  202. package/dest/rpc/index.d.ts +0 -9
  203. package/dest/rpc/index.d.ts.map +0 -1
  204. package/dest/rpc/index.js +0 -15
  205. package/src/archiver/archiver.ts +0 -1858
  206. package/src/archiver/archiver_store.ts +0 -305
  207. package/src/archiver/archiver_store_test_suite.ts +0 -1264
  208. package/src/archiver/errors.ts +0 -26
  209. package/src/archiver/index.ts +0 -6
  210. package/src/archiver/instrumentation.ts +0 -187
  211. package/src/archiver/kv_archiver_store/block_store.ts +0 -481
  212. package/src/archiver/kv_archiver_store/contract_class_store.ts +0 -176
  213. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +0 -422
  214. package/src/archiver/kv_archiver_store/log_store.ts +0 -406
  215. package/src/rpc/index.ts +0 -16
  216. /package/dest/{archiver/structs → structs}/data_retrieval.js +0 -0
  217. /package/dest/{archiver/structs → structs}/published.js +0 -0
  218. /package/src/{archiver/structs → structs}/data_retrieval.ts +0 -0
@@ -1,3 +1,4 @@
1
+ import type { BlobClientInterface } from '@aztec/blob-client/client';
1
2
  import {
2
3
  BlobDeserializationError,
3
4
  type CheckpointBlobData,
@@ -5,57 +6,61 @@ import {
5
6
  decodeCheckpointBlobDataFromBlobs,
6
7
  encodeBlockBlobData,
7
8
  } from '@aztec/blob-lib';
8
- import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
9
9
  import type {
10
+ CheckpointProposedLog,
10
11
  EpochProofPublicInputArgs,
11
- ViemClient,
12
- ViemCommitteeAttestations,
13
- ViemHeader,
14
- ViemPublicClient,
15
- } from '@aztec/ethereum';
12
+ InboxContract,
13
+ MessageSentLog,
14
+ RollupContract,
15
+ } from '@aztec/ethereum/contracts';
16
+ import type { ViemPublicClient, ViemPublicDebugClient } from '@aztec/ethereum/types';
16
17
  import { asyncPool } from '@aztec/foundation/async-pool';
17
- import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
18
- import type { EthAddress } from '@aztec/foundation/eth-address';
19
- import type { ViemSignature } from '@aztec/foundation/eth-signature';
20
- import { Fr } from '@aztec/foundation/fields';
18
+ import { CheckpointNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
19
+ import { Fr } from '@aztec/foundation/curves/bn254';
20
+ import { EthAddress } from '@aztec/foundation/eth-address';
21
21
  import { type Logger, createLogger } from '@aztec/foundation/log';
22
- import { type InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
23
- import { Body, CommitteeAttestation, L2BlockNew } from '@aztec/stdlib/block';
24
- import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
22
+ import { RollupAbi } from '@aztec/l1-artifacts';
23
+ import { Body, CommitteeAttestation, L2Block } from '@aztec/stdlib/block';
24
+ import { Checkpoint, L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
25
25
  import { Proof } from '@aztec/stdlib/proofs';
26
26
  import { CheckpointHeader } from '@aztec/stdlib/rollup';
27
27
  import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
28
28
  import { BlockHeader, GlobalVariables, PartialStateReference, StateReference } from '@aztec/stdlib/tx';
29
29
 
30
- import {
31
- type GetContractEventsReturnType,
32
- type GetContractReturnType,
33
- type Hex,
34
- decodeFunctionData,
35
- getAbiItem,
36
- hexToBytes,
37
- multicall3Abi,
38
- } from 'viem';
39
-
40
- import { NoBlobBodiesFoundError } from './errors.js';
41
- import type { DataRetrieval } from './structs/data_retrieval.js';
42
- import type { InboxMessage } from './structs/inbox_message.js';
43
- import type { L1PublishedData } from './structs/published.js';
44
-
45
- export type RetrievedCheckpoint = {
46
- checkpointNumber: number;
30
+ import { type Hex, decodeFunctionData, getAbiItem, hexToBytes } from 'viem';
31
+
32
+ import { NoBlobBodiesFoundError } from '../errors.js';
33
+ import type { ArchiverInstrumentation } from '../modules/instrumentation.js';
34
+ import type { DataRetrieval } from '../structs/data_retrieval.js';
35
+ import type { InboxMessage } from '../structs/inbox_message.js';
36
+ import { CalldataRetriever } from './calldata_retriever.js';
37
+
38
+ type RetrievedCheckpointBase = {
39
+ checkpointNumber: CheckpointNumber;
47
40
  archiveRoot: Fr;
41
+ feeAssetPriceModifier: bigint;
48
42
  header: CheckpointHeader;
49
- checkpointBlobData: CheckpointBlobData;
50
43
  l1: L1PublishedData;
51
44
  chainId: Fr;
52
45
  version: Fr;
53
46
  attestations: CommitteeAttestation[];
54
47
  };
55
48
 
49
+ /** Checkpoint data as retrieved from L1 calldata and blob data. */
50
+ export type RetrievedCheckpoint = RetrievedCheckpointBase & { checkpointBlobData: CheckpointBlobData };
51
+
52
+ /** Checkpoint data retrieved from L1 calldata only, without blob data. */
53
+ export type RetrievedCheckpointFromCalldata = RetrievedCheckpointBase & {
54
+ /** Versioned blob hashes from the checkpoint proposed event. */
55
+ blobHashes: Buffer[];
56
+ /** Parent beacon block root from the L1 block, used for blob fetching. */
57
+ parentBeaconBlockRoot: string | undefined;
58
+ };
59
+
56
60
  export async function retrievedToPublishedCheckpoint({
57
61
  checkpointNumber,
58
62
  archiveRoot,
63
+ feeAssetPriceModifier,
59
64
  header: checkpointHeader,
60
65
  checkpointBlobData,
61
66
  l1,
@@ -71,12 +76,12 @@ export async function retrievedToPublishedCheckpoint({
71
76
  .slice(1)
72
77
  .concat([archiveRoot]);
73
78
 
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:
79
+ // An error will be thrown from `decodeCheckpointBlobDataFromBlobs` if it can't read a field for the
80
+ // `l1ToL2MessageRoot` of the first block. So below we can safely assume it exists:
76
81
  const l1toL2MessageTreeRoot = blocksBlobData[0].l1ToL2MessageRoot!;
77
82
 
78
83
  const spongeBlob = SpongeBlob.init();
79
- const l2Blocks: L2BlockNew[] = [];
84
+ const l2Blocks: L2Block[] = [];
80
85
  for (let i = 0; i < blocksBlobData.length; i++) {
81
86
  const blockBlobData = blocksBlobData[i];
82
87
  const { blockEndMarker, blockEndStateField, lastArchiveRoot, noteHashRoot, nullifierRoot, publicDataRoot } =
@@ -107,7 +112,7 @@ export async function retrievedToPublishedCheckpoint({
107
112
  }),
108
113
  });
109
114
 
110
- const body = Body.fromTxBlobData(checkpointBlobData.blocks[0].txs);
115
+ const body = Body.fromTxBlobData(blockBlobData.txs);
111
116
 
112
117
  const blobFields = encodeBlockBlobData(blockBlobData);
113
118
  await spongeBlob.absorb(blobFields);
@@ -126,7 +131,7 @@ export async function retrievedToPublishedCheckpoint({
126
131
 
127
132
  const newArchive = new AppendOnlyTreeSnapshot(newArchiveRoots[i], l2BlockNumber + 1);
128
133
 
129
- l2Blocks.push(new L2BlockNew(newArchive, header, body));
134
+ l2Blocks.push(new L2Block(newArchive, header, body, checkpointNumber, IndexWithinCheckpoint(i)));
130
135
  }
131
136
 
132
137
  const lastBlock = l2Blocks.at(-1)!;
@@ -135,29 +140,34 @@ export async function retrievedToPublishedCheckpoint({
135
140
  header: checkpointHeader,
136
141
  blocks: l2Blocks,
137
142
  number: checkpointNumber,
143
+ feeAssetPriceModifier: feeAssetPriceModifier,
138
144
  });
139
145
 
140
146
  return PublishedCheckpoint.from({ checkpoint, l1, attestations });
141
147
  }
142
148
 
143
149
  /**
144
- * Fetches new checkpoints.
150
+ * Fetches checkpoint calldata from the rollup contract without fetching blob data.
151
+ * Returns RetrievedCheckpointFromCalldata objects that preserve the information needed for deferred blob fetching.
152
+ * @param rollup - The rollup contract wrapper.
145
153
  * @param publicClient - The viem public client to use for transaction retrieval.
146
- * @param rollupAddress - The address of the rollup contract.
154
+ * @param debugClient - The viem debug client to use for trace/debug RPC methods (optional).
147
155
  * @param searchStartBlock - The block number to use for starting the search.
148
156
  * @param searchEndBlock - The highest block number that we should search up to.
149
- * @param expectedNextL2BlockNum - The next L2 block number that we expect to find.
150
- * @returns An array of block; as well as the next eth block to search from.
157
+ * @param instrumentation - The archiver instrumentation instance.
158
+ * @param logger - The logger instance.
159
+ * @returns An array of calldata-only checkpoints.
151
160
  */
152
- export async function retrieveCheckpointsFromRollup(
153
- rollup: GetContractReturnType<typeof RollupAbi, ViemPublicClient>,
161
+ export async function retrieveCheckpointCalldataFromRollup(
162
+ rollup: RollupContract,
154
163
  publicClient: ViemPublicClient,
155
- blobSinkClient: BlobSinkClientInterface,
164
+ debugClient: ViemPublicDebugClient,
156
165
  searchStartBlock: bigint,
157
166
  searchEndBlock: bigint,
167
+ instrumentation: ArchiverInstrumentation,
158
168
  logger: Logger = createLogger('archiver'),
159
- ): Promise<RetrievedCheckpoint[]> {
160
- const retrievedCheckpoints: RetrievedCheckpoint[] = [];
169
+ ): Promise<RetrievedCheckpointFromCalldata[]> {
170
+ const retrievedCheckpoints: RetrievedCheckpointFromCalldata[] = [];
161
171
 
162
172
  let rollupConstants: { chainId: Fr; version: Fr; targetCommitteeSize: number } | undefined;
163
173
 
@@ -165,15 +175,7 @@ export async function retrieveCheckpointsFromRollup(
165
175
  if (searchStartBlock > searchEndBlock) {
166
176
  break;
167
177
  }
168
- const checkpointProposedLogs = (
169
- await rollup.getEvents.CheckpointProposed(
170
- {},
171
- {
172
- fromBlock: searchStartBlock,
173
- toBlock: searchEndBlock,
174
- },
175
- )
176
- ).filter(log => log.blockNumber! >= searchStartBlock && log.blockNumber! <= searchEndBlock);
178
+ const checkpointProposedLogs = await rollup.getCheckpointProposedEvents(searchStartBlock, searchEndBlock);
177
179
 
178
180
  if (checkpointProposedLogs.length === 0) {
179
181
  break;
@@ -181,90 +183,108 @@ export async function retrieveCheckpointsFromRollup(
181
183
 
182
184
  const lastLog = checkpointProposedLogs.at(-1)!;
183
185
  logger.debug(
184
- `Got ${checkpointProposedLogs.length} processed logs for checkpoints ${checkpointProposedLogs[0].args.checkpointNumber}-${lastLog.args.checkpointNumber} between L1 blocks ${searchStartBlock}-${searchEndBlock}`,
186
+ `Got ${checkpointProposedLogs.length} processed logs for checkpoints ${checkpointProposedLogs[0].args.checkpointNumber}-${lastLog.args.checkpointNumber} between L1 blocks ${searchStartBlock}-${searchEndBlock}`,
185
187
  );
186
188
 
187
189
  if (rollupConstants === undefined) {
188
190
  const [chainId, version, targetCommitteeSize] = await Promise.all([
189
191
  publicClient.getChainId(),
190
- rollup.read.getVersion(),
191
- rollup.read.getTargetCommitteeSize(),
192
+ rollup.getVersion(),
193
+ rollup.getTargetCommitteeSize(),
192
194
  ]);
193
195
  rollupConstants = {
194
196
  chainId: new Fr(chainId),
195
197
  version: new Fr(version),
196
- targetCommitteeSize: Number(targetCommitteeSize),
198
+ targetCommitteeSize,
197
199
  };
198
200
  }
199
201
 
200
202
  const newCheckpoints = await processCheckpointProposedLogs(
201
203
  rollup,
202
204
  publicClient,
203
- blobSinkClient,
205
+ debugClient,
204
206
  checkpointProposedLogs,
205
207
  rollupConstants,
208
+ instrumentation,
206
209
  logger,
207
210
  );
208
211
  retrievedCheckpoints.push(...newCheckpoints);
209
- searchStartBlock = lastLog.blockNumber! + 1n;
212
+ searchStartBlock = lastLog.l1BlockNumber + 1n;
210
213
  } while (searchStartBlock <= searchEndBlock);
211
214
 
212
- // The asyncPool from processCheckpointProposedLogs will not necessarily return the checkpoints in order, so we sort them before returning.
213
215
  return retrievedCheckpoints.sort((a, b) => Number(a.l1.blockNumber - b.l1.blockNumber));
214
216
  }
215
217
 
216
218
  /**
217
- * Processes newly received CheckpointProposed logs.
218
- * @param rollup - The rollup contract
219
+ * Processes CheckpointProposed logs, fetching only calldata (no blobs).
220
+ * @param rollup - The rollup contract wrapper.
219
221
  * @param publicClient - The viem public client to use for transaction retrieval.
222
+ * @param debugClient - The viem debug client to use for trace/debug RPC methods (optional).
220
223
  * @param logs - CheckpointProposed logs.
221
- * @returns - An array of checkpoints.
224
+ * @param rollupConstants - The rollup constants (chainId, version, targetCommitteeSize).
225
+ * @param instrumentation - The archiver instrumentation instance.
226
+ * @param logger - The logger instance.
227
+ * @returns An array of calldata-only checkpoints.
222
228
  */
223
229
  async function processCheckpointProposedLogs(
224
- rollup: GetContractReturnType<typeof RollupAbi, ViemPublicClient>,
230
+ rollup: RollupContract,
225
231
  publicClient: ViemPublicClient,
226
- blobSinkClient: BlobSinkClientInterface,
227
- logs: GetContractEventsReturnType<typeof RollupAbi, 'CheckpointProposed'>,
232
+ debugClient: ViemPublicDebugClient,
233
+ logs: CheckpointProposedLog[],
228
234
  { chainId, version, targetCommitteeSize }: { chainId: Fr; version: Fr; targetCommitteeSize: number },
235
+ instrumentation: ArchiverInstrumentation,
229
236
  logger: Logger,
230
- ): Promise<RetrievedCheckpoint[]> {
231
- const retrievedCheckpoints: RetrievedCheckpoint[] = [];
237
+ ): Promise<RetrievedCheckpointFromCalldata[]> {
238
+ const retrievedCheckpoints: RetrievedCheckpointFromCalldata[] = [];
239
+ const calldataRetriever = new CalldataRetriever(
240
+ publicClient,
241
+ debugClient,
242
+ targetCommitteeSize,
243
+ instrumentation,
244
+ logger,
245
+ EthAddress.fromString(rollup.address),
246
+ );
247
+
232
248
  await asyncPool(10, logs, async log => {
233
- const checkpointNumber = Number(log.args.checkpointNumber!);
234
- const archive = log.args.archive!;
235
- const archiveFromChain = await rollup.read.archiveAt([BigInt(checkpointNumber)]);
236
- const blobHashes = log.args.versionedBlobHashes!.map(blobHash => Buffer.from(blobHash.slice(2), 'hex'));
237
-
238
- // The value from the event and contract will match only if the checkpoint is in the chain.
239
- if (archive === archiveFromChain) {
240
- const checkpoint = await getCheckpointFromRollupTx(
241
- publicClient,
242
- blobSinkClient,
243
- log.transactionHash!,
249
+ const checkpointNumber = log.args.checkpointNumber;
250
+ const archive = log.args.archive;
251
+ const archiveFromChain = await rollup.archiveAt(checkpointNumber);
252
+ const blobHashes = log.args.versionedBlobHashes;
253
+
254
+ if (archive.equals(archiveFromChain)) {
255
+ const expectedHashes = {
256
+ attestationsHash: log.args.attestationsHash.toString() as Hex,
257
+ payloadDigest: log.args.payloadDigest.toString() as Hex,
258
+ };
259
+
260
+ const checkpoint = await calldataRetriever.getCheckpointFromRollupTx(
261
+ log.l1TransactionHash,
244
262
  blobHashes,
245
263
  checkpointNumber,
246
- rollup.address,
247
- targetCommitteeSize,
248
- logger,
264
+ expectedHashes,
249
265
  );
266
+ const { timestamp, parentBeaconBlockRoot } = await getL1Block(publicClient, log.l1BlockNumber);
267
+ const l1 = new L1PublishedData(log.l1BlockNumber, timestamp, log.l1BlockHash.toString());
268
+
269
+ retrievedCheckpoints.push({
270
+ ...checkpoint,
271
+ l1,
272
+ chainId,
273
+ version,
274
+ blobHashes,
275
+ parentBeaconBlockRoot,
276
+ });
250
277
 
251
- const l1: L1PublishedData = {
252
- blockNumber: log.blockNumber,
253
- blockHash: log.blockHash,
254
- timestamp: await getL1BlockTime(publicClient, log.blockNumber),
255
- };
256
-
257
- retrievedCheckpoints.push({ ...checkpoint, l1, chainId, version });
258
- logger.trace(`Retrieved checkpoint ${checkpointNumber} from L1 tx ${log.transactionHash}`, {
259
- l1BlockNumber: log.blockNumber,
278
+ logger.trace(`Retrieved checkpoint calldata ${checkpointNumber} from L1 tx ${log.l1TransactionHash}`, {
279
+ l1BlockNumber: log.l1BlockNumber,
260
280
  checkpointNumber,
261
281
  archive: archive.toString(),
262
282
  attestations: checkpoint.attestations,
263
283
  });
264
284
  } else {
265
285
  logger.warn(`Ignoring checkpoint ${checkpointNumber} due to archive root mismatch`, {
266
- actual: archive,
267
- expected: archiveFromChain,
286
+ actual: archive.toString(),
287
+ expected: archiveFromChain.toString(),
268
288
  });
269
289
  }
270
290
  });
@@ -272,123 +292,29 @@ async function processCheckpointProposedLogs(
272
292
  return retrievedCheckpoints;
273
293
  }
274
294
 
275
- export async function getL1BlockTime(publicClient: ViemPublicClient, blockNumber: bigint): Promise<bigint> {
295
+ export async function getL1Block(
296
+ publicClient: ViemPublicClient,
297
+ blockNumber: bigint,
298
+ ): Promise<{ timestamp: bigint; parentBeaconBlockRoot: string | undefined }> {
276
299
  const block = await publicClient.getBlock({ blockNumber, includeTransactions: false });
277
- return block.timestamp;
300
+ return { timestamp: block.timestamp, parentBeaconBlockRoot: block.parentBeaconBlockRoot };
278
301
  }
279
302
 
280
- /**
281
- * Extracts the first 'propose' method calldata from a multicall3 transaction's data.
282
- * @param multicall3Data - The multicall3 transaction input data
283
- * @param rollupAddress - The address of the rollup contract
284
- * @returns The calldata for the first 'propose' method call to the rollup contract
285
- */
286
- function extractRollupProposeCalldata(multicall3Data: Hex, rollupAddress: Hex): Hex {
287
- const { functionName: multicall3FunctionName, args: multicall3Args } = decodeFunctionData({
288
- abi: multicall3Abi,
289
- data: multicall3Data,
290
- });
291
-
292
- if (multicall3FunctionName !== 'aggregate3') {
293
- throw new Error(`Unexpected multicall3 method called ${multicall3FunctionName}`);
294
- }
295
-
296
- if (multicall3Args.length !== 1) {
297
- throw new Error(`Unexpected number of arguments for multicall3`);
298
- }
299
-
300
- const [calls] = multicall3Args;
301
-
302
- // Find all rollup calls
303
- const rollupAddressLower = rollupAddress.toLowerCase();
304
-
305
- for (let i = 0; i < calls.length; i++) {
306
- const addr = calls[i].target;
307
- if (addr.toLowerCase() !== rollupAddressLower) {
308
- continue;
309
- }
310
- const callData = calls[i].callData;
311
-
312
- try {
313
- const { functionName: rollupFunctionName } = decodeFunctionData({
314
- abi: RollupAbi,
315
- data: callData,
316
- });
317
-
318
- if (rollupFunctionName === 'propose') {
319
- return callData;
320
- }
321
- } catch {
322
- // Skip invalid function data
323
- continue;
324
- }
325
- }
326
-
327
- throw new Error(`Rollup address not found in multicall3 args`);
328
- }
329
-
330
- /**
331
- * Gets checkpoint from the calldata of an L1 transaction.
332
- * Assumes that the checkpoint was published from an EOA.
333
- * TODO: Add retries and error management.
334
- * @param publicClient - The viem public client to use for transaction retrieval.
335
- * @param txHash - Hash of the tx that published it.
336
- * @param checkpointNumber - Checkpoint number.
337
- * @returns Checkpoint from the calldata, deserialized
338
- */
339
- async function getCheckpointFromRollupTx(
340
- publicClient: ViemPublicClient,
341
- blobSinkClient: BlobSinkClientInterface,
342
- txHash: `0x${string}`,
343
- blobHashes: Buffer[], // TODO(md): buffer32?
344
- checkpointNumber: number,
345
- rollupAddress: Hex,
346
- targetCommitteeSize: number,
303
+ export async function getCheckpointBlobDataFromBlobs(
304
+ blobClient: BlobClientInterface,
305
+ blockHash: string,
306
+ blobHashes: Buffer<ArrayBufferLike>[],
307
+ checkpointNumber: CheckpointNumber,
347
308
  logger: Logger,
348
- ): Promise<Omit<RetrievedCheckpoint, 'l1' | 'chainId' | 'version'>> {
349
- logger.trace(`Fetching checkpoint ${checkpointNumber} from rollup tx ${txHash}`);
350
- const { input: forwarderData, blockHash } = await publicClient.getTransaction({ hash: txHash });
351
-
352
- const rollupData = extractRollupProposeCalldata(forwarderData, rollupAddress);
353
- const { functionName: rollupFunctionName, args: rollupArgs } = decodeFunctionData({
354
- abi: RollupAbi,
355
- data: rollupData,
309
+ isHistoricalSync: boolean,
310
+ parentBeaconBlockRoot?: string,
311
+ l1BlockTimestamp?: bigint,
312
+ ): Promise<CheckpointBlobData> {
313
+ const blobBodies = await blobClient.getBlobSidecar(blockHash, blobHashes, {
314
+ isHistoricalSync,
315
+ parentBeaconBlockRoot,
316
+ l1BlockTimestamp,
356
317
  });
357
-
358
- if (rollupFunctionName !== 'propose') {
359
- throw new Error(`Unexpected rollup method called ${rollupFunctionName}`);
360
- }
361
-
362
- const [decodedArgs, packedAttestations, _signers, _blobInput] = rollupArgs! as readonly [
363
- {
364
- archive: Hex;
365
- oracleInput: {
366
- feeAssetPriceModifier: bigint;
367
- };
368
- header: ViemHeader;
369
- txHashes: readonly Hex[];
370
- },
371
- ViemCommitteeAttestations,
372
- Hex[],
373
- ViemSignature,
374
- Hex,
375
- ];
376
-
377
- const attestations = CommitteeAttestation.fromPacked(packedAttestations, targetCommitteeSize);
378
-
379
- logger.trace(`Recovered propose calldata from tx ${txHash}`, {
380
- checkpointNumber,
381
- archive: decodedArgs.archive,
382
- header: decodedArgs.header,
383
- l1BlockHash: blockHash,
384
- blobHashes,
385
- attestations,
386
- packedAttestations,
387
- targetCommitteeSize,
388
- });
389
-
390
- const header = CheckpointHeader.fromViem(decodedArgs.header);
391
- const blobBodies = await blobSinkClient.getBlobSidecar(blockHash, blobHashes);
392
318
  if (blobBodies.length === 0) {
393
319
  throw new NoBlobBodiesFoundError(checkpointNumber);
394
320
  }
@@ -396,83 +322,65 @@ async function getCheckpointFromRollupTx(
396
322
  let checkpointBlobData: CheckpointBlobData;
397
323
  try {
398
324
  // Attempt to decode the checkpoint blob data.
399
- checkpointBlobData = decodeCheckpointBlobDataFromBlobs(blobBodies.map(b => b.blob));
325
+ checkpointBlobData = decodeCheckpointBlobDataFromBlobs(blobBodies);
400
326
  } catch (err: any) {
401
327
  if (err instanceof BlobDeserializationError) {
402
328
  logger.fatal(err.message);
403
329
  } else {
404
330
  logger.fatal('Unable to sync: failed to decode fetched blob, this blob was likely not created by us');
405
331
  }
332
+ // Throwing an error since this is most likely caused by a bug.
406
333
  throw err;
407
334
  }
408
335
 
409
- const archiveRoot = new Fr(Buffer.from(hexToBytes(decodedArgs.archive)));
410
-
411
- return {
412
- checkpointNumber,
413
- archiveRoot,
414
- header,
415
- checkpointBlobData,
416
- attestations,
417
- };
336
+ return checkpointBlobData;
418
337
  }
419
338
 
420
339
  /** Given an L1 to L2 message, retrieves its corresponding event from the Inbox within a specific block range. */
421
340
  export async function retrieveL1ToL2Message(
422
- inbox: GetContractReturnType<typeof InboxAbi, ViemClient>,
423
- leaf: Fr,
424
- fromBlock: bigint,
425
- toBlock: bigint,
341
+ inbox: InboxContract,
342
+ message: InboxMessage,
426
343
  ): Promise<InboxMessage | undefined> {
427
- const logs = await inbox.getEvents.MessageSent({ hash: leaf.toString() }, { fromBlock, toBlock });
428
-
429
- const messages = mapLogsInboxMessage(logs);
430
- return messages.length > 0 ? messages[0] : undefined;
344
+ const log = await inbox.getMessageSentEventByHash(message.leaf.toString(), message.l1BlockNumber);
345
+ return log && mapLogInboxMessage(log);
431
346
  }
432
347
 
433
348
  /**
434
349
  * Fetch L1 to L2 messages.
435
- * @param publicClient - The viem public client to use for transaction retrieval.
436
- * @param inboxAddress - The address of the inbox contract to fetch messages from.
437
- * @param blockUntilSynced - If true, blocks until the archiver has fully synced.
350
+ * @param inbox - The inbox contract wrapper.
438
351
  * @param searchStartBlock - The block number to use for starting the search.
439
352
  * @param searchEndBlock - The highest block number that we should search up to.
440
353
  * @returns An array of InboxLeaf and next eth block to search from.
441
354
  */
442
355
  export async function retrieveL1ToL2Messages(
443
- inbox: GetContractReturnType<typeof InboxAbi, ViemClient>,
356
+ inbox: InboxContract,
444
357
  searchStartBlock: bigint,
445
358
  searchEndBlock: bigint,
446
359
  ): Promise<InboxMessage[]> {
447
360
  const retrievedL1ToL2Messages: InboxMessage[] = [];
448
361
  while (searchStartBlock <= searchEndBlock) {
449
- const messageSentLogs = (
450
- await inbox.getEvents.MessageSent({}, { fromBlock: searchStartBlock, toBlock: searchEndBlock })
451
- ).filter(log => log.blockNumber! >= searchStartBlock && log.blockNumber! <= searchEndBlock);
362
+ const messageSentLogs = await inbox.getMessageSentEvents(searchStartBlock, searchEndBlock);
452
363
 
453
364
  if (messageSentLogs.length === 0) {
454
365
  break;
455
366
  }
456
367
 
457
- retrievedL1ToL2Messages.push(...mapLogsInboxMessage(messageSentLogs));
458
- searchStartBlock = messageSentLogs.at(-1)!.blockNumber + 1n;
368
+ retrievedL1ToL2Messages.push(...messageSentLogs.map(mapLogInboxMessage));
369
+ searchStartBlock = messageSentLogs.at(-1)!.l1BlockNumber + 1n;
459
370
  }
460
371
 
461
372
  return retrievedL1ToL2Messages;
462
373
  }
463
374
 
464
- function mapLogsInboxMessage(logs: GetContractEventsReturnType<typeof InboxAbi, 'MessageSent'>): InboxMessage[] {
465
- return logs.map(log => {
466
- const { index, hash, checkpointNumber, rollingHash } = log.args;
467
- return {
468
- index: index!,
469
- leaf: Fr.fromHexString(hash!),
470
- l1BlockNumber: log.blockNumber,
471
- l1BlockHash: Buffer32.fromString(log.blockHash),
472
- l2BlockNumber: Number(checkpointNumber!),
473
- rollingHash: Buffer16.fromString(rollingHash!),
474
- };
475
- });
375
+ function mapLogInboxMessage(log: MessageSentLog): InboxMessage {
376
+ return {
377
+ index: log.args.index,
378
+ leaf: log.args.leaf,
379
+ l1BlockNumber: log.l1BlockNumber,
380
+ l1BlockHash: log.l1BlockHash,
381
+ checkpointNumber: log.args.checkpointNumber,
382
+ rollingHash: log.args.rollingHash,
383
+ };
476
384
  }
477
385
 
478
386
  /** Retrieves L2ProofVerified events from the rollup contract. */
@@ -481,7 +389,7 @@ export async function retrieveL2ProofVerifiedEvents(
481
389
  rollupAddress: EthAddress,
482
390
  searchStartBlock: bigint,
483
391
  searchEndBlock?: bigint,
484
- ): Promise<{ l1BlockNumber: bigint; checkpointNumber: number; proverId: Fr; txHash: Hex }[]> {
392
+ ): Promise<{ l1BlockNumber: bigint; checkpointNumber: CheckpointNumber; proverId: Fr; txHash: Hex }[]> {
485
393
  const logs = await publicClient.getLogs({
486
394
  address: rollupAddress.toString(),
487
395
  fromBlock: searchStartBlock,
@@ -492,7 +400,7 @@ export async function retrieveL2ProofVerifiedEvents(
492
400
 
493
401
  return logs.map(log => ({
494
402
  l1BlockNumber: log.blockNumber,
495
- checkpointNumber: Number(log.args.checkpointNumber),
403
+ checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber),
496
404
  proverId: Fr.fromHexString(log.args.proverId),
497
405
  txHash: log.transactionHash,
498
406
  }));