@aztec/archiver 4.0.0-nightly.20260113 → 4.0.0-nightly.20260114

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 (47) hide show
  1. package/README.md +139 -22
  2. package/dest/archiver/archive_source_base.d.ts +75 -0
  3. package/dest/archiver/archive_source_base.d.ts.map +1 -0
  4. package/dest/archiver/archive_source_base.js +202 -0
  5. package/dest/archiver/archiver.d.ts +28 -167
  6. package/dest/archiver/archiver.d.ts.map +1 -1
  7. package/dest/archiver/archiver.js +46 -601
  8. package/dest/archiver/archiver_store_updates.d.ts +38 -0
  9. package/dest/archiver/archiver_store_updates.d.ts.map +1 -0
  10. package/dest/archiver/archiver_store_updates.js +212 -0
  11. package/dest/archiver/index.d.ts +3 -2
  12. package/dest/archiver/index.d.ts.map +1 -1
  13. package/dest/archiver/index.js +2 -0
  14. package/dest/archiver/kv_archiver_store/block_store.d.ts +1 -1
  15. package/dest/archiver/kv_archiver_store/block_store.js +1 -1
  16. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +1 -1
  17. package/dest/archiver/kv_archiver_store/contract_class_store.js +1 -1
  18. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +1 -1
  19. package/dest/archiver/kv_archiver_store/contract_instance_store.js +1 -1
  20. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +169 -9
  21. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  22. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +157 -49
  23. package/dest/archiver/l1/data_retrieval.d.ts +9 -11
  24. package/dest/archiver/l1/data_retrieval.d.ts.map +1 -1
  25. package/dest/archiver/l1/data_retrieval.js +32 -51
  26. package/dest/archiver/test/fake_l1_state.d.ts +173 -0
  27. package/dest/archiver/test/fake_l1_state.d.ts.map +1 -0
  28. package/dest/archiver/test/fake_l1_state.js +364 -0
  29. package/package.json +13 -13
  30. package/src/archiver/archive_source_base.ts +339 -0
  31. package/src/archiver/archiver.ts +62 -808
  32. package/src/archiver/archiver_store_updates.ts +321 -0
  33. package/src/archiver/index.ts +2 -1
  34. package/src/archiver/kv_archiver_store/block_store.ts +1 -1
  35. package/src/archiver/kv_archiver_store/contract_class_store.ts +1 -1
  36. package/src/archiver/kv_archiver_store/contract_instance_store.ts +1 -1
  37. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +170 -8
  38. package/src/archiver/l1/data_retrieval.ts +51 -68
  39. package/src/archiver/test/fake_l1_state.ts +561 -0
  40. package/dest/archiver/archiver_store.d.ts +0 -315
  41. package/dest/archiver/archiver_store.d.ts.map +0 -1
  42. package/dest/archiver/archiver_store.js +0 -4
  43. package/dest/archiver/archiver_store_test_suite.d.ts +0 -8
  44. package/dest/archiver/archiver_store_test_suite.d.ts.map +0 -1
  45. package/dest/archiver/archiver_store_test_suite.js +0 -2770
  46. package/src/archiver/archiver_store.ts +0 -380
  47. package/src/archiver/archiver_store_test_suite.ts +0 -2842
@@ -11,31 +11,16 @@ import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/f
11
11
  import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
12
12
  import { merge, pick } from '@aztec/foundation/collection';
13
13
  import { Fr } from '@aztec/foundation/curves/bn254';
14
- import type { EthAddress } from '@aztec/foundation/eth-address';
14
+ import { EthAddress } from '@aztec/foundation/eth-address';
15
15
  import { type Logger, createLogger } from '@aztec/foundation/log';
16
16
  import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundation/promise';
17
17
  import { RunningPromise, makeLoggingErrorHandler } from '@aztec/foundation/running-promise';
18
18
  import { count } from '@aztec/foundation/string';
19
19
  import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
20
20
  import { isDefined } from '@aztec/foundation/types';
21
- import type { CustomRange } from '@aztec/kv-store';
22
- import { RollupAbi } from '@aztec/l1-artifacts';
23
- import {
24
- ContractClassPublishedEvent,
25
- PrivateFunctionBroadcastedEvent,
26
- UtilityFunctionBroadcastedEvent,
27
- } from '@aztec/protocol-contracts/class-registry';
28
- import {
29
- ContractInstancePublishedEvent,
30
- ContractInstanceUpdatedEvent,
31
- } from '@aztec/protocol-contracts/instance-registry';
32
- import type { FunctionSelector } from '@aztec/stdlib/abi';
33
- import type { AztecAddress } from '@aztec/stdlib/aztec-address';
34
21
  import {
35
22
  type ArchiverEmitter,
36
23
  type CheckpointId,
37
- CheckpointedL2Block,
38
- CommitteeAttestation,
39
24
  GENESIS_CHECKPOINT_HEADER_HASH,
40
25
  L2Block,
41
26
  L2BlockNew,
@@ -43,19 +28,9 @@ import {
43
28
  type L2BlockSource,
44
29
  L2BlockSourceEvents,
45
30
  type L2Tips,
46
- PublishedL2Block,
47
31
  } from '@aztec/stdlib/block';
48
32
  import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
49
- import {
50
- type ContractClassPublic,
51
- type ContractDataSource,
52
- type ContractInstanceWithAddress,
53
- type ExecutablePrivateFunctionWithMembershipProof,
54
- type UtilityFunctionWithMembershipProof,
55
- computePublicBytecodeCommitment,
56
- isValidPrivateFunctionMembershipProof,
57
- isValidUtilityFunctionMembershipProof,
58
- } from '@aztec/stdlib/contract';
33
+ import type { ContractDataSource } from '@aztec/stdlib/contract';
59
34
  import {
60
35
  type L1RollupConstants,
61
36
  getEpochAtSlot,
@@ -64,21 +39,11 @@ import {
64
39
  getSlotRangeForEpoch,
65
40
  getTimestampRangeForEpoch,
66
41
  } from '@aztec/stdlib/epoch-helpers';
67
- import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
68
42
  import type { L2LogsSource } from '@aztec/stdlib/interfaces/server';
69
- import {
70
- ContractClassLog,
71
- type LogFilter,
72
- type PrivateLog,
73
- type PublicLog,
74
- type SiloedTag,
75
- Tag,
76
- TxScopedL2Log,
77
- } from '@aztec/stdlib/logs';
78
- import { type L1ToL2MessageSource, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
43
+ import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
44
+ import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
79
45
  import type { CheckpointHeader } from '@aztec/stdlib/rollup';
80
- import { type BlockHeader, type IndexedTxEffect, TxHash, TxReceipt } from '@aztec/stdlib/tx';
81
- import type { UInt64 } from '@aztec/stdlib/types';
46
+ import type { BlockHeader } from '@aztec/stdlib/tx';
82
47
  import {
83
48
  type TelemetryClient,
84
49
  type Traceable,
@@ -89,14 +54,19 @@ import {
89
54
  } from '@aztec/telemetry-client';
90
55
 
91
56
  import { EventEmitter } from 'events';
92
- import groupBy from 'lodash.groupby';
93
- import { type GetContractReturnType, type Hex, createPublicClient, fallback, http } from 'viem';
57
+ import { type Hex, createPublicClient, fallback, http } from 'viem';
94
58
 
95
- import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
59
+ import { ArchiveSourceBase } from './archive_source_base.js';
60
+ import {
61
+ addBlocksWithContractData,
62
+ addCheckpointsWithContractData,
63
+ unwindCheckpointsWithContractData,
64
+ } from './archiver_store_updates.js';
96
65
  import type { ArchiverConfig } from './config.js';
97
66
  import { InitialCheckpointNumberNotSequentialError, NoBlobBodiesFoundError } from './errors.js';
98
67
  import { ArchiverInstrumentation } from './instrumentation.js';
99
68
  import type { CheckpointData } from './kv_archiver_store/block_store.js';
69
+ import type { KVArchiverDataStore } from './kv_archiver_store/kv_archiver_store.js';
100
70
  import {
101
71
  retrieveCheckpointsFromRollup,
102
72
  retrieveL1ToL2Message,
@@ -151,18 +121,13 @@ type RollupStatus = {
151
121
  * Responsible for handling robust L1 polling so that other components do not need to
152
122
  * concern themselves with it.
153
123
  */
154
- export class Archiver
155
- extends (EventEmitter as new () => ArchiverEmitter)
156
- implements ArchiveSource, L2BlockSink, Traceable
157
- {
124
+ export class Archiver extends ArchiveSourceBase implements L2BlockSink, Traceable {
125
+ /** Event emitter for archiver events (L2BlockProven, L2PruneDetected, etc). */
126
+ public readonly events: ArchiverEmitter = new EventEmitter() as ArchiverEmitter;
127
+
158
128
  /** A loop in which we will be continually fetching new checkpoints. */
159
129
  private runningPromise: RunningPromise;
160
130
 
161
- private rollup: RollupContract;
162
- private inbox: InboxContract;
163
-
164
- private store: ArchiverStoreHelper;
165
-
166
131
  private l1BlockNumber: bigint | undefined;
167
132
  private l1Timestamp: bigint | undefined;
168
133
  private initialSyncComplete: boolean = false;
@@ -177,21 +142,28 @@ export class Archiver
177
142
  * Creates a new instance of the Archiver.
178
143
  * @param publicClient - A client for interacting with the Ethereum node.
179
144
  * @param debugClient - A client for interacting with the Ethereum node for debug/trace methods.
180
- * @param rollupAddress - Ethereum address of the rollup contract.
181
- * @param inboxAddress - Ethereum address of the inbox contract.
182
- * @param registryAddress - Ethereum address of the registry contract.
183
- * @param pollingIntervalMs - The interval for polling for L1 logs (in milliseconds).
184
- * @param store - An archiver data store for storage & retrieval of blocks, encrypted logs & contract data.
145
+ * @param rollup - Rollup contract instance.
146
+ * @param inbox - Inbox contract instance.
147
+ * @param l1Addresses - L1 contract addresses (registry, governance proposer, slash factory, slashing proposer).
148
+ * @param dataStore - An archiver data store for storage & retrieval of blocks, encrypted logs & contract data.
149
+ * @param config - Archiver configuration options.
150
+ * @param blobClient - Client for retrieving blob data.
151
+ * @param epochCache - Cache for epoch-related data.
152
+ * @param dateProvider - Provider for current date/time.
153
+ * @param instrumentation - Instrumentation for metrics and tracing.
154
+ * @param l1constants - L1 rollup constants.
185
155
  * @param log - A logger.
186
156
  */
187
157
  constructor(
188
158
  private readonly publicClient: ViemPublicClient,
189
159
  private readonly debugClient: ViemPublicDebugClient,
160
+ private readonly rollup: RollupContract,
161
+ private readonly inbox: InboxContract,
190
162
  private readonly l1Addresses: Pick<
191
163
  L1ContractAddresses,
192
- 'rollupAddress' | 'inboxAddress' | 'registryAddress' | 'governanceProposerAddress' | 'slashFactoryAddress'
164
+ 'registryAddress' | 'governanceProposerAddress' | 'slashFactoryAddress'
193
165
  > & { slashingProposerAddress: EthAddress },
194
- readonly dataStore: ArchiverDataStore,
166
+ readonly dataStore: KVArchiverDataStore,
195
167
  private config: {
196
168
  pollingIntervalMs: number;
197
169
  batchSize: number;
@@ -206,13 +178,9 @@ export class Archiver
206
178
  private readonly l1constants: L1RollupConstants & { l1StartBlockHash: Buffer32; genesisArchiveRoot: Fr },
207
179
  private readonly log: Logger = createLogger('archiver'),
208
180
  ) {
209
- super();
181
+ super(dataStore);
210
182
 
211
183
  this.tracer = instrumentation.tracer;
212
- this.store = new ArchiverStoreHelper(dataStore);
213
-
214
- this.rollup = new RollupContract(publicClient, l1Addresses.rollupAddress);
215
- this.inbox = new InboxContract(publicClient, l1Addresses.inboxAddress);
216
184
  this.initialSyncPromise = promiseWithResolvers();
217
185
 
218
186
  // Running promise starts with a small interval inbetween runs, so all iterations needed for the initial sync
@@ -234,7 +202,7 @@ export class Archiver
234
202
  */
235
203
  public static async createAndSync(
236
204
  config: ArchiverConfig,
237
- archiverStore: ArchiverDataStore,
205
+ archiverStore: KVArchiverDataStore,
238
206
  deps: ArchiverDeps,
239
207
  blockUntilSynced = true,
240
208
  ): Promise<Archiver> {
@@ -254,6 +222,7 @@ export class Archiver
254
222
  }) as ViemPublicDebugClient;
255
223
 
256
224
  const rollup = new RollupContract(publicClient, config.l1Contracts.rollupAddress);
225
+ const inbox = new InboxContract(publicClient, config.l1Contracts.inboxAddress);
257
226
 
258
227
  const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, genesisArchiveRoot, slashingProposerAddress] =
259
228
  await Promise.all([
@@ -297,6 +266,8 @@ export class Archiver
297
266
  const archiver = new Archiver(
298
267
  publicClient,
299
268
  debugClient,
269
+ rollup,
270
+ inbox,
300
271
  { ...config.l1Contracts, slashingProposerAddress },
301
272
  archiverStore,
302
273
  opts,
@@ -333,7 +304,7 @@ export class Archiver
333
304
  const { blocksSynchedTo = l1StartBlock, messagesSynchedTo = l1StartBlock } = await this.store.getSynchPoint();
334
305
  const currentL2Checkpoint = await this.getSynchedCheckpointNumber();
335
306
  this.log.info(
336
- `Starting archiver sync to rollup contract ${this.l1Addresses.rollupAddress.toString()} from L1 block ${blocksSynchedTo} and L2 checkpoint ${currentL2Checkpoint}`,
307
+ `Starting archiver sync to rollup contract ${this.rollup.address} from L1 block ${blocksSynchedTo} and L2 checkpoint ${currentL2Checkpoint}`,
337
308
  { blocksSynchedTo, messagesSynchedTo, currentL2Checkpoint },
338
309
  );
339
310
 
@@ -383,7 +354,7 @@ export class Archiver
383
354
  // Process each block individually to properly resolve/reject each promise
384
355
  for (const { block, resolve, reject } of queuedItems) {
385
356
  try {
386
- await this.store.addBlocks([block]);
357
+ await addBlocksWithContractData(this.store, [block]);
387
358
  this.log.debug(`Added block ${block.number} to store`);
388
359
  resolve();
389
360
  } catch (err: any) {
@@ -519,9 +490,16 @@ export class Archiver
519
490
  this.l1Timestamp = currentL1Timestamp;
520
491
  this.l1BlockNumber = currentL1BlockNumber;
521
492
 
493
+ const l1BlockNumberAtEnd = await this.publicClient.getBlockNumber();
494
+ this.log.trace(`Archiver sync iteration complete`, {
495
+ l1BlockNumberAtStart: currentL1BlockNumber,
496
+ l1TimestampAtStart: currentL1Timestamp,
497
+ l1BlockNumberAtEnd,
498
+ });
499
+
522
500
  // We resolve the initial sync only once we've caught up with the latest L1 block number (with 1 block grace)
523
501
  // so if the initial sync took too long, we still go for another iteration.
524
- if (!this.initialSyncComplete && currentL1BlockNumber + 1n >= (await this.publicClient.getBlockNumber())) {
502
+ if (!this.initialSyncComplete && currentL1BlockNumber + 1n >= l1BlockNumberAtEnd) {
525
503
  this.log.info(`Initial archiver sync to L1 block ${currentL1BlockNumber} complete`, {
526
504
  l1BlockNumber: currentL1BlockNumber,
527
505
  syncPoint: await this.store.getSynchPoint(),
@@ -596,7 +574,7 @@ export class Archiver
596
574
  const newBlocks = blockPromises.filter(isDefined).flat();
597
575
 
598
576
  // Emit an event for listening services to react to the chain prune
599
- this.emit(L2BlockSourceEvents.L2PruneDetected, {
577
+ this.events.emit(L2BlockSourceEvents.L2PruneDetected, {
600
578
  type: L2BlockSourceEvents.L2PruneDetected,
601
579
  epochNumber: pruneFromEpochNumber,
602
580
  blocks: newBlocks,
@@ -614,7 +592,7 @@ export class Archiver
614
592
  this.instrumentation.processPrune(timer.ms());
615
593
  // TODO(palla/reorg): Do we need to set the block synched L1 block number here?
616
594
  // Seems like the next iteration should handle this.
617
- // await this.store.setBlockSynchedL1BlockNumber(currentL1BlockNumber);
595
+ // await this.store.setCheckpointSynchedL1BlockNumber(currentL1BlockNumber);
618
596
  }
619
597
 
620
598
  return { rollupCanPrune };
@@ -693,7 +671,7 @@ export class Archiver
693
671
  do {
694
672
  [searchStartBlock, searchEndBlock] = this.nextRange(searchEndBlock, currentL1BlockNumber);
695
673
  this.log.trace(`Retrieving L1 to L2 messages between L1 blocks ${searchStartBlock} and ${searchEndBlock}.`);
696
- const messages = await retrieveL1ToL2Messages(this.inbox.getContract(), searchStartBlock, searchEndBlock);
674
+ const messages = await retrieveL1ToL2Messages(this.inbox, searchStartBlock, searchEndBlock);
697
675
  this.log.verbose(
698
676
  `Retrieved ${messages.length} new L1 to L2 messages between L1 blocks ${searchStartBlock} and ${searchEndBlock}.`,
699
677
  );
@@ -733,7 +711,7 @@ export class Archiver
733
711
  do {
734
712
  [searchStartBlock, searchEndBlock] = this.nextRange(searchEndBlock, currentL1BlockNumber);
735
713
 
736
- const message = await retrieveL1ToL2Message(this.inbox.getContract(), leaf, searchStartBlock, searchEndBlock);
714
+ const message = await retrieveL1ToL2Message(this.inbox, leaf, searchStartBlock, searchEndBlock);
737
715
 
738
716
  if (message) {
739
717
  return message;
@@ -866,7 +844,7 @@ export class Archiver
866
844
  localCheckpointForDestinationProvenCheckpointNumber.numBlocks -
867
845
  1;
868
846
 
869
- this.emit(L2BlockSourceEvents.L2BlockProven, {
847
+ this.events.emit(L2BlockSourceEvents.L2BlockProven, {
870
848
  type: L2BlockSourceEvents.L2BlockProven,
871
849
  blockNumber: BlockNumber(lastBlockNumberInCheckpoint),
872
850
  slotNumber: provenSlotNumber,
@@ -910,7 +888,7 @@ export class Archiver
910
888
  // However, in the re-org scenario, our L1 node is temporarily lying to us and we end up potentially missing checkpoints.
911
889
  // We must only set this block number based on actually retrieved logs.
912
890
  // TODO(#8621): Tackle this properly when we handle L1 Re-orgs.
913
- // await this.store.setBlockSynchedL1BlockNumber(currentL1BlockNumber);
891
+ // await this.store.setCheckpointSynchedL1BlockNumber(currentL1BlockNumber);
914
892
  this.log.debug(`No checkpoints to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
915
893
  return rollupStatus;
916
894
  }
@@ -975,7 +953,7 @@ export class Archiver
975
953
  // TODO(md): Retrieve from blob client then from consensus client, then from peers
976
954
  const retrievedCheckpoints = await execInSpan(this.tracer, 'Archiver.retrieveCheckpointsFromRollup', () =>
977
955
  retrieveCheckpointsFromRollup(
978
- this.rollup.getContract() as GetContractReturnType<typeof RollupAbi, ViemPublicClient>,
956
+ this.rollup,
979
957
  this.publicClient,
980
958
  this.debugClient,
981
959
  this.blobClient,
@@ -1034,7 +1012,7 @@ export class Archiver
1034
1012
  });
1035
1013
 
1036
1014
  // Emit event for invalid checkpoint detection
1037
- this.emit(L2BlockSourceEvents.InvalidAttestationsCheckpointDetected, {
1015
+ this.events.emit(L2BlockSourceEvents.InvalidAttestationsCheckpointDetected, {
1038
1016
  type: L2BlockSourceEvents.InvalidAttestationsCheckpointDetected,
1039
1017
  validationResult,
1040
1018
  });
@@ -1095,7 +1073,7 @@ export class Archiver
1095
1073
  ? await this.store.getCheckpointData(CheckpointNumber(previousCheckpointNumber))
1096
1074
  : undefined;
1097
1075
  const updatedL1SyncPoint = previousCheckpoint?.l1.blockNumber ?? this.l1constants.l1StartBlock;
1098
- await this.store.setBlockSynchedL1BlockNumber(updatedL1SyncPoint);
1076
+ await this.store.setCheckpointSynchedL1BlockNumber(updatedL1SyncPoint);
1099
1077
  this.log.warn(
1100
1078
  `Attempting to insert checkpoint ${newCheckpointNumber} with previous block ${previousCheckpointNumber}. Rolling back L1 sync point to ${updatedL1SyncPoint} to try and fetch the missing blocks.`,
1101
1079
  {
@@ -1166,7 +1144,7 @@ export class Archiver
1166
1144
  ...status,
1167
1145
  },
1168
1146
  );
1169
- await this.store.setBlockSynchedL1BlockNumber(targetL1BlockNumber);
1147
+ await this.store.setCheckpointSynchedL1BlockNumber(targetL1BlockNumber);
1170
1148
  } else {
1171
1149
  this.log.trace(`No new checkpoints behind L1 sync point to retrieve.`, {
1172
1150
  latestLocalCheckpointNumber,
@@ -1209,7 +1187,7 @@ export class Archiver
1209
1187
  }
1210
1188
 
1211
1189
  public getRollupAddress(): Promise<EthAddress> {
1212
- return Promise.resolve(this.l1Addresses.rollupAddress);
1190
+ return Promise.resolve(EthAddress.fromString(this.rollup.address));
1213
1191
  }
1214
1192
 
1215
1193
  public getRegistryAddress(): Promise<EthAddress> {
@@ -1349,7 +1327,7 @@ export class Archiver
1349
1327
  }
1350
1328
 
1351
1329
  public unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number): Promise<boolean> {
1352
- return this.store.unwindCheckpoints(from, checkpointsToUnwind);
1330
+ return unwindCheckpointsWithContractData(this.store, from, checkpointsToUnwind);
1353
1331
  }
1354
1332
 
1355
1333
  public async getLastBlockNumberInCheckpoint(checkpointNumber: CheckpointNumber): Promise<BlockNumber | undefined> {
@@ -1364,193 +1342,14 @@ export class Archiver
1364
1342
  checkpoints: PublishedCheckpoint[],
1365
1343
  pendingChainValidationStatus?: ValidateCheckpointResult,
1366
1344
  ): Promise<boolean> {
1367
- return this.store.addCheckpoints(checkpoints, pendingChainValidationStatus);
1368
- }
1369
-
1370
- public getBlockHeaderByHash(blockHash: Fr): Promise<BlockHeader | undefined> {
1371
- return this.store.getBlockHeaderByHash(blockHash);
1372
- }
1373
-
1374
- public getBlockHeaderByArchive(archive: Fr): Promise<BlockHeader | undefined> {
1375
- return this.store.getBlockHeaderByArchive(archive);
1376
- }
1377
-
1378
- /**
1379
- * Gets an l2 block.
1380
- * @param number - The block number to return.
1381
- * @returns The requested L2 block.
1382
- */
1383
- public async getL2BlockNew(number: BlockNumber): Promise<L2BlockNew | undefined> {
1384
- // If the number provided is -ve, then return the latest block.
1385
- if (number < 0) {
1386
- number = await this.store.getSynchedL2BlockNumber();
1387
- }
1388
- if (number === 0) {
1389
- return undefined;
1390
- }
1391
- const publishedBlock = await this.store.store.getBlock(number);
1392
- return publishedBlock;
1393
- }
1394
-
1395
- public async getL2BlocksNew(from: BlockNumber, limit: number, proven?: boolean): Promise<L2BlockNew[]> {
1396
- const blocks = await this.store.store.getBlocks(from, limit);
1397
-
1398
- if (proven === true) {
1399
- const provenBlockNumber = await this.store.getProvenBlockNumber();
1400
- return blocks.filter(b => b.number <= provenBlockNumber);
1401
- }
1402
- return blocks;
1403
- }
1404
-
1405
- public async getBlockHeader(number: BlockNumber | 'latest'): Promise<BlockHeader | undefined> {
1406
- if (number === 'latest') {
1407
- number = await this.store.getSynchedL2BlockNumber();
1408
- }
1409
- if (number === 0) {
1410
- return undefined;
1411
- }
1412
- const headers = await this.store.getBlockHeaders(number, 1);
1413
- return headers.length === 0 ? undefined : headers[0];
1414
- }
1415
-
1416
- getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
1417
- return this.store.getCheckpointedBlock(number);
1418
- }
1419
-
1420
- public async getCheckpointedBlocks(
1421
- from: BlockNumber,
1422
- limit: number,
1423
- proven?: boolean,
1424
- ): Promise<CheckpointedL2Block[]> {
1425
- const blocks = await this.store.store.getCheckpointedBlocks(from, limit);
1426
-
1427
- if (proven === true) {
1428
- const provenBlockNumber = await this.store.getProvenBlockNumber();
1429
- return blocks.filter(b => b.block.number <= provenBlockNumber);
1430
- }
1431
- return blocks;
1432
- }
1433
-
1434
- getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
1435
- return this.store.getCheckpointedBlockByHash(blockHash);
1345
+ return addCheckpointsWithContractData(this.store, checkpoints, pendingChainValidationStatus);
1436
1346
  }
1437
1347
 
1438
- getProvenBlockNumber(): Promise<BlockNumber> {
1439
- return this.store.getProvenBlockNumber();
1440
- }
1441
1348
  getCheckpointedBlockNumber(): Promise<BlockNumber> {
1442
1349
  return this.store.getCheckpointedL2BlockNumber();
1443
1350
  }
1444
- getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
1445
- return this.store.getCheckpointedBlockByArchive(archive);
1446
- }
1447
-
1448
- public getTxEffect(txHash: TxHash) {
1449
- return this.store.getTxEffect(txHash);
1450
- }
1451
-
1452
- public getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
1453
- return this.store.getSettledTxReceipt(txHash);
1454
- }
1455
-
1456
- getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
1457
- return this.store.getPrivateLogsByTags(tags);
1458
- }
1459
-
1460
- getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
1461
- return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
1462
- }
1463
-
1464
- /**
1465
- * Gets public logs based on the provided filter.
1466
- * @param filter - The filter to apply to the logs.
1467
- * @returns The requested logs.
1468
- */
1469
- getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
1470
- return this.store.getPublicLogs(filter);
1471
- }
1472
-
1473
- /**
1474
- * Gets contract class logs based on the provided filter.
1475
- * @param filter - The filter to apply to the logs.
1476
- * @returns The requested logs.
1477
- */
1478
- getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse> {
1479
- return this.store.getContractClassLogs(filter);
1480
- }
1481
-
1482
- /**
1483
- * Gets the number of the latest L2 block processed by the block source implementation.
1484
- * This includes both checkpointed and uncheckpointed blocks.
1485
- * @returns The number of the latest L2 block processed by the block source implementation.
1486
- */
1487
- public getBlockNumber(): Promise<BlockNumber> {
1488
- return this.store.getLatestBlockNumber();
1489
- }
1490
-
1491
- public getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
1492
- return this.store.getContractClass(id);
1493
- }
1494
-
1495
- public getBytecodeCommitment(id: Fr): Promise<Fr | undefined> {
1496
- return this.store.getBytecodeCommitment(id);
1497
- }
1498
-
1499
- public async getContract(
1500
- address: AztecAddress,
1501
- maybeTimestamp?: UInt64,
1502
- ): Promise<ContractInstanceWithAddress | undefined> {
1503
- let timestamp;
1504
- if (maybeTimestamp === undefined) {
1505
- const latestBlockHeader = await this.getBlockHeader('latest');
1506
- // If we get undefined block header, it means that the archiver has not yet synced any block so we default to 0.
1507
- timestamp = latestBlockHeader ? latestBlockHeader.globalVariables.timestamp : 0n;
1508
- } else {
1509
- timestamp = maybeTimestamp;
1510
- }
1511
-
1512
- return this.store.getContractInstance(address, timestamp);
1513
- }
1514
-
1515
- /**
1516
- * Gets L1 to L2 message (to be) included in a given checkpoint.
1517
- * @param checkpointNumber - Checkpoint number to get messages for.
1518
- * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found).
1519
- */
1520
- getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
1521
- return this.store.getL1ToL2Messages(checkpointNumber);
1522
- }
1523
1351
 
1524
- /**
1525
- * Gets the L1 to L2 message index in the L1 to L2 message tree.
1526
- * @param l1ToL2Message - The L1 to L2 message.
1527
- * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found).
1528
- */
1529
- getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
1530
- return this.store.getL1ToL2MessageIndex(l1ToL2Message);
1531
- }
1532
-
1533
- getContractClassIds(): Promise<Fr[]> {
1534
- return this.store.getContractClassIds();
1535
- }
1536
-
1537
- registerContractFunctionSignatures(signatures: string[]): Promise<void> {
1538
- return this.store.registerContractFunctionSignatures(signatures);
1539
- }
1540
-
1541
- getDebugFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
1542
- return this.store.getDebugFunctionName(address, selector);
1543
- }
1544
-
1545
- async getPendingChainValidationStatus(): Promise<ValidateCheckpointResult> {
1546
- return (await this.store.getPendingChainValidationStatus()) ?? { valid: true };
1547
- }
1548
-
1549
- isPendingChainInvalid(): Promise<boolean> {
1550
- return this.getPendingChainValidationStatus().then(status => !status.valid);
1551
- }
1552
-
1553
- async getL2Tips(): Promise<L2Tips> {
1352
+ public async getL2Tips(): Promise<L2Tips> {
1554
1353
  const [latestBlockNumber, provenBlockNumber, checkpointedBlockNumber] = await Promise.all([
1555
1354
  this.getBlockNumber(),
1556
1355
  this.getProvenBlockNumber(),
@@ -1681,11 +1480,11 @@ export class Archiver
1681
1480
  const targetCheckpointNumber = CheckpointNumber.fromBlockNumber(targetL2BlockNumber);
1682
1481
  const targetL1BlockHash = await this.getL1BlockHash(targetL1BlockNumber);
1683
1482
  this.log.info(`Unwinding ${blocksToUnwind} checkpoints from L2 block ${currentL2Block}`);
1684
- await this.store.unwindCheckpoints(CheckpointNumber(currentL2Block), blocksToUnwind);
1483
+ await unwindCheckpointsWithContractData(this.store, CheckpointNumber(currentL2Block), blocksToUnwind);
1685
1484
  this.log.info(`Unwinding L1 to L2 messages to checkpoint ${targetCheckpointNumber}`);
1686
1485
  await this.store.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
1687
1486
  this.log.info(`Setting L1 syncpoints to ${targetL1BlockNumber}`);
1688
- await this.store.setBlockSynchedL1BlockNumber(targetL1BlockNumber);
1487
+ await this.store.setCheckpointSynchedL1BlockNumber(targetL1BlockNumber);
1689
1488
  await this.store.setMessageSynchedL1Block({ l1BlockNumber: targetL1BlockNumber, l1BlockHash: targetL1BlockHash });
1690
1489
  if (targetL2BlockNumber < currentProvenBlock) {
1691
1490
  this.log.info(`Clearing proven L2 block number`);
@@ -1698,35 +1497,6 @@ export class Archiver
1698
1497
  // }
1699
1498
  }
1700
1499
 
1701
- public async getPublishedCheckpoints(
1702
- checkpointNumber: CheckpointNumber,
1703
- limit: number,
1704
- ): Promise<PublishedCheckpoint[]> {
1705
- const checkpoints = await this.store.getRangeOfCheckpoints(checkpointNumber, limit);
1706
- const blocks = (
1707
- await Promise.all(checkpoints.map(ch => this.store.getBlocksForCheckpoint(ch.checkpointNumber)))
1708
- ).filter(isDefined);
1709
-
1710
- const fullCheckpoints: PublishedCheckpoint[] = [];
1711
- for (let i = 0; i < checkpoints.length; i++) {
1712
- const blocksForCheckpoint = blocks[i];
1713
- const checkpoint = checkpoints[i];
1714
- const fullCheckpoint = new Checkpoint(
1715
- checkpoint.archive,
1716
- checkpoint.header,
1717
- blocksForCheckpoint,
1718
- checkpoint.checkpointNumber,
1719
- );
1720
- const publishedCheckpoint = new PublishedCheckpoint(
1721
- fullCheckpoint,
1722
- checkpoint.l1,
1723
- checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
1724
- );
1725
- fullCheckpoints.push(publishedCheckpoint);
1726
- }
1727
- return fullCheckpoints;
1728
- }
1729
-
1730
1500
  public async getCheckpointsForEpoch(epochNumber: EpochNumber): Promise<Checkpoint[]> {
1731
1501
  const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1constants);
1732
1502
  const checkpoints: Checkpoint[] = [];
@@ -1746,520 +1516,4 @@ export class Archiver
1746
1516
 
1747
1517
  return checkpoints.reverse();
1748
1518
  }
1749
-
1750
- /* Legacy APIs */
1751
-
1752
- public async getPublishedBlockByHash(blockHash: Fr): Promise<PublishedL2Block | undefined> {
1753
- const checkpointedBlock = await this.store.getCheckpointedBlockByHash(blockHash);
1754
- return this.buildOldBlockFromCheckpointedBlock(checkpointedBlock);
1755
- }
1756
- public async getPublishedBlockByArchive(archive: Fr): Promise<PublishedL2Block | undefined> {
1757
- const checkpointedBlock = await this.store.getCheckpointedBlockByArchive(archive);
1758
- return this.buildOldBlockFromCheckpointedBlock(checkpointedBlock);
1759
- }
1760
-
1761
- /**
1762
- * Gets up to `limit` amount of L2 blocks starting from `from`.
1763
- * @param from - Number of the first block to return (inclusive).
1764
- * @param limit - The number of blocks to return.
1765
- * @param proven - If true, only return blocks that have been proven.
1766
- * @returns The requested L2 blocks.
1767
- */
1768
- public async getBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<L2Block[]> {
1769
- const publishedBlocks = await this.getPublishedBlocks(from, limit, proven);
1770
- return publishedBlocks.map(x => x.block);
1771
- }
1772
-
1773
- public async getPublishedBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<PublishedL2Block[]> {
1774
- const checkpoints = await this.store.getRangeOfCheckpoints(CheckpointNumber(from), limit);
1775
- const provenCheckpointNumber = await this.getProvenCheckpointNumber();
1776
- const blocks = (
1777
- await Promise.all(checkpoints.map(ch => this.store.getBlocksForCheckpoint(ch.checkpointNumber)))
1778
- ).filter(isDefined);
1779
-
1780
- const olbBlocks: PublishedL2Block[] = [];
1781
- for (let i = 0; i < checkpoints.length; i++) {
1782
- const blockForCheckpoint = blocks[i][0];
1783
- const checkpoint = checkpoints[i];
1784
- if (checkpoint.checkpointNumber > provenCheckpointNumber && proven === true) {
1785
- // this checkpointisn't proven and we only want proven
1786
- continue;
1787
- }
1788
- const oldCheckpoint = new Checkpoint(
1789
- blockForCheckpoint.archive,
1790
- checkpoint.header,
1791
- [blockForCheckpoint],
1792
- checkpoint.checkpointNumber,
1793
- );
1794
- const oldBlock = L2Block.fromCheckpoint(oldCheckpoint);
1795
- const publishedBlock = new PublishedL2Block(
1796
- oldBlock,
1797
- checkpoint.l1,
1798
- checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
1799
- );
1800
- olbBlocks.push(publishedBlock);
1801
- }
1802
- return olbBlocks;
1803
- }
1804
-
1805
- private async buildOldBlockFromCheckpointedBlock(
1806
- checkpointedBlock: CheckpointedL2Block | undefined,
1807
- ): Promise<PublishedL2Block | undefined> {
1808
- if (!checkpointedBlock) {
1809
- return undefined;
1810
- }
1811
- const checkpoint = await this.store.getCheckpointData(checkpointedBlock.checkpointNumber);
1812
- if (!checkpoint) {
1813
- return checkpoint;
1814
- }
1815
- const fullCheckpoint = new Checkpoint(
1816
- checkpointedBlock?.block.archive,
1817
- checkpoint?.header,
1818
- [checkpointedBlock.block],
1819
- checkpoint.checkpointNumber,
1820
- );
1821
- const oldBlock = L2Block.fromCheckpoint(fullCheckpoint);
1822
- const published = new PublishedL2Block(
1823
- oldBlock,
1824
- checkpoint.l1,
1825
- checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
1826
- );
1827
- return published;
1828
- }
1829
-
1830
- public async getBlock(number: BlockNumber): Promise<L2Block | undefined> {
1831
- // If the number provided is -ve, then return the latest block.
1832
- if (number < 0) {
1833
- number = await this.store.getSynchedL2BlockNumber();
1834
- }
1835
- if (number === 0) {
1836
- return undefined;
1837
- }
1838
- const publishedBlocks = await this.getPublishedBlocks(number, 1);
1839
- if (publishedBlocks.length === 0) {
1840
- return undefined;
1841
- }
1842
- return publishedBlocks[0].block;
1843
- }
1844
- }
1845
-
1846
- enum Operation {
1847
- Store,
1848
- Delete,
1849
- }
1850
-
1851
- /**
1852
- * A helper class that we use to deal with some of the logic needed when adding blocks.
1853
- *
1854
- * I would have preferred to not have this type. But it is useful for handling the logic that any
1855
- * store would need to include otherwise while exposing fewer functions and logic directly to the archiver.
1856
- */
1857
- export class ArchiverStoreHelper
1858
- implements
1859
- Omit<
1860
- ArchiverDataStore,
1861
- | 'addLogs'
1862
- | 'deleteLogs'
1863
- | 'addContractClasses'
1864
- | 'deleteContractClasses'
1865
- | 'addContractInstances'
1866
- | 'deleteContractInstances'
1867
- | 'addContractInstanceUpdates'
1868
- | 'deleteContractInstanceUpdates'
1869
- | 'addFunctions'
1870
- | 'backupTo'
1871
- | 'close'
1872
- | 'transactionAsync'
1873
- | 'addBlocks'
1874
- | 'getBlock'
1875
- | 'getBlocks'
1876
- | 'getCheckpointedBlocks'
1877
- >
1878
- {
1879
- #log = createLogger('archiver:block-helper');
1880
-
1881
- constructor(public readonly store: ArchiverDataStore) {}
1882
-
1883
- /**
1884
- * Extracts and stores contract classes out of ContractClassPublished events emitted by the class registry contract.
1885
- * @param allLogs - All logs emitted in a bunch of blocks.
1886
- */
1887
- async #updatePublishedContractClasses(allLogs: ContractClassLog[], blockNum: BlockNumber, operation: Operation) {
1888
- const contractClassPublishedEvents = allLogs
1889
- .filter(log => ContractClassPublishedEvent.isContractClassPublishedEvent(log))
1890
- .map(log => ContractClassPublishedEvent.fromLog(log));
1891
-
1892
- const contractClasses = await Promise.all(contractClassPublishedEvents.map(e => e.toContractClassPublic()));
1893
- if (contractClasses.length > 0) {
1894
- contractClasses.forEach(c => this.#log.verbose(`${Operation[operation]} contract class ${c.id.toString()}`));
1895
- if (operation == Operation.Store) {
1896
- // TODO: Will probably want to create some worker threads to compute these bytecode commitments as they are expensive
1897
- const commitments = await Promise.all(
1898
- contractClasses.map(c => computePublicBytecodeCommitment(c.packedBytecode)),
1899
- );
1900
- return await this.store.addContractClasses(contractClasses, commitments, blockNum);
1901
- } else if (operation == Operation.Delete) {
1902
- return await this.store.deleteContractClasses(contractClasses, blockNum);
1903
- }
1904
- }
1905
- return true;
1906
- }
1907
-
1908
- /**
1909
- * Extracts and stores contract instances out of ContractInstancePublished events emitted by the canonical deployer contract.
1910
- * @param allLogs - All logs emitted in a bunch of blocks.
1911
- */
1912
- async #updateDeployedContractInstances(allLogs: PrivateLog[], blockNum: BlockNumber, operation: Operation) {
1913
- const contractInstances = allLogs
1914
- .filter(log => ContractInstancePublishedEvent.isContractInstancePublishedEvent(log))
1915
- .map(log => ContractInstancePublishedEvent.fromLog(log))
1916
- .map(e => e.toContractInstance());
1917
- if (contractInstances.length > 0) {
1918
- contractInstances.forEach(c =>
1919
- this.#log.verbose(`${Operation[operation]} contract instance at ${c.address.toString()}`),
1920
- );
1921
- if (operation == Operation.Store) {
1922
- return await this.store.addContractInstances(contractInstances, blockNum);
1923
- } else if (operation == Operation.Delete) {
1924
- return await this.store.deleteContractInstances(contractInstances, blockNum);
1925
- }
1926
- }
1927
- return true;
1928
- }
1929
-
1930
- /**
1931
- * Extracts and stores contract instances out of ContractInstancePublished events emitted by the canonical deployer contract.
1932
- * @param allLogs - All logs emitted in a bunch of blocks.
1933
- * @param timestamp - Timestamp at which the updates were scheduled.
1934
- * @param operation - The operation to perform on the contract instance updates (Store or Delete).
1935
- */
1936
- async #updateUpdatedContractInstances(allLogs: PublicLog[], timestamp: UInt64, operation: Operation) {
1937
- const contractUpdates = allLogs
1938
- .filter(log => ContractInstanceUpdatedEvent.isContractInstanceUpdatedEvent(log))
1939
- .map(log => ContractInstanceUpdatedEvent.fromLog(log))
1940
- .map(e => e.toContractInstanceUpdate());
1941
-
1942
- if (contractUpdates.length > 0) {
1943
- contractUpdates.forEach(c =>
1944
- this.#log.verbose(`${Operation[operation]} contract instance update at ${c.address.toString()}`),
1945
- );
1946
- if (operation == Operation.Store) {
1947
- return await this.store.addContractInstanceUpdates(contractUpdates, timestamp);
1948
- } else if (operation == Operation.Delete) {
1949
- return await this.store.deleteContractInstanceUpdates(contractUpdates, timestamp);
1950
- }
1951
- }
1952
- return true;
1953
- }
1954
-
1955
- /**
1956
- * Stores the functions that were broadcasted individually
1957
- *
1958
- * @dev Beware that there is not a delete variant of this, since they are added to contract classes
1959
- * and will be deleted as part of the class if needed.
1960
- *
1961
- * @param allLogs - The logs from the block
1962
- * @param _blockNum - The block number
1963
- * @returns
1964
- */
1965
- async #storeBroadcastedIndividualFunctions(allLogs: ContractClassLog[], _blockNum: BlockNumber) {
1966
- // Filter out private and utility function broadcast events
1967
- const privateFnEvents = allLogs
1968
- .filter(log => PrivateFunctionBroadcastedEvent.isPrivateFunctionBroadcastedEvent(log))
1969
- .map(log => PrivateFunctionBroadcastedEvent.fromLog(log));
1970
- const utilityFnEvents = allLogs
1971
- .filter(log => UtilityFunctionBroadcastedEvent.isUtilityFunctionBroadcastedEvent(log))
1972
- .map(log => UtilityFunctionBroadcastedEvent.fromLog(log));
1973
-
1974
- // Group all events by contract class id
1975
- for (const [classIdString, classEvents] of Object.entries(
1976
- groupBy([...privateFnEvents, ...utilityFnEvents], e => e.contractClassId.toString()),
1977
- )) {
1978
- const contractClassId = Fr.fromHexString(classIdString);
1979
- const contractClass = await this.getContractClass(contractClassId);
1980
- if (!contractClass) {
1981
- this.#log.warn(`Skipping broadcasted functions as contract class ${contractClassId.toString()} was not found`);
1982
- continue;
1983
- }
1984
-
1985
- // Split private and utility functions, and filter out invalid ones
1986
- const allFns = classEvents.map(e => e.toFunctionWithMembershipProof());
1987
- const privateFns = allFns.filter(
1988
- (fn): fn is ExecutablePrivateFunctionWithMembershipProof => 'utilityFunctionsTreeRoot' in fn,
1989
- );
1990
- const utilityFns = allFns.filter(
1991
- (fn): fn is UtilityFunctionWithMembershipProof => 'privateFunctionsArtifactTreeRoot' in fn,
1992
- );
1993
-
1994
- const privateFunctionsWithValidity = await Promise.all(
1995
- privateFns.map(async fn => ({ fn, valid: await isValidPrivateFunctionMembershipProof(fn, contractClass) })),
1996
- );
1997
- const validPrivateFns = privateFunctionsWithValidity.filter(({ valid }) => valid).map(({ fn }) => fn);
1998
- const utilityFunctionsWithValidity = await Promise.all(
1999
- utilityFns.map(async fn => ({
2000
- fn,
2001
- valid: await isValidUtilityFunctionMembershipProof(fn, contractClass),
2002
- })),
2003
- );
2004
- const validUtilityFns = utilityFunctionsWithValidity.filter(({ valid }) => valid).map(({ fn }) => fn);
2005
- const validFnCount = validPrivateFns.length + validUtilityFns.length;
2006
- if (validFnCount !== allFns.length) {
2007
- this.#log.warn(`Skipping ${allFns.length - validFnCount} invalid functions`);
2008
- }
2009
-
2010
- // Store the functions in the contract class in a single operation
2011
- if (validFnCount > 0) {
2012
- this.#log.verbose(`Storing ${validFnCount} functions for contract class ${contractClassId.toString()}`);
2013
- }
2014
- return await this.store.addFunctions(contractClassId, validPrivateFns, validUtilityFns);
2015
- }
2016
- return true;
2017
- }
2018
-
2019
- private async addBlockDataToDB(block: L2BlockNew) {
2020
- const contractClassLogs = block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
2021
- // ContractInstancePublished event logs are broadcast in privateLogs.
2022
- const privateLogs = block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
2023
- const publicLogs = block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
2024
-
2025
- return (
2026
- await Promise.all([
2027
- this.#updatePublishedContractClasses(contractClassLogs, block.number, Operation.Store),
2028
- this.#updateDeployedContractInstances(privateLogs, block.number, Operation.Store),
2029
- this.#updateUpdatedContractInstances(publicLogs, block.header.globalVariables.timestamp, Operation.Store),
2030
- this.#storeBroadcastedIndividualFunctions(contractClassLogs, block.number),
2031
- ])
2032
- ).every(Boolean);
2033
- }
2034
-
2035
- public addBlocks(blocks: L2BlockNew[], pendingChainValidationStatus?: ValidateCheckpointResult): Promise<boolean> {
2036
- // Add the blocks to the store. Store will throw if the blocks are not in order, there are gaps,
2037
- // or if the previous block is not in the store.
2038
- return this.store.transactionAsync(async () => {
2039
- await this.store.addBlocks(blocks);
2040
-
2041
- const opResults = await Promise.all([
2042
- // Update the pending chain validation status if provided
2043
- pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
2044
- // Add any logs emitted during the retrieved blocks
2045
- this.store.addLogs(blocks),
2046
- // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
2047
- ...blocks.map(block => {
2048
- return this.addBlockDataToDB(block);
2049
- }),
2050
- ]);
2051
-
2052
- return opResults.every(Boolean);
2053
- });
2054
- }
2055
-
2056
- public addCheckpoints(
2057
- checkpoints: PublishedCheckpoint[],
2058
- pendingChainValidationStatus?: ValidateCheckpointResult,
2059
- ): Promise<boolean> {
2060
- // Add the blocks to the store. Store will throw if the blocks are not in order, there are gaps,
2061
- // or if the previous block is not in the store.
2062
- return this.store.transactionAsync(async () => {
2063
- await this.store.addCheckpoints(checkpoints);
2064
- const allBlocks = checkpoints.flatMap((ch: PublishedCheckpoint) => ch.checkpoint.blocks);
2065
-
2066
- const opResults = await Promise.all([
2067
- // Update the pending chain validation status if provided
2068
- pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
2069
- // Add any logs emitted during the retrieved blocks
2070
- this.store.addLogs(allBlocks),
2071
- // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
2072
- ...allBlocks.map(block => {
2073
- return this.addBlockDataToDB(block);
2074
- }),
2075
- ]);
2076
-
2077
- return opResults.every(Boolean);
2078
- });
2079
- }
2080
-
2081
- public async unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number): Promise<boolean> {
2082
- if (checkpointsToUnwind <= 0) {
2083
- throw new Error(`Cannot unwind ${checkpointsToUnwind} blocks`);
2084
- }
2085
-
2086
- const last = await this.getSynchedCheckpointNumber();
2087
- if (from != last) {
2088
- throw new Error(`Cannot unwind checkpoints from checkpoint ${from} when the last checkpoint is ${last}`);
2089
- }
2090
-
2091
- const blocks = [];
2092
- const lastCheckpointNumber = from + checkpointsToUnwind - 1;
2093
- for (let checkpointNumber = from; checkpointNumber <= lastCheckpointNumber; checkpointNumber++) {
2094
- const blocksForCheckpoint = await this.store.getBlocksForCheckpoint(checkpointNumber);
2095
- if (!blocksForCheckpoint) {
2096
- continue;
2097
- }
2098
- blocks.push(...blocksForCheckpoint);
2099
- }
2100
-
2101
- const opResults = await Promise.all([
2102
- // Prune rolls back to the last proven block, which is by definition valid
2103
- this.store.setPendingChainValidationStatus({ valid: true }),
2104
- // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
2105
- ...blocks.map(async block => {
2106
- const contractClassLogs = block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
2107
- // ContractInstancePublished event logs are broadcast in privateLogs.
2108
- const privateLogs = block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
2109
- const publicLogs = block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
2110
-
2111
- return (
2112
- await Promise.all([
2113
- this.#updatePublishedContractClasses(contractClassLogs, block.number, Operation.Delete),
2114
- this.#updateDeployedContractInstances(privateLogs, block.number, Operation.Delete),
2115
- this.#updateUpdatedContractInstances(publicLogs, block.header.globalVariables.timestamp, Operation.Delete),
2116
- ])
2117
- ).every(Boolean);
2118
- }),
2119
-
2120
- this.store.deleteLogs(blocks),
2121
- this.store.unwindCheckpoints(from, checkpointsToUnwind),
2122
- ]);
2123
-
2124
- return opResults.every(Boolean);
2125
- }
2126
-
2127
- getCheckpointData(checkpointNumber: CheckpointNumber): Promise<CheckpointData | undefined> {
2128
- return this.store.getCheckpointData(checkpointNumber);
2129
- }
2130
-
2131
- getRangeOfCheckpoints(from: CheckpointNumber, limit: number): Promise<CheckpointData[]> {
2132
- return this.store.getRangeOfCheckpoints(from, limit);
2133
- }
2134
-
2135
- getCheckpointedL2BlockNumber(): Promise<BlockNumber> {
2136
- return this.store.getCheckpointedL2BlockNumber();
2137
- }
2138
- getSynchedCheckpointNumber(): Promise<CheckpointNumber> {
2139
- return this.store.getSynchedCheckpointNumber();
2140
- }
2141
- setCheckpointSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
2142
- return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
2143
- }
2144
- getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
2145
- return this.store.getCheckpointedBlock(number);
2146
- }
2147
- getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
2148
- return this.store.getCheckpointedBlockByHash(blockHash);
2149
- }
2150
- getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
2151
- return this.store.getCheckpointedBlockByArchive(archive);
2152
- }
2153
- getBlockHeaders(from: BlockNumber, limit: number): Promise<BlockHeader[]> {
2154
- return this.store.getBlockHeaders(from, limit);
2155
- }
2156
- getBlockHeaderByHash(blockHash: Fr): Promise<BlockHeader | undefined> {
2157
- return this.store.getBlockHeaderByHash(blockHash);
2158
- }
2159
- getBlockHeaderByArchive(archive: Fr): Promise<BlockHeader | undefined> {
2160
- return this.store.getBlockHeaderByArchive(archive);
2161
- }
2162
- getBlockByHash(blockHash: Fr): Promise<L2BlockNew | undefined> {
2163
- return this.store.getBlockByHash(blockHash);
2164
- }
2165
- getBlockByArchive(archive: Fr): Promise<L2BlockNew | undefined> {
2166
- return this.store.getBlockByArchive(archive);
2167
- }
2168
- getLatestBlockNumber(): Promise<BlockNumber> {
2169
- return this.store.getLatestBlockNumber();
2170
- }
2171
- getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2BlockNew[] | undefined> {
2172
- return this.store.getBlocksForCheckpoint(checkpointNumber);
2173
- }
2174
- getTxEffect(txHash: TxHash): Promise<IndexedTxEffect | undefined> {
2175
- return this.store.getTxEffect(txHash);
2176
- }
2177
- getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
2178
- return this.store.getSettledTxReceipt(txHash);
2179
- }
2180
- addL1ToL2Messages(messages: InboxMessage[]): Promise<void> {
2181
- return this.store.addL1ToL2Messages(messages);
2182
- }
2183
- getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
2184
- return this.store.getL1ToL2Messages(checkpointNumber);
2185
- }
2186
- getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
2187
- return this.store.getL1ToL2MessageIndex(l1ToL2Message);
2188
- }
2189
- getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
2190
- return this.store.getPrivateLogsByTags(tags);
2191
- }
2192
- getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
2193
- return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
2194
- }
2195
- getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
2196
- return this.store.getPublicLogs(filter);
2197
- }
2198
- getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse> {
2199
- return this.store.getContractClassLogs(filter);
2200
- }
2201
- getSynchedL2BlockNumber(): Promise<BlockNumber> {
2202
- return this.store.getLatestBlockNumber();
2203
- }
2204
- getProvenCheckpointNumber(): Promise<CheckpointNumber> {
2205
- return this.store.getProvenCheckpointNumber();
2206
- }
2207
- getProvenBlockNumber(): Promise<BlockNumber> {
2208
- return this.store.getProvenBlockNumber();
2209
- }
2210
- setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
2211
- return this.store.setProvenCheckpointNumber(checkpointNumber);
2212
- }
2213
- setBlockSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
2214
- return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
2215
- }
2216
- setMessageSynchedL1Block(l1Block: L1BlockId): Promise<void> {
2217
- return this.store.setMessageSynchedL1Block(l1Block);
2218
- }
2219
- getSynchPoint(): Promise<ArchiverL1SynchPoint> {
2220
- return this.store.getSynchPoint();
2221
- }
2222
- getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
2223
- return this.store.getContractClass(id);
2224
- }
2225
- getBytecodeCommitment(contractClassId: Fr): Promise<Fr | undefined> {
2226
- return this.store.getBytecodeCommitment(contractClassId);
2227
- }
2228
- getContractInstance(address: AztecAddress, timestamp: UInt64): Promise<ContractInstanceWithAddress | undefined> {
2229
- return this.store.getContractInstance(address, timestamp);
2230
- }
2231
- getContractClassIds(): Promise<Fr[]> {
2232
- return this.store.getContractClassIds();
2233
- }
2234
- registerContractFunctionSignatures(signatures: string[]): Promise<void> {
2235
- return this.store.registerContractFunctionSignatures(signatures);
2236
- }
2237
- getDebugFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
2238
- return this.store.getDebugFunctionName(address, selector);
2239
- }
2240
- getTotalL1ToL2MessageCount(): Promise<bigint> {
2241
- return this.store.getTotalL1ToL2MessageCount();
2242
- }
2243
- estimateSize(): Promise<{ mappingSize: number; physicalFileSize: number; actualSize: number; numItems: number }> {
2244
- return this.store.estimateSize();
2245
- }
2246
- rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber: CheckpointNumber): Promise<void> {
2247
- return this.store.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
2248
- }
2249
- iterateL1ToL2Messages(range: CustomRange<bigint> = {}): AsyncIterableIterator<InboxMessage> {
2250
- return this.store.iterateL1ToL2Messages(range);
2251
- }
2252
- removeL1ToL2Messages(startIndex: bigint): Promise<void> {
2253
- return this.store.removeL1ToL2Messages(startIndex);
2254
- }
2255
- getLastL1ToL2Message(): Promise<InboxMessage | undefined> {
2256
- return this.store.getLastL1ToL2Message();
2257
- }
2258
- getPendingChainValidationStatus(): Promise<ValidateCheckpointResult | undefined> {
2259
- return this.store.getPendingChainValidationStatus();
2260
- }
2261
- setPendingChainValidationStatus(status: ValidateCheckpointResult | undefined): Promise<void> {
2262
- this.#log.debug(`Setting pending chain validation status to valid ${status?.valid}`, status);
2263
- return this.store.setPendingChainValidationStatus(status);
2264
- }
2265
1519
  }