@aztec/aztec-node 0.0.1-commit.9593d84 → 0.0.1-commit.96bb3f7

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.
@@ -1,6 +1,6 @@
1
1
  import { Archiver, createArchiver } from '@aztec/archiver';
2
2
  import { BBCircuitVerifier, QueuedIVCVerifier, TestCircuitVerifier } from '@aztec/bb-prover';
3
- import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client';
3
+ import { type BlobClientInterface, createBlobClientWithFileStores } from '@aztec/blob-client/client';
4
4
  import {
5
5
  ARCHIVE_HEIGHT,
6
6
  INITIAL_L2_BLOCK_NUM,
@@ -10,17 +10,14 @@ import {
10
10
  type PUBLIC_DATA_TREE_HEIGHT,
11
11
  } from '@aztec/constants';
12
12
  import { EpochCache, type EpochCacheInterface } from '@aztec/epoch-cache';
13
- import {
14
- type L1ContractAddresses,
15
- RegistryContract,
16
- RollupContract,
17
- createEthereumChain,
18
- getPublicClient,
19
- } from '@aztec/ethereum';
20
- import { SlotNumber } from '@aztec/foundation/branded-types';
13
+ import { createEthereumChain } from '@aztec/ethereum/chain';
14
+ import { getPublicClient } from '@aztec/ethereum/client';
15
+ import { RegistryContract, RollupContract } from '@aztec/ethereum/contracts';
16
+ import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
17
+ import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
21
18
  import { compactArray, pick } from '@aztec/foundation/collection';
19
+ import { Fr } from '@aztec/foundation/curves/bn254';
22
20
  import { EthAddress } from '@aztec/foundation/eth-address';
23
- import { Fr } from '@aztec/foundation/fields';
24
21
  import { BadRequestError } from '@aztec/foundation/json-rpc';
25
22
  import { type Logger, createLogger } from '@aztec/foundation/log';
26
23
  import { count } from '@aztec/foundation/string';
@@ -28,16 +25,13 @@ import { DateProvider, Timer } from '@aztec/foundation/timer';
28
25
  import { MembershipWitness, SiblingPath } from '@aztec/foundation/trees';
29
26
  import { KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore';
30
27
  import { trySnapshotSync, uploadSnapshot } from '@aztec/node-lib/actions';
31
- import { createL1TxUtilsWithBlobsFromEthSigner } from '@aztec/node-lib/factories';
28
+ import {
29
+ createForwarderL1TxUtilsFromEthSigner,
30
+ createL1TxUtilsWithBlobsFromEthSigner,
31
+ } from '@aztec/node-lib/factories';
32
32
  import { type P2P, type P2PClientDeps, createP2PClient, getDefaultAllowedSetupFunctions } from '@aztec/p2p';
33
33
  import { ProtocolContractAddress } from '@aztec/protocol-contracts';
34
- import {
35
- BlockBuilder,
36
- GlobalVariableBuilder,
37
- SequencerClient,
38
- type SequencerPublisher,
39
- createValidatorForAcceptingTxs,
40
- } from '@aztec/sequencer-client';
34
+ import { BlockBuilder, GlobalVariableBuilder, SequencerClient, type SequencerPublisher } from '@aztec/sequencer-client';
41
35
  import { PublicProcessorFactory } from '@aztec/simulator/server';
42
36
  import {
43
37
  AttestationsBlockWatcher,
@@ -46,16 +40,18 @@ import {
46
40
  type Watcher,
47
41
  createSlasher,
48
42
  } from '@aztec/slasher';
49
- import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
43
+ import { CollectionLimitsConfig, PublicSimulatorConfig } from '@aztec/stdlib/avm';
50
44
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
51
45
  import {
52
- type InBlock,
46
+ type BlockParameter,
47
+ type DataInBlock,
53
48
  type L2Block,
54
49
  L2BlockHash,
55
- type L2BlockNumber,
50
+ L2BlockNew,
56
51
  type L2BlockSource,
57
52
  type PublishedL2Block,
58
53
  } from '@aztec/stdlib/block';
54
+ import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
59
55
  import type {
60
56
  ContractClassPublic,
61
57
  ContractDataSource,
@@ -63,7 +59,7 @@ import type {
63
59
  NodeInfo,
64
60
  ProtocolContractAddresses,
65
61
  } from '@aztec/stdlib/contract';
66
- import type { GasFees } from '@aztec/stdlib/gas';
62
+ import { GasFees } from '@aztec/stdlib/gas';
67
63
  import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
68
64
  import {
69
65
  type AztecNode,
@@ -82,7 +78,7 @@ import {
82
78
  type WorldStateSynchronizer,
83
79
  tryStop,
84
80
  } from '@aztec/stdlib/interfaces/server';
85
- import type { LogFilter, PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs';
81
+ import type { LogFilter, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
86
82
  import { InboxLeaf, type L1ToL2MessageSource } from '@aztec/stdlib/messaging';
87
83
  import { P2PClientType } from '@aztec/stdlib/p2p';
88
84
  import type { Offense, SlashPayloadRound } from '@aztec/stdlib/slashing';
@@ -110,10 +106,13 @@ import {
110
106
  trackSpan,
111
107
  } from '@aztec/telemetry-client';
112
108
  import {
109
+ FullNodeCheckpointsBuilder as CheckpointsBuilder,
110
+ FullNodeCheckpointsBuilder,
113
111
  NodeKeystoreAdapter,
114
112
  ValidatorClient,
115
113
  createBlockProposalHandler,
116
114
  createValidatorClient,
115
+ createValidatorForAcceptingTxs,
117
116
  } from '@aztec/validator-client';
118
117
  import { createWorldStateSynchronizer } from '@aztec/world-state';
119
118
 
@@ -155,6 +154,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
155
154
  private proofVerifier: ClientProtocolCircuitVerifier,
156
155
  private telemetry: TelemetryClient = getTelemetryClient(),
157
156
  private log = createLogger('node'),
157
+ private blobClient?: BlobClientInterface,
158
158
  ) {
159
159
  this.metrics = new NodeMetrics(telemetry, 'AztecNodeService');
160
160
  this.tracer = telemetry.getTracer('AztecNodeService');
@@ -184,7 +184,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
184
184
  logger?: Logger;
185
185
  publisher?: SequencerPublisher;
186
186
  dateProvider?: DateProvider;
187
- blobSinkClient?: BlobSinkClientInterface;
188
187
  p2pClientDeps?: P2PClientDeps<P2PClientType.Full>;
189
188
  } = {},
190
189
  options: {
@@ -197,8 +196,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
197
196
  const packageVersion = getPackageVersion() ?? '';
198
197
  const telemetry = deps.telemetry ?? getTelemetryClient();
199
198
  const dateProvider = deps.dateProvider ?? new DateProvider();
200
- const blobSinkClient =
201
- deps.blobSinkClient ?? createBlobSinkClient(config, { logger: createLogger('node:blob-sink:client') });
202
199
  const ethereumChain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
203
200
 
204
201
  // Build a key store from file if given or from environment otherwise
@@ -238,7 +235,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
238
235
 
239
236
  const publicClient = createPublicClient({
240
237
  chain: ethereumChain.chainInfo,
241
- transport: fallback(config.l1RpcUrls.map((url: string) => http(url))),
238
+ transport: fallback(config.l1RpcUrls.map((url: string) => http(url, { batch: false }))),
242
239
  pollingInterval: config.viemPollingIntervalMS,
243
240
  });
244
241
 
@@ -266,6 +263,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
266
263
  );
267
264
  }
268
265
 
266
+ const blobClient = await createBlobClientWithFileStores(config, createLogger('node:blob-client:client'));
267
+
269
268
  // attempt snapshot sync if possible
270
269
  await trySnapshotSync(config, log);
271
270
 
@@ -273,7 +272,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
273
272
 
274
273
  const archiver = await createArchiver(
275
274
  config,
276
- { blobSinkClient, epochCache, telemetry, dateProvider },
275
+ { blobClient, epochCache, telemetry, dateProvider },
277
276
  { blockUntilSync: !config.skipArchiverInitialSync },
278
277
  );
279
278
 
@@ -284,9 +283,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
284
283
  options.prefilledPublicData,
285
284
  telemetry,
286
285
  );
287
- const circuitVerifier = config.realProofs
288
- ? await BBCircuitVerifier.new(config)
289
- : new TestCircuitVerifier(config.proverTestVerificationDelayMs);
286
+ const circuitVerifier =
287
+ config.realProofs || config.debugForceTxProofVerification
288
+ ? await BBCircuitVerifier.new(config)
289
+ : new TestCircuitVerifier(config.proverTestVerificationDelayMs);
290
290
  if (!config.realProofs) {
291
291
  log.warn(`Aztec node is accepting fake proofs`);
292
292
  }
@@ -309,6 +309,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
309
309
  // We should really not be modifying the config object
310
310
  config.txPublicSetupAllowList = config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
311
311
 
312
+ // Create BlockBuilder for EpochPruneWatcher (slasher functionality)
312
313
  const blockBuilder = new BlockBuilder(
313
314
  { ...config, l1GenesisTime, slotDuration: Number(slotDuration) },
314
315
  worldStateSynchronizer,
@@ -317,19 +318,29 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
317
318
  telemetry,
318
319
  );
319
320
 
321
+ // Create FullNodeCheckpointsBuilder for validator and non-validator block proposal handling
322
+ const validatorCheckpointsBuilder = new FullNodeCheckpointsBuilder(
323
+ { ...config, l1GenesisTime, slotDuration: Number(slotDuration) },
324
+ archiver,
325
+ dateProvider,
326
+ telemetry,
327
+ );
328
+
320
329
  // We'll accumulate sentinel watchers here
321
330
  const watchers: Watcher[] = [];
322
331
 
323
332
  // Create validator client if required
324
333
  const validatorClient = createValidatorClient(config, {
334
+ checkpointsBuilder: validatorCheckpointsBuilder,
335
+ worldState: worldStateSynchronizer,
325
336
  p2pClient,
326
337
  telemetry,
327
338
  dateProvider,
328
339
  epochCache,
329
- blockBuilder,
330
340
  blockSource: archiver,
331
341
  l1ToL2MessageSource: archiver,
332
342
  keyStoreManager,
343
+ blobClient,
333
344
  });
334
345
 
335
346
  // If we have a validator client, register it as a source of offenses for the slasher,
@@ -347,7 +358,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
347
358
  if (!validatorClient && config.alwaysReexecuteBlockProposals) {
348
359
  log.info('Setting up block proposal reexecution for monitoring');
349
360
  createBlockProposalHandler(config, {
350
- blockBuilder,
361
+ checkpointsBuilder: validatorCheckpointsBuilder,
362
+ worldState: worldStateSynchronizer,
351
363
  epochCache,
352
364
  blockSource: archiver,
353
365
  l1ToL2MessageSource: archiver,
@@ -403,7 +415,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
403
415
  // Validator enabled, create/start relevant service
404
416
  let sequencer: SequencerClient | undefined;
405
417
  let slasherClient: SlasherClientInterface | undefined;
406
- if (!config.disableValidator) {
418
+ if (!config.disableValidator && validatorClient) {
407
419
  // We create a slasher only if we have a sequencer, since all slashing actions go through the sequencer publisher
408
420
  // as they are executed when the node is selected as proposer.
409
421
  const validatorAddresses = keyStoreManager
@@ -422,14 +434,29 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
422
434
  );
423
435
  await slasherClient.start();
424
436
 
425
- const l1TxUtils = await createL1TxUtilsWithBlobsFromEthSigner(
426
- publicClient,
427
- keyStoreManager!.createAllValidatorPublisherSigners(),
428
- { ...config, scope: 'sequencer' },
429
- { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
430
- );
437
+ const l1TxUtils = config.publisherForwarderAddress
438
+ ? await createForwarderL1TxUtilsFromEthSigner(
439
+ publicClient,
440
+ keyStoreManager!.createAllValidatorPublisherSigners(),
441
+ config.publisherForwarderAddress,
442
+ { ...config, scope: 'sequencer' },
443
+ { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
444
+ )
445
+ : await createL1TxUtilsWithBlobsFromEthSigner(
446
+ publicClient,
447
+ keyStoreManager!.createAllValidatorPublisherSigners(),
448
+ { ...config, scope: 'sequencer' },
449
+ { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
450
+ );
431
451
 
432
452
  // Create and start the sequencer client
453
+ const checkpointsBuilder = new CheckpointsBuilder(
454
+ { ...config, l1GenesisTime, slotDuration: Number(slotDuration) },
455
+ archiver,
456
+ dateProvider,
457
+ telemetry,
458
+ );
459
+
433
460
  sequencer = await SequencerClient.new(config, {
434
461
  ...deps,
435
462
  epochCache,
@@ -438,12 +465,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
438
465
  p2pClient,
439
466
  worldStateSynchronizer,
440
467
  slasherClient,
441
- blockBuilder,
468
+ checkpointsBuilder,
442
469
  l2BlockSource: archiver,
443
470
  l1ToL2MessageSource: archiver,
444
471
  telemetry,
445
472
  dateProvider,
446
- blobSinkClient,
473
+ blobClient,
447
474
  nodeKeyStore: keyStoreManager!,
448
475
  });
449
476
  }
@@ -455,6 +482,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
455
482
  log.warn(`Sequencer created but not started`);
456
483
  }
457
484
 
485
+ const globalVariableBuilder = new GlobalVariableBuilder({
486
+ ...config,
487
+ rollupVersion: BigInt(config.rollupVersion),
488
+ l1GenesisTime,
489
+ slotDuration: Number(slotDuration),
490
+ });
491
+
458
492
  return new AztecNodeService(
459
493
  config,
460
494
  p2pClient,
@@ -469,12 +503,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
469
503
  epochPruneWatcher,
470
504
  ethereumChain.chainInfo.id,
471
505
  config.rollupVersion,
472
- new GlobalVariableBuilder(config),
506
+ globalVariableBuilder,
473
507
  epochCache,
474
508
  packageVersion,
475
509
  proofVerifier,
476
510
  telemetry,
477
511
  log,
512
+ blobClient,
478
513
  );
479
514
  }
480
515
 
@@ -549,8 +584,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
549
584
  * @param number - The block number being requested.
550
585
  * @returns The requested block.
551
586
  */
552
- public async getBlock(number: L2BlockNumber): Promise<L2Block | undefined> {
553
- const blockNumber = number === 'latest' ? await this.getBlockNumber() : number;
587
+ public async getBlock(number: BlockParameter): Promise<L2Block | undefined> {
588
+ const blockNumber = number === 'latest' ? await this.getBlockNumber() : (number as BlockNumber);
554
589
  return await this.blockSource.getBlock(blockNumber);
555
590
  }
556
591
 
@@ -580,31 +615,51 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
580
615
  * @param limit - The maximum number of blocks to obtain.
581
616
  * @returns The blocks requested.
582
617
  */
583
- public async getBlocks(from: number, limit: number): Promise<L2Block[]> {
618
+ public async getBlocks(from: BlockNumber, limit: number): Promise<L2Block[]> {
584
619
  return (await this.blockSource.getBlocks(from, limit)) ?? [];
585
620
  }
586
621
 
587
- public async getPublishedBlocks(from: number, limit: number): Promise<PublishedL2Block[]> {
622
+ public async getPublishedBlocks(from: BlockNumber, limit: number): Promise<PublishedL2Block[]> {
588
623
  return (await this.blockSource.getPublishedBlocks(from, limit)) ?? [];
589
624
  }
590
625
 
626
+ public async getPublishedCheckpoints(from: CheckpointNumber, limit: number): Promise<PublishedCheckpoint[]> {
627
+ return (await this.blockSource.getPublishedCheckpoints(from, limit)) ?? [];
628
+ }
629
+
630
+ public async getL2BlocksNew(from: BlockNumber, limit: number): Promise<L2BlockNew[]> {
631
+ return (await this.blockSource.getL2BlocksNew(from, limit)) ?? [];
632
+ }
633
+
634
+ public async getCheckpointedBlocks(from: BlockNumber, limit: number, proven?: boolean) {
635
+ return (await this.blockSource.getCheckpointedBlocks(from, limit, proven)) ?? [];
636
+ }
637
+
591
638
  /**
592
- * Method to fetch the current base fees.
593
- * @returns The current base fees.
639
+ * Method to fetch the current min L2 fees.
640
+ * @returns The current min L2 fees.
594
641
  */
595
- public async getCurrentBaseFees(): Promise<GasFees> {
596
- return await this.globalVariableBuilder.getCurrentBaseFees();
642
+ public async getCurrentMinFees(): Promise<GasFees> {
643
+ return await this.globalVariableBuilder.getCurrentMinFees();
644
+ }
645
+
646
+ public async getMaxPriorityFees(): Promise<GasFees> {
647
+ for await (const tx of this.p2pClient.iteratePendingTxs()) {
648
+ return tx.getGasSettings().maxPriorityFeesPerGas;
649
+ }
650
+
651
+ return GasFees.from({ feePerDaGas: 0n, feePerL2Gas: 0n });
597
652
  }
598
653
 
599
654
  /**
600
655
  * Method to fetch the latest block number synchronized by the node.
601
656
  * @returns The block number.
602
657
  */
603
- public async getBlockNumber(): Promise<number> {
658
+ public async getBlockNumber(): Promise<BlockNumber> {
604
659
  return await this.blockSource.getBlockNumber();
605
660
  }
606
661
 
607
- public async getProvenBlockNumber(): Promise<number> {
662
+ public async getProvenBlockNumber(): Promise<BlockNumber> {
608
663
  return await this.blockSource.getProvenBlockNumber();
609
664
  }
610
665
 
@@ -640,25 +695,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
640
695
  return this.contractDataSource.getContract(address);
641
696
  }
642
697
 
643
- /**
644
- * Retrieves all private logs from up to `limit` blocks, starting from the block number `from`.
645
- * @param from - The block number from which to begin retrieving logs.
646
- * @param limit - The maximum number of blocks to retrieve logs from.
647
- * @returns An array of private logs from the specified range of blocks.
648
- */
649
- public getPrivateLogs(from: number, limit: number): Promise<PrivateLog[]> {
650
- return this.logsSource.getPrivateLogs(from, limit);
698
+ public getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
699
+ return this.logsSource.getPrivateLogsByTags(tags);
651
700
  }
652
701
 
653
- /**
654
- * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag).
655
- * @param tags - The tags to filter the logs by.
656
- * @param logsPerTag - The maximum number of logs to return for each tag. By default no limit is set
657
- * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
658
- * that tag.
659
- */
660
- public getLogsByTags(tags: Fr[], logsPerTag?: number): Promise<TxScopedL2Log[][]> {
661
- return this.logsSource.getLogsByTags(tags, logsPerTag);
702
+ public getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
703
+ return this.logsSource.getPublicLogsByTagsFromContract(contractAddress, tags);
662
704
  }
663
705
 
664
706
  /**
@@ -739,10 +781,19 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
739
781
  await tryStop(this.p2pClient);
740
782
  await tryStop(this.worldStateSynchronizer);
741
783
  await tryStop(this.blockSource);
784
+ await tryStop(this.blobClient);
742
785
  await tryStop(this.telemetry);
743
786
  this.log.info(`Stopped Aztec Node`);
744
787
  }
745
788
 
789
+ /**
790
+ * Returns the blob client used by this node.
791
+ * @internal - Exposed for testing purposes only.
792
+ */
793
+ public getBlobClient(): BlobClientInterface | undefined {
794
+ return this.blobClient;
795
+ }
796
+
746
797
  /**
747
798
  * Method to retrieve pending txs.
748
799
  * @param limit - The number of items to returns
@@ -784,10 +835,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
784
835
  * @returns The indices of leaves and the block metadata of a block in which the leaves were inserted.
785
836
  */
786
837
  public async findLeavesIndexes(
787
- blockNumber: L2BlockNumber,
838
+ blockNumber: BlockParameter,
788
839
  treeId: MerkleTreeId,
789
840
  leafValues: Fr[],
790
- ): Promise<(InBlock<bigint> | undefined)[]> {
841
+ ): Promise<(DataInBlock<bigint> | undefined)[]> {
791
842
  const committedDb = await this.#getWorldState(blockNumber);
792
843
  const maybeIndices = await committedDb.findLeafIndices(
793
844
  treeId,
@@ -813,7 +864,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
813
864
  // (note that block number corresponds to the leaf index in the archive tree).
814
865
  const blockHashes = await Promise.all(
815
866
  uniqueBlockNumbers.map(blockNumber => {
816
- return committedDb.getLeafValue(MerkleTreeId.ARCHIVE, blockNumber!);
867
+ return committedDb.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(blockNumber));
817
868
  }),
818
869
  );
819
870
 
@@ -824,7 +875,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
824
875
  }
825
876
  }
826
877
 
827
- // Create InBlock objects by combining indices, blockNumbers and blockHashes and return them.
878
+ // Create DataInBlock objects by combining indices, blockNumbers and blockHashes and return them.
828
879
  return maybeIndices.map((index, i) => {
829
880
  if (index === undefined) {
830
881
  return undefined;
@@ -839,7 +890,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
839
890
  return undefined;
840
891
  }
841
892
  return {
842
- l2BlockNumber: Number(blockNumber),
893
+ l2BlockNumber: BlockNumber(Number(blockNumber)),
843
894
  l2BlockHash: L2BlockHash.fromField(blockHash),
844
895
  data: index,
845
896
  };
@@ -853,7 +904,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
853
904
  * @returns The sibling path for the leaf index.
854
905
  */
855
906
  public async getNullifierSiblingPath(
856
- blockNumber: L2BlockNumber,
907
+ blockNumber: BlockParameter,
857
908
  leafIndex: bigint,
858
909
  ): Promise<SiblingPath<typeof NULLIFIER_TREE_HEIGHT>> {
859
910
  const committedDb = await this.#getWorldState(blockNumber);
@@ -867,7 +918,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
867
918
  * @returns The sibling path for the leaf index.
868
919
  */
869
920
  public async getNoteHashSiblingPath(
870
- blockNumber: L2BlockNumber,
921
+ blockNumber: BlockParameter,
871
922
  leafIndex: bigint,
872
923
  ): Promise<SiblingPath<typeof NOTE_HASH_TREE_HEIGHT>> {
873
924
  const committedDb = await this.#getWorldState(blockNumber);
@@ -875,7 +926,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
875
926
  }
876
927
 
877
928
  public async getArchiveMembershipWitness(
878
- blockNumber: L2BlockNumber,
929
+ blockNumber: BlockParameter,
879
930
  archive: Fr,
880
931
  ): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
881
932
  const committedDb = await this.#getWorldState(blockNumber);
@@ -886,7 +937,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
886
937
  }
887
938
 
888
939
  public async getNoteHashMembershipWitness(
889
- blockNumber: L2BlockNumber,
940
+ blockNumber: BlockParameter,
890
941
  noteHash: Fr,
891
942
  ): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
892
943
  const committedDb = await this.#getWorldState(blockNumber);
@@ -906,7 +957,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
906
957
  * @returns A tuple of the index and the sibling path of the L1ToL2Message (undefined if not found).
907
958
  */
908
959
  public async getL1ToL2MessageMembershipWitness(
909
- blockNumber: L2BlockNumber,
960
+ blockNumber: BlockParameter,
910
961
  l1ToL2Message: Fr,
911
962
  ): Promise<[bigint, SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>] | undefined> {
912
963
  const db = await this.#getWorldState(blockNumber);
@@ -919,9 +970,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
919
970
  return [witness.index, witness.path];
920
971
  }
921
972
 
922
- public async getL1ToL2MessageBlock(l1ToL2Message: Fr): Promise<number | undefined> {
973
+ public async getL1ToL2MessageBlock(l1ToL2Message: Fr): Promise<BlockNumber | undefined> {
923
974
  const messageIndex = await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message);
924
- return messageIndex ? InboxLeaf.l2BlockFromIndex(messageIndex) : undefined;
975
+ return messageIndex
976
+ ? BlockNumber.fromCheckpointNumber(InboxLeaf.checkpointNumberFromIndex(messageIndex))
977
+ : undefined;
925
978
  }
926
979
 
927
980
  /**
@@ -935,13 +988,28 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
935
988
  }
936
989
 
937
990
  /**
938
- * Returns all the L2 to L1 messages in a block.
939
- * @param blockNumber - The block number at which to get the data.
940
- * @returns The L2 to L1 messages (undefined if the block number is not found).
991
+ * Returns all the L2 to L1 messages in an epoch.
992
+ * @param epoch - The epoch at which to get the data.
993
+ * @returns The L2 to L1 messages (empty array if the epoch is not found).
941
994
  */
942
- public async getL2ToL1Messages(blockNumber: L2BlockNumber): Promise<Fr[][] | undefined> {
943
- const block = await this.blockSource.getBlock(blockNumber === 'latest' ? await this.getBlockNumber() : blockNumber);
944
- return block?.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs);
995
+ public async getL2ToL1Messages(epoch: EpochNumber): Promise<Fr[][][][]> {
996
+ // Assumes `getBlocksForEpoch` returns blocks in ascending order of block number.
997
+ const blocks = await this.blockSource.getBlocksForEpoch(epoch);
998
+ const blocksInCheckpoints: L2Block[][] = [];
999
+ let previousSlotNumber = SlotNumber.ZERO;
1000
+ let checkpointIndex = -1;
1001
+ for (const block of blocks) {
1002
+ const slotNumber = block.header.globalVariables.slotNumber;
1003
+ if (slotNumber !== previousSlotNumber) {
1004
+ checkpointIndex++;
1005
+ blocksInCheckpoints.push([]);
1006
+ previousSlotNumber = slotNumber;
1007
+ }
1008
+ blocksInCheckpoints[checkpointIndex].push(block);
1009
+ }
1010
+ return blocksInCheckpoints.map(blocks =>
1011
+ blocks.map(block => block.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs)),
1012
+ );
945
1013
  }
946
1014
 
947
1015
  /**
@@ -951,7 +1019,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
951
1019
  * @returns The sibling path.
952
1020
  */
953
1021
  public async getArchiveSiblingPath(
954
- blockNumber: L2BlockNumber,
1022
+ blockNumber: BlockParameter,
955
1023
  leafIndex: bigint,
956
1024
  ): Promise<SiblingPath<typeof ARCHIVE_HEIGHT>> {
957
1025
  const committedDb = await this.#getWorldState(blockNumber);
@@ -965,7 +1033,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
965
1033
  * @returns The sibling path.
966
1034
  */
967
1035
  public async getPublicDataSiblingPath(
968
- blockNumber: L2BlockNumber,
1036
+ blockNumber: BlockParameter,
969
1037
  leafIndex: bigint,
970
1038
  ): Promise<SiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>> {
971
1039
  const committedDb = await this.#getWorldState(blockNumber);
@@ -979,7 +1047,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
979
1047
  * @returns The nullifier membership witness (if found).
980
1048
  */
981
1049
  public async getNullifierMembershipWitness(
982
- blockNumber: L2BlockNumber,
1050
+ blockNumber: BlockParameter,
983
1051
  nullifier: Fr,
984
1052
  ): Promise<NullifierMembershipWitness | undefined> {
985
1053
  const db = await this.#getWorldState(blockNumber);
@@ -1012,7 +1080,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1012
1080
  * TODO: This is a confusing behavior and we should eventually address that.
1013
1081
  */
1014
1082
  public async getLowNullifierMembershipWitness(
1015
- blockNumber: L2BlockNumber,
1083
+ blockNumber: BlockParameter,
1016
1084
  nullifier: Fr,
1017
1085
  ): Promise<NullifierMembershipWitness | undefined> {
1018
1086
  const committedDb = await this.#getWorldState(blockNumber);
@@ -1030,7 +1098,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1030
1098
  return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath);
1031
1099
  }
1032
1100
 
1033
- async getPublicDataWitness(blockNumber: L2BlockNumber, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
1101
+ async getPublicDataWitness(blockNumber: BlockParameter, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
1034
1102
  const committedDb = await this.#getWorldState(blockNumber);
1035
1103
  const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
1036
1104
  if (!lowLeafResult) {
@@ -1056,7 +1124,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1056
1124
  * @param blockNumber - The block number at which to get the data or 'latest'.
1057
1125
  * @returns Storage value at the given contract slot.
1058
1126
  */
1059
- public async getPublicStorageAt(blockNumber: L2BlockNumber, contract: AztecAddress, slot: Fr): Promise<Fr> {
1127
+ public async getPublicStorageAt(blockNumber: BlockParameter, contract: AztecAddress, slot: Fr): Promise<Fr> {
1060
1128
  const committedDb = await this.#getWorldState(blockNumber);
1061
1129
  const leafSlot = await computePublicDataTreeLeafSlot(contract, slot);
1062
1130
 
@@ -1075,10 +1143,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1075
1143
  * Returns the currently committed block header, or the initial header if no blocks have been produced.
1076
1144
  * @returns The current committed block header.
1077
1145
  */
1078
- public async getBlockHeader(blockNumber: L2BlockNumber = 'latest'): Promise<BlockHeader | undefined> {
1079
- return blockNumber === 0 || (blockNumber === 'latest' && (await this.blockSource.getBlockNumber()) === 0)
1146
+ public async getBlockHeader(blockNumber: BlockParameter = 'latest'): Promise<BlockHeader | undefined> {
1147
+ return blockNumber === BlockNumber.ZERO ||
1148
+ (blockNumber === 'latest' && (await this.blockSource.getBlockNumber()) === BlockNumber.ZERO)
1080
1149
  ? this.worldStateSynchronizer.getCommitted().getInitialHeader()
1081
- : this.blockSource.getBlockHeader(blockNumber);
1150
+ : this.blockSource.getBlockHeader(blockNumber === 'latest' ? blockNumber : (blockNumber as BlockNumber));
1082
1151
  }
1083
1152
 
1084
1153
  /**
@@ -1122,7 +1191,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1122
1191
  }
1123
1192
 
1124
1193
  const txHash = tx.getTxHash();
1125
- const blockNumber = (await this.blockSource.getBlockNumber()) + 1;
1194
+ const blockNumber = BlockNumber((await this.blockSource.getBlockNumber()) + 1);
1126
1195
 
1127
1196
  // If sequencer is not initialized, we just set these values to zero for simulation.
1128
1197
  const coinbase = EthAddress.ZERO;
@@ -1152,8 +1221,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1152
1221
  collectDebugLogs: true,
1153
1222
  collectHints: false,
1154
1223
  collectCallMetadata: true,
1155
- maxDebugLogMemoryReads: this.config.rpcSimulatePublicMaxDebugLogMemoryReads,
1156
1224
  collectStatistics: false,
1225
+ collectionLimits: CollectionLimitsConfig.from({
1226
+ maxDebugLogMemoryReads: this.config.rpcSimulatePublicMaxDebugLogMemoryReads,
1227
+ }),
1157
1228
  });
1158
1229
  const processor = publicProcessorFactory.create(merkleTreeFork, newGlobalVariables, config);
1159
1230
 
@@ -1187,14 +1258,14 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1187
1258
 
1188
1259
  // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1189
1260
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1190
- const blockNumber = (await this.blockSource.getBlockNumber()) + 1;
1261
+ const blockNumber = BlockNumber((await this.blockSource.getBlockNumber()) + 1);
1191
1262
  const validator = createValidatorForAcceptingTxs(db, this.contractDataSource, verifier, {
1192
1263
  timestamp: nextSlotTimestamp,
1193
1264
  blockNumber,
1194
1265
  l1ChainId: this.l1ChainId,
1195
1266
  rollupVersion: this.version,
1196
1267
  setupAllowList: this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions()),
1197
- gasFees: await this.getCurrentBaseFees(),
1268
+ gasFees: await this.getCurrentMinFees(),
1198
1269
  skipFeeEnforcement,
1199
1270
  txsPermitted: !this.config.disableTransactions,
1200
1271
  });
@@ -1266,7 +1337,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1266
1337
  }
1267
1338
 
1268
1339
  // And it has an L2 block hash
1269
- const l2BlockHash = await archiver.getL2Tips().then(tips => tips.latest.hash);
1340
+ const l2BlockHash = await archiver.getL2Tips().then(tips => tips.proposed.hash);
1270
1341
  if (!l2BlockHash) {
1271
1342
  this.metrics.recordSnapshotError();
1272
1343
  throw new Error(`Archiver has no latest L2 block hash downloaded. Cannot start snapshot.`);
@@ -1294,13 +1365,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1294
1365
  return Promise.resolve();
1295
1366
  }
1296
1367
 
1297
- public async rollbackTo(targetBlock: number, force?: boolean): Promise<void> {
1368
+ public async rollbackTo(targetBlock: BlockNumber, force?: boolean): Promise<void> {
1298
1369
  const archiver = this.blockSource as Archiver;
1299
1370
  if (!('rollbackTo' in archiver)) {
1300
1371
  throw new Error('Archiver implementation does not support rollbacks.');
1301
1372
  }
1302
1373
 
1303
- const finalizedBlock = await archiver.getL2Tips().then(tips => tips.finalized.number);
1374
+ const finalizedBlock = await archiver.getL2Tips().then(tips => tips.finalized.block.number);
1304
1375
  if (targetBlock < finalizedBlock) {
1305
1376
  if (force) {
1306
1377
  this.log.warn(`Clearing world state database to allow rolling back behind finalized block ${finalizedBlock}`);
@@ -1366,12 +1437,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1366
1437
  * @param blockNumber - The block number at which to get the data.
1367
1438
  * @returns An instance of a committed MerkleTreeOperations
1368
1439
  */
1369
- async #getWorldState(blockNumber: L2BlockNumber) {
1440
+ async #getWorldState(blockNumber: BlockParameter) {
1370
1441
  if (typeof blockNumber === 'number' && blockNumber < INITIAL_L2_BLOCK_NUM - 1) {
1371
1442
  throw new Error('Invalid block number to get world state for: ' + blockNumber);
1372
1443
  }
1373
1444
 
1374
- let blockSyncedTo: number = 0;
1445
+ let blockSyncedTo: BlockNumber = BlockNumber.ZERO;
1375
1446
  try {
1376
1447
  // Attempt to sync the world state if necessary
1377
1448
  blockSyncedTo = await this.#syncWorldState();
@@ -1385,7 +1456,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1385
1456
  return this.worldStateSynchronizer.getCommitted();
1386
1457
  } else if (blockNumber <= blockSyncedTo) {
1387
1458
  this.log.debug(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
1388
- return this.worldStateSynchronizer.getSnapshot(blockNumber);
1459
+ return this.worldStateSynchronizer.getSnapshot(blockNumber as BlockNumber);
1389
1460
  } else {
1390
1461
  throw new Error(`Block ${blockNumber} not yet synced`);
1391
1462
  }
@@ -1395,8 +1466,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1395
1466
  * Ensure we fully sync the world state
1396
1467
  * @returns A promise that fulfils once the world state is synced
1397
1468
  */
1398
- async #syncWorldState(): Promise<number> {
1469
+ async #syncWorldState(): Promise<BlockNumber> {
1399
1470
  const blockSourceHeight = await this.blockSource.getBlockNumber();
1400
- return this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
1471
+ return await this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
1401
1472
  }
1402
1473
  }