@aztec/archiver 0.0.1-commit.e588bc7e5 → 0.0.1-commit.e5a3663dd

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 (105) hide show
  1. package/dest/archiver.d.ts +19 -11
  2. package/dest/archiver.d.ts.map +1 -1
  3. package/dest/archiver.js +96 -53
  4. package/dest/config.d.ts +3 -1
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +14 -3
  7. package/dest/errors.d.ts +32 -5
  8. package/dest/errors.d.ts.map +1 -1
  9. package/dest/errors.js +51 -6
  10. package/dest/factory.d.ts +4 -4
  11. package/dest/factory.d.ts.map +1 -1
  12. package/dest/factory.js +13 -10
  13. package/dest/index.d.ts +10 -3
  14. package/dest/index.d.ts.map +1 -1
  15. package/dest/index.js +9 -2
  16. package/dest/l1/calldata_retriever.d.ts +2 -1
  17. package/dest/l1/calldata_retriever.d.ts.map +1 -1
  18. package/dest/l1/calldata_retriever.js +9 -4
  19. package/dest/l1/data_retrieval.d.ts +18 -9
  20. package/dest/l1/data_retrieval.d.ts.map +1 -1
  21. package/dest/l1/data_retrieval.js +13 -19
  22. package/dest/l1/validate_historical_logs.d.ts +23 -0
  23. package/dest/l1/validate_historical_logs.d.ts.map +1 -0
  24. package/dest/l1/validate_historical_logs.js +108 -0
  25. package/dest/modules/contract_data_source_adapter.d.ts +25 -0
  26. package/dest/modules/contract_data_source_adapter.d.ts.map +1 -0
  27. package/dest/modules/contract_data_source_adapter.js +42 -0
  28. package/dest/modules/data_source_base.d.ts +16 -10
  29. package/dest/modules/data_source_base.d.ts.map +1 -1
  30. package/dest/modules/data_source_base.js +71 -60
  31. package/dest/modules/data_store_updater.d.ts +16 -9
  32. package/dest/modules/data_store_updater.d.ts.map +1 -1
  33. package/dest/modules/data_store_updater.js +52 -40
  34. package/dest/modules/instrumentation.d.ts +7 -2
  35. package/dest/modules/instrumentation.d.ts.map +1 -1
  36. package/dest/modules/instrumentation.js +22 -6
  37. package/dest/modules/l1_synchronizer.d.ts +8 -4
  38. package/dest/modules/l1_synchronizer.d.ts.map +1 -1
  39. package/dest/modules/l1_synchronizer.js +212 -79
  40. package/dest/modules/validation.d.ts +4 -3
  41. package/dest/modules/validation.d.ts.map +1 -1
  42. package/dest/modules/validation.js +4 -4
  43. package/dest/store/block_store.d.ts +60 -21
  44. package/dest/store/block_store.d.ts.map +1 -1
  45. package/dest/store/block_store.js +229 -70
  46. package/dest/store/contract_class_store.d.ts +17 -3
  47. package/dest/store/contract_class_store.d.ts.map +1 -1
  48. package/dest/store/contract_class_store.js +17 -1
  49. package/dest/store/contract_instance_store.d.ts +28 -1
  50. package/dest/store/contract_instance_store.d.ts.map +1 -1
  51. package/dest/store/contract_instance_store.js +31 -0
  52. package/dest/store/data_stores.d.ts +68 -0
  53. package/dest/store/data_stores.d.ts.map +1 -0
  54. package/dest/store/data_stores.js +50 -0
  55. package/dest/store/function_names_cache.d.ts +17 -0
  56. package/dest/store/function_names_cache.d.ts.map +1 -0
  57. package/dest/store/function_names_cache.js +30 -0
  58. package/dest/store/l2_tips_cache.d.ts +1 -1
  59. package/dest/store/l2_tips_cache.d.ts.map +1 -1
  60. package/dest/store/l2_tips_cache.js +3 -3
  61. package/dest/store/log_store.d.ts +1 -1
  62. package/dest/store/log_store.d.ts.map +1 -1
  63. package/dest/store/log_store.js +2 -4
  64. package/dest/store/message_store.d.ts +9 -3
  65. package/dest/store/message_store.d.ts.map +1 -1
  66. package/dest/store/message_store.js +31 -1
  67. package/dest/test/fake_l1_state.d.ts +14 -3
  68. package/dest/test/fake_l1_state.d.ts.map +1 -1
  69. package/dest/test/fake_l1_state.js +55 -15
  70. package/dest/test/mock_l2_block_source.d.ts +12 -3
  71. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  72. package/dest/test/mock_l2_block_source.js +24 -2
  73. package/dest/test/noop_l1_archiver.d.ts +4 -4
  74. package/dest/test/noop_l1_archiver.d.ts.map +1 -1
  75. package/dest/test/noop_l1_archiver.js +9 -7
  76. package/package.json +13 -13
  77. package/src/archiver.ts +113 -52
  78. package/src/config.ts +15 -1
  79. package/src/errors.ts +75 -8
  80. package/src/factory.ts +11 -10
  81. package/src/index.ts +17 -2
  82. package/src/l1/calldata_retriever.ts +15 -4
  83. package/src/l1/data_retrieval.ts +30 -35
  84. package/src/l1/validate_historical_logs.ts +140 -0
  85. package/src/modules/contract_data_source_adapter.ts +59 -0
  86. package/src/modules/data_source_base.ts +75 -57
  87. package/src/modules/data_store_updater.ts +71 -39
  88. package/src/modules/instrumentation.ts +27 -7
  89. package/src/modules/l1_synchronizer.ts +301 -83
  90. package/src/modules/validation.ts +8 -7
  91. package/src/store/block_store.ts +264 -77
  92. package/src/store/contract_class_store.ts +28 -2
  93. package/src/store/contract_instance_store.ts +43 -0
  94. package/src/store/data_stores.ts +108 -0
  95. package/src/store/function_names_cache.ts +37 -0
  96. package/src/store/l2_tips_cache.ts +9 -3
  97. package/src/store/log_store.ts +2 -5
  98. package/src/store/message_store.ts +35 -2
  99. package/src/test/fake_l1_state.ts +62 -24
  100. package/src/test/mock_l2_block_source.ts +23 -2
  101. package/src/test/noop_l1_archiver.ts +9 -7
  102. package/dest/store/kv_archiver_store.d.ts +0 -377
  103. package/dest/store/kv_archiver_store.d.ts.map +0 -1
  104. package/dest/store/kv_archiver_store.js +0 -494
  105. package/src/store/kv_archiver_store.ts +0 -713
@@ -24,19 +24,19 @@ import type { BlockHeader, IndexedTxEffect, TxHash, TxReceipt } from '@aztec/std
24
24
  import type { UInt64 } from '@aztec/stdlib/types';
25
25
 
26
26
  import type { ArchiverDataSource } from '../interfaces.js';
27
- import type { KVArchiverDataStore } from '../store/kv_archiver_store.js';
27
+ import type { ArchiverDataStores } from '../store/data_stores.js';
28
28
  import type { ValidateCheckpointResult } from './validation.js';
29
29
 
30
30
  /**
31
- * Abstract base class implementing ArchiverDataSource using a KVArchiverDataStore.
32
- * Provides implementations for all store-delegating methods and declares abstract methods
33
- * for L1-dependent functionality that subclasses must implement.
31
+ * Abstract base class implementing ArchiverDataSource using a bundle of archiver substores.
32
+ * Provides implementations for all read-side methods and declares abstract methods for
33
+ * L1-dependent functionality that subclasses must implement.
34
34
  */
35
35
  export abstract class ArchiverDataSourceBase
36
36
  implements ArchiverDataSource, L2LogsSource, ContractDataSource, L1ToL2MessageSource
37
37
  {
38
38
  constructor(
39
- protected readonly store: KVArchiverDataStore,
39
+ protected readonly stores: ArchiverDataStores,
40
40
  protected readonly l1Constants?: L1RollupConstants,
41
41
  ) {}
42
42
 
@@ -61,54 +61,54 @@ export abstract class ArchiverDataSourceBase
61
61
  abstract syncImmediate(): Promise<void>;
62
62
 
63
63
  public getCheckpointNumber(): Promise<CheckpointNumber> {
64
- return this.store.getSynchedCheckpointNumber();
64
+ return this.stores.blocks.getLatestCheckpointNumber();
65
65
  }
66
66
 
67
67
  public getSynchedCheckpointNumber(): Promise<CheckpointNumber> {
68
- return this.store.getSynchedCheckpointNumber();
68
+ return this.stores.blocks.getLatestCheckpointNumber();
69
69
  }
70
70
 
71
71
  public getProvenCheckpointNumber(): Promise<CheckpointNumber> {
72
- return this.store.getProvenCheckpointNumber();
72
+ return this.stores.blocks.getProvenCheckpointNumber();
73
73
  }
74
74
 
75
75
  public getBlockNumber(): Promise<BlockNumber> {
76
- return this.store.getLatestBlockNumber();
76
+ return this.stores.blocks.getLatestL2BlockNumber();
77
77
  }
78
78
 
79
79
  public getProvenBlockNumber(): Promise<BlockNumber> {
80
- return this.store.getProvenBlockNumber();
80
+ return this.stores.blocks.getProvenBlockNumber();
81
81
  }
82
82
 
83
83
  public async getBlockHeader(number: BlockNumber | 'latest'): Promise<BlockHeader | undefined> {
84
- const blockNumber = number === 'latest' ? await this.store.getLatestBlockNumber() : number;
84
+ const blockNumber = number === 'latest' ? await this.stores.blocks.getLatestL2BlockNumber() : number;
85
85
  if (blockNumber === 0) {
86
86
  return undefined;
87
87
  }
88
- const headers = await this.store.getBlockHeaders(blockNumber, 1);
88
+ const headers = await this.stores.blocks.getBlockHeaders(blockNumber, 1);
89
89
  return headers.length === 0 ? undefined : headers[0];
90
90
  }
91
91
 
92
92
  public getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
93
- return this.store.getCheckpointedBlock(number);
93
+ return this.stores.blocks.getCheckpointedBlock(number);
94
94
  }
95
95
 
96
96
  public getCheckpointedL2BlockNumber(): Promise<BlockNumber> {
97
- return this.store.getCheckpointedL2BlockNumber();
97
+ return this.stores.blocks.getCheckpointedL2BlockNumber();
98
98
  }
99
99
 
100
100
  public getFinalizedL2BlockNumber(): Promise<BlockNumber> {
101
- return this.store.getFinalizedL2BlockNumber();
101
+ return this.stores.blocks.getFinalizedL2BlockNumber();
102
102
  }
103
103
 
104
104
  public async getCheckpointHeader(number: CheckpointNumber | 'latest'): Promise<CheckpointHeader | undefined> {
105
105
  if (number === 'latest') {
106
- number = await this.store.getSynchedCheckpointNumber();
106
+ number = await this.stores.blocks.getLatestCheckpointNumber();
107
107
  }
108
108
  if (number === 0) {
109
109
  return undefined;
110
110
  }
111
- const checkpoint = await this.store.getCheckpointData(number);
111
+ const checkpoint = await this.stores.blocks.getCheckpointData(number);
112
112
  if (!checkpoint) {
113
113
  return undefined;
114
114
  }
@@ -116,7 +116,7 @@ export abstract class ArchiverDataSourceBase
116
116
  }
117
117
 
118
118
  public async getLastBlockNumberInCheckpoint(checkpointNumber: CheckpointNumber): Promise<BlockNumber | undefined> {
119
- const checkpointData = await this.store.getCheckpointData(checkpointNumber);
119
+ const checkpointData = await this.stores.blocks.getCheckpointData(checkpointNumber);
120
120
  if (!checkpointData) {
121
121
  return undefined;
122
122
  }
@@ -124,51 +124,66 @@ export abstract class ArchiverDataSourceBase
124
124
  }
125
125
 
126
126
  public getCheckpointedBlocks(from: BlockNumber, limit: number): Promise<CheckpointedL2Block[]> {
127
- return this.store.getCheckpointedBlocks(from, limit);
127
+ return this.stores.blocks.getCheckpointedBlocks(from, limit);
128
+ }
129
+
130
+ public getCheckpointData(checkpointNumber: CheckpointNumber): Promise<CheckpointData | undefined> {
131
+ return this.stores.blocks.getCheckpointData(checkpointNumber);
132
+ }
133
+
134
+ public getCheckpointDataRange(from: CheckpointNumber, limit: number): Promise<CheckpointData[]> {
135
+ return this.stores.blocks.getRangeOfCheckpoints(from, limit);
136
+ }
137
+
138
+ public getCheckpointNumberBySlot(slot: SlotNumber): Promise<CheckpointNumber | undefined> {
139
+ return this.stores.blocks.getCheckpointNumberBySlot(slot);
140
+ }
141
+
142
+ public getBlockDataWithCheckpointContext(blockNumber: BlockNumber) {
143
+ return this.stores.blocks.getBlockDataWithCheckpointContext(blockNumber);
128
144
  }
129
145
 
130
146
  public getBlockHeaderByHash(blockHash: BlockHash): Promise<BlockHeader | undefined> {
131
- return this.store.getBlockHeaderByHash(blockHash);
147
+ return this.stores.blocks.getBlockHeaderByHash(blockHash);
132
148
  }
133
149
 
134
150
  public getBlockHeaderByArchive(archive: Fr): Promise<BlockHeader | undefined> {
135
- return this.store.getBlockHeaderByArchive(archive);
151
+ return this.stores.blocks.getBlockHeaderByArchive(archive);
136
152
  }
137
153
 
138
154
  public getBlockData(number: BlockNumber): Promise<BlockData | undefined> {
139
- return this.store.getBlockData(number);
155
+ return this.stores.blocks.getBlockData(number);
140
156
  }
141
157
 
142
158
  public getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined> {
143
- return this.store.getBlockDataByArchive(archive);
159
+ return this.stores.blocks.getBlockDataByArchive(archive);
144
160
  }
145
161
 
146
162
  public async getL2Block(number: BlockNumber): Promise<L2Block | undefined> {
147
163
  // If the number provided is -ve, then return the latest block.
148
164
  if (number < 0) {
149
- number = await this.store.getLatestBlockNumber();
165
+ number = await this.stores.blocks.getLatestL2BlockNumber();
150
166
  }
151
167
  if (number === 0) {
152
168
  return undefined;
153
169
  }
154
- const publishedBlock = await this.store.getBlock(number);
155
- return publishedBlock;
170
+ return this.stores.blocks.getBlock(number);
156
171
  }
157
172
 
158
173
  public getTxEffect(txHash: TxHash): Promise<IndexedTxEffect | undefined> {
159
- return this.store.getTxEffect(txHash);
174
+ return this.stores.blocks.getTxEffect(txHash);
160
175
  }
161
176
 
162
177
  public getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
163
- return this.store.getSettledTxReceipt(txHash, this.l1Constants);
178
+ return this.stores.blocks.getSettledTxReceipt(txHash, this.l1Constants);
164
179
  }
165
180
 
166
- public getProposedCheckpoint(): Promise<CommonCheckpointData | undefined> {
167
- return this.store.getProposedCheckpoint();
181
+ public getLastCheckpoint(): Promise<CommonCheckpointData | undefined> {
182
+ return this.stores.blocks.getLastCheckpoint();
168
183
  }
169
184
 
170
- public getProposedCheckpointOnly(): Promise<ProposedCheckpointData | undefined> {
171
- return this.store.getProposedCheckpointOnly();
185
+ public getLastProposedCheckpoint(): Promise<ProposedCheckpointData | undefined> {
186
+ return this.stores.blocks.getLastProposedCheckpoint();
172
187
  }
173
188
 
174
189
  public isPendingChainInvalid(): Promise<boolean> {
@@ -176,7 +191,7 @@ export abstract class ArchiverDataSourceBase
176
191
  }
177
192
 
178
193
  public async getPendingChainValidationStatus(): Promise<ValidateCheckpointResult> {
179
- return (await this.store.getPendingChainValidationStatus()) ?? { valid: true };
194
+ return (await this.stores.blocks.getPendingChainValidationStatus()) ?? { valid: true };
180
195
  }
181
196
 
182
197
  public getPrivateLogsByTags(
@@ -184,7 +199,7 @@ export abstract class ArchiverDataSourceBase
184
199
  page?: number,
185
200
  upToBlockNumber?: BlockNumber,
186
201
  ): Promise<TxScopedL2Log[][]> {
187
- return this.store.getPrivateLogsByTags(tags, page, upToBlockNumber);
202
+ return this.stores.logs.getPrivateLogsByTags(tags, page, upToBlockNumber);
188
203
  }
189
204
 
190
205
  public getPublicLogsByTagsFromContract(
@@ -193,23 +208,23 @@ export abstract class ArchiverDataSourceBase
193
208
  page?: number,
194
209
  upToBlockNumber?: BlockNumber,
195
210
  ): Promise<TxScopedL2Log[][]> {
196
- return this.store.getPublicLogsByTagsFromContract(contractAddress, tags, page, upToBlockNumber);
211
+ return this.stores.logs.getPublicLogsByTagsFromContract(contractAddress, tags, page, upToBlockNumber);
197
212
  }
198
213
 
199
214
  public getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
200
- return this.store.getPublicLogs(filter);
215
+ return this.stores.logs.getPublicLogs(filter);
201
216
  }
202
217
 
203
218
  public getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse> {
204
- return this.store.getContractClassLogs(filter);
219
+ return this.stores.logs.getContractClassLogs(filter);
205
220
  }
206
221
 
207
222
  public getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
208
- return this.store.getContractClass(id);
223
+ return this.stores.contractClasses.getContractClass(id);
209
224
  }
210
225
 
211
226
  public getBytecodeCommitment(id: Fr): Promise<Fr | undefined> {
212
- return this.store.getBytecodeCommitment(id);
227
+ return this.stores.contractClasses.getBytecodeCommitment(id);
213
228
  }
214
229
 
215
230
  public async getContract(
@@ -225,36 +240,38 @@ export abstract class ArchiverDataSourceBase
225
240
  timestamp = maybeTimestamp;
226
241
  }
227
242
 
228
- return this.store.getContractInstance(address, timestamp);
243
+ return this.stores.contractInstances.getContractInstance(address, timestamp);
229
244
  }
230
245
 
231
246
  public getContractClassIds(): Promise<Fr[]> {
232
- return this.store.getContractClassIds();
247
+ return this.stores.contractClasses.getContractClassIds();
233
248
  }
234
249
 
235
- public getDebugFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
236
- return this.store.getDebugFunctionName(address, selector);
250
+ /** Looks up a public function name given a selector. */
251
+ public getDebugFunctionName(_address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
252
+ return Promise.resolve(this.stores.functionNames.get(selector));
237
253
  }
238
254
 
255
+ /** Register public function signatures so they can be looked up by selector. */
239
256
  public registerContractFunctionSignatures(signatures: string[]): Promise<void> {
240
- return this.store.registerContractFunctionSignatures(signatures);
257
+ return this.stores.functionNames.register(signatures);
241
258
  }
242
259
 
243
260
  public getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
244
- return this.store.getL1ToL2Messages(checkpointNumber);
261
+ return this.stores.messages.getL1ToL2Messages(checkpointNumber);
245
262
  }
246
263
 
247
264
  public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
248
- return this.store.getL1ToL2MessageIndex(l1ToL2Message);
265
+ return this.stores.messages.getL1ToL2MessageIndex(l1ToL2Message);
249
266
  }
250
267
 
251
268
  public async getCheckpoints(checkpointNumber: CheckpointNumber, limit: number): Promise<PublishedCheckpoint[]> {
252
- const checkpoints = await this.store.getRangeOfCheckpoints(checkpointNumber, limit);
269
+ const checkpoints = await this.stores.blocks.getRangeOfCheckpoints(checkpointNumber, limit);
253
270
  return Promise.all(checkpoints.map(ch => this.getPublishedCheckpointFromCheckpointData(ch)));
254
271
  }
255
272
 
256
273
  private async getPublishedCheckpointFromCheckpointData(checkpoint: CheckpointData): Promise<PublishedCheckpoint> {
257
- const blocksForCheckpoint = await this.store.getBlocksForCheckpoint(checkpoint.checkpointNumber);
274
+ const blocksForCheckpoint = await this.stores.blocks.getBlocksForCheckpoint(checkpoint.checkpointNumber);
258
275
  if (!blocksForCheckpoint) {
259
276
  throw new Error(`Blocks for checkpoint ${checkpoint.checkpointNumber} not found`);
260
277
  }
@@ -263,12 +280,13 @@ export abstract class ArchiverDataSourceBase
263
280
  checkpoint.header,
264
281
  blocksForCheckpoint,
265
282
  checkpoint.checkpointNumber,
283
+ checkpoint.feeAssetPriceModifier,
266
284
  );
267
285
  return new PublishedCheckpoint(fullCheckpoint, checkpoint.l1, checkpoint.attestations);
268
286
  }
269
287
 
270
288
  public getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]> {
271
- return this.store.getBlocksForSlot(slotNumber);
289
+ return this.stores.blocks.getBlocksForSlot(slotNumber);
272
290
  }
273
291
 
274
292
  public async getCheckpointedBlocksForEpoch(epochNumber: EpochNumber): Promise<CheckpointedL2Block[]> {
@@ -309,39 +327,39 @@ export abstract class ArchiverDataSourceBase
309
327
  }
310
328
 
311
329
  const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1Constants);
312
- return this.store.getCheckpointDataForSlotRange(start, end);
330
+ return this.stores.blocks.getCheckpointDataForSlotRange(start, end);
313
331
  }
314
332
 
315
333
  public async getBlock(number: BlockNumber): Promise<L2Block | undefined> {
316
334
  // If the number provided is -ve, then return the latest block.
317
335
  if (number < 0) {
318
- number = await this.store.getLatestBlockNumber();
336
+ number = await this.stores.blocks.getLatestL2BlockNumber();
319
337
  }
320
338
  if (number === 0) {
321
339
  return undefined;
322
340
  }
323
- return this.store.getBlock(number);
341
+ return this.stores.blocks.getBlock(number);
324
342
  }
325
343
 
326
344
  public getBlocks(from: BlockNumber, limit: number): Promise<L2Block[]> {
327
- return this.store.getBlocks(from, limit);
345
+ return this.stores.blocks.getBlocks(from, limit);
328
346
  }
329
347
 
330
348
  public getCheckpointedBlockByHash(blockHash: BlockHash): Promise<CheckpointedL2Block | undefined> {
331
- return this.store.getCheckpointedBlockByHash(blockHash);
349
+ return this.stores.blocks.getCheckpointedBlockByHash(blockHash);
332
350
  }
333
351
 
334
352
  public getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
335
- return this.store.getCheckpointedBlockByArchive(archive);
353
+ return this.stores.blocks.getCheckpointedBlockByArchive(archive);
336
354
  }
337
355
 
338
356
  public async getL2BlockByHash(blockHash: BlockHash): Promise<L2Block | undefined> {
339
- const checkpointedBlock = await this.store.getCheckpointedBlockByHash(blockHash);
357
+ const checkpointedBlock = await this.stores.blocks.getCheckpointedBlockByHash(blockHash);
340
358
  return checkpointedBlock?.block;
341
359
  }
342
360
 
343
361
  public async getL2BlockByArchive(archive: Fr): Promise<L2Block | undefined> {
344
- const checkpointedBlock = await this.store.getCheckpointedBlockByArchive(archive);
362
+ const checkpointedBlock = await this.stores.blocks.getCheckpointedBlockByArchive(archive);
345
363
  return checkpointedBlock?.block;
346
364
  }
347
365
  }
@@ -6,8 +6,13 @@ import {
6
6
  ContractInstancePublishedEvent,
7
7
  ContractInstanceUpdatedEvent,
8
8
  } from '@aztec/protocol-contracts/instance-registry';
9
- import type { L2Block, ValidateCheckpointResult } from '@aztec/stdlib/block';
10
- import { type ProposedCheckpointInput, type PublishedCheckpoint, validateCheckpoint } from '@aztec/stdlib/checkpoint';
9
+ import type { CommitteeAttestation, L2Block, ValidateCheckpointResult } from '@aztec/stdlib/block';
10
+ import {
11
+ type L1PublishedData,
12
+ type ProposedCheckpointInput,
13
+ type PublishedCheckpoint,
14
+ validateCheckpoint,
15
+ } from '@aztec/stdlib/checkpoint';
11
16
  import {
12
17
  type ContractClassPublicWithCommitment,
13
18
  computeContractAddressFromInstance,
@@ -16,7 +21,7 @@ import {
16
21
  import type { ContractClassLog, PrivateLog, PublicLog } from '@aztec/stdlib/logs';
17
22
  import type { UInt64 } from '@aztec/stdlib/types';
18
23
 
19
- import type { KVArchiverDataStore } from '../store/kv_archiver_store.js';
24
+ import type { ArchiverDataStores } from '../store/data_stores.js';
20
25
  import type { L2TipsCache } from '../store/l2_tips_cache.js';
21
26
 
22
27
  /** Operation type for contract data updates. */
@@ -38,7 +43,7 @@ export class ArchiverDataStoreUpdater {
38
43
  private readonly log = createLogger('archiver:store_updater');
39
44
 
40
45
  constructor(
41
- private store: KVArchiverDataStore,
46
+ private stores: ArchiverDataStores,
42
47
  private l2TipsCache?: L2TipsCache,
43
48
  private opts: { rollupManaLimit?: number } = {},
44
49
  ) {}
@@ -56,14 +61,15 @@ export class ArchiverDataStoreUpdater {
56
61
  block: L2Block,
57
62
  pendingChainValidationStatus?: ValidateCheckpointResult,
58
63
  ): Promise<boolean> {
59
- const result = await this.store.transactionAsync(async () => {
60
- await this.store.addProposedBlock(block);
64
+ const result = await this.stores.db.transactionAsync(async () => {
65
+ await this.stores.blocks.addProposedBlock(block);
61
66
 
62
67
  const opResults = await Promise.all([
63
68
  // Update the pending chain validation status if provided
64
- pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
69
+ pendingChainValidationStatus &&
70
+ this.stores.blocks.setPendingChainValidationStatus(pendingChainValidationStatus),
65
71
  // Add any logs emitted during the retrieved block
66
- this.store.addLogs([block]),
72
+ this.stores.logs.addLogs([block]),
67
73
  // Unroll all logs emitted during the retrieved block and extract any contract classes and instances from it
68
74
  this.addContractDataToDb(block),
69
75
  ]);
@@ -79,24 +85,36 @@ export class ArchiverDataStoreUpdater {
79
85
  * Adds new checkpoints to the store with contract class/instance extraction from logs.
80
86
  * Prunes any local blocks that conflict with checkpoint data (by comparing archive roots).
81
87
  * Extracts ContractClassPublished, ContractInstancePublished, ContractInstanceUpdated events from the checkpoint block logs.
88
+ * If `promoteProposed` is supplied, the proposed-checkpoint promotion runs inside the same transaction
89
+ * as the added checkpoints so both updates are applied atomically.
82
90
  *
83
- * @param checkpoints - The published checkpoints to add.
91
+ * @param checkpoints - The published checkpoints to add (excluding any being promoted from proposed).
84
92
  * @param pendingChainValidationStatus - Optional validation status to set.
93
+ * @param promoteProposed - Optional promotion of the current proposed checkpoint (fast path when blocks are already local).
85
94
  * @returns Result with information about any pruned blocks.
86
95
  */
87
96
  public async addCheckpoints(
88
97
  checkpoints: PublishedCheckpoint[],
89
98
  pendingChainValidationStatus?: ValidateCheckpointResult,
99
+ promoteProposed?: {
100
+ l1: L1PublishedData;
101
+ attestations: CommitteeAttestation[];
102
+ checkpoint: PublishedCheckpoint;
103
+ },
104
+ evictProposedFrom?: CheckpointNumber,
90
105
  ): Promise<ReconcileCheckpointsResult> {
91
106
  for (const checkpoint of checkpoints) {
92
107
  validateCheckpoint(checkpoint.checkpoint, { rollupManaLimit: this.opts?.rollupManaLimit });
93
108
  }
109
+ if (promoteProposed) {
110
+ validateCheckpoint(promoteProposed.checkpoint.checkpoint, { rollupManaLimit: this.opts?.rollupManaLimit });
111
+ }
94
112
 
95
- const result = await this.store.transactionAsync(async () => {
113
+ const result = await this.stores.db.transactionAsync(async () => {
96
114
  // Before adding checkpoints, check for conflicts with local blocks if any
97
115
  const { prunedBlocks, lastAlreadyInsertedBlockNumber } = await this.pruneMismatchingLocalBlocks(checkpoints);
98
116
 
99
- await this.store.addCheckpoints(checkpoints);
117
+ await this.stores.blocks.addCheckpoints(checkpoints);
100
118
 
101
119
  // Filter out blocks that were already inserted via addProposedBlock() to avoid duplicating logs/contract data
102
120
  const newBlocks = checkpoints
@@ -105,11 +123,25 @@ export class ArchiverDataStoreUpdater {
105
123
 
106
124
  await Promise.all([
107
125
  // Update the pending chain validation status if provided
108
- pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
126
+ pendingChainValidationStatus &&
127
+ this.stores.blocks.setPendingChainValidationStatus(pendingChainValidationStatus),
109
128
  // Add any logs emitted during the retrieved blocks
110
- this.store.addLogs(newBlocks),
129
+ this.stores.logs.addLogs(newBlocks),
111
130
  // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
112
131
  ...newBlocks.map(block => this.addContractDataToDb(block)),
132
+ // Promote the proposed checkpoint if requested (uses explicit checkpoint number)
133
+ promoteProposed
134
+ ? this.stores.blocks.promoteProposedToCheckpointed(
135
+ promoteProposed.checkpoint.checkpoint.number,
136
+ promoteProposed.l1,
137
+ promoteProposed.attestations,
138
+ promoteProposed.checkpoint.checkpoint.archive.root,
139
+ )
140
+ : undefined,
141
+ // Evict pending checkpoints that diverged from what L1 mined
142
+ evictProposedFrom !== undefined
143
+ ? this.stores.blocks.evictProposedCheckpointsFrom(evictProposedFrom)
144
+ : undefined,
113
145
  ]);
114
146
 
115
147
  await this.l2TipsCache?.refresh();
@@ -118,9 +150,9 @@ export class ArchiverDataStoreUpdater {
118
150
  return result;
119
151
  }
120
152
 
121
- public async setProposedCheckpoint(proposedCheckpoint: ProposedCheckpointInput) {
122
- const result = await this.store.transactionAsync(async () => {
123
- await this.store.setProposedCheckpoint(proposedCheckpoint);
153
+ public async addProposedCheckpoint(proposedCheckpoint: ProposedCheckpointInput) {
154
+ const result = await this.stores.db.transactionAsync(async () => {
155
+ await this.stores.blocks.addProposedCheckpoint(proposedCheckpoint);
124
156
  await this.l2TipsCache?.refresh();
125
157
  });
126
158
 
@@ -135,8 +167,8 @@ export class ArchiverDataStoreUpdater {
135
167
  */
136
168
  private async pruneMismatchingLocalBlocks(checkpoints: PublishedCheckpoint[]): Promise<ReconcileCheckpointsResult> {
137
169
  const [lastCheckpointedBlockNumber, lastBlockNumber] = await Promise.all([
138
- this.store.getCheckpointedL2BlockNumber(),
139
- this.store.getLatestBlockNumber(),
170
+ this.stores.blocks.getCheckpointedL2BlockNumber(),
171
+ this.stores.blocks.getLatestL2BlockNumber(),
140
172
  ]);
141
173
 
142
174
  // Exit early if there are no local uncheckpointed blocks
@@ -145,7 +177,7 @@ export class ArchiverDataStoreUpdater {
145
177
  }
146
178
 
147
179
  // Get all uncheckpointed local blocks
148
- const uncheckpointedLocalBlocks = await this.store.getBlocks(
180
+ const uncheckpointedLocalBlocks = await this.stores.blocks.getBlocks(
149
181
  BlockNumber.add(lastCheckpointedBlockNumber, 1),
150
182
  lastBlockNumber - lastCheckpointedBlockNumber,
151
183
  );
@@ -210,9 +242,9 @@ export class ArchiverDataStoreUpdater {
210
242
  * @throws Error if any block to be removed is checkpointed.
211
243
  */
212
244
  public async removeUncheckpointedBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
213
- const result = await this.store.transactionAsync(async () => {
245
+ const result = await this.stores.db.transactionAsync(async () => {
214
246
  // Verify we're only removing uncheckpointed blocks
215
- const lastCheckpointedBlockNumber = await this.store.getCheckpointedL2BlockNumber();
247
+ const lastCheckpointedBlockNumber = await this.stores.blocks.getCheckpointedL2BlockNumber();
216
248
  if (blockNumber < lastCheckpointedBlockNumber) {
217
249
  throw new Error(
218
250
  `Cannot remove blocks after ${blockNumber} because checkpointed blocks exist up to ${lastCheckpointedBlockNumber}`,
@@ -221,8 +253,8 @@ export class ArchiverDataStoreUpdater {
221
253
 
222
254
  const result = await this.removeBlocksAfter(blockNumber);
223
255
 
224
- // Clear the proposed checkpoint if it exists, since its blocks have been pruned
225
- await this.store.deleteProposedCheckpoint();
256
+ // Clear all pending proposed checkpoints since their blocks have been pruned
257
+ await this.stores.blocks.deleteProposedCheckpoints();
226
258
 
227
259
  await this.l2TipsCache?.refresh();
228
260
  return result;
@@ -236,11 +268,11 @@ export class ArchiverDataStoreUpdater {
236
268
  */
237
269
  private async removeBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
238
270
  // First get the blocks to be removed so we can clean up contract data
239
- const removedBlocks = await this.store.removeBlocksAfter(blockNumber);
271
+ const removedBlocks = await this.stores.blocks.removeBlocksAfter(blockNumber);
240
272
 
241
273
  // Clean up contract data and logs for the removed blocks
242
274
  await Promise.all([
243
- this.store.deleteLogs(removedBlocks),
275
+ this.stores.logs.deleteLogs(removedBlocks),
244
276
  ...removedBlocks.map(block => this.removeContractDataFromDb(block)),
245
277
  ]);
246
278
 
@@ -257,15 +289,15 @@ export class ArchiverDataStoreUpdater {
257
289
  * @returns True if the operation is successful.
258
290
  */
259
291
  public async removeCheckpointsAfter(checkpointNumber: CheckpointNumber): Promise<boolean> {
260
- return await this.store.transactionAsync(async () => {
261
- const { blocksRemoved = [] } = await this.store.removeCheckpointsAfter(checkpointNumber);
292
+ return await this.stores.db.transactionAsync(async () => {
293
+ const { blocksRemoved = [] } = await this.stores.blocks.removeCheckpointsAfter(checkpointNumber);
262
294
 
263
295
  const opResults = await Promise.all([
264
296
  // Prune rolls back to the last proven block, which is by definition valid
265
- this.store.setPendingChainValidationStatus({ valid: true }),
297
+ this.stores.blocks.setPendingChainValidationStatus({ valid: true }),
266
298
  // Remove contract data for all blocks being removed
267
299
  ...blocksRemoved.map(block => this.removeContractDataFromDb(block)),
268
- this.store.deleteLogs(blocksRemoved),
300
+ this.stores.logs.deleteLogs(blocksRemoved),
269
301
  ]);
270
302
 
271
303
  await this.l2TipsCache?.refresh();
@@ -278,8 +310,8 @@ export class ArchiverDataStoreUpdater {
278
310
  * @param checkpointNumber - The checkpoint number to set as proven.
279
311
  */
280
312
  public async setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
281
- await this.store.transactionAsync(async () => {
282
- await this.store.setProvenCheckpointNumber(checkpointNumber);
313
+ await this.stores.db.transactionAsync(async () => {
314
+ await this.stores.blocks.setProvenCheckpointNumber(checkpointNumber);
283
315
  await this.l2TipsCache?.refresh();
284
316
  });
285
317
  }
@@ -289,8 +321,8 @@ export class ArchiverDataStoreUpdater {
289
321
  * @param checkpointNumber - The checkpoint number to set as finalized.
290
322
  */
291
323
  public async setFinalizedCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
292
- await this.store.transactionAsync(async () => {
293
- await this.store.setFinalizedCheckpointNumber(checkpointNumber);
324
+ await this.stores.db.transactionAsync(async () => {
325
+ await this.stores.blocks.setFinalizedCheckpointNumber(checkpointNumber);
294
326
  await this.l2TipsCache?.refresh();
295
327
  });
296
328
  }
@@ -336,7 +368,7 @@ export class ArchiverDataStoreUpdater {
336
368
  const contractClasses = contractClassPublishedEvents.map(e => e.toContractClassPublic());
337
369
  if (contractClasses.length > 0) {
338
370
  contractClasses.forEach(c => this.log.verbose(`${Operation[operation]} contract class ${c.id.toString()}`));
339
- return await this.store.deleteContractClasses(contractClasses, blockNum);
371
+ return await this.stores.contractClasses.deleteContractClasses(contractClasses, blockNum);
340
372
  }
341
373
  return true;
342
374
  }
@@ -362,7 +394,7 @@ export class ArchiverDataStoreUpdater {
362
394
 
363
395
  if (contractClasses.length > 0) {
364
396
  contractClasses.forEach(c => this.log.verbose(`${Operation[operation]} contract class ${c.id.toString()}`));
365
- return await this.store.addContractClasses(contractClasses, blockNum);
397
+ return await this.stores.contractClasses.addContractClasses(contractClasses, blockNum);
366
398
  }
367
399
  return true;
368
400
  }
@@ -401,9 +433,9 @@ export class ArchiverDataStoreUpdater {
401
433
  this.log.verbose(`${Operation[operation]} contract instance at ${c.address.toString()}`),
402
434
  );
403
435
  if (operation == Operation.Store) {
404
- return await this.store.addContractInstances(contractInstances, blockNum);
436
+ return await this.stores.contractInstances.addContractInstances(contractInstances, blockNum);
405
437
  } else if (operation == Operation.Delete) {
406
- return await this.store.deleteContractInstances(contractInstances, blockNum);
438
+ return await this.stores.contractInstances.deleteContractInstances(contractInstances);
407
439
  }
408
440
  }
409
441
  return true;
@@ -427,9 +459,9 @@ export class ArchiverDataStoreUpdater {
427
459
  this.log.verbose(`${Operation[operation]} contract instance update at ${c.address.toString()}`),
428
460
  );
429
461
  if (operation == Operation.Store) {
430
- return await this.store.addContractInstanceUpdates(contractUpdates, timestamp);
462
+ return await this.stores.contractInstances.addContractInstanceUpdates(contractUpdates, timestamp);
431
463
  } else if (operation == Operation.Delete) {
432
- return await this.store.deleteContractInstanceUpdates(contractUpdates, timestamp);
464
+ return await this.stores.contractInstances.deleteContractInstanceUpdates(contractUpdates, timestamp);
433
465
  }
434
466
  }
435
467
  return true;