@aztec/archiver 0.0.1-commit.d3ec352c → 0.0.1-commit.d58ff9d0

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 (236) hide show
  1. package/README.md +164 -22
  2. package/dest/archiver.d.ts +194 -0
  3. package/dest/archiver.d.ts.map +1 -0
  4. package/dest/archiver.js +949 -0
  5. package/dest/config.d.ts +34 -0
  6. package/dest/config.d.ts.map +1 -0
  7. package/dest/config.js +95 -0
  8. package/dest/errors.d.ts +87 -0
  9. package/dest/errors.d.ts.map +1 -0
  10. package/dest/errors.js +129 -0
  11. package/dest/factory.d.ts +16 -10
  12. package/dest/factory.d.ts.map +1 -1
  13. package/dest/factory.js +117 -20
  14. package/dest/index.d.ts +19 -4
  15. package/dest/index.d.ts.map +1 -1
  16. package/dest/index.js +17 -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 +143 -0
  24. package/dest/l1/calldata_retriever.d.ts.map +1 -0
  25. package/dest/l1/calldata_retriever.js +413 -0
  26. package/dest/l1/data_retrieval.d.ts +102 -0
  27. package/dest/l1/data_retrieval.d.ts.map +1 -0
  28. package/dest/{archiver → l1}/data_retrieval.js +85 -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 +43 -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/contract_data_source_adapter.d.ts +25 -0
  48. package/dest/modules/contract_data_source_adapter.d.ts.map +1 -0
  49. package/dest/modules/contract_data_source_adapter.js +32 -0
  50. package/dest/modules/data_source_base.d.ts +112 -0
  51. package/dest/modules/data_source_base.d.ts.map +1 -0
  52. package/dest/modules/data_source_base.js +322 -0
  53. package/dest/modules/data_store_updater.d.ts +105 -0
  54. package/dest/modules/data_store_updater.d.ts.map +1 -0
  55. package/dest/modules/data_store_updater.js +393 -0
  56. package/dest/modules/instrumentation.d.ts +63 -0
  57. package/dest/modules/instrumentation.d.ts.map +1 -0
  58. package/dest/modules/instrumentation.js +166 -0
  59. package/dest/modules/l1_synchronizer.d.ts +77 -0
  60. package/dest/modules/l1_synchronizer.d.ts.map +1 -0
  61. package/dest/modules/l1_synchronizer.js +1381 -0
  62. package/dest/modules/outbox_trees_resolver.d.ts +62 -0
  63. package/dest/modules/outbox_trees_resolver.d.ts.map +1 -0
  64. package/dest/modules/outbox_trees_resolver.js +162 -0
  65. package/dest/modules/validation.d.ts +40 -0
  66. package/dest/modules/validation.d.ts.map +1 -0
  67. package/dest/{archiver → modules}/validation.js +41 -17
  68. package/dest/store/block_store.d.ts +303 -0
  69. package/dest/store/block_store.d.ts.map +1 -0
  70. package/dest/store/block_store.js +1206 -0
  71. package/dest/store/contract_class_store.d.ts +31 -0
  72. package/dest/store/contract_class_store.d.ts.map +1 -0
  73. package/dest/store/contract_class_store.js +98 -0
  74. package/dest/store/contract_instance_store.d.ts +51 -0
  75. package/dest/store/contract_instance_store.d.ts.map +1 -0
  76. package/dest/{archiver/kv_archiver_store → store}/contract_instance_store.js +55 -3
  77. package/dest/store/data_stores.d.ts +68 -0
  78. package/dest/store/data_stores.d.ts.map +1 -0
  79. package/dest/store/data_stores.js +54 -0
  80. package/dest/store/function_names_cache.d.ts +17 -0
  81. package/dest/store/function_names_cache.d.ts.map +1 -0
  82. package/dest/store/function_names_cache.js +30 -0
  83. package/dest/store/l2_tips_cache.d.ts +25 -0
  84. package/dest/store/l2_tips_cache.d.ts.map +1 -0
  85. package/dest/store/l2_tips_cache.js +26 -0
  86. package/dest/store/log_store.d.ts +59 -0
  87. package/dest/store/log_store.d.ts.map +1 -0
  88. package/dest/store/log_store.js +310 -0
  89. package/dest/store/log_store_codec.d.ts +78 -0
  90. package/dest/store/log_store_codec.d.ts.map +1 -0
  91. package/dest/store/log_store_codec.js +110 -0
  92. package/dest/store/message_store.d.ts +50 -0
  93. package/dest/store/message_store.d.ts.map +1 -0
  94. package/dest/{archiver/kv_archiver_store → store}/message_store.js +66 -23
  95. package/dest/{archiver/structs → structs}/data_retrieval.d.ts +1 -1
  96. package/dest/structs/data_retrieval.d.ts.map +1 -0
  97. package/dest/structs/inbox_message.d.ts +15 -0
  98. package/dest/structs/inbox_message.d.ts.map +1 -0
  99. package/dest/{archiver/structs → structs}/inbox_message.js +6 -6
  100. package/dest/structs/published.d.ts +2 -0
  101. package/dest/structs/published.d.ts.map +1 -0
  102. package/dest/test/fake_l1_state.d.ts +214 -0
  103. package/dest/test/fake_l1_state.d.ts.map +1 -0
  104. package/dest/test/fake_l1_state.js +517 -0
  105. package/dest/test/index.d.ts +2 -1
  106. package/dest/test/index.d.ts.map +1 -1
  107. package/dest/test/index.js +4 -1
  108. package/dest/test/mock_archiver.d.ts +5 -6
  109. package/dest/test/mock_archiver.d.ts.map +1 -1
  110. package/dest/test/mock_archiver.js +8 -12
  111. package/dest/test/mock_l1_to_l2_message_source.d.ts +6 -7
  112. package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
  113. package/dest/test/mock_l1_to_l2_message_source.js +19 -14
  114. package/dest/test/mock_l2_block_source.d.ts +68 -40
  115. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  116. package/dest/test/mock_l2_block_source.js +347 -145
  117. package/dest/test/mock_structs.d.ts +83 -4
  118. package/dest/test/mock_structs.d.ts.map +1 -1
  119. package/dest/test/mock_structs.js +157 -12
  120. package/dest/test/noop_l1_archiver.d.ts +34 -0
  121. package/dest/test/noop_l1_archiver.d.ts.map +1 -0
  122. package/dest/test/noop_l1_archiver.js +88 -0
  123. package/package.json +18 -18
  124. package/src/archiver.ts +785 -0
  125. package/src/config.ts +125 -0
  126. package/src/errors.ts +203 -0
  127. package/src/factory.ts +185 -22
  128. package/src/index.ts +27 -3
  129. package/src/interfaces.ts +9 -0
  130. package/src/l1/README.md +55 -0
  131. package/src/l1/bin/retrieve-calldata.ts +194 -0
  132. package/src/l1/calldata_retriever.ts +529 -0
  133. package/src/{archiver → l1}/data_retrieval.ts +157 -243
  134. package/src/l1/debug_tx.ts +99 -0
  135. package/src/l1/spire_proposer.ts +152 -0
  136. package/src/l1/trace_tx.ts +128 -0
  137. package/src/l1/types.ts +13 -0
  138. package/src/l1/validate_historical_logs.ts +140 -0
  139. package/src/l1/validate_trace.ts +229 -0
  140. package/src/modules/contract_data_source_adapter.ts +46 -0
  141. package/src/modules/data_source_base.ts +466 -0
  142. package/src/modules/data_store_updater.ts +519 -0
  143. package/src/modules/instrumentation.ts +217 -0
  144. package/src/modules/l1_synchronizer.ts +1320 -0
  145. package/src/modules/outbox_trees_resolver.ts +199 -0
  146. package/src/modules/validation.ts +186 -0
  147. package/src/store/block_store.ts +1551 -0
  148. package/src/store/contract_class_store.ts +126 -0
  149. package/src/{archiver/kv_archiver_store → store}/contract_instance_store.ts +70 -7
  150. package/src/store/data_stores.ts +104 -0
  151. package/src/store/function_names_cache.ts +37 -0
  152. package/src/store/l2_tips_cache.ts +35 -0
  153. package/src/store/log_store.ts +380 -0
  154. package/src/store/log_store_codec.ts +143 -0
  155. package/src/{archiver/kv_archiver_store → store}/message_store.ts +81 -28
  156. package/src/{archiver/structs → structs}/inbox_message.ts +8 -9
  157. package/src/{archiver/structs → structs}/published.ts +0 -1
  158. package/src/test/fake_l1_state.ts +770 -0
  159. package/src/test/fixtures/debug_traceTransaction-multicall3.json +88 -0
  160. package/src/test/fixtures/debug_traceTransaction-multiplePropose.json +153 -0
  161. package/src/test/fixtures/debug_traceTransaction-proxied.json +122 -0
  162. package/src/test/fixtures/trace_transaction-multicall3.json +65 -0
  163. package/src/test/fixtures/trace_transaction-multiplePropose.json +319 -0
  164. package/src/test/fixtures/trace_transaction-proxied.json +128 -0
  165. package/src/test/fixtures/trace_transaction-randomRevert.json +216 -0
  166. package/src/test/index.ts +4 -0
  167. package/src/test/mock_archiver.ts +10 -14
  168. package/src/test/mock_l1_to_l2_message_source.ts +16 -15
  169. package/src/test/mock_l2_block_source.ts +416 -161
  170. package/src/test/mock_structs.ts +292 -14
  171. package/src/test/noop_l1_archiver.ts +158 -0
  172. package/dest/archiver/archiver.d.ts +0 -290
  173. package/dest/archiver/archiver.d.ts.map +0 -1
  174. package/dest/archiver/archiver.js +0 -1434
  175. package/dest/archiver/archiver_store.d.ts +0 -256
  176. package/dest/archiver/archiver_store.d.ts.map +0 -1
  177. package/dest/archiver/archiver_store.js +0 -4
  178. package/dest/archiver/archiver_store_test_suite.d.ts +0 -8
  179. package/dest/archiver/archiver_store_test_suite.d.ts.map +0 -1
  180. package/dest/archiver/archiver_store_test_suite.js +0 -1289
  181. package/dest/archiver/config.d.ts +0 -21
  182. package/dest/archiver/config.d.ts.map +0 -1
  183. package/dest/archiver/config.js +0 -55
  184. package/dest/archiver/data_retrieval.d.ts +0 -80
  185. package/dest/archiver/data_retrieval.d.ts.map +0 -1
  186. package/dest/archiver/errors.d.ts +0 -12
  187. package/dest/archiver/errors.d.ts.map +0 -1
  188. package/dest/archiver/errors.js +0 -17
  189. package/dest/archiver/index.d.ts +0 -7
  190. package/dest/archiver/index.d.ts.map +0 -1
  191. package/dest/archiver/index.js +0 -4
  192. package/dest/archiver/instrumentation.d.ts +0 -35
  193. package/dest/archiver/instrumentation.d.ts.map +0 -1
  194. package/dest/archiver/instrumentation.js +0 -140
  195. package/dest/archiver/kv_archiver_store/block_store.d.ts +0 -125
  196. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +0 -1
  197. package/dest/archiver/kv_archiver_store/block_store.js +0 -371
  198. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +0 -18
  199. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +0 -1
  200. package/dest/archiver/kv_archiver_store/contract_class_store.js +0 -120
  201. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +0 -24
  202. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +0 -1
  203. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +0 -169
  204. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +0 -1
  205. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +0 -296
  206. package/dest/archiver/kv_archiver_store/log_store.d.ts +0 -49
  207. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +0 -1
  208. package/dest/archiver/kv_archiver_store/log_store.js +0 -337
  209. package/dest/archiver/kv_archiver_store/message_store.d.ts +0 -39
  210. package/dest/archiver/kv_archiver_store/message_store.d.ts.map +0 -1
  211. package/dest/archiver/structs/data_retrieval.d.ts.map +0 -1
  212. package/dest/archiver/structs/inbox_message.d.ts +0 -15
  213. package/dest/archiver/structs/inbox_message.d.ts.map +0 -1
  214. package/dest/archiver/structs/published.d.ts +0 -3
  215. package/dest/archiver/structs/published.d.ts.map +0 -1
  216. package/dest/archiver/validation.d.ts +0 -17
  217. package/dest/archiver/validation.d.ts.map +0 -1
  218. package/dest/rpc/index.d.ts +0 -9
  219. package/dest/rpc/index.d.ts.map +0 -1
  220. package/dest/rpc/index.js +0 -15
  221. package/src/archiver/archiver.ts +0 -1880
  222. package/src/archiver/archiver_store.ts +0 -310
  223. package/src/archiver/archiver_store_test_suite.ts +0 -1295
  224. package/src/archiver/config.ts +0 -79
  225. package/src/archiver/errors.ts +0 -26
  226. package/src/archiver/index.ts +0 -6
  227. package/src/archiver/instrumentation.ts +0 -187
  228. package/src/archiver/kv_archiver_store/block_store.ts +0 -482
  229. package/src/archiver/kv_archiver_store/contract_class_store.ts +0 -176
  230. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +0 -423
  231. package/src/archiver/kv_archiver_store/log_store.ts +0 -407
  232. package/src/archiver/validation.ts +0 -124
  233. package/src/rpc/index.ts +0 -16
  234. /package/dest/{archiver/structs → structs}/data_retrieval.js +0 -0
  235. /package/dest/{archiver/structs → structs}/published.js +0 -0
  236. /package/src/{archiver/structs → structs}/data_retrieval.ts +0 -0
@@ -0,0 +1,466 @@
1
+ import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
2
+ import {
3
+ BlockNumber,
4
+ CheckpointNumber,
5
+ type EpochNumber,
6
+ IndexWithinCheckpoint,
7
+ type SlotNumber,
8
+ } from '@aztec/foundation/branded-types';
9
+ import type { Fr } from '@aztec/foundation/curves/bn254';
10
+ import type { EthAddress } from '@aztec/foundation/eth-address';
11
+ import type { FunctionSelector } from '@aztec/stdlib/abi';
12
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
13
+ import {
14
+ type BlockData,
15
+ type BlockHash,
16
+ type BlockQuery,
17
+ type BlockTag,
18
+ type BlocksQuery,
19
+ Body,
20
+ type CheckpointQuery,
21
+ type CheckpointsQuery,
22
+ L2Block,
23
+ type L2Tips,
24
+ type ProposedCheckpointQuery,
25
+ } from '@aztec/stdlib/block';
26
+ import {
27
+ Checkpoint,
28
+ type CheckpointData,
29
+ type ProposedCheckpointData,
30
+ PublishedCheckpoint,
31
+ } from '@aztec/stdlib/checkpoint';
32
+ import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
33
+ import {
34
+ type L1RollupConstants,
35
+ getEpochAtSlot,
36
+ getEpochNumberAtTimestamp,
37
+ getLastL1SlotTimestampForL2Slot,
38
+ getProofSubmissionDeadlineEpoch,
39
+ getSlotRangeForEpoch,
40
+ } from '@aztec/stdlib/epoch-helpers';
41
+ import type { L2LogsSource } from '@aztec/stdlib/interfaces/server';
42
+ import type { LogResult, PrivateLogsQuery, PublicLogsQuery } from '@aztec/stdlib/logs';
43
+ import type { L1ToL2MessageSource, L2ToL1MembershipWitness } from '@aztec/stdlib/messaging';
44
+ import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
45
+ import type { BlockHeader, IndexedTxEffect, TxHash } from '@aztec/stdlib/tx';
46
+ import type { UInt64 } from '@aztec/stdlib/types';
47
+
48
+ import type { ArchiverDataSource } from '../interfaces.js';
49
+ import type { ResolvedBlockQuery, ResolvedBlocksQuery } from '../store/block_store.js';
50
+ import type { ArchiverDataStores } from '../store/data_stores.js';
51
+ import type { ValidateCheckpointResult } from './validation.js';
52
+
53
+ /**
54
+ * Sentinel returned by {@link ArchiverDataSourceBase#resolveBlockQuery} when a query resolves
55
+ * to the genesis block. Forces single-block lookup methods to take the genesis branch
56
+ * explicitly rather than silently falling through to the BlockStore (which never has a block 0).
57
+ */
58
+ type GenesisBlockQuery = { genesis: true };
59
+
60
+ /**
61
+ * Abstract base class implementing ArchiverDataSource using a bundle of archiver substores.
62
+ * Provides implementations for all read-side methods and declares abstract methods for
63
+ * L1-dependent functionality that subclasses must implement.
64
+ */
65
+ export abstract class ArchiverDataSourceBase
66
+ implements ArchiverDataSource, L2LogsSource, ContractDataSource, L1ToL2MessageSource
67
+ {
68
+ /** The injected genesis block header. */
69
+ protected readonly initialHeader: BlockHeader;
70
+ /** Precomputed hash of the initial header, exposed via {@link getGenesisBlockHash}. */
71
+ protected readonly initialBlockHash: BlockHash;
72
+ /** Archive root after block 0 was appended — read from L1 (`Rollup.getGenesisArchiveTreeRoot`). */
73
+ protected readonly genesisArchiveRoot: Fr;
74
+
75
+ /** Memoized synthetic genesis block — callers rely on referential identity for caching. */
76
+ private readonly genesisBlock: L2Block;
77
+ /** Memoized synthetic genesis block data — kept consistent with {@link genesisBlock}. */
78
+ private readonly genesisBlockData: BlockData;
79
+
80
+ constructor(
81
+ protected readonly stores: ArchiverDataStores,
82
+ protected readonly l1Constants: L1RollupConstants | undefined,
83
+ initialHeader: BlockHeader,
84
+ initialBlockHash: BlockHash,
85
+ genesisArchiveRoot: Fr,
86
+ ) {
87
+ this.initialHeader = initialHeader;
88
+ this.initialBlockHash = initialBlockHash;
89
+ this.genesisArchiveRoot = genesisArchiveRoot;
90
+
91
+ const genesisArchive = new AppendOnlyTreeSnapshot(genesisArchiveRoot, 1);
92
+ this.genesisBlock = new L2Block(
93
+ genesisArchive,
94
+ initialHeader,
95
+ Body.empty(),
96
+ CheckpointNumber.ZERO,
97
+ IndexWithinCheckpoint(0),
98
+ );
99
+ this.genesisBlockData = {
100
+ header: initialHeader,
101
+ archive: genesisArchive,
102
+ blockHash: initialBlockHash,
103
+ checkpointNumber: CheckpointNumber.ZERO,
104
+ indexWithinCheckpoint: IndexWithinCheckpoint(0),
105
+ };
106
+ }
107
+
108
+ /** Returns the precomputed hash of the genesis block header. */
109
+ public getGenesisBlockHash(): BlockHash {
110
+ return this.initialBlockHash;
111
+ }
112
+
113
+ /** Returns the synthetic genesis L2Block (memoized — same instance across calls). */
114
+ private getGenesisBlock(): L2Block {
115
+ return this.genesisBlock;
116
+ }
117
+
118
+ /** Returns genesis block data (memoized — same instance across calls). */
119
+ private getGenesisBlockData(): BlockData {
120
+ return this.genesisBlockData;
121
+ }
122
+
123
+ /**
124
+ * Type guard distinguishing the genesis sentinel from a {@link ResolvedBlockQuery}.
125
+ * `resolveBlockQuery` already rewrites every genesis-matching shape to the sentinel,
126
+ * so callers only need this single sync check.
127
+ */
128
+ private isGenesisBlockQuery(query: ResolvedBlockQuery | GenesisBlockQuery): query is GenesisBlockQuery {
129
+ return 'genesis' in query;
130
+ }
131
+
132
+ abstract getRollupAddress(): Promise<EthAddress>;
133
+
134
+ abstract getRegistryAddress(): Promise<EthAddress>;
135
+
136
+ abstract getL1Constants(): Promise<L1RollupConstants>;
137
+
138
+ abstract getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }>;
139
+
140
+ abstract getL1Timestamp(): Promise<bigint | undefined>;
141
+
142
+ abstract getL2Tips(): Promise<L2Tips>;
143
+
144
+ abstract getSyncedL2SlotNumber(): Promise<SlotNumber | undefined>;
145
+
146
+ abstract getSyncedL2EpochNumber(): Promise<EpochNumber | undefined>;
147
+
148
+ abstract isEpochComplete(epochNumber: EpochNumber): Promise<boolean>;
149
+
150
+ abstract syncImmediate(): Promise<void>;
151
+
152
+ abstract getL2ToL1MembershipWitness(
153
+ txHash: TxHash,
154
+ message: Fr,
155
+ messageIndexInTx?: number,
156
+ ): Promise<L2ToL1MembershipWitness | undefined>;
157
+
158
+ public async isPruneDueAtSlot(slot: SlotNumber): Promise<boolean> {
159
+ if (!this.l1Constants) {
160
+ throw new Error('isPruneDueAtSlot requires l1Constants');
161
+ }
162
+ const tips = await this.getL2Tips();
163
+ const proven = tips.proven.checkpoint.number;
164
+ const pending = tips.checkpointed.checkpoint.number;
165
+ if (pending === proven) {
166
+ return false;
167
+ }
168
+
169
+ const oldestUnproven = await this.getCheckpointData({ number: CheckpointNumber(Number(proven) + 1) });
170
+ if (!oldestUnproven) {
171
+ return false;
172
+ }
173
+
174
+ const slotTs = getLastL1SlotTimestampForL2Slot(slot, this.l1Constants);
175
+ const slotEpoch = getEpochNumberAtTimestamp(slotTs, this.l1Constants);
176
+ const oldestUnprovenEpoch = getEpochAtSlot(oldestUnproven.header.slotNumber, this.l1Constants);
177
+ const deadlineEpoch = getProofSubmissionDeadlineEpoch(oldestUnprovenEpoch, this.l1Constants);
178
+ return slotEpoch >= deadlineEpoch;
179
+ }
180
+
181
+ public getCheckpointNumber(): Promise<CheckpointNumber> {
182
+ return this.stores.blocks.getLatestCheckpointNumber();
183
+ }
184
+
185
+ public getProvenCheckpointNumber(): Promise<CheckpointNumber> {
186
+ return this.stores.blocks.getProvenCheckpointNumber();
187
+ }
188
+
189
+ public getBlockNumber(): Promise<BlockNumber>;
190
+ public getBlockNumber(query: BlockQuery): Promise<BlockNumber | undefined>;
191
+ public async getBlockNumber(query?: BlockQuery): Promise<BlockNumber | undefined> {
192
+ if (!query) {
193
+ return this.stores.blocks.getLatestL2BlockNumber();
194
+ }
195
+ const resolved = await this.resolveBlockQuery(query);
196
+ if (resolved === undefined) {
197
+ return undefined;
198
+ }
199
+ if (this.isGenesisBlockQuery(resolved)) {
200
+ return BlockNumber.ZERO;
201
+ }
202
+ return this.stores.blocks.getBlockNumber(resolved);
203
+ }
204
+
205
+ /**
206
+ * Resolves a {@link CheckpointQuery} to a concrete `CheckpointNumber`, or undefined when the
207
+ * query refers to a position that has no checkpoint yet (e.g. `{ slot }` not found).
208
+ */
209
+ private resolveCheckpointQuery(query: CheckpointQuery): Promise<CheckpointNumber | undefined> {
210
+ if ('number' in query) {
211
+ return Promise.resolve(query.number);
212
+ }
213
+ if ('slot' in query) {
214
+ return this.stores.blocks.getCheckpointNumberBySlot(query.slot);
215
+ }
216
+ // tag variant
217
+ switch (query.tag) {
218
+ case 'checkpointed':
219
+ return this.stores.blocks.getLatestCheckpointNumber();
220
+ case 'proven':
221
+ return this.stores.blocks.getProvenCheckpointNumber();
222
+ case 'finalized':
223
+ return this.stores.blocks.getFinalizedCheckpointNumber();
224
+ }
225
+ }
226
+
227
+ public async getCheckpoint(query: CheckpointQuery): Promise<PublishedCheckpoint | undefined> {
228
+ const number = await this.resolveCheckpointQuery(query);
229
+ if (number === undefined || number === 0) {
230
+ return undefined;
231
+ }
232
+ const data = await this.stores.blocks.getCheckpointData(number);
233
+ if (!data) {
234
+ return undefined;
235
+ }
236
+ return this.getPublishedCheckpointFromCheckpointData(data);
237
+ }
238
+
239
+ public async getCheckpoints(query: CheckpointsQuery): Promise<PublishedCheckpoint[]> {
240
+ const checkpoints = await this.getCheckpointsData(query);
241
+ return Promise.all(checkpoints.map(ch => this.getPublishedCheckpointFromCheckpointData(ch)));
242
+ }
243
+
244
+ public async getCheckpointData(query: CheckpointQuery): Promise<CheckpointData | undefined> {
245
+ const number = await this.resolveCheckpointQuery(query);
246
+ if (number === undefined || number === 0) {
247
+ return undefined;
248
+ }
249
+ return this.stores.blocks.getCheckpointData(number);
250
+ }
251
+
252
+ public async getCheckpointsData(query: CheckpointsQuery): Promise<CheckpointData[]> {
253
+ if ('fromSlot' in query) {
254
+ return this.stores.blocks.getCheckpointsBySlot(query.fromSlot, query.limit, query.reverse ?? false);
255
+ }
256
+ if ('from' in query) {
257
+ return this.stores.blocks.getRangeOfCheckpoints(query.from, query.limit);
258
+ }
259
+ const numbers = await this.getCheckpointNumbersForEpoch(query.epoch);
260
+ return numbers.length > 0 ? this.stores.blocks.getRangeOfCheckpoints(numbers[0], numbers.length) : [];
261
+ }
262
+
263
+ public getProposedCheckpointData(query?: ProposedCheckpointQuery): Promise<ProposedCheckpointData | undefined> {
264
+ if (!query || 'tag' in query) {
265
+ return this.stores.blocks.getLastProposedCheckpoint();
266
+ }
267
+ if ('number' in query) {
268
+ return this.stores.blocks.getProposedCheckpointByNumber(query.number);
269
+ }
270
+ return this.stores.blocks.getProposedCheckpointBySlot(query.slot);
271
+ }
272
+
273
+ public getTxEffect(txHash: TxHash): Promise<IndexedTxEffect | undefined> {
274
+ return this.stores.blocks.getTxEffect(txHash);
275
+ }
276
+
277
+ public isPendingChainInvalid(): Promise<boolean> {
278
+ return this.getPendingChainValidationStatus().then(status => !status.valid);
279
+ }
280
+
281
+ public async getPendingChainValidationStatus(): Promise<ValidateCheckpointResult> {
282
+ return (await this.stores.blocks.getPendingChainValidationStatus()) ?? { valid: true };
283
+ }
284
+
285
+ public getPrivateLogsByTags(query: PrivateLogsQuery): Promise<LogResult[][]> {
286
+ return this.stores.logs.getPrivateLogsByTags(query);
287
+ }
288
+
289
+ public getPublicLogsByTags(query: PublicLogsQuery): Promise<LogResult[][]> {
290
+ return this.stores.logs.getPublicLogsByTags(query);
291
+ }
292
+
293
+ public getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
294
+ return this.stores.contractClasses.getContractClass(id);
295
+ }
296
+
297
+ public getBytecodeCommitment(id: Fr): Promise<Fr | undefined> {
298
+ return this.stores.contractClasses.getBytecodeCommitment(id);
299
+ }
300
+
301
+ public getContract(address: AztecAddress, timestamp: UInt64): Promise<ContractInstanceWithAddress | undefined> {
302
+ return this.stores.contractInstances.getContractInstance(address, timestamp);
303
+ }
304
+
305
+ public getContractClassIds(): Promise<Fr[]> {
306
+ return this.stores.contractClasses.getContractClassIds();
307
+ }
308
+
309
+ /** Looks up a public function name given a selector. */
310
+ public getDebugFunctionName(_address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
311
+ return Promise.resolve(this.stores.functionNames.get(selector));
312
+ }
313
+
314
+ /** Register public function signatures so they can be looked up by selector. */
315
+ public registerContractFunctionSignatures(signatures: string[]): Promise<void> {
316
+ return this.stores.functionNames.register(signatures);
317
+ }
318
+
319
+ public getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
320
+ return this.stores.messages.getL1ToL2Messages(checkpointNumber);
321
+ }
322
+
323
+ public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
324
+ return this.stores.messages.getL1ToL2MessageIndex(l1ToL2Message);
325
+ }
326
+
327
+ private async getPublishedCheckpointFromCheckpointData(checkpoint: CheckpointData): Promise<PublishedCheckpoint> {
328
+ const blocksForCheckpoint = await this.stores.blocks.getBlocksForCheckpoint(checkpoint.checkpointNumber);
329
+ if (!blocksForCheckpoint) {
330
+ throw new Error(`Blocks for checkpoint ${checkpoint.checkpointNumber} not found`);
331
+ }
332
+ const fullCheckpoint = new Checkpoint(
333
+ checkpoint.archive,
334
+ checkpoint.header,
335
+ blocksForCheckpoint,
336
+ checkpoint.checkpointNumber,
337
+ checkpoint.feeAssetPriceModifier,
338
+ );
339
+ return new PublishedCheckpoint(fullCheckpoint, checkpoint.l1, checkpoint.attestations);
340
+ }
341
+
342
+ public getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]> {
343
+ return this.stores.blocks.getBlocksForSlot(slotNumber);
344
+ }
345
+
346
+ /** Returns just the checkpoint numbers for all checkpoints whose slot falls within the given epoch. */
347
+ private getCheckpointNumbersForEpoch(epochNumber: EpochNumber): Promise<CheckpointNumber[]> {
348
+ if (!this.l1Constants) {
349
+ throw new Error('L1 constants not set');
350
+ }
351
+
352
+ const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1Constants);
353
+ return this.stores.blocks.getCheckpointNumbersForSlotRange(start, end);
354
+ }
355
+
356
+ public async getBlock(query: BlockQuery): Promise<L2Block | undefined> {
357
+ const resolved = await this.resolveBlockQuery(query);
358
+ if (resolved === undefined) {
359
+ return undefined;
360
+ }
361
+ if (this.isGenesisBlockQuery(resolved)) {
362
+ return this.getGenesisBlock();
363
+ }
364
+ return this.stores.blocks.getBlock(resolved);
365
+ }
366
+
367
+ /**
368
+ * Range queries iterate physical blocks only; the genesis block is NOT prepended.
369
+ * `L2BlockStream` consumers (`world-state.handleL2Blocks`, etc.) emit `blocks-added` events for
370
+ * real blocks and would be surprised by a synthetic block 0. Use {@link getBlock} or
371
+ * {@link getBlockData} for genesis-aware single-block lookups.
372
+ */
373
+ public async getBlocks(query: BlocksQuery): Promise<L2Block[]> {
374
+ const resolved = await this.resolveBlocksQuery(query);
375
+ return resolved ? this.stores.blocks.getBlocks(resolved) : [];
376
+ }
377
+
378
+ public async getBlockData(query: BlockQuery): Promise<BlockData | undefined> {
379
+ const resolved = await this.resolveBlockQuery(query);
380
+ if (resolved === undefined) {
381
+ return undefined;
382
+ }
383
+ if (this.isGenesisBlockQuery(resolved)) {
384
+ return this.getGenesisBlockData();
385
+ }
386
+ return this.stores.blocks.getBlockData(resolved);
387
+ }
388
+
389
+ /** See {@link getBlocks} — range queries do not prepend the genesis block. */
390
+ public async getBlocksData(query: BlocksQuery): Promise<BlockData[]> {
391
+ const resolved = await this.resolveBlocksQuery(query);
392
+ return resolved ? this.stores.blocks.getBlocksData(resolved) : [];
393
+ }
394
+
395
+ /**
396
+ * Resolves a {@link BlockQuery} to either the genesis sentinel or a {@link ResolvedBlockQuery}
397
+ * understood by BlockStore. Detects every shape that points at block 0 — `{number:0}`,
398
+ * `{hash}` matching the initial header, `{archive}` matching the post-genesis archive root,
399
+ * and `{tag}` resolving to 0 — and rewrites them to the sentinel so callers branch once.
400
+ */
401
+ private async resolveBlockQuery(query: BlockQuery): Promise<ResolvedBlockQuery | GenesisBlockQuery | undefined> {
402
+ if ('number' in query) {
403
+ return query.number === BlockNumber.ZERO ? { genesis: true } : query;
404
+ }
405
+ if ('hash' in query) {
406
+ return query.hash.equals(this.initialBlockHash) ? { genesis: true } : query;
407
+ }
408
+ if ('archive' in query) {
409
+ return query.archive.equals(this.genesisArchiveRoot) ? { genesis: true } : query;
410
+ }
411
+ const number = await this.resolveBlockTag(query.tag);
412
+ if (number === BlockNumber.ZERO) {
413
+ return { genesis: true };
414
+ }
415
+ return { number };
416
+ }
417
+
418
+ /** Maps a {@link BlockTag} to the matching block number for the current chain state. */
419
+ private resolveBlockTag(tag: BlockTag): Promise<BlockNumber> {
420
+ switch (tag) {
421
+ case 'latest':
422
+ case 'proposed':
423
+ return this.stores.blocks.getLatestL2BlockNumber();
424
+ case 'checkpointed':
425
+ return this.stores.blocks.getCheckpointedL2BlockNumber();
426
+ case 'proven':
427
+ return this.stores.blocks.getProvenBlockNumber();
428
+ case 'finalized':
429
+ return this.stores.blocks.getFinalizedL2BlockNumber();
430
+ }
431
+ }
432
+
433
+ /**
434
+ * Converts an epoch-based BlocksQuery to a from/limit query using l1Constants.
435
+ * Returns undefined when the epoch has no checkpoints, so callers can return [] without
436
+ * entering BlockStore. Reads only the two endpoint checkpoints rather than the whole epoch.
437
+ */
438
+ private async resolveBlocksQuery(query: BlocksQuery): Promise<ResolvedBlocksQuery | undefined> {
439
+ if (!('epoch' in query)) {
440
+ if (query.from < INITIAL_L2_BLOCK_NUM) {
441
+ throw new Error(
442
+ `getBlocks/getBlocksData: 'from' must be >= ${INITIAL_L2_BLOCK_NUM}, got ${query.from}. ` +
443
+ `Use getBlock({number:0})/getBlockData({number:0}) for genesis-aware single-block lookups.`,
444
+ );
445
+ }
446
+ return query;
447
+ }
448
+ const checkpointNumbers = await this.getCheckpointNumbersForEpoch(query.epoch);
449
+ if (checkpointNumbers.length === 0) {
450
+ return undefined;
451
+ }
452
+ const firstNumber = checkpointNumbers[0];
453
+ const lastNumber = checkpointNumbers[checkpointNumbers.length - 1];
454
+ const first = await this.stores.blocks.getCheckpointData(firstNumber);
455
+ if (!first) {
456
+ return undefined;
457
+ }
458
+ const last = firstNumber === lastNumber ? first : await this.stores.blocks.getCheckpointData(lastNumber);
459
+ if (!last) {
460
+ return undefined;
461
+ }
462
+ const from = BlockNumber(first.startBlock);
463
+ const limit = last.startBlock + last.blockCount - first.startBlock;
464
+ return { from, limit, onlyCheckpointed: true };
465
+ }
466
+ }