@aztec/archiver 0.76.4 → 0.77.0-testnet-ignition.21

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 (91) hide show
  1. package/README.md +1 -1
  2. package/dest/archiver/archiver.d.ts +22 -10
  3. package/dest/archiver/archiver.d.ts.map +1 -1
  4. package/dest/archiver/archiver.js +762 -713
  5. package/dest/archiver/archiver_store.d.ts +20 -7
  6. package/dest/archiver/archiver_store.d.ts.map +1 -1
  7. package/dest/archiver/archiver_store.js +4 -2
  8. package/dest/archiver/archiver_store_test_suite.d.ts +2 -2
  9. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  10. package/dest/archiver/archiver_store_test_suite.js +398 -227
  11. package/dest/archiver/config.d.ts +1 -1
  12. package/dest/archiver/config.d.ts.map +1 -1
  13. package/dest/archiver/config.js +10 -12
  14. package/dest/archiver/data_retrieval.d.ts +17 -14
  15. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  16. package/dest/archiver/data_retrieval.js +90 -88
  17. package/dest/archiver/errors.js +1 -2
  18. package/dest/archiver/index.d.ts +1 -1
  19. package/dest/archiver/index.d.ts.map +1 -1
  20. package/dest/archiver/index.js +0 -1
  21. package/dest/archiver/instrumentation.d.ts +3 -1
  22. package/dest/archiver/instrumentation.d.ts.map +1 -1
  23. package/dest/archiver/instrumentation.js +37 -17
  24. package/dest/archiver/kv_archiver_store/block_store.d.ts +5 -3
  25. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  26. package/dest/archiver/kv_archiver_store/block_store.js +125 -130
  27. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +2 -1
  28. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
  29. package/dest/archiver/kv_archiver_store/contract_class_store.js +45 -37
  30. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +10 -2
  31. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
  32. package/dest/archiver/kv_archiver_store/contract_instance_store.js +54 -15
  33. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +16 -9
  34. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  35. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +143 -160
  36. package/dest/archiver/kv_archiver_store/log_store.d.ts +5 -3
  37. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  38. package/dest/archiver/kv_archiver_store/log_store.js +296 -255
  39. package/dest/archiver/kv_archiver_store/message_store.d.ts +3 -3
  40. package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
  41. package/dest/archiver/kv_archiver_store/message_store.js +45 -50
  42. package/dest/archiver/kv_archiver_store/nullifier_store.d.ts +2 -2
  43. package/dest/archiver/kv_archiver_store/nullifier_store.d.ts.map +1 -1
  44. package/dest/archiver/kv_archiver_store/nullifier_store.js +36 -43
  45. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts +2 -2
  46. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts.map +1 -1
  47. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.js +17 -26
  48. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +16 -7
  49. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
  50. package/dest/archiver/memory_archiver_store/memory_archiver_store.js +287 -247
  51. package/dest/archiver/structs/data_retrieval.js +5 -2
  52. package/dest/archiver/structs/published.js +1 -2
  53. package/dest/factory.d.ts +20 -6
  54. package/dest/factory.d.ts.map +1 -1
  55. package/dest/factory.js +54 -30
  56. package/dest/index.js +0 -1
  57. package/dest/rpc/index.d.ts +2 -1
  58. package/dest/rpc/index.d.ts.map +1 -1
  59. package/dest/rpc/index.js +8 -4
  60. package/dest/test/index.js +0 -1
  61. package/dest/test/mock_archiver.d.ts +3 -2
  62. package/dest/test/mock_archiver.d.ts.map +1 -1
  63. package/dest/test/mock_archiver.js +8 -13
  64. package/dest/test/mock_l1_to_l2_message_source.d.ts +2 -2
  65. package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
  66. package/dest/test/mock_l1_to_l2_message_source.js +4 -4
  67. package/dest/test/mock_l2_block_source.d.ts +5 -3
  68. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  69. package/dest/test/mock_l2_block_source.js +71 -68
  70. package/package.json +15 -16
  71. package/src/archiver/archiver.ts +149 -89
  72. package/src/archiver/archiver_store.ts +27 -27
  73. package/src/archiver/archiver_store_test_suite.ts +22 -15
  74. package/src/archiver/config.ts +1 -1
  75. package/src/archiver/data_retrieval.ts +32 -44
  76. package/src/archiver/index.ts +1 -1
  77. package/src/archiver/instrumentation.ts +11 -1
  78. package/src/archiver/kv_archiver_store/block_store.ts +10 -4
  79. package/src/archiver/kv_archiver_store/contract_class_store.ts +9 -9
  80. package/src/archiver/kv_archiver_store/contract_instance_store.ts +81 -3
  81. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +44 -29
  82. package/src/archiver/kv_archiver_store/log_store.ts +56 -32
  83. package/src/archiver/kv_archiver_store/message_store.ts +4 -3
  84. package/src/archiver/kv_archiver_store/nullifier_store.ts +3 -2
  85. package/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +3 -3
  86. package/src/archiver/memory_archiver_store/memory_archiver_store.ts +110 -57
  87. package/src/factory.ts +44 -25
  88. package/src/rpc/index.ts +2 -6
  89. package/src/test/mock_archiver.ts +3 -2
  90. package/src/test/mock_l1_to_l2_message_source.ts +2 -2
  91. package/src/test/mock_l2_block_source.ts +16 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/archiver",
3
- "version": "0.76.4",
3
+ "version": "0.77.0-testnet-ignition.21",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -22,7 +22,7 @@
22
22
  "clean": "rm -rf ./dest .tsbuildinfo",
23
23
  "formatting": "run -T prettier --check ./src && run -T eslint ./src",
24
24
  "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
25
- "test": "HARDWARE_CONCURRENCY=${HARDWARE_CONCURRENCY:-16} RAYON_NUM_THREADS=${RAYON_NUM_THREADS:-4} NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}",
25
+ "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}",
26
26
  "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"",
27
27
  "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
28
28
  },
@@ -58,25 +58,24 @@
58
58
  "reporters": [
59
59
  "default"
60
60
  ],
61
- "testTimeout": 30000,
61
+ "testTimeout": 120000,
62
62
  "setupFiles": [
63
63
  "../../foundation/src/jest/setup.mjs"
64
64
  ]
65
65
  },
66
66
  "dependencies": {
67
- "@aztec/blob-lib": "0.76.4",
68
- "@aztec/blob-sink": "0.76.4",
69
- "@aztec/circuit-types": "0.76.4",
70
- "@aztec/circuits.js": "0.76.4",
71
- "@aztec/ethereum": "0.76.4",
72
- "@aztec/foundation": "0.76.4",
73
- "@aztec/kv-store": "0.76.4",
74
- "@aztec/l1-artifacts": "0.76.4",
75
- "@aztec/noir-contracts.js": "0.76.4",
76
- "@aztec/noir-protocol-circuits-types": "0.76.4",
77
- "@aztec/protocol-contracts": "0.76.4",
78
- "@aztec/telemetry-client": "0.76.4",
79
- "@aztec/types": "0.76.4",
67
+ "@aztec/blob-lib": "0.77.0-testnet-ignition.21",
68
+ "@aztec/blob-sink": "0.77.0-testnet-ignition.21",
69
+ "@aztec/constants": "0.77.0-testnet-ignition.21",
70
+ "@aztec/ethereum": "0.77.0-testnet-ignition.21",
71
+ "@aztec/foundation": "0.77.0-testnet-ignition.21",
72
+ "@aztec/kv-store": "0.77.0-testnet-ignition.21",
73
+ "@aztec/l1-artifacts": "0.77.0-testnet-ignition.21",
74
+ "@aztec/noir-contracts.js": "0.77.0-testnet-ignition.21",
75
+ "@aztec/noir-protocol-circuits-types": "0.77.0-testnet-ignition.21",
76
+ "@aztec/protocol-contracts": "0.77.0-testnet-ignition.21",
77
+ "@aztec/stdlib": "0.77.0-testnet-ignition.21",
78
+ "@aztec/telemetry-client": "0.77.0-testnet-ignition.21",
80
79
  "debug": "^4.3.4",
81
80
  "lodash.groupby": "^4.6.0",
82
81
  "lodash.omit": "^4.5.0",
@@ -1,77 +1,69 @@
1
- import { type BlobSinkClientInterface } from '@aztec/blob-sink/client';
1
+ import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
2
+ import { type ViemPublicClient, createEthereumChain } from '@aztec/ethereum';
3
+ import type { EthAddress } from '@aztec/foundation/eth-address';
4
+ import { Fr } from '@aztec/foundation/fields';
5
+ import { type Logger, createLogger } from '@aztec/foundation/log';
6
+ import { RunningPromise, makeLoggingErrorHandler } from '@aztec/foundation/running-promise';
7
+ import { count } from '@aztec/foundation/string';
8
+ import { elapsed } from '@aztec/foundation/timer';
9
+ import { InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
10
+ import {
11
+ ContractClassRegisteredEvent,
12
+ PrivateFunctionBroadcastedEvent,
13
+ UnconstrainedFunctionBroadcastedEvent,
14
+ } from '@aztec/protocol-contracts/class-registerer';
15
+ import {
16
+ ContractInstanceDeployedEvent,
17
+ ContractInstanceUpdatedEvent,
18
+ } from '@aztec/protocol-contracts/instance-deployer';
19
+ import type { FunctionSelector } from '@aztec/stdlib/abi';
20
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
2
21
  import {
3
- type GetContractClassLogsResponse,
4
- type GetPublicLogsResponse,
5
22
  type InBlock,
6
- type InboxLeaf,
7
- type L1RollupConstants,
8
- type L1ToL2MessageSource,
9
23
  type L2Block,
10
24
  type L2BlockId,
11
25
  type L2BlockSource,
12
- type L2LogsSource,
26
+ L2BlockSourceEvents,
13
27
  type L2Tips,
14
- type LogFilter,
15
28
  type NullifierWithBlockSource,
16
- type TxEffect,
17
- type TxHash,
18
- type TxReceipt,
19
- type TxScopedL2Log,
20
- type UnencryptedL2Log,
21
- getEpochNumberAtTimestamp,
22
- getSlotAtTimestamp,
23
- getSlotRangeForEpoch,
24
- getTimestampRangeForEpoch,
25
- } from '@aztec/circuit-types';
29
+ } from '@aztec/stdlib/block';
26
30
  import {
27
- type BlockHeader,
28
31
  type ContractClassPublic,
29
32
  type ContractDataSource,
30
33
  type ContractInstanceWithAddress,
31
34
  type ExecutablePrivateFunctionWithMembershipProof,
32
- type FunctionSelector,
33
- type PrivateLog,
34
35
  type PublicFunction,
35
36
  type UnconstrainedFunctionWithMembershipProof,
36
37
  computePublicBytecodeCommitment,
37
38
  isValidPrivateFunctionMembershipProof,
38
39
  isValidUnconstrainedFunctionMembershipProof,
39
- } from '@aztec/circuits.js';
40
- import { createEthereumChain } from '@aztec/ethereum';
41
- import { type AztecAddress } from '@aztec/foundation/aztec-address';
42
- import { type EthAddress } from '@aztec/foundation/eth-address';
43
- import { Fr } from '@aztec/foundation/fields';
44
- import { type Logger, createLogger } from '@aztec/foundation/log';
45
- import { RunningPromise } from '@aztec/foundation/running-promise';
46
- import { count } from '@aztec/foundation/string';
47
- import { elapsed } from '@aztec/foundation/timer';
48
- import { InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
40
+ } from '@aztec/stdlib/contract';
49
41
  import {
50
- ContractClassRegisteredEvent,
51
- PrivateFunctionBroadcastedEvent,
52
- UnconstrainedFunctionBroadcastedEvent,
53
- } from '@aztec/protocol-contracts/class-registerer';
54
- import { ContractInstanceDeployedEvent } from '@aztec/protocol-contracts/instance-deployer';
42
+ type L1RollupConstants,
43
+ getEpochAtSlot,
44
+ getEpochNumberAtTimestamp,
45
+ getSlotAtTimestamp,
46
+ getSlotRangeForEpoch,
47
+ getTimestampRangeForEpoch,
48
+ } from '@aztec/stdlib/epoch-helpers';
49
+ import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
50
+ import type { L2LogsSource } from '@aztec/stdlib/interfaces/server';
51
+ import { ContractClassLog, type LogFilter, type PrivateLog, type PublicLog, TxScopedL2Log } from '@aztec/stdlib/logs';
52
+ import type { InboxLeaf, L1ToL2MessageSource } from '@aztec/stdlib/messaging';
53
+ import { type BlockHeader, TxEffect, TxHash, TxReceipt } from '@aztec/stdlib/tx';
55
54
  import { Attributes, type TelemetryClient, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
56
55
 
56
+ import { EventEmitter } from 'events';
57
57
  import groupBy from 'lodash.groupby';
58
- import {
59
- type Chain,
60
- type GetContractReturnType,
61
- type HttpTransport,
62
- type PublicClient,
63
- createPublicClient,
64
- getContract,
65
- http,
66
- } from 'viem';
67
-
68
- import { type ArchiverDataStore, type ArchiverL1SynchPoint } from './archiver_store.js';
69
- import { type ArchiverConfig } from './config.js';
58
+ import { type GetContractReturnType, createPublicClient, fallback, getContract, http } from 'viem';
59
+
60
+ import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
61
+ import type { ArchiverConfig } from './config.js';
70
62
  import { retrieveBlocksFromRollup, retrieveL1ToL2Messages } from './data_retrieval.js';
71
63
  import { NoBlobBodiesFoundError } from './errors.js';
72
64
  import { ArchiverInstrumentation } from './instrumentation.js';
73
- import { type DataRetrieval } from './structs/data_retrieval.js';
74
- import { type L1Published } from './structs/published.js';
65
+ import type { DataRetrieval } from './structs/data_retrieval.js';
66
+ import type { L1Published } from './structs/published.js';
75
67
 
76
68
  /**
77
69
  * Helper interface to combine all sources this archiver implementation provides.
@@ -87,14 +79,14 @@ export type ArchiveSource = L2BlockSource &
87
79
  * Responsible for handling robust L1 polling so that other components do not need to
88
80
  * concern themselves with it.
89
81
  */
90
- export class Archiver implements ArchiveSource, Traceable {
82
+ export class Archiver extends EventEmitter implements ArchiveSource, Traceable {
91
83
  /**
92
84
  * A promise in which we will be continually fetching new L2 blocks.
93
85
  */
94
86
  private runningPromise?: RunningPromise;
95
87
 
96
- private rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>;
97
- private inbox: GetContractReturnType<typeof InboxAbi, PublicClient<HttpTransport, Chain>>;
88
+ private rollup: GetContractReturnType<typeof RollupAbi, ViemPublicClient>;
89
+ private inbox: GetContractReturnType<typeof InboxAbi, ViemPublicClient>;
98
90
 
99
91
  private store: ArchiverStoreHelper;
100
92
 
@@ -114,7 +106,7 @@ export class Archiver implements ArchiveSource, Traceable {
114
106
  * @param log - A logger.
115
107
  */
116
108
  constructor(
117
- private readonly publicClient: PublicClient<HttpTransport, Chain>,
109
+ private readonly publicClient: ViemPublicClient,
118
110
  private readonly l1Addresses: { rollupAddress: EthAddress; inboxAddress: EthAddress; registryAddress: EthAddress },
119
111
  readonly dataStore: ArchiverDataStore,
120
112
  private readonly config: { pollingIntervalMs: number; batchSize: number },
@@ -123,6 +115,8 @@ export class Archiver implements ArchiveSource, Traceable {
123
115
  private readonly l1constants: L1RollupConstants,
124
116
  private readonly log: Logger = createLogger('archiver'),
125
117
  ) {
118
+ super();
119
+
126
120
  this.tracer = instrumentation.tracer;
127
121
  this.store = new ArchiverStoreHelper(dataStore);
128
122
 
@@ -152,10 +146,10 @@ export class Archiver implements ArchiveSource, Traceable {
152
146
  deps: { telemetry: TelemetryClient; blobSinkClient: BlobSinkClientInterface },
153
147
  blockUntilSynced = true,
154
148
  ): Promise<Archiver> {
155
- const chain = createEthereumChain(config.l1RpcUrl, config.l1ChainId);
149
+ const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
156
150
  const publicClient = createPublicClient({
157
151
  chain: chain.chainInfo,
158
- transport: http(chain.rpcUrl),
152
+ transport: fallback(config.l1RpcUrls.map(url => http(url))),
159
153
  pollingInterval: config.viemPollingIntervalMS,
160
154
  });
161
155
 
@@ -198,18 +192,32 @@ export class Archiver implements ArchiveSource, Traceable {
198
192
  }
199
193
 
200
194
  if (blockUntilSynced) {
201
- await this.sync(blockUntilSynced);
195
+ await this.syncSafe(blockUntilSynced);
202
196
  }
203
197
 
204
- this.runningPromise = new RunningPromise(() => this.sync(false), this.log, this.config.pollingIntervalMs, [
205
- // Ignored errors will not log to the console
206
- // We ignore NoBlobBodiesFound as the message may not have been passed to the blob sink yet
207
- NoBlobBodiesFoundError,
208
- ]);
198
+ this.runningPromise = new RunningPromise(
199
+ () => this.sync(false),
200
+ this.log,
201
+ this.config.pollingIntervalMs,
202
+ makeLoggingErrorHandler(
203
+ this.log,
204
+ // Ignored errors will not log to the console
205
+ // We ignore NoBlobBodiesFound as the message may not have been passed to the blob sink yet
206
+ NoBlobBodiesFoundError,
207
+ ),
208
+ );
209
209
 
210
210
  this.runningPromise.start();
211
211
  }
212
212
 
213
+ private async syncSafe(initialRun: boolean) {
214
+ try {
215
+ await this.sync(initialRun);
216
+ } catch (error) {
217
+ this.log.error('Error during sync', { error });
218
+ }
219
+ }
220
+
213
221
  /**
214
222
  * Fetches logs from L1 contracts and processes them.
215
223
  */
@@ -278,29 +286,46 @@ export class Archiver implements ArchiveSource, Traceable {
278
286
  // the chain locally before we start unwinding stuff. This can be optimized by figuring out
279
287
  // up to which point we're pruning, and then requesting L2 blocks up to that point only.
280
288
  await this.handleEpochPrune(provenBlockNumber, currentL1BlockNumber);
289
+
290
+ this.instrumentation.updateL1BlockHeight(currentL1BlockNumber);
281
291
  }
282
292
 
283
293
  if (initialRun) {
284
294
  this.log.info(`Initial archiver sync to L1 block ${currentL1BlockNumber} complete.`, {
285
295
  l1BlockNumber: currentL1BlockNumber,
296
+ syncPoint: await this.store.getSynchPoint(),
286
297
  ...(await this.getL2Tips()),
287
298
  });
288
299
  }
289
300
  }
290
301
 
302
+ /** Queries the rollup contract on whether a prune can be executed on the immediatenext L1 block. */
303
+ private async canPrune(currentL1BlockNumber: bigint) {
304
+ const time = (this.l1Timestamp ?? 0n) + BigInt(this.l1constants.ethereumSlotDuration);
305
+ return await this.rollup.read.canPruneAtTime([time], { blockNumber: currentL1BlockNumber });
306
+ }
307
+
291
308
  /** Checks if there'd be a reorg for the next block submission and start pruning now. */
292
309
  private async handleEpochPrune(provenBlockNumber: bigint, currentL1BlockNumber: bigint) {
293
310
  const localPendingBlockNumber = BigInt(await this.getBlockNumber());
294
-
295
- const time = (this.l1Timestamp ?? 0n) + BigInt(this.l1constants.ethereumSlotDuration);
296
-
297
- const canPrune =
298
- localPendingBlockNumber > provenBlockNumber &&
299
- (await this.rollup.read.canPruneAtTime([time], { blockNumber: currentL1BlockNumber }));
311
+ const canPrune = localPendingBlockNumber > provenBlockNumber && (await this.canPrune(currentL1BlockNumber));
300
312
 
301
313
  if (canPrune) {
314
+ const localPendingSlotNumber = await this.getL2SlotNumber();
315
+ const localPendingEpochNumber = getEpochAtSlot(localPendingSlotNumber, this.l1constants);
316
+
317
+ // Emit an event for listening services to react to the chain prune
318
+ this.emit(L2BlockSourceEvents.L2PruneDetected, {
319
+ type: L2BlockSourceEvents.L2PruneDetected,
320
+ blockNumber: localPendingBlockNumber,
321
+ slotNumber: localPendingSlotNumber,
322
+ epochNumber: localPendingEpochNumber,
323
+ });
324
+
302
325
  const blocksToUnwind = localPendingBlockNumber - provenBlockNumber;
303
- this.log.debug(`L2 prune will occur on next block submission.`);
326
+ this.log.debug(
327
+ `L2 prune from ${provenBlockNumber + 1n} to ${localPendingBlockNumber} will occur on next block submission.`,
328
+ );
304
329
  await this.store.unwindBlocks(Number(localPendingBlockNumber), Number(blocksToUnwind));
305
330
  this.log.warn(
306
331
  `Unwound ${count(blocksToUnwind, 'block')} from L2 block ${localPendingBlockNumber} ` +
@@ -688,9 +713,11 @@ export class Archiver implements ArchiveSource, Traceable {
688
713
  if (!instance) {
689
714
  throw new Error(`Contract ${address.toString()} not found`);
690
715
  }
691
- const contractClass = await this.getContractClass(instance.contractClassId);
716
+ const contractClass = await this.getContractClass(instance.currentContractClassId);
692
717
  if (!contractClass) {
693
- throw new Error(`Contract class ${instance.contractClassId.toString()} for ${address.toString()} not found`);
718
+ throw new Error(
719
+ `Contract class ${instance.currentContractClassId.toString()} for ${address.toString()} not found`,
720
+ );
694
721
  }
695
722
  return contractClass.publicFunctions.find(f => f.selector.equals(selector));
696
723
  }
@@ -842,9 +869,18 @@ export class Archiver implements ArchiveSource, Traceable {
842
869
  const provenBlockHeaderHash = await provenBlockHeader?.hash();
843
870
  const finalizedBlockHeaderHash = await provenBlockHeader?.hash();
844
871
  return {
845
- latest: { number: latestBlockNumber, hash: latestBlockHeaderHash?.toString() } as L2BlockId,
846
- proven: { number: provenBlockNumber, hash: provenBlockHeaderHash?.toString() } as L2BlockId,
847
- finalized: { number: provenBlockNumber, hash: finalizedBlockHeaderHash?.toString() } as L2BlockId,
872
+ latest: {
873
+ number: latestBlockNumber,
874
+ hash: latestBlockHeaderHash?.toString(),
875
+ } as L2BlockId,
876
+ proven: {
877
+ number: provenBlockNumber,
878
+ hash: provenBlockHeaderHash?.toString(),
879
+ } as L2BlockId,
880
+ finalized: {
881
+ number: provenBlockNumber,
882
+ hash: finalizedBlockHeaderHash?.toString(),
883
+ } as L2BlockId,
848
884
  };
849
885
  }
850
886
  }
@@ -872,6 +908,8 @@ class ArchiverStoreHelper
872
908
  | 'deleteContractClasses'
873
909
  | 'addContractInstances'
874
910
  | 'deleteContractInstances'
911
+ | 'addContractInstanceUpdates'
912
+ | 'deleteContractInstanceUpdates'
875
913
  | 'addFunctions'
876
914
  >
877
915
  {
@@ -892,10 +930,10 @@ class ArchiverStoreHelper
892
930
  * Extracts and stores contract classes out of ContractClassRegistered events emitted by the class registerer contract.
893
931
  * @param allLogs - All logs emitted in a bunch of blocks.
894
932
  */
895
- async #updateRegisteredContractClasses(allLogs: UnencryptedL2Log[], blockNum: number, operation: Operation) {
933
+ async #updateRegisteredContractClasses(allLogs: ContractClassLog[], blockNum: number, operation: Operation) {
896
934
  const contractClassRegisteredEvents = allLogs
897
- .filter(log => ContractClassRegisteredEvent.isContractClassRegisteredEvent(log.data))
898
- .map(log => ContractClassRegisteredEvent.fromLog(log.data));
935
+ .filter(log => ContractClassRegisteredEvent.isContractClassRegisteredEvent(log))
936
+ .map(log => ContractClassRegisteredEvent.fromLog(log));
899
937
 
900
938
  const contractClasses = await Promise.all(contractClassRegisteredEvents.map(e => e.toContractClassPublic()));
901
939
  if (contractClasses.length > 0) {
@@ -935,6 +973,29 @@ class ArchiverStoreHelper
935
973
  return true;
936
974
  }
937
975
 
976
+ /**
977
+ * Extracts and stores contract instances out of ContractInstanceDeployed events emitted by the canonical deployer contract.
978
+ * @param allLogs - All logs emitted in a bunch of blocks.
979
+ */
980
+ async #updateUpdatedContractInstances(allLogs: PublicLog[], blockNum: number, operation: Operation) {
981
+ const contractUpdates = allLogs
982
+ .filter(log => ContractInstanceUpdatedEvent.isContractInstanceUpdatedEvent(log))
983
+ .map(log => ContractInstanceUpdatedEvent.fromLog(log))
984
+ .map(e => e.toContractInstanceUpdate());
985
+
986
+ if (contractUpdates.length > 0) {
987
+ contractUpdates.forEach(c =>
988
+ this.#log.verbose(`${Operation[operation]} contract instance update at ${c.address.toString()}`),
989
+ );
990
+ if (operation == Operation.Store) {
991
+ return await this.store.addContractInstanceUpdates(contractUpdates, blockNum);
992
+ } else if (operation == Operation.Delete) {
993
+ return await this.store.deleteContractInstanceUpdates(contractUpdates, blockNum);
994
+ }
995
+ }
996
+ return true;
997
+ }
998
+
938
999
  /**
939
1000
  * Stores the functions that was broadcasted individually
940
1001
  *
@@ -945,14 +1006,14 @@ class ArchiverStoreHelper
945
1006
  * @param _blockNum - The block number
946
1007
  * @returns
947
1008
  */
948
- async #storeBroadcastedIndividualFunctions(allLogs: UnencryptedL2Log[], _blockNum: number) {
1009
+ async #storeBroadcastedIndividualFunctions(allLogs: ContractClassLog[], _blockNum: number) {
949
1010
  // Filter out private and unconstrained function broadcast events
950
1011
  const privateFnEvents = allLogs
951
- .filter(log => PrivateFunctionBroadcastedEvent.isPrivateFunctionBroadcastedEvent(log.data))
952
- .map(log => PrivateFunctionBroadcastedEvent.fromLog(log.data));
1012
+ .filter(log => PrivateFunctionBroadcastedEvent.isPrivateFunctionBroadcastedEvent(log))
1013
+ .map(log => PrivateFunctionBroadcastedEvent.fromLog(log));
953
1014
  const unconstrainedFnEvents = allLogs
954
- .filter(log => UnconstrainedFunctionBroadcastedEvent.isUnconstrainedFunctionBroadcastedEvent(log.data))
955
- .map(log => UnconstrainedFunctionBroadcastedEvent.fromLog(log.data));
1015
+ .filter(log => UnconstrainedFunctionBroadcastedEvent.isUnconstrainedFunctionBroadcastedEvent(log))
1016
+ .map(log => UnconstrainedFunctionBroadcastedEvent.fromLog(log));
956
1017
 
957
1018
  // Group all events by contract class id
958
1019
  for (const [classIdString, classEvents] of Object.entries(
@@ -1004,15 +1065,15 @@ class ArchiverStoreHelper
1004
1065
  this.store.addLogs(blocks.map(block => block.data)),
1005
1066
  // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
1006
1067
  ...blocks.map(async block => {
1007
- const contractClassLogs = block.data.body.txEffects
1008
- .flatMap(txEffect => (txEffect ? [txEffect.contractClassLogs] : []))
1009
- .flatMap(txLog => txLog.unrollLogs());
1068
+ const contractClassLogs = block.data.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
1010
1069
  // ContractInstanceDeployed event logs are broadcast in privateLogs.
1011
1070
  const privateLogs = block.data.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
1071
+ const publicLogs = block.data.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
1012
1072
  return (
1013
1073
  await Promise.all([
1014
1074
  this.#updateRegisteredContractClasses(contractClassLogs, block.data.number, Operation.Store),
1015
1075
  this.#updateDeployedContractInstances(privateLogs, block.data.number, Operation.Store),
1076
+ this.#updateUpdatedContractInstances(publicLogs, block.data.number, Operation.Store),
1016
1077
  this.#storeBroadcastedIndividualFunctions(contractClassLogs, block.data.number),
1017
1078
  ])
1018
1079
  ).every(Boolean);
@@ -1036,17 +1097,16 @@ class ArchiverStoreHelper
1036
1097
  const opResults = await Promise.all([
1037
1098
  // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
1038
1099
  ...blocks.map(async block => {
1039
- const contractClassLogs = block.data.body.txEffects
1040
- .flatMap(txEffect => (txEffect ? [txEffect.contractClassLogs] : []))
1041
- .flatMap(txLog => txLog.unrollLogs());
1042
-
1100
+ const contractClassLogs = block.data.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
1043
1101
  // ContractInstanceDeployed event logs are broadcast in privateLogs.
1044
1102
  const privateLogs = block.data.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
1103
+ const publicLogs = block.data.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
1045
1104
 
1046
1105
  return (
1047
1106
  await Promise.all([
1048
1107
  this.#updateRegisteredContractClasses(contractClassLogs, block.data.number, Operation.Delete),
1049
1108
  this.#updateDeployedContractInstances(privateLogs, block.data.number, Operation.Delete),
1109
+ this.#updateUpdatedContractInstances(publicLogs, block.data.number, Operation.Delete),
1050
1110
  ])
1051
1111
  ).every(Boolean);
1052
1112
  }),
@@ -1,29 +1,21 @@
1
- import {
2
- type GetContractClassLogsResponse,
3
- type GetPublicLogsResponse,
4
- type InBlock,
5
- type InboxLeaf,
6
- type L2Block,
7
- type LogFilter,
8
- type TxEffect,
9
- type TxHash,
10
- type TxReceipt,
11
- type TxScopedL2Log,
12
- } from '@aztec/circuit-types';
13
- import {
14
- type BlockHeader,
15
- type ContractClassPublic,
16
- type ContractInstanceWithAddress,
17
- type ExecutablePrivateFunctionWithMembershipProof,
18
- type Fr,
19
- type PrivateLog,
20
- type UnconstrainedFunctionWithMembershipProof,
21
- } from '@aztec/circuits.js';
22
- import { type FunctionSelector } from '@aztec/foundation/abi';
23
- import { type AztecAddress } from '@aztec/foundation/aztec-address';
24
-
25
- import { type DataRetrieval } from './structs/data_retrieval.js';
26
- import { type L1Published } from './structs/published.js';
1
+ import type { Fr } from '@aztec/foundation/fields';
2
+ import type { FunctionSelector } from '@aztec/stdlib/abi';
3
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
4
+ import type { InBlock, L2Block } from '@aztec/stdlib/block';
5
+ import type {
6
+ ContractClassPublic,
7
+ ContractInstanceUpdateWithAddress,
8
+ ContractInstanceWithAddress,
9
+ ExecutablePrivateFunctionWithMembershipProof,
10
+ UnconstrainedFunctionWithMembershipProof,
11
+ } from '@aztec/stdlib/contract';
12
+ import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
13
+ import type { LogFilter, PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs';
14
+ import type { InboxLeaf } from '@aztec/stdlib/messaging';
15
+ import { BlockHeader, type TxEffect, type TxHash, type TxReceipt } from '@aztec/stdlib/tx';
16
+
17
+ import type { DataRetrieval } from './structs/data_retrieval.js';
18
+ import type { L1Published } from './structs/published.js';
27
19
 
28
20
  /**
29
21
  * Represents the latest L1 block processed by the archiver for various objects in L2.
@@ -244,6 +236,14 @@ export interface ArchiverDataStore {
244
236
  addContractInstances(data: ContractInstanceWithAddress[], blockNumber: number): Promise<boolean>;
245
237
  deleteContractInstances(data: ContractInstanceWithAddress[], blockNumber: number): Promise<boolean>;
246
238
 
239
+ /**
240
+ * Add new contract instance updates
241
+ * @param data - List of contract updates to be added.
242
+ * @param blockNumber - Number of the L2 block the updates were scheduled in.
243
+ * @returns True if the operation is successful.
244
+ */
245
+ addContractInstanceUpdates(data: ContractInstanceUpdateWithAddress[], blockNumber: number): Promise<boolean>;
246
+ deleteContractInstanceUpdates(data: ContractInstanceUpdateWithAddress[], blockNumber: number): Promise<boolean>;
247
247
  /**
248
248
  * Adds private functions to a contract class.
249
249
  */
@@ -254,7 +254,7 @@ export interface ArchiverDataStore {
254
254
  ): Promise<boolean>;
255
255
 
256
256
  /**
257
- * Returns a contract instance given its address, or undefined if not exists.
257
+ * Returns a contract instance given its address and the given block number, or undefined if not exists.
258
258
  * @param address - Address of the contract.
259
259
  */
260
260
  getContractInstance(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined>;
@@ -1,30 +1,33 @@
1
- import { InboxLeaf, L2Block, LogId, TxEffect, TxHash, wrapInBlock } from '@aztec/circuit-types';
2
- import '@aztec/circuit-types/jest';
3
1
  import {
4
- AztecAddress,
5
- type ContractClassPublic,
6
- type ContractInstanceWithAddress,
7
- Fr,
8
2
  INITIAL_L2_BLOCK_NUM,
9
3
  L1_TO_L2_MSG_SUBTREE_HEIGHT,
10
4
  MAX_NULLIFIERS_PER_TX,
11
5
  PRIVATE_LOG_SIZE_IN_FIELDS,
12
6
  PUBLIC_LOG_DATA_SIZE_IN_FIELDS,
13
- PrivateLog,
14
- PublicLog,
7
+ } from '@aztec/constants';
8
+ import { times, timesParallel } from '@aztec/foundation/collection';
9
+ import { randomInt } from '@aztec/foundation/crypto';
10
+ import { Fr } from '@aztec/foundation/fields';
11
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
12
+ import { L2Block, wrapInBlock } from '@aztec/stdlib/block';
13
+ import {
14
+ type ContractClassPublic,
15
+ type ContractInstanceWithAddress,
15
16
  SerializableContractInstance,
16
17
  computePublicBytecodeCommitment,
17
- } from '@aztec/circuits.js';
18
+ } from '@aztec/stdlib/contract';
19
+ import { LogId, PrivateLog, PublicLog } from '@aztec/stdlib/logs';
20
+ import { InboxLeaf } from '@aztec/stdlib/messaging';
18
21
  import {
19
22
  makeContractClassPublic,
20
23
  makeExecutablePrivateFunctionWithMembershipProof,
21
24
  makeUnconstrainedFunctionWithMembershipProof,
22
- } from '@aztec/circuits.js/testing';
23
- import { times, timesParallel } from '@aztec/foundation/collection';
24
- import { randomInt } from '@aztec/foundation/crypto';
25
+ } from '@aztec/stdlib/testing';
26
+ import '@aztec/stdlib/testing/jest';
27
+ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
25
28
 
26
- import { type ArchiverDataStore, type ArchiverL1SynchPoint } from './archiver_store.js';
27
- import { type L1Published } from './structs/published.js';
29
+ import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
30
+ import type { L1Published } from './structs/published.js';
28
31
 
29
32
  /**
30
33
  * @param testName - The name of the test suite.
@@ -279,7 +282,11 @@ export function describeArchiverDataStore(
279
282
  const blockNum = 10;
280
283
 
281
284
  beforeEach(async () => {
282
- const randomInstance = await SerializableContractInstance.random();
285
+ const classId = Fr.random();
286
+ const randomInstance = await SerializableContractInstance.random({
287
+ currentContractClassId: classId,
288
+ originalContractClassId: classId,
289
+ });
283
290
  contractInstance = { ...randomInstance, address: await AztecAddress.random() };
284
291
  await store.addContractInstances([contractInstance], blockNum);
285
292
  });
@@ -1,5 +1,4 @@
1
1
  import { type BlobSinkConfig, blobSinkConfigMapping } from '@aztec/blob-sink/client';
2
- import { type ChainConfig, chainConfigMappings } from '@aztec/circuit-types/config';
3
2
  import {
4
3
  type L1ContractAddresses,
5
4
  type L1ContractsConfig,
@@ -8,6 +7,7 @@ import {
8
7
  l1ReaderConfigMappings,
9
8
  } from '@aztec/ethereum';
10
9
  import { type ConfigMappingsType, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config';
10
+ import { type ChainConfig, chainConfigMappings } from '@aztec/stdlib/config';
11
11
 
12
12
  /**
13
13
  * There are 2 polling intervals used in this configuration. The first is the archiver polling interval, archiverPollingIntervalMS.