@aztec/archiver 0.55.1 → 0.57.0

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 (78) hide show
  1. package/README.md +1 -1
  2. package/dest/archiver/archiver.d.ts +27 -25
  3. package/dest/archiver/archiver.d.ts.map +1 -1
  4. package/dest/archiver/archiver.js +391 -169
  5. package/dest/archiver/archiver_store.d.ts +47 -23
  6. package/dest/archiver/archiver_store.d.ts.map +1 -1
  7. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  8. package/dest/archiver/archiver_store_test_suite.js +75 -42
  9. package/dest/archiver/config.js +6 -6
  10. package/dest/archiver/data_retrieval.d.ts +32 -5
  11. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  12. package/dest/archiver/data_retrieval.js +126 -16
  13. package/dest/archiver/epoch_helpers.d.ts +15 -0
  14. package/dest/archiver/epoch_helpers.d.ts.map +1 -0
  15. package/dest/archiver/epoch_helpers.js +23 -0
  16. package/dest/archiver/kv_archiver_store/block_store.d.ts +22 -3
  17. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  18. package/dest/archiver/kv_archiver_store/block_store.js +75 -12
  19. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +2 -1
  20. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
  21. package/dest/archiver/kv_archiver_store/contract_class_store.js +11 -4
  22. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +1 -0
  23. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
  24. package/dest/archiver/kv_archiver_store/contract_instance_store.js +4 -1
  25. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +31 -23
  26. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  27. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +65 -38
  28. package/dest/archiver/kv_archiver_store/log_store.d.ts +4 -5
  29. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  30. package/dest/archiver/kv_archiver_store/log_store.js +18 -14
  31. package/dest/archiver/kv_archiver_store/message_store.d.ts +2 -0
  32. package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
  33. package/dest/archiver/kv_archiver_store/message_store.js +18 -8
  34. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts +1 -0
  35. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts.map +1 -1
  36. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.js +4 -1
  37. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +23 -39
  38. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
  39. package/dest/archiver/memory_archiver_store/memory_archiver_store.js +132 -91
  40. package/dest/index.d.ts +0 -1
  41. package/dest/index.d.ts.map +1 -1
  42. package/dest/index.js +2 -2
  43. package/dest/test/index.d.ts +2 -0
  44. package/dest/test/index.d.ts.map +1 -0
  45. package/dest/test/index.js +2 -0
  46. package/dest/test/mock_l2_block_source.d.ts +73 -0
  47. package/dest/test/mock_l2_block_source.d.ts.map +1 -0
  48. package/dest/test/mock_l2_block_source.js +134 -0
  49. package/package.json +15 -11
  50. package/src/archiver/archiver.ts +531 -248
  51. package/src/archiver/archiver_store.ts +53 -31
  52. package/src/archiver/archiver_store_test_suite.ts +93 -81
  53. package/src/archiver/config.ts +5 -5
  54. package/src/archiver/data_retrieval.ts +189 -30
  55. package/src/archiver/epoch_helpers.ts +26 -0
  56. package/src/archiver/kv_archiver_store/block_store.ts +87 -12
  57. package/src/archiver/kv_archiver_store/contract_class_store.ts +18 -5
  58. package/src/archiver/kv_archiver_store/contract_instance_store.ts +4 -0
  59. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +74 -47
  60. package/src/archiver/kv_archiver_store/log_store.ts +18 -18
  61. package/src/archiver/kv_archiver_store/message_store.ts +18 -5
  62. package/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +4 -0
  63. package/src/archiver/memory_archiver_store/memory_archiver_store.ts +155 -108
  64. package/src/index.ts +1 -2
  65. package/src/test/index.ts +1 -0
  66. package/src/test/mock_l2_block_source.ts +165 -0
  67. package/dest/archiver/eth_log_handlers.d.ts +0 -59
  68. package/dest/archiver/eth_log_handlers.d.ts.map +0 -1
  69. package/dest/archiver/eth_log_handlers.js +0 -155
  70. package/dest/archiver/kv_archiver_store/block_body_store.d.ts +0 -34
  71. package/dest/archiver/kv_archiver_store/block_body_store.d.ts.map +0 -1
  72. package/dest/archiver/kv_archiver_store/block_body_store.js +0 -65
  73. package/dest/archiver/kv_archiver_store/proven_store.d.ts +0 -14
  74. package/dest/archiver/kv_archiver_store/proven_store.d.ts.map +0 -1
  75. package/dest/archiver/kv_archiver_store/proven_store.js +0 -30
  76. package/src/archiver/eth_log_handlers.ts +0 -213
  77. package/src/archiver/kv_archiver_store/block_body_store.ts +0 -74
  78. package/src/archiver/kv_archiver_store/proven_store.ts +0 -34
@@ -1,17 +1,17 @@
1
- import { ContractClassRegisteredEvent } from '@aztec/circuits.js';
2
- import { ContractInstanceDeployedEvent, PrivateFunctionBroadcastedEvent, UnconstrainedFunctionBroadcastedEvent, isValidPrivateFunctionMembershipProof, isValidUnconstrainedFunctionMembershipProof, } from '@aztec/circuits.js/contract';
1
+ var _ArchiverStoreHelper_instances, _ArchiverStoreHelper_log, _ArchiverStoreHelper_updateRegisteredContractClasses, _ArchiverStoreHelper_updateDeployedContractInstances, _ArchiverStoreHelper_storeBroadcastedIndividualFunctions;
2
+ import { __classPrivateFieldGet } from "tslib";
3
+ import { ContractClassRegisteredEvent, ContractInstanceDeployedEvent, PrivateFunctionBroadcastedEvent, UnconstrainedFunctionBroadcastedEvent, isValidPrivateFunctionMembershipProof, isValidUnconstrainedFunctionMembershipProof, } from '@aztec/circuits.js';
3
4
  import { createEthereumChain } from '@aztec/ethereum';
4
- import { compactArray, unique } from '@aztec/foundation/collection';
5
5
  import { Fr } from '@aztec/foundation/fields';
6
6
  import { createDebugLogger } from '@aztec/foundation/log';
7
7
  import { RunningPromise } from '@aztec/foundation/running-promise';
8
8
  import { Timer } from '@aztec/foundation/timer';
9
- import { RollupAbi } from '@aztec/l1-artifacts';
9
+ import { InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
10
10
  import { ClassRegistererAddress } from '@aztec/protocol-contracts/class-registerer';
11
11
  import groupBy from 'lodash.groupby';
12
- import { createPublicClient, getContract, http } from 'viem';
13
- import { retrieveBlockFromRollup, retrieveL1ToL2Messages, retrieveL2ProofVerifiedEvents } from './data_retrieval.js';
14
- import { getL1BlockTime } from './eth_log_handlers.js';
12
+ import { createPublicClient, getContract, http, } from 'viem';
13
+ import { retrieveBlockFromRollup, retrieveL1ToL2Messages } from './data_retrieval.js';
14
+ import { getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampRangeForEpoch, } from './epoch_helpers.js';
15
15
  import { ArchiverInstrumentation } from './instrumentation.js';
16
16
  /**
17
17
  * Pulls L2 blocks in a non-blocking manner and provides interface for their retrieval.
@@ -29,16 +29,27 @@ export class Archiver {
29
29
  * @param store - An archiver data store for storage & retrieval of blocks, encrypted logs & contract data.
30
30
  * @param log - A logger.
31
31
  */
32
- constructor(publicClient, rollupAddress, inboxAddress, registryAddress, store, pollingIntervalMs = 10000, instrumentation, l1StartBlock = 0n, log = createDebugLogger('aztec:archiver')) {
32
+ constructor(publicClient, rollupAddress, inboxAddress, registryAddress, dataStore, pollingIntervalMs, instrumentation, l1constants = EmptyL1RollupConstants, log = createDebugLogger('aztec:archiver')) {
33
33
  this.publicClient = publicClient;
34
34
  this.rollupAddress = rollupAddress;
35
35
  this.inboxAddress = inboxAddress;
36
36
  this.registryAddress = registryAddress;
37
- this.store = store;
37
+ this.dataStore = dataStore;
38
38
  this.pollingIntervalMs = pollingIntervalMs;
39
39
  this.instrumentation = instrumentation;
40
- this.l1StartBlock = l1StartBlock;
40
+ this.l1constants = l1constants;
41
41
  this.log = log;
42
+ this.store = new ArchiverStoreHelper(dataStore);
43
+ this.rollup = getContract({
44
+ address: rollupAddress.toString(),
45
+ abi: RollupAbi,
46
+ client: publicClient,
47
+ });
48
+ this.inbox = getContract({
49
+ address: inboxAddress.toString(),
50
+ abi: InboxAbi,
51
+ client: publicClient,
52
+ });
42
53
  }
43
54
  /**
44
55
  * Creates a new instance of the Archiver and blocks until it syncs from chain.
@@ -59,8 +70,11 @@ export class Archiver {
59
70
  abi: RollupAbi,
60
71
  client: publicClient,
61
72
  });
62
- const l1StartBlock = await rollup.read.L1_BLOCK_AT_GENESIS();
63
- const archiver = new Archiver(publicClient, config.l1Contracts.rollupAddress, config.l1Contracts.inboxAddress, config.l1Contracts.registryAddress, archiverStore, config.archiverPollingIntervalMS, new ArchiverInstrumentation(telemetry), BigInt(l1StartBlock));
73
+ const [l1StartBlock, l1GenesisTime] = await Promise.all([
74
+ rollup.read.L1_BLOCK_AT_GENESIS(),
75
+ rollup.read.GENESIS_TIME(),
76
+ ]);
77
+ const archiver = new Archiver(publicClient, config.l1Contracts.rollupAddress, config.l1Contracts.inboxAddress, config.l1Contracts.registryAddress, archiverStore, config.archiverPollingIntervalMS ?? 10000, new ArchiverInstrumentation(telemetry), { l1StartBlock, l1GenesisTime });
64
78
  await archiver.start(blockUntilSynced);
65
79
  return archiver;
66
80
  }
@@ -107,23 +121,9 @@ export class Archiver {
107
121
  *
108
122
  * This code does not handle reorgs.
109
123
  */
110
- const { blockBodiesSynchedTo = this.l1StartBlock, blocksSynchedTo = this.l1StartBlock, messagesSynchedTo = this.l1StartBlock, provenLogsSynchedTo = this.l1StartBlock, } = await this.store.getSynchPoint();
124
+ const { l1StartBlock } = this.l1constants;
125
+ const { blocksSynchedTo = l1StartBlock, messagesSynchedTo = l1StartBlock } = await this.store.getSynchPoint();
111
126
  const currentL1BlockNumber = await this.publicClient.getBlockNumber();
112
- if (currentL1BlockNumber <= blocksSynchedTo &&
113
- currentL1BlockNumber <= messagesSynchedTo &&
114
- currentL1BlockNumber <= blockBodiesSynchedTo &&
115
- currentL1BlockNumber <= provenLogsSynchedTo) {
116
- // chain hasn't moved forward
117
- // or it's been rolled back
118
- this.log.debug(`Nothing to sync`, {
119
- currentL1BlockNumber,
120
- blocksSynchedTo,
121
- messagesSynchedTo,
122
- provenLogsSynchedTo,
123
- blockBodiesSynchedTo,
124
- });
125
- return;
126
- }
127
127
  // ********** Ensuring Consistency of data pulled from L1 **********
128
128
  /**
129
129
  * There are a number of calls in this sync operation to L1 for retrieving
@@ -142,158 +142,112 @@ export class Archiver {
142
142
  * in future but for the time being it should give us the guarantees that we need
143
143
  */
144
144
  // ********** Events that are processed per L1 block **********
145
+ await this.handleL1ToL2Messages(blockUntilSynced, messagesSynchedTo, currentL1BlockNumber);
145
146
  // ********** Events that are processed per L2 block **********
146
- const retrievedL1ToL2Messages = await retrieveL1ToL2Messages(this.publicClient, this.inboxAddress, blockUntilSynced, messagesSynchedTo + 1n, currentL1BlockNumber);
147
- if (retrievedL1ToL2Messages.retrievedData.length !== 0) {
148
- this.log.verbose(`Retrieved ${retrievedL1ToL2Messages.retrievedData.length} new L1 -> L2 messages between L1 blocks ${messagesSynchedTo + 1n} and ${currentL1BlockNumber}.`);
149
- }
150
- await this.store.addL1ToL2Messages(retrievedL1ToL2Messages);
151
- // Read all data from chain and then write to our stores at the end
152
- const nextExpectedL2BlockNum = BigInt((await this.store.getSynchedL2BlockNumber()) + 1);
153
- this.log.debug(`Retrieving blocks from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
154
- const retrievedBlocks = await retrieveBlockFromRollup(this.publicClient, this.rollupAddress, blockUntilSynced, blocksSynchedTo + 1n, currentL1BlockNumber, nextExpectedL2BlockNum);
155
- // Add the body
156
- (retrievedBlocks.length ? this.log.verbose : this.log.debug)(`Retrieved ${retrievedBlocks.length || 'no'} new L2 blocks between L1 blocks ${blocksSynchedTo + 1n} and ${currentL1BlockNumber}.`);
157
- const lastProcessedL1BlockNumber = retrievedBlocks.length > 0 ? retrievedBlocks[retrievedBlocks.length - 1].l1.blockNumber : blocksSynchedTo;
158
- this.log.debug(`Processing retrieved blocks ${retrievedBlocks
159
- .map(b => b.data.number)
160
- .join(',')} with last processed L1 block ${lastProcessedL1BlockNumber}`);
161
- if (retrievedBlocks.length > 0) {
162
- await Promise.all(retrievedBlocks.map(block => {
163
- const noteEncryptedLogs = block.data.body.noteEncryptedLogs;
164
- const encryptedLogs = block.data.body.encryptedLogs;
165
- const unencryptedLogs = block.data.body.unencryptedLogs;
166
- return this.store.addLogs(noteEncryptedLogs, encryptedLogs, unencryptedLogs, block.data.number);
167
- }));
168
- // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
169
- await Promise.all(retrievedBlocks.map(async (block) => {
170
- const blockLogs = block.data.body.txEffects
171
- .flatMap(txEffect => (txEffect ? [txEffect.unencryptedLogs] : []))
172
- .flatMap(txLog => txLog.unrollLogs());
173
- await this.storeRegisteredContractClasses(blockLogs, block.data.number);
174
- await this.storeDeployedContractInstances(blockLogs, block.data.number);
175
- await this.storeBroadcastedIndividualFunctions(blockLogs, block.data.number);
176
- }));
177
- const timer = new Timer();
178
- await this.store.addBlockBodies({
179
- lastProcessedL1BlockNumber: lastProcessedL1BlockNumber,
180
- retrievedData: retrievedBlocks.map(b => b.data.body),
181
- });
182
- await this.store.addBlocks(retrievedBlocks);
183
- this.instrumentation.processNewBlocks(timer.ms() / retrievedBlocks.length, retrievedBlocks.map(b => b.data));
184
- const lastL2BlockNumber = retrievedBlocks[retrievedBlocks.length - 1].data.number;
185
- this.log.verbose(`Processed ${retrievedBlocks.length} new L2 blocks up to ${lastL2BlockNumber}`);
186
- }
187
- // Fetch the logs for proven blocks in the block range and update the last proven block number.
188
- if (currentL1BlockNumber > provenLogsSynchedTo) {
189
- await this.updateLastProvenL2Block(provenLogsSynchedTo + 1n, currentL1BlockNumber);
190
- }
191
- if (retrievedBlocks.length > 0 || blockUntilSynced) {
192
- (blockUntilSynced ? this.log.info : this.log.verbose)(`Synced to L1 block ${currentL1BlockNumber}`);
147
+ await this.handleL2blocks(blockUntilSynced, blocksSynchedTo, currentL1BlockNumber);
148
+ // Store latest l1 block number and timestamp seen. Used for epoch and slots calculations.
149
+ if (!this.l1BlockNumber || this.l1BlockNumber < currentL1BlockNumber) {
150
+ this.l1Timestamp = await this.publicClient.getBlock({ blockNumber: currentL1BlockNumber }).then(b => b.timestamp);
151
+ this.l1BlockNumber = currentL1BlockNumber;
193
152
  }
194
153
  }
195
- async updateLastProvenL2Block(fromBlock, toBlock) {
196
- const logs = await retrieveL2ProofVerifiedEvents(this.publicClient, this.rollupAddress, fromBlock, toBlock);
197
- const lastLog = logs[logs.length - 1];
198
- if (!lastLog) {
154
+ async handleL1ToL2Messages(blockUntilSynced, messagesSynchedTo, currentL1BlockNumber) {
155
+ if (currentL1BlockNumber <= messagesSynchedTo) {
199
156
  return;
200
157
  }
201
- const provenBlockNumber = lastLog.l2BlockNumber;
202
- if (!provenBlockNumber) {
203
- throw new Error(`Missing argument blockNumber from L2ProofVerified event`);
204
- }
205
- await this.emitProofVerifiedMetrics(logs);
206
- const currentProvenBlockNumber = await this.store.getProvenL2BlockNumber();
207
- if (provenBlockNumber > currentProvenBlockNumber) {
208
- // Update the last proven block number
209
- this.log.verbose(`Updated last proven block number from ${currentProvenBlockNumber} to ${provenBlockNumber}`);
210
- await this.store.setProvenL2BlockNumber({
211
- retrievedData: Number(provenBlockNumber),
212
- lastProcessedL1BlockNumber: lastLog.l1BlockNumber,
213
- });
214
- this.instrumentation.updateLastProvenBlock(Number(provenBlockNumber));
215
- }
216
- else {
217
- // We set the last processed L1 block number to the last L1 block number in the range to avoid duplicate processing
218
- await this.store.setProvenL2BlockNumber({
219
- retrievedData: Number(currentProvenBlockNumber),
220
- lastProcessedL1BlockNumber: lastLog.l1BlockNumber,
221
- });
158
+ const localTotalMessageCount = await this.store.getTotalL1ToL2MessageCount();
159
+ const destinationTotalMessageCount = await this.inbox.read.totalMessagesInserted();
160
+ if (localTotalMessageCount === destinationTotalMessageCount) {
161
+ await this.store.setMessageSynchedL1BlockNumber(currentL1BlockNumber);
162
+ this.log.verbose(`Retrieved no new L1 -> L2 messages between L1 blocks ${messagesSynchedTo + 1n} and ${currentL1BlockNumber}.`);
163
+ return;
222
164
  }
165
+ const retrievedL1ToL2Messages = await retrieveL1ToL2Messages(this.inbox, blockUntilSynced, messagesSynchedTo + 1n, currentL1BlockNumber);
166
+ await this.store.addL1ToL2Messages(retrievedL1ToL2Messages);
167
+ this.log.verbose(`Retrieved ${retrievedL1ToL2Messages.retrievedData.length} new L1 -> L2 messages between L1 blocks ${messagesSynchedTo + 1n} and ${currentL1BlockNumber}.`);
223
168
  }
224
- /**
225
- * Emits as metrics the block number proven, who proved it, and how much time passed since it was submitted.
226
- * @param logs - The ProofVerified logs to emit metrics for, as collected from `retrieveL2ProofVerifiedEvents`.
227
- **/
228
- async emitProofVerifiedMetrics(logs) {
229
- if (!logs.length || !this.instrumentation.isEnabled()) {
169
+ async handleL2blocks(blockUntilSynced, blocksSynchedTo, currentL1BlockNumber) {
170
+ if (currentL1BlockNumber <= blocksSynchedTo) {
230
171
  return;
231
172
  }
232
- const l1BlockTimes = new Map(await Promise.all(unique(logs.map(log => log.l1BlockNumber)).map(async (blockNumber) => [blockNumber, await getL1BlockTime(this.publicClient, blockNumber)])));
233
- // Collect L2 block times for all the blocks verified, this is the time in which the block proven was
234
- // originally submitted to L1, using the L1 timestamp of the transaction.
235
- const getL2BlockTime = async (blockNumber) => (await this.store.getBlocks(Number(blockNumber), 1))[0]?.l1.timestamp;
236
- const l2BlockTimes = new Map(await Promise.all(unique(logs.map(log => log.l2BlockNumber)).map(async (blockNumber) => [blockNumber, await getL2BlockTime(blockNumber)])));
237
- // Emit the prover id and the time difference between block submission and proof.
238
- this.instrumentation.processProofsVerified(compactArray(logs.map(log => {
239
- const l1BlockTime = l1BlockTimes.get(log.l1BlockNumber);
240
- const l2BlockTime = l2BlockTimes.get(log.l2BlockNumber);
241
- if (!l2BlockTime) {
242
- return undefined;
173
+ const localPendingBlockNumber = BigInt(await this.getBlockNumber());
174
+ const [provenBlockNumber, provenArchive, pendingBlockNumber, pendingArchive, archiveForLocalPendingBlockNumber, provenEpochNumber,] = await this.rollup.read.status([localPendingBlockNumber]);
175
+ const updateProvenBlock = async () => {
176
+ const localBlockForDestinationProvenBlockNumber = await this.getBlock(Number(provenBlockNumber));
177
+ if (localBlockForDestinationProvenBlockNumber &&
178
+ provenArchive === localBlockForDestinationProvenBlockNumber.archive.root.toString()) {
179
+ this.log.info(`Updating the proven block number to ${provenBlockNumber} and epoch to ${provenEpochNumber}`);
180
+ await this.store.setProvenL2BlockNumber(Number(provenBlockNumber));
181
+ // if we are here then we must have a valid proven epoch number
182
+ await this.store.setProvenL2EpochNumber(Number(provenEpochNumber));
243
183
  }
244
- return { ...log, delay: l1BlockTime - l2BlockTime, proverId: log.proverId.toString() };
245
- })));
246
- }
247
- /**
248
- * Extracts and stores contract classes out of ContractClassRegistered events emitted by the class registerer contract.
249
- * @param allLogs - All logs emitted in a bunch of blocks.
250
- */
251
- async storeRegisteredContractClasses(allLogs, blockNum) {
252
- const contractClasses = ContractClassRegisteredEvent.fromLogs(allLogs, ClassRegistererAddress).map(e => e.toContractClassPublic());
253
- if (contractClasses.length > 0) {
254
- contractClasses.forEach(c => this.log.verbose(`Registering contract class ${c.id.toString()}`));
255
- await this.store.addContractClasses(contractClasses, blockNum);
256
- }
257
- }
258
- /**
259
- * Extracts and stores contract instances out of ContractInstanceDeployed events emitted by the canonical deployer contract.
260
- * @param allLogs - All logs emitted in a bunch of blocks.
261
- */
262
- async storeDeployedContractInstances(allLogs, blockNum) {
263
- const contractInstances = ContractInstanceDeployedEvent.fromLogs(allLogs).map(e => e.toContractInstance());
264
- if (contractInstances.length > 0) {
265
- contractInstances.forEach(c => this.log.verbose(`Storing contract instance at ${c.address.toString()}`));
266
- await this.store.addContractInstances(contractInstances, blockNum);
184
+ };
185
+ // This is an edge case that we only hit if there are no proposed blocks.
186
+ // If we have 0 blocks locally and there are no blocks onchain there is nothing to do.
187
+ const noBlocks = localPendingBlockNumber === 0n && pendingBlockNumber === 0n;
188
+ if (noBlocks) {
189
+ await this.store.setBlockSynchedL1BlockNumber(currentL1BlockNumber);
190
+ this.log.verbose(`No blocks to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
191
+ return;
267
192
  }
268
- }
269
- async storeBroadcastedIndividualFunctions(allLogs, _blockNum) {
270
- // Filter out private and unconstrained function broadcast events
271
- const privateFnEvents = PrivateFunctionBroadcastedEvent.fromLogs(allLogs, ClassRegistererAddress);
272
- const unconstrainedFnEvents = UnconstrainedFunctionBroadcastedEvent.fromLogs(allLogs, ClassRegistererAddress);
273
- // Group all events by contract class id
274
- for (const [classIdString, classEvents] of Object.entries(groupBy([...privateFnEvents, ...unconstrainedFnEvents], e => e.contractClassId.toString()))) {
275
- const contractClassId = Fr.fromString(classIdString);
276
- const contractClass = await this.store.getContractClass(contractClassId);
277
- if (!contractClass) {
278
- this.log.warn(`Skipping broadcasted functions as contract class ${contractClassId.toString()} was not found`);
279
- continue;
193
+ await updateProvenBlock();
194
+ // Related to the L2 reorgs of the pending chain. We are only interested in actually addressing a reorg if there
195
+ // are any state that could be impacted by it. If we have no blocks, there is no impact.
196
+ if (localPendingBlockNumber > 0) {
197
+ const localPendingBlock = await this.getBlock(Number(localPendingBlockNumber));
198
+ if (localPendingBlock === undefined) {
199
+ throw new Error(`Missing block ${localPendingBlockNumber}`);
280
200
  }
281
- // Split private and unconstrained functions, and filter out invalid ones
282
- const allFns = classEvents.map(e => e.toFunctionWithMembershipProof());
283
- const privateFns = allFns.filter((fn) => 'unconstrainedFunctionsArtifactTreeRoot' in fn);
284
- const unconstrainedFns = allFns.filter((fn) => 'privateFunctionsArtifactTreeRoot' in fn);
285
- const validPrivateFns = privateFns.filter(fn => isValidPrivateFunctionMembershipProof(fn, contractClass));
286
- const validUnconstrainedFns = unconstrainedFns.filter(fn => isValidUnconstrainedFunctionMembershipProof(fn, contractClass));
287
- const validFnCount = validPrivateFns.length + validUnconstrainedFns.length;
288
- if (validFnCount !== allFns.length) {
289
- this.log.warn(`Skipping ${allFns.length - validFnCount} invalid functions`);
201
+ const noBlockSinceLast = localPendingBlock && pendingArchive === localPendingBlock.archive.root.toString();
202
+ if (noBlockSinceLast) {
203
+ await this.store.setBlockSynchedL1BlockNumber(currentL1BlockNumber);
204
+ this.log.verbose(`No blocks to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
205
+ return;
290
206
  }
291
- // Store the functions in the contract class in a single operation
292
- if (validFnCount > 0) {
293
- this.log.verbose(`Storing ${validFnCount} functions for contract class ${contractClassId.toString()}`);
207
+ const localPendingBlockInChain = archiveForLocalPendingBlockNumber === localPendingBlock.archive.root.toString();
208
+ if (!localPendingBlockInChain) {
209
+ // If our local pending block tip is not in the chain on L1 a "prune" must have happened
210
+ // or the L1 have reorged.
211
+ // In any case, we have to figure out how far into the past the action will take us.
212
+ // For simplicity here, we will simply rewind until we end in a block that is also on the chain on L1.
213
+ this.log.verbose(`L2 prune have occurred, unwind state`);
214
+ let tipAfterUnwind = localPendingBlockNumber;
215
+ while (true) {
216
+ const candidateBlock = await this.getBlock(Number(tipAfterUnwind));
217
+ if (candidateBlock === undefined) {
218
+ break;
219
+ }
220
+ const archiveAtContract = await this.rollup.read.archiveAt([BigInt(candidateBlock.number)]);
221
+ if (archiveAtContract === candidateBlock.archive.root.toString()) {
222
+ break;
223
+ }
224
+ tipAfterUnwind--;
225
+ }
226
+ const blocksToUnwind = localPendingBlockNumber - tipAfterUnwind;
227
+ this.log.verbose(`Unwinding ${blocksToUnwind} block${blocksToUnwind > 1n ? 's' : ''} from block ${localPendingBlockNumber}`);
228
+ await this.store.unwindBlocks(Number(localPendingBlockNumber), Number(blocksToUnwind));
294
229
  }
295
- await this.store.addFunctions(contractClassId, validPrivateFns, validUnconstrainedFns);
296
230
  }
231
+ this.log.debug(`Retrieving blocks from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
232
+ const retrievedBlocks = await retrieveBlockFromRollup(this.rollup, this.publicClient, blockUntilSynced, blocksSynchedTo + 1n, currentL1BlockNumber, this.log);
233
+ if (retrievedBlocks.length === 0) {
234
+ // We are not calling `setBlockSynchedL1BlockNumber` because it may cause sync issues if based off infura.
235
+ // See further details in earlier comments.
236
+ this.log.verbose(`Retrieved no new blocks from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
237
+ return;
238
+ }
239
+ this.log.debug(`Retrieved ${retrievedBlocks.length} new L2 blocks between L1 blocks ${blocksSynchedTo + 1n} and ${currentL1BlockNumber}.`);
240
+ const lastProcessedL1BlockNumber = retrievedBlocks[retrievedBlocks.length - 1].l1.blockNumber;
241
+ this.log.debug(`Processing retrieved blocks ${retrievedBlocks
242
+ .map(b => b.data.number)
243
+ .join(',')} with last processed L1 block ${lastProcessedL1BlockNumber}`);
244
+ const timer = new Timer();
245
+ await this.store.addBlocks(retrievedBlocks);
246
+ // Important that we update AFTER inserting the blocks.
247
+ await updateProvenBlock();
248
+ this.instrumentation.processNewBlocks(timer.ms() / retrievedBlocks.length, retrievedBlocks.map(b => b.data));
249
+ const lastL2BlockNumber = retrievedBlocks[retrievedBlocks.length - 1].data.number;
250
+ this.log.verbose(`Processed ${retrievedBlocks.length} new L2 blocks up to ${lastL2BlockNumber}`);
297
251
  }
298
252
  /**
299
253
  * Stops the archiver.
@@ -311,6 +265,58 @@ export class Archiver {
311
265
  getRegistryAddress() {
312
266
  return Promise.resolve(this.registryAddress);
313
267
  }
268
+ getL1BlockNumber() {
269
+ const l1BlockNumber = this.l1BlockNumber;
270
+ if (!l1BlockNumber) {
271
+ throw new Error('L1 block number not yet available. Complete an initial sync first.');
272
+ }
273
+ return l1BlockNumber;
274
+ }
275
+ getL1Timestamp() {
276
+ const l1Timestamp = this.l1Timestamp;
277
+ if (!l1Timestamp) {
278
+ throw new Error('L1 timestamp not yet available. Complete an initial sync first.');
279
+ }
280
+ return l1Timestamp;
281
+ }
282
+ getL2SlotNumber() {
283
+ return Promise.resolve(getSlotAtTimestamp(this.getL1Timestamp(), this.l1constants));
284
+ }
285
+ getL2EpochNumber() {
286
+ return Promise.resolve(getEpochNumberAtTimestamp(this.getL1Timestamp(), this.l1constants));
287
+ }
288
+ async getBlocksForEpoch(epochNumber) {
289
+ const [start, end] = getSlotRangeForEpoch(epochNumber);
290
+ const blocks = [];
291
+ // Walk the list of blocks backwards and filter by slots matching the requested epoch.
292
+ // We'll typically ask for blocks for a very recent epoch, so we shouldn't need an index here.
293
+ let block = await this.getBlock(await this.store.getSynchedL2BlockNumber());
294
+ const slot = (b) => b.header.globalVariables.slotNumber.toBigInt();
295
+ while (block && slot(block) >= start) {
296
+ if (slot(block) <= end) {
297
+ blocks.push(block);
298
+ }
299
+ block = await this.getBlock(block.number - 1);
300
+ }
301
+ return blocks.reverse();
302
+ }
303
+ async isEpochComplete(epochNumber) {
304
+ // The epoch is complete if the current L2 block is the last one in the epoch (or later)
305
+ const header = await this.getBlockHeader('latest');
306
+ const slot = header?.globalVariables.slotNumber.toBigInt();
307
+ const [_startSlot, endSlot] = getSlotRangeForEpoch(epochNumber);
308
+ if (slot && slot >= endSlot) {
309
+ return true;
310
+ }
311
+ // If not, the epoch may also be complete if the L2 slot has passed without a block
312
+ // We compute this based on the timestamp for the given epoch and the timestamp of the last L1 block
313
+ const l1Timestamp = this.getL1Timestamp();
314
+ const [_startTimestamp, endTimestamp] = getTimestampRangeForEpoch(epochNumber, this.l1constants);
315
+ // For this computation, we throw in a few extra seconds just for good measure,
316
+ // since we know the next L1 block won't be mined within this range
317
+ const leeway = 3n;
318
+ return l1Timestamp + leeway >= endTimestamp;
319
+ }
314
320
  /**
315
321
  * Gets up to `limit` amount of L2 blocks starting from `from`.
316
322
  * @param from - Number of the first block to return (inclusive).
@@ -326,7 +332,7 @@ export class Archiver {
326
332
  }
327
333
  /**
328
334
  * Gets an l2 block.
329
- * @param number - The block number to return (inclusive).
335
+ * @param number - The block number to return.
330
336
  * @returns The requested L2 block.
331
337
  */
332
338
  async getBlock(number) {
@@ -334,9 +340,19 @@ export class Archiver {
334
340
  if (number < 0) {
335
341
  number = await this.store.getSynchedL2BlockNumber();
336
342
  }
343
+ if (number == 0) {
344
+ return undefined;
345
+ }
337
346
  const blocks = await this.store.getBlocks(number, 1);
338
347
  return blocks.length === 0 ? undefined : blocks[0].data;
339
348
  }
349
+ async getBlockHeader(number) {
350
+ if (number === 'latest') {
351
+ number = await this.store.getSynchedL2BlockNumber();
352
+ }
353
+ const headers = await this.store.getBlockHeaders(number, 1);
354
+ return headers.length === 0 ? undefined : headers[0];
355
+ }
340
356
  getTxEffect(txHash) {
341
357
  return this.store.getTxEffect(txHash);
342
358
  }
@@ -388,9 +404,12 @@ export class Archiver {
388
404
  getProvenBlockNumber() {
389
405
  return this.store.getProvenL2BlockNumber();
390
406
  }
407
+ getProvenL2EpochNumber() {
408
+ return this.store.getProvenL2EpochNumber();
409
+ }
391
410
  /** Forcefully updates the last proven block number. Use for testing. */
392
- setProvenBlockNumber(block) {
393
- return this.store.setProvenL2BlockNumber(block);
411
+ setProvenBlockNumber(blockNumber) {
412
+ return this.store.setProvenL2BlockNumber(blockNumber);
394
413
  }
395
414
  getContractClass(id) {
396
415
  return this.store.getContractClass(id);
@@ -425,4 +444,207 @@ export class Archiver {
425
444
  return this.store.getContractArtifact(address);
426
445
  }
427
446
  }
428
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJjaGl2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXJjaGl2ZXIvYXJjaGl2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBZUEsT0FBTyxFQUFFLDRCQUE0QixFQUF5QixNQUFNLG9CQUFvQixDQUFDO0FBQ3pGLE9BQU8sRUFDTCw2QkFBNkIsRUFDN0IsK0JBQStCLEVBQy9CLHFDQUFxQyxFQUNyQyxxQ0FBcUMsRUFDckMsMkNBQTJDLEdBQzVDLE1BQU0sNkJBQTZCLENBQUM7QUFDckMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFHdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUVwRSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDOUMsT0FBTyxFQUFvQixpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzVFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBV3BGLE9BQU8sT0FBTyxNQUFNLGdCQUFnQixDQUFDO0FBQ3JDLE9BQU8sRUFBcUQsa0JBQWtCLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUloSCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsc0JBQXNCLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNySCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDdkQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFRL0Q7Ozs7R0FJRztBQUNILE1BQU0s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
447
+ var Operation;
448
+ (function (Operation) {
449
+ Operation[Operation["Store"] = 0] = "Store";
450
+ Operation[Operation["Delete"] = 1] = "Delete";
451
+ })(Operation || (Operation = {}));
452
+ /**
453
+ * A helper class that we use to deal with some of the logic needed when adding blocks.
454
+ *
455
+ * I would have preferred to not have this type. But it is useful for handling the logic that any
456
+ * store would need to include otherwise while exposing fewer functions and logic directly to the archiver.
457
+ */
458
+ class ArchiverStoreHelper {
459
+ constructor(store) {
460
+ _ArchiverStoreHelper_instances.add(this);
461
+ this.store = store;
462
+ _ArchiverStoreHelper_log.set(this, createDebugLogger('aztec:archiver:block-helper'));
463
+ }
464
+ async addBlocks(blocks) {
465
+ return [
466
+ this.store.addLogs(blocks.map(block => block.data)),
467
+ // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
468
+ ...(await Promise.all(blocks.map(async (block) => {
469
+ const blockLogs = block.data.body.txEffects
470
+ .flatMap(txEffect => (txEffect ? [txEffect.unencryptedLogs] : []))
471
+ .flatMap(txLog => txLog.unrollLogs());
472
+ return (await Promise.all([
473
+ __classPrivateFieldGet(this, _ArchiverStoreHelper_instances, "m", _ArchiverStoreHelper_updateRegisteredContractClasses).call(this, blockLogs, block.data.number, Operation.Store),
474
+ __classPrivateFieldGet(this, _ArchiverStoreHelper_instances, "m", _ArchiverStoreHelper_updateDeployedContractInstances).call(this, blockLogs, block.data.number, Operation.Store),
475
+ __classPrivateFieldGet(this, _ArchiverStoreHelper_instances, "m", _ArchiverStoreHelper_storeBroadcastedIndividualFunctions).call(this, blockLogs, block.data.number),
476
+ ])).every(Boolean);
477
+ }))),
478
+ this.store.addBlocks(blocks),
479
+ ].every(Boolean);
480
+ }
481
+ async unwindBlocks(from, blocksToUnwind) {
482
+ const last = await this.getSynchedL2BlockNumber();
483
+ if (from != last) {
484
+ throw new Error(`Can only remove from the tip`);
485
+ }
486
+ // from - blocksToUnwind = the new head, so + 1 for what we need to remove
487
+ const blocks = await this.getBlocks(from - blocksToUnwind + 1, blocksToUnwind);
488
+ return [
489
+ // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
490
+ ...(await Promise.all(blocks.map(async (block) => {
491
+ const blockLogs = block.data.body.txEffects
492
+ .flatMap(txEffect => (txEffect ? [txEffect.unencryptedLogs] : []))
493
+ .flatMap(txLog => txLog.unrollLogs());
494
+ await __classPrivateFieldGet(this, _ArchiverStoreHelper_instances, "m", _ArchiverStoreHelper_updateRegisteredContractClasses).call(this, blockLogs, block.data.number, Operation.Delete);
495
+ await __classPrivateFieldGet(this, _ArchiverStoreHelper_instances, "m", _ArchiverStoreHelper_updateDeployedContractInstances).call(this, blockLogs, block.data.number, Operation.Delete);
496
+ }))),
497
+ this.store.deleteLogs(blocks.map(b => b.data)),
498
+ this.store.unwindBlocks(from, blocksToUnwind),
499
+ ].every(Boolean);
500
+ }
501
+ getBlocks(from, limit) {
502
+ return this.store.getBlocks(from, limit);
503
+ }
504
+ getBlockHeaders(from, limit) {
505
+ return this.store.getBlockHeaders(from, limit);
506
+ }
507
+ getTxEffect(txHash) {
508
+ return this.store.getTxEffect(txHash);
509
+ }
510
+ getSettledTxReceipt(txHash) {
511
+ return this.store.getSettledTxReceipt(txHash);
512
+ }
513
+ addL1ToL2Messages(messages) {
514
+ return this.store.addL1ToL2Messages(messages);
515
+ }
516
+ getL1ToL2Messages(blockNumber) {
517
+ return this.store.getL1ToL2Messages(blockNumber);
518
+ }
519
+ getL1ToL2MessageIndex(l1ToL2Message, startIndex) {
520
+ return this.store.getL1ToL2MessageIndex(l1ToL2Message, startIndex);
521
+ }
522
+ getLogs(from, limit, logType) {
523
+ return this.store.getLogs(from, limit, logType);
524
+ }
525
+ getUnencryptedLogs(filter) {
526
+ return this.store.getUnencryptedLogs(filter);
527
+ }
528
+ getSynchedL2BlockNumber() {
529
+ return this.store.getSynchedL2BlockNumber();
530
+ }
531
+ getProvenL2BlockNumber() {
532
+ return this.store.getProvenL2BlockNumber();
533
+ }
534
+ getProvenL2EpochNumber() {
535
+ return this.store.getProvenL2EpochNumber();
536
+ }
537
+ setProvenL2BlockNumber(l2BlockNumber) {
538
+ return this.store.setProvenL2BlockNumber(l2BlockNumber);
539
+ }
540
+ setProvenL2EpochNumber(l2EpochNumber) {
541
+ return this.store.setProvenL2EpochNumber(l2EpochNumber);
542
+ }
543
+ setBlockSynchedL1BlockNumber(l1BlockNumber) {
544
+ return this.store.setBlockSynchedL1BlockNumber(l1BlockNumber);
545
+ }
546
+ setMessageSynchedL1BlockNumber(l1BlockNumber) {
547
+ return this.store.setMessageSynchedL1BlockNumber(l1BlockNumber);
548
+ }
549
+ getSynchPoint() {
550
+ return this.store.getSynchPoint();
551
+ }
552
+ getContractClass(id) {
553
+ return this.store.getContractClass(id);
554
+ }
555
+ getContractInstance(address) {
556
+ return this.store.getContractInstance(address);
557
+ }
558
+ getContractClassIds() {
559
+ return this.store.getContractClassIds();
560
+ }
561
+ addContractArtifact(address, contract) {
562
+ return this.store.addContractArtifact(address, contract);
563
+ }
564
+ getContractArtifact(address) {
565
+ return this.store.getContractArtifact(address);
566
+ }
567
+ getTotalL1ToL2MessageCount() {
568
+ return this.store.getTotalL1ToL2MessageCount();
569
+ }
570
+ }
571
+ _ArchiverStoreHelper_log = new WeakMap(), _ArchiverStoreHelper_instances = new WeakSet(), _ArchiverStoreHelper_updateRegisteredContractClasses =
572
+ /**
573
+ * Extracts and stores contract classes out of ContractClassRegistered events emitted by the class registerer contract.
574
+ * @param allLogs - All logs emitted in a bunch of blocks.
575
+ */
576
+ async function _ArchiverStoreHelper_updateRegisteredContractClasses(allLogs, blockNum, operation) {
577
+ const contractClasses = ContractClassRegisteredEvent.fromLogs(allLogs, ClassRegistererAddress).map(e => e.toContractClassPublic());
578
+ if (contractClasses.length > 0) {
579
+ contractClasses.forEach(c => __classPrivateFieldGet(this, _ArchiverStoreHelper_log, "f").verbose(`Registering contract class ${c.id.toString()}`));
580
+ if (operation == Operation.Store) {
581
+ return await this.store.addContractClasses(contractClasses, blockNum);
582
+ }
583
+ else if (operation == Operation.Delete) {
584
+ return await this.store.deleteContractClasses(contractClasses, blockNum);
585
+ }
586
+ }
587
+ return true;
588
+ }, _ArchiverStoreHelper_updateDeployedContractInstances =
589
+ /**
590
+ * Extracts and stores contract instances out of ContractInstanceDeployed events emitted by the canonical deployer contract.
591
+ * @param allLogs - All logs emitted in a bunch of blocks.
592
+ */
593
+ async function _ArchiverStoreHelper_updateDeployedContractInstances(allLogs, blockNum, operation) {
594
+ const contractInstances = ContractInstanceDeployedEvent.fromLogs(allLogs).map(e => e.toContractInstance());
595
+ if (contractInstances.length > 0) {
596
+ contractInstances.forEach(c => __classPrivateFieldGet(this, _ArchiverStoreHelper_log, "f").verbose(`${Operation[operation]} contract instance at ${c.address.toString()}`));
597
+ if (operation == Operation.Store) {
598
+ return await this.store.addContractInstances(contractInstances, blockNum);
599
+ }
600
+ else if (operation == Operation.Delete) {
601
+ return await this.store.deleteContractInstances(contractInstances, blockNum);
602
+ }
603
+ }
604
+ return true;
605
+ }, _ArchiverStoreHelper_storeBroadcastedIndividualFunctions =
606
+ /**
607
+ * Stores the functions that was broadcasted individually
608
+ *
609
+ * @dev Beware that there is not a delete variant of this, since they are added to contract classes
610
+ * and will be deleted as part of the class if needed.
611
+ *
612
+ * @param allLogs - The logs from the block
613
+ * @param _blockNum - The block number
614
+ * @returns
615
+ */
616
+ async function _ArchiverStoreHelper_storeBroadcastedIndividualFunctions(allLogs, _blockNum) {
617
+ // Filter out private and unconstrained function broadcast events
618
+ const privateFnEvents = PrivateFunctionBroadcastedEvent.fromLogs(allLogs, ClassRegistererAddress);
619
+ const unconstrainedFnEvents = UnconstrainedFunctionBroadcastedEvent.fromLogs(allLogs, ClassRegistererAddress);
620
+ // Group all events by contract class id
621
+ for (const [classIdString, classEvents] of Object.entries(groupBy([...privateFnEvents, ...unconstrainedFnEvents], e => e.contractClassId.toString()))) {
622
+ const contractClassId = Fr.fromString(classIdString);
623
+ const contractClass = await this.getContractClass(contractClassId);
624
+ if (!contractClass) {
625
+ __classPrivateFieldGet(this, _ArchiverStoreHelper_log, "f").warn(`Skipping broadcasted functions as contract class ${contractClassId.toString()} was not found`);
626
+ continue;
627
+ }
628
+ // Split private and unconstrained functions, and filter out invalid ones
629
+ const allFns = classEvents.map(e => e.toFunctionWithMembershipProof());
630
+ const privateFns = allFns.filter((fn) => 'unconstrainedFunctionsArtifactTreeRoot' in fn);
631
+ const unconstrainedFns = allFns.filter((fn) => 'privateFunctionsArtifactTreeRoot' in fn);
632
+ const validPrivateFns = privateFns.filter(fn => isValidPrivateFunctionMembershipProof(fn, contractClass));
633
+ const validUnconstrainedFns = unconstrainedFns.filter(fn => isValidUnconstrainedFunctionMembershipProof(fn, contractClass));
634
+ const validFnCount = validPrivateFns.length + validUnconstrainedFns.length;
635
+ if (validFnCount !== allFns.length) {
636
+ __classPrivateFieldGet(this, _ArchiverStoreHelper_log, "f").warn(`Skipping ${allFns.length - validFnCount} invalid functions`);
637
+ }
638
+ // Store the functions in the contract class in a single operation
639
+ if (validFnCount > 0) {
640
+ __classPrivateFieldGet(this, _ArchiverStoreHelper_log, "f").verbose(`Storing ${validFnCount} functions for contract class ${contractClassId.toString()}`);
641
+ }
642
+ return await this.store.addFunctions(contractClassId, validPrivateFns, validUnconstrainedFns);
643
+ }
644
+ return true;
645
+ };
646
+ const EmptyL1RollupConstants = {
647
+ l1StartBlock: 0n,
648
+ l1GenesisTime: 0n,
649
+ };
650
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJjaGl2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXJjaGl2ZXIvYXJjaGl2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFnQkEsT0FBTyxFQUNMLDRCQUE0QixFQUM1Qiw2QkFBNkIsRUFHN0IsK0JBQStCLEVBQy9CLHFDQUFxQyxFQUNyQyxxQ0FBcUMsRUFDckMsMkNBQTJDLEdBQzVDLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFJdEQsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzlDLE9BQU8sRUFBb0IsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM1RSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDbkUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2hELE9BQU8sRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDMUQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFXcEYsT0FBTyxPQUFPLE1BQU0sZ0JBQWdCLENBQUM7QUFDckMsT0FBTyxFQUtMLGtCQUFrQixFQUNsQixXQUFXLEVBQ1gsSUFBSSxHQUNMLE1BQU0sTUFBTSxDQUFDO0FBSWQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLHNCQUFzQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdEYsT0FBTyxFQUNMLHlCQUF5QixFQUN6QixrQkFBa0IsRUFDbEIsb0JBQW9CLEVBQ3BCLHlCQUF5QixHQUMxQixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBUy9EOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sUUFBUTtJQWNuQjs7Ozs7Ozs7O09BU0c7SUFDSCxZQUNtQixZQUFn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