@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
@@ -380,23 +380,21 @@ import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
380
380
  import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
381
381
  import { merge, pick } from '@aztec/foundation/collection';
382
382
  import { Fr } from '@aztec/foundation/curves/bn254';
383
+ import { EthAddress } from '@aztec/foundation/eth-address';
383
384
  import { createLogger } from '@aztec/foundation/log';
384
385
  import { promiseWithResolvers } from '@aztec/foundation/promise';
385
386
  import { RunningPromise, makeLoggingErrorHandler } from '@aztec/foundation/running-promise';
386
387
  import { count } from '@aztec/foundation/string';
387
388
  import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
388
389
  import { isDefined } from '@aztec/foundation/types';
389
- import { ContractClassPublishedEvent, PrivateFunctionBroadcastedEvent, UtilityFunctionBroadcastedEvent } from '@aztec/protocol-contracts/class-registry';
390
- import { ContractInstancePublishedEvent, ContractInstanceUpdatedEvent } from '@aztec/protocol-contracts/instance-registry';
391
- import { CommitteeAttestation, GENESIS_CHECKPOINT_HEADER_HASH, L2Block, L2BlockSourceEvents, PublishedL2Block } from '@aztec/stdlib/block';
392
- import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
393
- import { computePublicBytecodeCommitment, isValidPrivateFunctionMembershipProof, isValidUtilityFunctionMembershipProof } from '@aztec/stdlib/contract';
390
+ import { GENESIS_CHECKPOINT_HEADER_HASH, L2BlockSourceEvents } from '@aztec/stdlib/block';
394
391
  import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
395
392
  import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
396
393
  import { execInSpan, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
397
394
  import { EventEmitter } from 'events';
398
- import groupBy from 'lodash.groupby';
399
395
  import { createPublicClient, fallback, http } from 'viem';
396
+ import { ArchiveSourceBase } from './archive_source_base.js';
397
+ import { addBlocksWithContractData, addCheckpointsWithContractData, unwindCheckpointsWithContractData } from './archiver_store_updates.js';
400
398
  import { InitialCheckpointNumberNotSequentialError, NoBlobBodiesFoundError } from './errors.js';
401
399
  import { ArchiverInstrumentation } from './instrumentation.js';
402
400
  import { retrieveCheckpointsFromRollup, retrieveL1ToL2Message, retrieveL1ToL2Messages, retrievedToPublishedCheckpoint } from './l1/data_retrieval.js';
@@ -416,9 +414,11 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
416
414
  * Pulls checkpoints in a non-blocking manner and provides interface for their retrieval.
417
415
  * Responsible for handling robust L1 polling so that other components do not need to
418
416
  * concern themselves with it.
419
- */ export class Archiver extends EventEmitter {
417
+ */ export class Archiver extends ArchiveSourceBase {
420
418
  publicClient;
421
419
  debugClient;
420
+ rollup;
421
+ inbox;
422
422
  l1Addresses;
423
423
  dataStore;
424
424
  config;
@@ -457,10 +457,8 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
457
457
  ]
458
458
  ], []));
459
459
  }
460
+ /** Event emitter for archiver events (L2BlockProven, L2PruneDetected, etc). */ events;
460
461
  /** A loop in which we will be continually fetching new checkpoints. */ runningPromise;
461
- rollup;
462
- inbox;
463
- store;
464
462
  l1BlockNumber;
465
463
  l1Timestamp;
466
464
  initialSyncComplete;
@@ -471,18 +469,20 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
471
469
  * Creates a new instance of the Archiver.
472
470
  * @param publicClient - A client for interacting with the Ethereum node.
473
471
  * @param debugClient - A client for interacting with the Ethereum node for debug/trace methods.
474
- * @param rollupAddress - Ethereum address of the rollup contract.
475
- * @param inboxAddress - Ethereum address of the inbox contract.
476
- * @param registryAddress - Ethereum address of the registry contract.
477
- * @param pollingIntervalMs - The interval for polling for L1 logs (in milliseconds).
478
- * @param store - An archiver data store for storage & retrieval of blocks, encrypted logs & contract data.
472
+ * @param rollup - Rollup contract instance.
473
+ * @param inbox - Inbox contract instance.
474
+ * @param l1Addresses - L1 contract addresses (registry, governance proposer, slash factory, slashing proposer).
475
+ * @param dataStore - An archiver data store for storage & retrieval of blocks, encrypted logs & contract data.
476
+ * @param config - Archiver configuration options.
477
+ * @param blobClient - Client for retrieving blob data.
478
+ * @param epochCache - Cache for epoch-related data.
479
+ * @param dateProvider - Provider for current date/time.
480
+ * @param instrumentation - Instrumentation for metrics and tracing.
481
+ * @param l1constants - L1 rollup constants.
479
482
  * @param log - A logger.
480
- */ constructor(publicClient, debugClient, l1Addresses, dataStore, config, blobClient, epochCache, dateProvider, instrumentation, l1constants, log = createLogger('archiver')){
481
- super(), this.publicClient = publicClient, this.debugClient = debugClient, this.l1Addresses = l1Addresses, this.dataStore = dataStore, this.config = config, this.blobClient = blobClient, this.epochCache = epochCache, this.dateProvider = dateProvider, this.instrumentation = instrumentation, this.l1constants = l1constants, this.log = log, this.initialSyncComplete = (_initProto(this), false), this.blockQueue = [];
483
+ */ constructor(publicClient, debugClient, rollup, inbox, l1Addresses, dataStore, config, blobClient, epochCache, dateProvider, instrumentation, l1constants, log = createLogger('archiver')){
484
+ super(dataStore), this.publicClient = publicClient, this.debugClient = debugClient, this.rollup = rollup, this.inbox = inbox, this.l1Addresses = l1Addresses, this.dataStore = dataStore, this.config = config, this.blobClient = blobClient, this.epochCache = epochCache, this.dateProvider = dateProvider, this.instrumentation = instrumentation, this.l1constants = l1constants, this.log = log, this.events = (_initProto(this), new EventEmitter()), this.initialSyncComplete = false, this.blockQueue = [];
482
485
  this.tracer = instrumentation.tracer;
483
- this.store = new ArchiverStoreHelper(dataStore);
484
- this.rollup = new RollupContract(publicClient, l1Addresses.rollupAddress);
485
- this.inbox = new InboxContract(publicClient, l1Addresses.inboxAddress);
486
486
  this.initialSyncPromise = promiseWithResolvers();
487
487
  // Running promise starts with a small interval inbetween runs, so all iterations needed for the initial sync
488
488
  // are done as fast as possible. This then gets updated once the initial sync completes.
@@ -513,6 +513,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
513
513
  pollingInterval: config.viemPollingIntervalMS
514
514
  });
515
515
  const rollup = new RollupContract(publicClient, config.l1Contracts.rollupAddress);
516
+ const inbox = new InboxContract(publicClient, config.l1Contracts.inboxAddress);
516
517
  const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, genesisArchiveRoot, slashingProposerAddress] = await Promise.all([
517
518
  rollup.getL1StartBlock(),
518
519
  rollup.getL1GenesisTime(),
@@ -543,7 +544,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
543
544
  }, mapArchiverConfig(config));
544
545
  const epochCache = deps.epochCache ?? await EpochCache.create(config.l1Contracts.rollupAddress, config, deps);
545
546
  const telemetry = deps.telemetry ?? getTelemetryClient();
546
- const archiver = new Archiver(publicClient, debugClient, {
547
+ const archiver = new Archiver(publicClient, debugClient, rollup, inbox, {
547
548
  ...config.l1Contracts,
548
549
  slashingProposerAddress
549
550
  }, archiverStore, opts, deps.blobClient, epochCache, deps.dateProvider ?? new DateProvider(), await ArchiverInstrumentation.new(telemetry, ()=>archiverStore.estimateSize()), l1Constants);
@@ -567,7 +568,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
567
568
  const { l1StartBlock } = this.l1constants;
568
569
  const { blocksSynchedTo = l1StartBlock, messagesSynchedTo = l1StartBlock } = await this.store.getSynchPoint();
569
570
  const currentL2Checkpoint = await this.getSynchedCheckpointNumber();
570
- this.log.info(`Starting archiver sync to rollup contract ${this.l1Addresses.rollupAddress.toString()} from L1 block ${blocksSynchedTo} and L2 checkpoint ${currentL2Checkpoint}`, {
571
+ this.log.info(`Starting archiver sync to rollup contract ${this.rollup.address} from L1 block ${blocksSynchedTo} and L2 checkpoint ${currentL2Checkpoint}`, {
571
572
  blocksSynchedTo,
572
573
  messagesSynchedTo,
573
574
  currentL2Checkpoint
@@ -615,7 +616,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
615
616
  // Process each block individually to properly resolve/reject each promise
616
617
  for (const { block, resolve, reject } of queuedItems){
617
618
  try {
618
- await this.store.addBlocks([
619
+ await addBlocksWithContractData(this.store, [
619
620
  block
620
621
  ]);
621
622
  this.log.debug(`Added block ${block.number} to store`);
@@ -732,9 +733,15 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
732
733
  // but the corresponding blocks have not been processed (see #12631).
733
734
  this.l1Timestamp = currentL1Timestamp;
734
735
  this.l1BlockNumber = currentL1BlockNumber;
736
+ const l1BlockNumberAtEnd = await this.publicClient.getBlockNumber();
737
+ this.log.trace(`Archiver sync iteration complete`, {
738
+ l1BlockNumberAtStart: currentL1BlockNumber,
739
+ l1TimestampAtStart: currentL1Timestamp,
740
+ l1BlockNumberAtEnd
741
+ });
735
742
  // We resolve the initial sync only once we've caught up with the latest L1 block number (with 1 block grace)
736
743
  // so if the initial sync took too long, we still go for another iteration.
737
- if (!this.initialSyncComplete && currentL1BlockNumber + 1n >= await this.publicClient.getBlockNumber()) {
744
+ if (!this.initialSyncComplete && currentL1BlockNumber + 1n >= l1BlockNumberAtEnd) {
738
745
  this.log.info(`Initial archiver sync to L1 block ${currentL1BlockNumber} complete`, {
739
746
  l1BlockNumber: currentL1BlockNumber,
740
747
  syncPoint: await this.store.getSynchPoint(),
@@ -788,7 +795,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
788
795
  const blockPromises = await Promise.all(checkpoints.filter(isDefined).map((cp)=>this.store.getBlocksForCheckpoint(CheckpointNumber(cp.checkpointNumber))));
789
796
  const newBlocks = blockPromises.filter(isDefined).flat();
790
797
  // Emit an event for listening services to react to the chain prune
791
- this.emit(L2BlockSourceEvents.L2PruneDetected, {
798
+ this.events.emit(L2BlockSourceEvents.L2PruneDetected, {
792
799
  type: L2BlockSourceEvents.L2PruneDetected,
793
800
  epochNumber: pruneFromEpochNumber,
794
801
  blocks: newBlocks
@@ -799,7 +806,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
799
806
  this.instrumentation.processPrune(timer.ms());
800
807
  // TODO(palla/reorg): Do we need to set the block synched L1 block number here?
801
808
  // Seems like the next iteration should handle this.
802
- // await this.store.setBlockSynchedL1BlockNumber(currentL1BlockNumber);
809
+ // await this.store.setCheckpointSynchedL1BlockNumber(currentL1BlockNumber);
803
810
  }
804
811
  return {
805
812
  rollupCanPrune
@@ -870,7 +877,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
870
877
  do {
871
878
  [searchStartBlock, searchEndBlock] = this.nextRange(searchEndBlock, currentL1BlockNumber);
872
879
  this.log.trace(`Retrieving L1 to L2 messages between L1 blocks ${searchStartBlock} and ${searchEndBlock}.`);
873
- const messages = await retrieveL1ToL2Messages(this.inbox.getContract(), searchStartBlock, searchEndBlock);
880
+ const messages = await retrieveL1ToL2Messages(this.inbox, searchStartBlock, searchEndBlock);
874
881
  this.log.verbose(`Retrieved ${messages.length} new L1 to L2 messages between L1 blocks ${searchStartBlock} and ${searchEndBlock}.`);
875
882
  const timer = new Timer();
876
883
  await this.store.addL1ToL2Messages(messages);
@@ -906,7 +913,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
906
913
  let searchEndBlock = this.l1constants.l1StartBlock - 1n;
907
914
  do {
908
915
  [searchStartBlock, searchEndBlock] = this.nextRange(searchEndBlock, currentL1BlockNumber);
909
- const message = await retrieveL1ToL2Message(this.inbox.getContract(), leaf, searchStartBlock, searchEndBlock);
916
+ const message = await retrieveL1ToL2Message(this.inbox, leaf, searchStartBlock, searchEndBlock);
910
917
  if (message) {
911
918
  return message;
912
919
  }
@@ -1015,7 +1022,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1015
1022
  const provenSlotNumber = localCheckpointForDestinationProvenCheckpointNumber.header.slotNumber;
1016
1023
  const provenEpochNumber = getEpochAtSlot(provenSlotNumber, this.l1constants);
1017
1024
  const lastBlockNumberInCheckpoint = localCheckpointForDestinationProvenCheckpointNumber.startBlock + localCheckpointForDestinationProvenCheckpointNumber.numBlocks - 1;
1018
- this.emit(L2BlockSourceEvents.L2BlockProven, {
1025
+ this.events.emit(L2BlockSourceEvents.L2BlockProven, {
1019
1026
  type: L2BlockSourceEvents.L2BlockProven,
1020
1027
  blockNumber: BlockNumber(lastBlockNumberInCheckpoint),
1021
1028
  slotNumber: provenSlotNumber,
@@ -1053,7 +1060,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1053
1060
  // However, in the re-org scenario, our L1 node is temporarily lying to us and we end up potentially missing checkpoints.
1054
1061
  // We must only set this block number based on actually retrieved logs.
1055
1062
  // TODO(#8621): Tackle this properly when we handle L1 Re-orgs.
1056
- // await this.store.setBlockSynchedL1BlockNumber(currentL1BlockNumber);
1063
+ // await this.store.setCheckpointSynchedL1BlockNumber(currentL1BlockNumber);
1057
1064
  this.log.debug(`No checkpoints to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
1058
1065
  return rollupStatus;
1059
1066
  }
@@ -1099,7 +1106,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1099
1106
  [searchStartBlock, searchEndBlock] = this.nextRange(searchEndBlock, currentL1BlockNumber);
1100
1107
  this.log.trace(`Retrieving checkpoints from L1 block ${searchStartBlock} to ${searchEndBlock}`);
1101
1108
  // TODO(md): Retrieve from blob client then from consensus client, then from peers
1102
- const retrievedCheckpoints = await execInSpan(this.tracer, 'Archiver.retrieveCheckpointsFromRollup', ()=>retrieveCheckpointsFromRollup(this.rollup.getContract(), this.publicClient, this.debugClient, this.blobClient, searchStartBlock, searchEndBlock, this.l1Addresses, this.instrumentation, this.log, !this.initialSyncComplete));
1109
+ const retrievedCheckpoints = await execInSpan(this.tracer, 'Archiver.retrieveCheckpointsFromRollup', ()=>retrieveCheckpointsFromRollup(this.rollup, this.publicClient, this.debugClient, this.blobClient, searchStartBlock, searchEndBlock, this.l1Addresses, this.instrumentation, this.log, !this.initialSyncComplete));
1103
1110
  if (retrievedCheckpoints.length === 0) {
1104
1111
  // We are not calling `setBlockSynchedL1BlockNumber` because it may cause sync issues if based off infura.
1105
1112
  // See further details in earlier comments.
@@ -1132,7 +1139,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1132
1139
  ...pick(validationResult, 'reason')
1133
1140
  });
1134
1141
  // Emit event for invalid checkpoint detection
1135
- this.emit(L2BlockSourceEvents.InvalidAttestationsCheckpointDetected, {
1142
+ this.events.emit(L2BlockSourceEvents.InvalidAttestationsCheckpointDetected, {
1136
1143
  type: L2BlockSourceEvents.InvalidAttestationsCheckpointDetected,
1137
1144
  validationResult
1138
1145
  });
@@ -1171,7 +1178,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1171
1178
  const { previousCheckpointNumber, newCheckpointNumber } = err;
1172
1179
  const previousCheckpoint = previousCheckpointNumber ? await this.store.getCheckpointData(CheckpointNumber(previousCheckpointNumber)) : undefined;
1173
1180
  const updatedL1SyncPoint = previousCheckpoint?.l1.blockNumber ?? this.l1constants.l1StartBlock;
1174
- await this.store.setBlockSynchedL1BlockNumber(updatedL1SyncPoint);
1181
+ await this.store.setCheckpointSynchedL1BlockNumber(updatedL1SyncPoint);
1175
1182
  this.log.warn(`Attempting to insert checkpoint ${newCheckpointNumber} with previous block ${previousCheckpointNumber}. Rolling back L1 sync point to ${updatedL1SyncPoint} to try and fetch the missing blocks.`, {
1176
1183
  previousCheckpointNumber,
1177
1184
  newCheckpointNumber,
@@ -1230,7 +1237,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1230
1237
  currentL1BlockNumber,
1231
1238
  ...status
1232
1239
  });
1233
- await this.store.setBlockSynchedL1BlockNumber(targetL1BlockNumber);
1240
+ await this.store.setCheckpointSynchedL1BlockNumber(targetL1BlockNumber);
1234
1241
  } else {
1235
1242
  this.log.trace(`No new checkpoints behind L1 sync point to retrieve.`, {
1236
1243
  latestLocalCheckpointNumber,
@@ -1266,7 +1273,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1266
1273
  });
1267
1274
  }
1268
1275
  getRollupAddress() {
1269
- return Promise.resolve(this.l1Addresses.rollupAddress);
1276
+ return Promise.resolve(EthAddress.fromString(this.rollup.address));
1270
1277
  }
1271
1278
  getRegistryAddress() {
1272
1279
  return Promise.resolve(this.l1Addresses.registryAddress);
@@ -1380,7 +1387,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1380
1387
  return this.store.setProvenCheckpointNumber(checkpointNumber);
1381
1388
  }
1382
1389
  unwindCheckpoints(from, checkpointsToUnwind) {
1383
- return this.store.unwindCheckpoints(from, checkpointsToUnwind);
1390
+ return unwindCheckpointsWithContractData(this.store, from, checkpointsToUnwind);
1384
1391
  }
1385
1392
  async getLastBlockNumberInCheckpoint(checkpointNumber) {
1386
1393
  const checkpointData = await this.store.getCheckpointData(checkpointNumber);
@@ -1390,151 +1397,11 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1390
1397
  return BlockNumber(checkpointData.startBlock + checkpointData.numBlocks - 1);
1391
1398
  }
1392
1399
  addCheckpoints(checkpoints, pendingChainValidationStatus) {
1393
- return this.store.addCheckpoints(checkpoints, pendingChainValidationStatus);
1394
- }
1395
- getBlockHeaderByHash(blockHash) {
1396
- return this.store.getBlockHeaderByHash(blockHash);
1397
- }
1398
- getBlockHeaderByArchive(archive) {
1399
- return this.store.getBlockHeaderByArchive(archive);
1400
- }
1401
- /**
1402
- * Gets an l2 block.
1403
- * @param number - The block number to return.
1404
- * @returns The requested L2 block.
1405
- */ async getL2BlockNew(number) {
1406
- // If the number provided is -ve, then return the latest block.
1407
- if (number < 0) {
1408
- number = await this.store.getSynchedL2BlockNumber();
1409
- }
1410
- if (number === 0) {
1411
- return undefined;
1412
- }
1413
- const publishedBlock = await this.store.store.getBlock(number);
1414
- return publishedBlock;
1415
- }
1416
- async getL2BlocksNew(from, limit, proven) {
1417
- const blocks = await this.store.store.getBlocks(from, limit);
1418
- if (proven === true) {
1419
- const provenBlockNumber = await this.store.getProvenBlockNumber();
1420
- return blocks.filter((b)=>b.number <= provenBlockNumber);
1421
- }
1422
- return blocks;
1423
- }
1424
- async getBlockHeader(number) {
1425
- if (number === 'latest') {
1426
- number = await this.store.getSynchedL2BlockNumber();
1427
- }
1428
- if (number === 0) {
1429
- return undefined;
1430
- }
1431
- const headers = await this.store.getBlockHeaders(number, 1);
1432
- return headers.length === 0 ? undefined : headers[0];
1433
- }
1434
- getCheckpointedBlock(number) {
1435
- return this.store.getCheckpointedBlock(number);
1436
- }
1437
- async getCheckpointedBlocks(from, limit, proven) {
1438
- const blocks = await this.store.store.getCheckpointedBlocks(from, limit);
1439
- if (proven === true) {
1440
- const provenBlockNumber = await this.store.getProvenBlockNumber();
1441
- return blocks.filter((b)=>b.block.number <= provenBlockNumber);
1442
- }
1443
- return blocks;
1444
- }
1445
- getCheckpointedBlockByHash(blockHash) {
1446
- return this.store.getCheckpointedBlockByHash(blockHash);
1447
- }
1448
- getProvenBlockNumber() {
1449
- return this.store.getProvenBlockNumber();
1400
+ return addCheckpointsWithContractData(this.store, checkpoints, pendingChainValidationStatus);
1450
1401
  }
1451
1402
  getCheckpointedBlockNumber() {
1452
1403
  return this.store.getCheckpointedL2BlockNumber();
1453
1404
  }
1454
- getCheckpointedBlockByArchive(archive) {
1455
- return this.store.getCheckpointedBlockByArchive(archive);
1456
- }
1457
- getTxEffect(txHash) {
1458
- return this.store.getTxEffect(txHash);
1459
- }
1460
- getSettledTxReceipt(txHash) {
1461
- return this.store.getSettledTxReceipt(txHash);
1462
- }
1463
- getPrivateLogsByTags(tags) {
1464
- return this.store.getPrivateLogsByTags(tags);
1465
- }
1466
- getPublicLogsByTagsFromContract(contractAddress, tags) {
1467
- return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
1468
- }
1469
- /**
1470
- * Gets public logs based on the provided filter.
1471
- * @param filter - The filter to apply to the logs.
1472
- * @returns The requested logs.
1473
- */ getPublicLogs(filter) {
1474
- return this.store.getPublicLogs(filter);
1475
- }
1476
- /**
1477
- * Gets contract class logs based on the provided filter.
1478
- * @param filter - The filter to apply to the logs.
1479
- * @returns The requested logs.
1480
- */ getContractClassLogs(filter) {
1481
- return this.store.getContractClassLogs(filter);
1482
- }
1483
- /**
1484
- * Gets the number of the latest L2 block processed by the block source implementation.
1485
- * This includes both checkpointed and uncheckpointed blocks.
1486
- * @returns The number of the latest L2 block processed by the block source implementation.
1487
- */ getBlockNumber() {
1488
- return this.store.getLatestBlockNumber();
1489
- }
1490
- getContractClass(id) {
1491
- return this.store.getContractClass(id);
1492
- }
1493
- getBytecodeCommitment(id) {
1494
- return this.store.getBytecodeCommitment(id);
1495
- }
1496
- async getContract(address, maybeTimestamp) {
1497
- let timestamp;
1498
- if (maybeTimestamp === undefined) {
1499
- const latestBlockHeader = await this.getBlockHeader('latest');
1500
- // If we get undefined block header, it means that the archiver has not yet synced any block so we default to 0.
1501
- timestamp = latestBlockHeader ? latestBlockHeader.globalVariables.timestamp : 0n;
1502
- } else {
1503
- timestamp = maybeTimestamp;
1504
- }
1505
- return this.store.getContractInstance(address, timestamp);
1506
- }
1507
- /**
1508
- * Gets L1 to L2 message (to be) included in a given checkpoint.
1509
- * @param checkpointNumber - Checkpoint number to get messages for.
1510
- * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found).
1511
- */ getL1ToL2Messages(checkpointNumber) {
1512
- return this.store.getL1ToL2Messages(checkpointNumber);
1513
- }
1514
- /**
1515
- * Gets the L1 to L2 message index in the L1 to L2 message tree.
1516
- * @param l1ToL2Message - The L1 to L2 message.
1517
- * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found).
1518
- */ getL1ToL2MessageIndex(l1ToL2Message) {
1519
- return this.store.getL1ToL2MessageIndex(l1ToL2Message);
1520
- }
1521
- getContractClassIds() {
1522
- return this.store.getContractClassIds();
1523
- }
1524
- registerContractFunctionSignatures(signatures) {
1525
- return this.store.registerContractFunctionSignatures(signatures);
1526
- }
1527
- getDebugFunctionName(address, selector) {
1528
- return this.store.getDebugFunctionName(address, selector);
1529
- }
1530
- async getPendingChainValidationStatus() {
1531
- return await this.store.getPendingChainValidationStatus() ?? {
1532
- valid: true
1533
- };
1534
- }
1535
- isPendingChainInvalid() {
1536
- return this.getPendingChainValidationStatus().then((status)=>!status.valid);
1537
- }
1538
1405
  async getL2Tips() {
1539
1406
  const [latestBlockNumber, provenBlockNumber, checkpointedBlockNumber] = await Promise.all([
1540
1407
  this.getBlockNumber(),
@@ -1641,11 +1508,11 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1641
1508
  const targetCheckpointNumber = CheckpointNumber.fromBlockNumber(targetL2BlockNumber);
1642
1509
  const targetL1BlockHash = await this.getL1BlockHash(targetL1BlockNumber);
1643
1510
  this.log.info(`Unwinding ${blocksToUnwind} checkpoints from L2 block ${currentL2Block}`);
1644
- await this.store.unwindCheckpoints(CheckpointNumber(currentL2Block), blocksToUnwind);
1511
+ await unwindCheckpointsWithContractData(this.store, CheckpointNumber(currentL2Block), blocksToUnwind);
1645
1512
  this.log.info(`Unwinding L1 to L2 messages to checkpoint ${targetCheckpointNumber}`);
1646
1513
  await this.store.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
1647
1514
  this.log.info(`Setting L1 syncpoints to ${targetL1BlockNumber}`);
1648
- await this.store.setBlockSynchedL1BlockNumber(targetL1BlockNumber);
1515
+ await this.store.setCheckpointSynchedL1BlockNumber(targetL1BlockNumber);
1649
1516
  await this.store.setMessageSynchedL1Block({
1650
1517
  l1BlockNumber: targetL1BlockNumber,
1651
1518
  l1BlockHash: targetL1BlockHash
@@ -1660,19 +1527,6 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1660
1527
  // await this.store.setFinalizedL2BlockNumber(0);
1661
1528
  // }
1662
1529
  }
1663
- async getPublishedCheckpoints(checkpointNumber, limit) {
1664
- const checkpoints = await this.store.getRangeOfCheckpoints(checkpointNumber, limit);
1665
- const blocks = (await Promise.all(checkpoints.map((ch)=>this.store.getBlocksForCheckpoint(ch.checkpointNumber)))).filter(isDefined);
1666
- const fullCheckpoints = [];
1667
- for(let i = 0; i < checkpoints.length; i++){
1668
- const blocksForCheckpoint = blocks[i];
1669
- const checkpoint = checkpoints[i];
1670
- const fullCheckpoint = new Checkpoint(checkpoint.archive, checkpoint.header, blocksForCheckpoint, checkpoint.checkpointNumber);
1671
- const publishedCheckpoint = new PublishedCheckpoint(fullCheckpoint, checkpoint.l1, checkpoint.attestations.map((x)=>CommitteeAttestation.fromBuffer(x)));
1672
- fullCheckpoints.push(publishedCheckpoint);
1673
- }
1674
- return fullCheckpoints;
1675
- }
1676
1530
  async getCheckpointsForEpoch(epochNumber) {
1677
1531
  const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1constants);
1678
1532
  const checkpoints = [];
@@ -1690,413 +1544,4 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.sync'), _de
1690
1544
  }
1691
1545
  return checkpoints.reverse();
1692
1546
  }
1693
- /* Legacy APIs */ async getPublishedBlockByHash(blockHash) {
1694
- const checkpointedBlock = await this.store.getCheckpointedBlockByHash(blockHash);
1695
- return this.buildOldBlockFromCheckpointedBlock(checkpointedBlock);
1696
- }
1697
- async getPublishedBlockByArchive(archive) {
1698
- const checkpointedBlock = await this.store.getCheckpointedBlockByArchive(archive);
1699
- return this.buildOldBlockFromCheckpointedBlock(checkpointedBlock);
1700
- }
1701
- /**
1702
- * Gets up to `limit` amount of L2 blocks starting from `from`.
1703
- * @param from - Number of the first block to return (inclusive).
1704
- * @param limit - The number of blocks to return.
1705
- * @param proven - If true, only return blocks that have been proven.
1706
- * @returns The requested L2 blocks.
1707
- */ async getBlocks(from, limit, proven) {
1708
- const publishedBlocks = await this.getPublishedBlocks(from, limit, proven);
1709
- return publishedBlocks.map((x)=>x.block);
1710
- }
1711
- async getPublishedBlocks(from, limit, proven) {
1712
- const checkpoints = await this.store.getRangeOfCheckpoints(CheckpointNumber(from), limit);
1713
- const provenCheckpointNumber = await this.getProvenCheckpointNumber();
1714
- const blocks = (await Promise.all(checkpoints.map((ch)=>this.store.getBlocksForCheckpoint(ch.checkpointNumber)))).filter(isDefined);
1715
- const olbBlocks = [];
1716
- for(let i = 0; i < checkpoints.length; i++){
1717
- const blockForCheckpoint = blocks[i][0];
1718
- const checkpoint = checkpoints[i];
1719
- if (checkpoint.checkpointNumber > provenCheckpointNumber && proven === true) {
1720
- continue;
1721
- }
1722
- const oldCheckpoint = new Checkpoint(blockForCheckpoint.archive, checkpoint.header, [
1723
- blockForCheckpoint
1724
- ], checkpoint.checkpointNumber);
1725
- const oldBlock = L2Block.fromCheckpoint(oldCheckpoint);
1726
- const publishedBlock = new PublishedL2Block(oldBlock, checkpoint.l1, checkpoint.attestations.map((x)=>CommitteeAttestation.fromBuffer(x)));
1727
- olbBlocks.push(publishedBlock);
1728
- }
1729
- return olbBlocks;
1730
- }
1731
- async buildOldBlockFromCheckpointedBlock(checkpointedBlock) {
1732
- if (!checkpointedBlock) {
1733
- return undefined;
1734
- }
1735
- const checkpoint = await this.store.getCheckpointData(checkpointedBlock.checkpointNumber);
1736
- if (!checkpoint) {
1737
- return checkpoint;
1738
- }
1739
- const fullCheckpoint = new Checkpoint(checkpointedBlock?.block.archive, checkpoint?.header, [
1740
- checkpointedBlock.block
1741
- ], checkpoint.checkpointNumber);
1742
- const oldBlock = L2Block.fromCheckpoint(fullCheckpoint);
1743
- const published = new PublishedL2Block(oldBlock, checkpoint.l1, checkpoint.attestations.map((x)=>CommitteeAttestation.fromBuffer(x)));
1744
- return published;
1745
- }
1746
- async getBlock(number) {
1747
- // If the number provided is -ve, then return the latest block.
1748
- if (number < 0) {
1749
- number = await this.store.getSynchedL2BlockNumber();
1750
- }
1751
- if (number === 0) {
1752
- return undefined;
1753
- }
1754
- const publishedBlocks = await this.getPublishedBlocks(number, 1);
1755
- if (publishedBlocks.length === 0) {
1756
- return undefined;
1757
- }
1758
- return publishedBlocks[0].block;
1759
- }
1760
- }
1761
- var Operation = /*#__PURE__*/ function(Operation) {
1762
- Operation[Operation["Store"] = 0] = "Store";
1763
- Operation[Operation["Delete"] = 1] = "Delete";
1764
- return Operation;
1765
- }(Operation || {});
1766
- /**
1767
- * A helper class that we use to deal with some of the logic needed when adding blocks.
1768
- *
1769
- * I would have preferred to not have this type. But it is useful for handling the logic that any
1770
- * store would need to include otherwise while exposing fewer functions and logic directly to the archiver.
1771
- */ export class ArchiverStoreHelper {
1772
- store;
1773
- #log;
1774
- constructor(store){
1775
- this.store = store;
1776
- this.#log = createLogger('archiver:block-helper');
1777
- }
1778
- /**
1779
- * Extracts and stores contract classes out of ContractClassPublished events emitted by the class registry contract.
1780
- * @param allLogs - All logs emitted in a bunch of blocks.
1781
- */ async #updatePublishedContractClasses(allLogs, blockNum, operation) {
1782
- const contractClassPublishedEvents = allLogs.filter((log)=>ContractClassPublishedEvent.isContractClassPublishedEvent(log)).map((log)=>ContractClassPublishedEvent.fromLog(log));
1783
- const contractClasses = await Promise.all(contractClassPublishedEvents.map((e)=>e.toContractClassPublic()));
1784
- if (contractClasses.length > 0) {
1785
- contractClasses.forEach((c)=>this.#log.verbose(`${Operation[operation]} contract class ${c.id.toString()}`));
1786
- if (operation == 0) {
1787
- // TODO: Will probably want to create some worker threads to compute these bytecode commitments as they are expensive
1788
- const commitments = await Promise.all(contractClasses.map((c)=>computePublicBytecodeCommitment(c.packedBytecode)));
1789
- return await this.store.addContractClasses(contractClasses, commitments, blockNum);
1790
- } else if (operation == 1) {
1791
- return await this.store.deleteContractClasses(contractClasses, blockNum);
1792
- }
1793
- }
1794
- return true;
1795
- }
1796
- /**
1797
- * Extracts and stores contract instances out of ContractInstancePublished events emitted by the canonical deployer contract.
1798
- * @param allLogs - All logs emitted in a bunch of blocks.
1799
- */ async #updateDeployedContractInstances(allLogs, blockNum, operation) {
1800
- const contractInstances = allLogs.filter((log)=>ContractInstancePublishedEvent.isContractInstancePublishedEvent(log)).map((log)=>ContractInstancePublishedEvent.fromLog(log)).map((e)=>e.toContractInstance());
1801
- if (contractInstances.length > 0) {
1802
- contractInstances.forEach((c)=>this.#log.verbose(`${Operation[operation]} contract instance at ${c.address.toString()}`));
1803
- if (operation == 0) {
1804
- return await this.store.addContractInstances(contractInstances, blockNum);
1805
- } else if (operation == 1) {
1806
- return await this.store.deleteContractInstances(contractInstances, blockNum);
1807
- }
1808
- }
1809
- return true;
1810
- }
1811
- /**
1812
- * Extracts and stores contract instances out of ContractInstancePublished events emitted by the canonical deployer contract.
1813
- * @param allLogs - All logs emitted in a bunch of blocks.
1814
- * @param timestamp - Timestamp at which the updates were scheduled.
1815
- * @param operation - The operation to perform on the contract instance updates (Store or Delete).
1816
- */ async #updateUpdatedContractInstances(allLogs, timestamp, operation) {
1817
- const contractUpdates = allLogs.filter((log)=>ContractInstanceUpdatedEvent.isContractInstanceUpdatedEvent(log)).map((log)=>ContractInstanceUpdatedEvent.fromLog(log)).map((e)=>e.toContractInstanceUpdate());
1818
- if (contractUpdates.length > 0) {
1819
- contractUpdates.forEach((c)=>this.#log.verbose(`${Operation[operation]} contract instance update at ${c.address.toString()}`));
1820
- if (operation == 0) {
1821
- return await this.store.addContractInstanceUpdates(contractUpdates, timestamp);
1822
- } else if (operation == 1) {
1823
- return await this.store.deleteContractInstanceUpdates(contractUpdates, timestamp);
1824
- }
1825
- }
1826
- return true;
1827
- }
1828
- /**
1829
- * Stores the functions that were broadcasted individually
1830
- *
1831
- * @dev Beware that there is not a delete variant of this, since they are added to contract classes
1832
- * and will be deleted as part of the class if needed.
1833
- *
1834
- * @param allLogs - The logs from the block
1835
- * @param _blockNum - The block number
1836
- * @returns
1837
- */ async #storeBroadcastedIndividualFunctions(allLogs, _blockNum) {
1838
- // Filter out private and utility function broadcast events
1839
- const privateFnEvents = allLogs.filter((log)=>PrivateFunctionBroadcastedEvent.isPrivateFunctionBroadcastedEvent(log)).map((log)=>PrivateFunctionBroadcastedEvent.fromLog(log));
1840
- const utilityFnEvents = allLogs.filter((log)=>UtilityFunctionBroadcastedEvent.isUtilityFunctionBroadcastedEvent(log)).map((log)=>UtilityFunctionBroadcastedEvent.fromLog(log));
1841
- // Group all events by contract class id
1842
- for (const [classIdString, classEvents] of Object.entries(groupBy([
1843
- ...privateFnEvents,
1844
- ...utilityFnEvents
1845
- ], (e)=>e.contractClassId.toString()))){
1846
- const contractClassId = Fr.fromHexString(classIdString);
1847
- const contractClass = await this.getContractClass(contractClassId);
1848
- if (!contractClass) {
1849
- this.#log.warn(`Skipping broadcasted functions as contract class ${contractClassId.toString()} was not found`);
1850
- continue;
1851
- }
1852
- // Split private and utility functions, and filter out invalid ones
1853
- const allFns = classEvents.map((e)=>e.toFunctionWithMembershipProof());
1854
- const privateFns = allFns.filter((fn)=>'utilityFunctionsTreeRoot' in fn);
1855
- const utilityFns = allFns.filter((fn)=>'privateFunctionsArtifactTreeRoot' in fn);
1856
- const privateFunctionsWithValidity = await Promise.all(privateFns.map(async (fn)=>({
1857
- fn,
1858
- valid: await isValidPrivateFunctionMembershipProof(fn, contractClass)
1859
- })));
1860
- const validPrivateFns = privateFunctionsWithValidity.filter(({ valid })=>valid).map(({ fn })=>fn);
1861
- const utilityFunctionsWithValidity = await Promise.all(utilityFns.map(async (fn)=>({
1862
- fn,
1863
- valid: await isValidUtilityFunctionMembershipProof(fn, contractClass)
1864
- })));
1865
- const validUtilityFns = utilityFunctionsWithValidity.filter(({ valid })=>valid).map(({ fn })=>fn);
1866
- const validFnCount = validPrivateFns.length + validUtilityFns.length;
1867
- if (validFnCount !== allFns.length) {
1868
- this.#log.warn(`Skipping ${allFns.length - validFnCount} invalid functions`);
1869
- }
1870
- // Store the functions in the contract class in a single operation
1871
- if (validFnCount > 0) {
1872
- this.#log.verbose(`Storing ${validFnCount} functions for contract class ${contractClassId.toString()}`);
1873
- }
1874
- return await this.store.addFunctions(contractClassId, validPrivateFns, validUtilityFns);
1875
- }
1876
- return true;
1877
- }
1878
- async addBlockDataToDB(block) {
1879
- const contractClassLogs = block.body.txEffects.flatMap((txEffect)=>txEffect.contractClassLogs);
1880
- // ContractInstancePublished event logs are broadcast in privateLogs.
1881
- const privateLogs = block.body.txEffects.flatMap((txEffect)=>txEffect.privateLogs);
1882
- const publicLogs = block.body.txEffects.flatMap((txEffect)=>txEffect.publicLogs);
1883
- return (await Promise.all([
1884
- this.#updatePublishedContractClasses(contractClassLogs, block.number, 0),
1885
- this.#updateDeployedContractInstances(privateLogs, block.number, 0),
1886
- this.#updateUpdatedContractInstances(publicLogs, block.header.globalVariables.timestamp, 0),
1887
- this.#storeBroadcastedIndividualFunctions(contractClassLogs, block.number)
1888
- ])).every(Boolean);
1889
- }
1890
- addBlocks(blocks, pendingChainValidationStatus) {
1891
- // Add the blocks to the store. Store will throw if the blocks are not in order, there are gaps,
1892
- // or if the previous block is not in the store.
1893
- return this.store.transactionAsync(async ()=>{
1894
- await this.store.addBlocks(blocks);
1895
- const opResults = await Promise.all([
1896
- // Update the pending chain validation status if provided
1897
- pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
1898
- // Add any logs emitted during the retrieved blocks
1899
- this.store.addLogs(blocks),
1900
- // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
1901
- ...blocks.map((block)=>{
1902
- return this.addBlockDataToDB(block);
1903
- })
1904
- ]);
1905
- return opResults.every(Boolean);
1906
- });
1907
- }
1908
- addCheckpoints(checkpoints, pendingChainValidationStatus) {
1909
- // Add the blocks to the store. Store will throw if the blocks are not in order, there are gaps,
1910
- // or if the previous block is not in the store.
1911
- return this.store.transactionAsync(async ()=>{
1912
- await this.store.addCheckpoints(checkpoints);
1913
- const allBlocks = checkpoints.flatMap((ch)=>ch.checkpoint.blocks);
1914
- const opResults = await Promise.all([
1915
- // Update the pending chain validation status if provided
1916
- pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
1917
- // Add any logs emitted during the retrieved blocks
1918
- this.store.addLogs(allBlocks),
1919
- // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
1920
- ...allBlocks.map((block)=>{
1921
- return this.addBlockDataToDB(block);
1922
- })
1923
- ]);
1924
- return opResults.every(Boolean);
1925
- });
1926
- }
1927
- async unwindCheckpoints(from, checkpointsToUnwind) {
1928
- if (checkpointsToUnwind <= 0) {
1929
- throw new Error(`Cannot unwind ${checkpointsToUnwind} blocks`);
1930
- }
1931
- const last = await this.getSynchedCheckpointNumber();
1932
- if (from != last) {
1933
- throw new Error(`Cannot unwind checkpoints from checkpoint ${from} when the last checkpoint is ${last}`);
1934
- }
1935
- const blocks = [];
1936
- const lastCheckpointNumber = from + checkpointsToUnwind - 1;
1937
- for(let checkpointNumber = from; checkpointNumber <= lastCheckpointNumber; checkpointNumber++){
1938
- const blocksForCheckpoint = await this.store.getBlocksForCheckpoint(checkpointNumber);
1939
- if (!blocksForCheckpoint) {
1940
- continue;
1941
- }
1942
- blocks.push(...blocksForCheckpoint);
1943
- }
1944
- const opResults = await Promise.all([
1945
- // Prune rolls back to the last proven block, which is by definition valid
1946
- this.store.setPendingChainValidationStatus({
1947
- valid: true
1948
- }),
1949
- // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
1950
- ...blocks.map(async (block)=>{
1951
- const contractClassLogs = block.body.txEffects.flatMap((txEffect)=>txEffect.contractClassLogs);
1952
- // ContractInstancePublished event logs are broadcast in privateLogs.
1953
- const privateLogs = block.body.txEffects.flatMap((txEffect)=>txEffect.privateLogs);
1954
- const publicLogs = block.body.txEffects.flatMap((txEffect)=>txEffect.publicLogs);
1955
- return (await Promise.all([
1956
- this.#updatePublishedContractClasses(contractClassLogs, block.number, 1),
1957
- this.#updateDeployedContractInstances(privateLogs, block.number, 1),
1958
- this.#updateUpdatedContractInstances(publicLogs, block.header.globalVariables.timestamp, 1)
1959
- ])).every(Boolean);
1960
- }),
1961
- this.store.deleteLogs(blocks),
1962
- this.store.unwindCheckpoints(from, checkpointsToUnwind)
1963
- ]);
1964
- return opResults.every(Boolean);
1965
- }
1966
- getCheckpointData(checkpointNumber) {
1967
- return this.store.getCheckpointData(checkpointNumber);
1968
- }
1969
- getRangeOfCheckpoints(from, limit) {
1970
- return this.store.getRangeOfCheckpoints(from, limit);
1971
- }
1972
- getCheckpointedL2BlockNumber() {
1973
- return this.store.getCheckpointedL2BlockNumber();
1974
- }
1975
- getSynchedCheckpointNumber() {
1976
- return this.store.getSynchedCheckpointNumber();
1977
- }
1978
- setCheckpointSynchedL1BlockNumber(l1BlockNumber) {
1979
- return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
1980
- }
1981
- getCheckpointedBlock(number) {
1982
- return this.store.getCheckpointedBlock(number);
1983
- }
1984
- getCheckpointedBlockByHash(blockHash) {
1985
- return this.store.getCheckpointedBlockByHash(blockHash);
1986
- }
1987
- getCheckpointedBlockByArchive(archive) {
1988
- return this.store.getCheckpointedBlockByArchive(archive);
1989
- }
1990
- getBlockHeaders(from, limit) {
1991
- return this.store.getBlockHeaders(from, limit);
1992
- }
1993
- getBlockHeaderByHash(blockHash) {
1994
- return this.store.getBlockHeaderByHash(blockHash);
1995
- }
1996
- getBlockHeaderByArchive(archive) {
1997
- return this.store.getBlockHeaderByArchive(archive);
1998
- }
1999
- getBlockByHash(blockHash) {
2000
- return this.store.getBlockByHash(blockHash);
2001
- }
2002
- getBlockByArchive(archive) {
2003
- return this.store.getBlockByArchive(archive);
2004
- }
2005
- getLatestBlockNumber() {
2006
- return this.store.getLatestBlockNumber();
2007
- }
2008
- getBlocksForCheckpoint(checkpointNumber) {
2009
- return this.store.getBlocksForCheckpoint(checkpointNumber);
2010
- }
2011
- getTxEffect(txHash) {
2012
- return this.store.getTxEffect(txHash);
2013
- }
2014
- getSettledTxReceipt(txHash) {
2015
- return this.store.getSettledTxReceipt(txHash);
2016
- }
2017
- addL1ToL2Messages(messages) {
2018
- return this.store.addL1ToL2Messages(messages);
2019
- }
2020
- getL1ToL2Messages(checkpointNumber) {
2021
- return this.store.getL1ToL2Messages(checkpointNumber);
2022
- }
2023
- getL1ToL2MessageIndex(l1ToL2Message) {
2024
- return this.store.getL1ToL2MessageIndex(l1ToL2Message);
2025
- }
2026
- getPrivateLogsByTags(tags) {
2027
- return this.store.getPrivateLogsByTags(tags);
2028
- }
2029
- getPublicLogsByTagsFromContract(contractAddress, tags) {
2030
- return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
2031
- }
2032
- getPublicLogs(filter) {
2033
- return this.store.getPublicLogs(filter);
2034
- }
2035
- getContractClassLogs(filter) {
2036
- return this.store.getContractClassLogs(filter);
2037
- }
2038
- getSynchedL2BlockNumber() {
2039
- return this.store.getLatestBlockNumber();
2040
- }
2041
- getProvenCheckpointNumber() {
2042
- return this.store.getProvenCheckpointNumber();
2043
- }
2044
- getProvenBlockNumber() {
2045
- return this.store.getProvenBlockNumber();
2046
- }
2047
- setProvenCheckpointNumber(checkpointNumber) {
2048
- return this.store.setProvenCheckpointNumber(checkpointNumber);
2049
- }
2050
- setBlockSynchedL1BlockNumber(l1BlockNumber) {
2051
- return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
2052
- }
2053
- setMessageSynchedL1Block(l1Block) {
2054
- return this.store.setMessageSynchedL1Block(l1Block);
2055
- }
2056
- getSynchPoint() {
2057
- return this.store.getSynchPoint();
2058
- }
2059
- getContractClass(id) {
2060
- return this.store.getContractClass(id);
2061
- }
2062
- getBytecodeCommitment(contractClassId) {
2063
- return this.store.getBytecodeCommitment(contractClassId);
2064
- }
2065
- getContractInstance(address, timestamp) {
2066
- return this.store.getContractInstance(address, timestamp);
2067
- }
2068
- getContractClassIds() {
2069
- return this.store.getContractClassIds();
2070
- }
2071
- registerContractFunctionSignatures(signatures) {
2072
- return this.store.registerContractFunctionSignatures(signatures);
2073
- }
2074
- getDebugFunctionName(address, selector) {
2075
- return this.store.getDebugFunctionName(address, selector);
2076
- }
2077
- getTotalL1ToL2MessageCount() {
2078
- return this.store.getTotalL1ToL2MessageCount();
2079
- }
2080
- estimateSize() {
2081
- return this.store.estimateSize();
2082
- }
2083
- rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber) {
2084
- return this.store.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
2085
- }
2086
- iterateL1ToL2Messages(range = {}) {
2087
- return this.store.iterateL1ToL2Messages(range);
2088
- }
2089
- removeL1ToL2Messages(startIndex) {
2090
- return this.store.removeL1ToL2Messages(startIndex);
2091
- }
2092
- getLastL1ToL2Message() {
2093
- return this.store.getLastL1ToL2Message();
2094
- }
2095
- getPendingChainValidationStatus() {
2096
- return this.store.getPendingChainValidationStatus();
2097
- }
2098
- setPendingChainValidationStatus(status) {
2099
- this.#log.debug(`Setting pending chain validation status to valid ${status?.valid}`, status);
2100
- return this.store.setPendingChainValidationStatus(status);
2101
- }
2102
1547
  }