@aztec/aztec-node 0.0.1-commit.9b94fc1 → 0.0.1-commit.c7c42ec

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,11 @@
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, createBlobClient } from '@aztec/blob-client/client';
4
+ import {
5
+ type BlobFileStoreMetadata,
6
+ createReadOnlyFileStoreBlobClients,
7
+ createWritableFileStoreBlobClient,
8
+ } from '@aztec/blob-client/filestore';
4
9
  import {
5
10
  ARCHIVE_HEIGHT,
6
11
  INITIAL_L2_BLOCK_NUM,
@@ -10,17 +15,14 @@ import {
10
15
  type PUBLIC_DATA_TREE_HEIGHT,
11
16
  } from '@aztec/constants';
12
17
  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';
18
+ import { createEthereumChain } from '@aztec/ethereum/chain';
19
+ import { getPublicClient } from '@aztec/ethereum/client';
20
+ import { RegistryContract, RollupContract } from '@aztec/ethereum/contracts';
21
+ import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
22
+ import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
21
23
  import { compactArray, pick } from '@aztec/foundation/collection';
24
+ import { Fr } from '@aztec/foundation/curves/bn254';
22
25
  import { EthAddress } from '@aztec/foundation/eth-address';
23
- import { Fr } from '@aztec/foundation/fields';
24
26
  import { BadRequestError } from '@aztec/foundation/json-rpc';
25
27
  import { type Logger, createLogger } from '@aztec/foundation/log';
26
28
  import { count } from '@aztec/foundation/string';
@@ -28,7 +30,10 @@ import { DateProvider, Timer } from '@aztec/foundation/timer';
28
30
  import { MembershipWitness, SiblingPath } from '@aztec/foundation/trees';
29
31
  import { KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore';
30
32
  import { trySnapshotSync, uploadSnapshot } from '@aztec/node-lib/actions';
31
- import { createL1TxUtilsWithBlobsFromEthSigner } from '@aztec/node-lib/factories';
33
+ import {
34
+ createForwarderL1TxUtilsFromEthSigner,
35
+ createL1TxUtilsWithBlobsFromEthSigner,
36
+ } from '@aztec/node-lib/factories';
32
37
  import { type P2P, type P2PClientDeps, createP2PClient, getDefaultAllowedSetupFunctions } from '@aztec/p2p';
33
38
  import { ProtocolContractAddress } from '@aztec/protocol-contracts';
34
39
  import {
@@ -38,6 +43,7 @@ import {
38
43
  type SequencerPublisher,
39
44
  createValidatorForAcceptingTxs,
40
45
  } from '@aztec/sequencer-client';
46
+ import { CheckpointsBuilder } from '@aztec/sequencer-client';
41
47
  import { PublicProcessorFactory } from '@aztec/simulator/server';
42
48
  import {
43
49
  AttestationsBlockWatcher,
@@ -46,13 +52,13 @@ import {
46
52
  type Watcher,
47
53
  createSlasher,
48
54
  } from '@aztec/slasher';
49
- import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
55
+ import { CollectionLimitsConfig, PublicSimulatorConfig } from '@aztec/stdlib/avm';
50
56
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
51
57
  import {
52
- type InBlock,
58
+ type BlockParameter,
59
+ type DataInBlock,
53
60
  type L2Block,
54
61
  L2BlockHash,
55
- type L2BlockNumber,
56
62
  type L2BlockSource,
57
63
  type PublishedL2Block,
58
64
  } from '@aztec/stdlib/block';
@@ -63,7 +69,7 @@ import type {
63
69
  NodeInfo,
64
70
  ProtocolContractAddresses,
65
71
  } from '@aztec/stdlib/contract';
66
- import type { GasFees } from '@aztec/stdlib/gas';
72
+ import { GasFees } from '@aztec/stdlib/gas';
67
73
  import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
68
74
  import {
69
75
  type AztecNode,
@@ -82,7 +88,7 @@ import {
82
88
  type WorldStateSynchronizer,
83
89
  tryStop,
84
90
  } from '@aztec/stdlib/interfaces/server';
85
- import type { LogFilter, PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs';
91
+ import type { LogFilter, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
86
92
  import { InboxLeaf, type L1ToL2MessageSource } from '@aztec/stdlib/messaging';
87
93
  import { P2PClientType } from '@aztec/stdlib/p2p';
88
94
  import type { Offense, SlashPayloadRound } from '@aztec/stdlib/slashing';
@@ -155,6 +161,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
155
161
  private proofVerifier: ClientProtocolCircuitVerifier,
156
162
  private telemetry: TelemetryClient = getTelemetryClient(),
157
163
  private log = createLogger('node'),
164
+ private blobClient?: BlobClientInterface,
158
165
  ) {
159
166
  this.metrics = new NodeMetrics(telemetry, 'AztecNodeService');
160
167
  this.tracer = telemetry.getTracer('AztecNodeService');
@@ -184,7 +191,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
184
191
  logger?: Logger;
185
192
  publisher?: SequencerPublisher;
186
193
  dateProvider?: DateProvider;
187
- blobSinkClient?: BlobSinkClientInterface;
194
+ blobClient?: BlobClientInterface;
188
195
  p2pClientDeps?: P2PClientDeps<P2PClientType.Full>;
189
196
  } = {},
190
197
  options: {
@@ -197,8 +204,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
197
204
  const packageVersion = getPackageVersion() ?? '';
198
205
  const telemetry = deps.telemetry ?? getTelemetryClient();
199
206
  const dateProvider = deps.dateProvider ?? new DateProvider();
200
- const blobSinkClient =
201
- deps.blobSinkClient ?? createBlobSinkClient(config, { logger: createLogger('node:blob-sink:client') });
202
207
  const ethereumChain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
203
208
 
204
209
  // Build a key store from file if given or from environment otherwise
@@ -238,7 +243,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
238
243
 
239
244
  const publicClient = createPublicClient({
240
245
  chain: ethereumChain.chainInfo,
241
- transport: fallback(config.l1RpcUrls.map((url: string) => http(url))),
246
+ transport: fallback(config.l1RpcUrls.map((url: string) => http(url, { batch: false }))),
242
247
  pollingInterval: config.viemPollingIntervalMS,
243
248
  });
244
249
 
@@ -266,6 +271,25 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
266
271
  );
267
272
  }
268
273
 
274
+ const blobFileStoreMetadata: BlobFileStoreMetadata = {
275
+ l1ChainId: config.l1ChainId,
276
+ rollupVersion: config.rollupVersion,
277
+ rollupAddress: config.l1Contracts.rollupAddress.toString(),
278
+ };
279
+
280
+ const [fileStoreClients, fileStoreUploadClient] = await Promise.all([
281
+ createReadOnlyFileStoreBlobClients(config.blobFileStoreUrls, blobFileStoreMetadata, log),
282
+ createWritableFileStoreBlobClient(config.blobFileStoreUploadUrl, blobFileStoreMetadata, log),
283
+ ]);
284
+
285
+ const blobClient =
286
+ deps.blobClient ??
287
+ createBlobClient(config, {
288
+ logger: createLogger('node:blob-client:client'),
289
+ fileStoreClients,
290
+ fileStoreUploadClient,
291
+ });
292
+
269
293
  // attempt snapshot sync if possible
270
294
  await trySnapshotSync(config, log);
271
295
 
@@ -273,7 +297,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
273
297
 
274
298
  const archiver = await createArchiver(
275
299
  config,
276
- { blobSinkClient, epochCache, telemetry, dateProvider },
300
+ { blobClient, epochCache, telemetry, dateProvider },
277
301
  { blockUntilSync: !config.skipArchiverInitialSync },
278
302
  );
279
303
 
@@ -284,9 +308,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
284
308
  options.prefilledPublicData,
285
309
  telemetry,
286
310
  );
287
- const circuitVerifier = config.realProofs
288
- ? await BBCircuitVerifier.new(config)
289
- : new TestCircuitVerifier(config.proverTestVerificationDelayMs);
311
+ const circuitVerifier =
312
+ config.realProofs || config.debugForceTxProofVerification
313
+ ? await BBCircuitVerifier.new(config)
314
+ : new TestCircuitVerifier(config.proverTestVerificationDelayMs);
290
315
  if (!config.realProofs) {
291
316
  log.warn(`Aztec node is accepting fake proofs`);
292
317
  }
@@ -330,6 +355,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
330
355
  blockSource: archiver,
331
356
  l1ToL2MessageSource: archiver,
332
357
  keyStoreManager,
358
+ fileStoreBlobUploadClient: fileStoreUploadClient,
333
359
  });
334
360
 
335
361
  // If we have a validator client, register it as a source of offenses for the slasher,
@@ -403,7 +429,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
403
429
  // Validator enabled, create/start relevant service
404
430
  let sequencer: SequencerClient | undefined;
405
431
  let slasherClient: SlasherClientInterface | undefined;
406
- if (!config.disableValidator) {
432
+ if (!config.disableValidator && validatorClient) {
407
433
  // We create a slasher only if we have a sequencer, since all slashing actions go through the sequencer publisher
408
434
  // as they are executed when the node is selected as proposer.
409
435
  const validatorAddresses = keyStoreManager
@@ -422,14 +448,29 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
422
448
  );
423
449
  await slasherClient.start();
424
450
 
425
- const l1TxUtils = await createL1TxUtilsWithBlobsFromEthSigner(
426
- publicClient,
427
- keyStoreManager!.createAllValidatorPublisherSigners(),
428
- { ...config, scope: 'sequencer' },
429
- { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
430
- );
451
+ const l1TxUtils = config.publisherForwarderAddress
452
+ ? await createForwarderL1TxUtilsFromEthSigner(
453
+ publicClient,
454
+ keyStoreManager!.createAllValidatorPublisherSigners(),
455
+ config.publisherForwarderAddress,
456
+ { ...config, scope: 'sequencer' },
457
+ { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
458
+ )
459
+ : await createL1TxUtilsWithBlobsFromEthSigner(
460
+ publicClient,
461
+ keyStoreManager!.createAllValidatorPublisherSigners(),
462
+ { ...config, scope: 'sequencer' },
463
+ { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
464
+ );
431
465
 
432
466
  // Create and start the sequencer client
467
+ const checkpointsBuilder = new CheckpointsBuilder(
468
+ { ...config, l1GenesisTime, slotDuration: Number(slotDuration) },
469
+ archiver,
470
+ dateProvider,
471
+ telemetry,
472
+ );
473
+
433
474
  sequencer = await SequencerClient.new(config, {
434
475
  ...deps,
435
476
  epochCache,
@@ -438,12 +479,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
438
479
  p2pClient,
439
480
  worldStateSynchronizer,
440
481
  slasherClient,
441
- blockBuilder,
482
+ checkpointsBuilder,
442
483
  l2BlockSource: archiver,
443
484
  l1ToL2MessageSource: archiver,
444
485
  telemetry,
445
486
  dateProvider,
446
- blobSinkClient,
487
+ blobClient,
447
488
  nodeKeyStore: keyStoreManager!,
448
489
  });
449
490
  }
@@ -455,6 +496,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
455
496
  log.warn(`Sequencer created but not started`);
456
497
  }
457
498
 
499
+ const globalVariableBuilder = new GlobalVariableBuilder({
500
+ ...config,
501
+ rollupVersion: BigInt(config.rollupVersion),
502
+ l1GenesisTime,
503
+ slotDuration: Number(slotDuration),
504
+ });
505
+
458
506
  return new AztecNodeService(
459
507
  config,
460
508
  p2pClient,
@@ -469,12 +517,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
469
517
  epochPruneWatcher,
470
518
  ethereumChain.chainInfo.id,
471
519
  config.rollupVersion,
472
- new GlobalVariableBuilder(config),
520
+ globalVariableBuilder,
473
521
  epochCache,
474
522
  packageVersion,
475
523
  proofVerifier,
476
524
  telemetry,
477
525
  log,
526
+ blobClient,
478
527
  );
479
528
  }
480
529
 
@@ -549,8 +598,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
549
598
  * @param number - The block number being requested.
550
599
  * @returns The requested block.
551
600
  */
552
- public async getBlock(number: L2BlockNumber): Promise<L2Block | undefined> {
553
- const blockNumber = number === 'latest' ? await this.getBlockNumber() : number;
601
+ public async getBlock(number: BlockParameter): Promise<L2Block | undefined> {
602
+ const blockNumber = number === 'latest' ? await this.getBlockNumber() : (number as BlockNumber);
554
603
  return await this.blockSource.getBlock(blockNumber);
555
604
  }
556
605
 
@@ -580,11 +629,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
580
629
  * @param limit - The maximum number of blocks to obtain.
581
630
  * @returns The blocks requested.
582
631
  */
583
- public async getBlocks(from: number, limit: number): Promise<L2Block[]> {
632
+ public async getBlocks(from: BlockNumber, limit: number): Promise<L2Block[]> {
584
633
  return (await this.blockSource.getBlocks(from, limit)) ?? [];
585
634
  }
586
635
 
587
- public async getPublishedBlocks(from: number, limit: number): Promise<PublishedL2Block[]> {
636
+ public async getPublishedBlocks(from: BlockNumber, limit: number): Promise<PublishedL2Block[]> {
588
637
  return (await this.blockSource.getPublishedBlocks(from, limit)) ?? [];
589
638
  }
590
639
 
@@ -596,15 +645,23 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
596
645
  return await this.globalVariableBuilder.getCurrentBaseFees();
597
646
  }
598
647
 
648
+ public async getMaxPriorityFees(): Promise<GasFees> {
649
+ for await (const tx of this.p2pClient.iteratePendingTxs()) {
650
+ return tx.getGasSettings().maxPriorityFeesPerGas;
651
+ }
652
+
653
+ return GasFees.from({ feePerDaGas: 0n, feePerL2Gas: 0n });
654
+ }
655
+
599
656
  /**
600
657
  * Method to fetch the latest block number synchronized by the node.
601
658
  * @returns The block number.
602
659
  */
603
- public async getBlockNumber(): Promise<number> {
660
+ public async getBlockNumber(): Promise<BlockNumber> {
604
661
  return await this.blockSource.getBlockNumber();
605
662
  }
606
663
 
607
- public async getProvenBlockNumber(): Promise<number> {
664
+ public async getProvenBlockNumber(): Promise<BlockNumber> {
608
665
  return await this.blockSource.getProvenBlockNumber();
609
666
  }
610
667
 
@@ -640,25 +697,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
640
697
  return this.contractDataSource.getContract(address);
641
698
  }
642
699
 
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);
700
+ public getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
701
+ return this.logsSource.getPrivateLogsByTags(tags);
651
702
  }
652
703
 
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);
704
+ public getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
705
+ return this.logsSource.getPublicLogsByTagsFromContract(contractAddress, tags);
662
706
  }
663
707
 
664
708
  /**
@@ -739,6 +783,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
739
783
  await tryStop(this.p2pClient);
740
784
  await tryStop(this.worldStateSynchronizer);
741
785
  await tryStop(this.blockSource);
786
+ await tryStop(this.blobClient);
742
787
  await tryStop(this.telemetry);
743
788
  this.log.info(`Stopped Aztec Node`);
744
789
  }
@@ -784,10 +829,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
784
829
  * @returns The indices of leaves and the block metadata of a block in which the leaves were inserted.
785
830
  */
786
831
  public async findLeavesIndexes(
787
- blockNumber: L2BlockNumber,
832
+ blockNumber: BlockParameter,
788
833
  treeId: MerkleTreeId,
789
834
  leafValues: Fr[],
790
- ): Promise<(InBlock<bigint> | undefined)[]> {
835
+ ): Promise<(DataInBlock<bigint> | undefined)[]> {
791
836
  const committedDb = await this.#getWorldState(blockNumber);
792
837
  const maybeIndices = await committedDb.findLeafIndices(
793
838
  treeId,
@@ -813,7 +858,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
813
858
  // (note that block number corresponds to the leaf index in the archive tree).
814
859
  const blockHashes = await Promise.all(
815
860
  uniqueBlockNumbers.map(blockNumber => {
816
- return committedDb.getLeafValue(MerkleTreeId.ARCHIVE, blockNumber!);
861
+ return committedDb.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(blockNumber));
817
862
  }),
818
863
  );
819
864
 
@@ -824,7 +869,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
824
869
  }
825
870
  }
826
871
 
827
- // Create InBlock objects by combining indices, blockNumbers and blockHashes and return them.
872
+ // Create DataInBlock objects by combining indices, blockNumbers and blockHashes and return them.
828
873
  return maybeIndices.map((index, i) => {
829
874
  if (index === undefined) {
830
875
  return undefined;
@@ -839,7 +884,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
839
884
  return undefined;
840
885
  }
841
886
  return {
842
- l2BlockNumber: Number(blockNumber),
887
+ l2BlockNumber: BlockNumber(Number(blockNumber)),
843
888
  l2BlockHash: L2BlockHash.fromField(blockHash),
844
889
  data: index,
845
890
  };
@@ -853,7 +898,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
853
898
  * @returns The sibling path for the leaf index.
854
899
  */
855
900
  public async getNullifierSiblingPath(
856
- blockNumber: L2BlockNumber,
901
+ blockNumber: BlockParameter,
857
902
  leafIndex: bigint,
858
903
  ): Promise<SiblingPath<typeof NULLIFIER_TREE_HEIGHT>> {
859
904
  const committedDb = await this.#getWorldState(blockNumber);
@@ -867,7 +912,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
867
912
  * @returns The sibling path for the leaf index.
868
913
  */
869
914
  public async getNoteHashSiblingPath(
870
- blockNumber: L2BlockNumber,
915
+ blockNumber: BlockParameter,
871
916
  leafIndex: bigint,
872
917
  ): Promise<SiblingPath<typeof NOTE_HASH_TREE_HEIGHT>> {
873
918
  const committedDb = await this.#getWorldState(blockNumber);
@@ -875,7 +920,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
875
920
  }
876
921
 
877
922
  public async getArchiveMembershipWitness(
878
- blockNumber: L2BlockNumber,
923
+ blockNumber: BlockParameter,
879
924
  archive: Fr,
880
925
  ): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
881
926
  const committedDb = await this.#getWorldState(blockNumber);
@@ -886,7 +931,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
886
931
  }
887
932
 
888
933
  public async getNoteHashMembershipWitness(
889
- blockNumber: L2BlockNumber,
934
+ blockNumber: BlockParameter,
890
935
  noteHash: Fr,
891
936
  ): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
892
937
  const committedDb = await this.#getWorldState(blockNumber);
@@ -906,7 +951,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
906
951
  * @returns A tuple of the index and the sibling path of the L1ToL2Message (undefined if not found).
907
952
  */
908
953
  public async getL1ToL2MessageMembershipWitness(
909
- blockNumber: L2BlockNumber,
954
+ blockNumber: BlockParameter,
910
955
  l1ToL2Message: Fr,
911
956
  ): Promise<[bigint, SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>] | undefined> {
912
957
  const db = await this.#getWorldState(blockNumber);
@@ -919,9 +964,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
919
964
  return [witness.index, witness.path];
920
965
  }
921
966
 
922
- public async getL1ToL2MessageBlock(l1ToL2Message: Fr): Promise<number | undefined> {
967
+ public async getL1ToL2MessageBlock(l1ToL2Message: Fr): Promise<BlockNumber | undefined> {
923
968
  const messageIndex = await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message);
924
- return messageIndex ? InboxLeaf.l2BlockFromIndex(messageIndex) : undefined;
969
+ return messageIndex
970
+ ? BlockNumber.fromCheckpointNumber(InboxLeaf.checkpointNumberFromIndex(messageIndex))
971
+ : undefined;
925
972
  }
926
973
 
927
974
  /**
@@ -939,8 +986,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
939
986
  * @param blockNumber - The block number at which to get the data.
940
987
  * @returns The L2 to L1 messages (undefined if the block number is not found).
941
988
  */
942
- public async getL2ToL1Messages(blockNumber: L2BlockNumber): Promise<Fr[][] | undefined> {
943
- const block = await this.blockSource.getBlock(blockNumber === 'latest' ? await this.getBlockNumber() : blockNumber);
989
+ public async getL2ToL1Messages(blockNumber: BlockParameter): Promise<Fr[][] | undefined> {
990
+ const block = await this.blockSource.getBlock(
991
+ blockNumber === 'latest' ? await this.getBlockNumber() : (blockNumber as BlockNumber),
992
+ );
944
993
  return block?.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs);
945
994
  }
946
995
 
@@ -951,7 +1000,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
951
1000
  * @returns The sibling path.
952
1001
  */
953
1002
  public async getArchiveSiblingPath(
954
- blockNumber: L2BlockNumber,
1003
+ blockNumber: BlockParameter,
955
1004
  leafIndex: bigint,
956
1005
  ): Promise<SiblingPath<typeof ARCHIVE_HEIGHT>> {
957
1006
  const committedDb = await this.#getWorldState(blockNumber);
@@ -965,7 +1014,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
965
1014
  * @returns The sibling path.
966
1015
  */
967
1016
  public async getPublicDataSiblingPath(
968
- blockNumber: L2BlockNumber,
1017
+ blockNumber: BlockParameter,
969
1018
  leafIndex: bigint,
970
1019
  ): Promise<SiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>> {
971
1020
  const committedDb = await this.#getWorldState(blockNumber);
@@ -979,7 +1028,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
979
1028
  * @returns The nullifier membership witness (if found).
980
1029
  */
981
1030
  public async getNullifierMembershipWitness(
982
- blockNumber: L2BlockNumber,
1031
+ blockNumber: BlockParameter,
983
1032
  nullifier: Fr,
984
1033
  ): Promise<NullifierMembershipWitness | undefined> {
985
1034
  const db = await this.#getWorldState(blockNumber);
@@ -1012,7 +1061,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1012
1061
  * TODO: This is a confusing behavior and we should eventually address that.
1013
1062
  */
1014
1063
  public async getLowNullifierMembershipWitness(
1015
- blockNumber: L2BlockNumber,
1064
+ blockNumber: BlockParameter,
1016
1065
  nullifier: Fr,
1017
1066
  ): Promise<NullifierMembershipWitness | undefined> {
1018
1067
  const committedDb = await this.#getWorldState(blockNumber);
@@ -1030,7 +1079,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1030
1079
  return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath);
1031
1080
  }
1032
1081
 
1033
- async getPublicDataWitness(blockNumber: L2BlockNumber, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
1082
+ async getPublicDataWitness(blockNumber: BlockParameter, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
1034
1083
  const committedDb = await this.#getWorldState(blockNumber);
1035
1084
  const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
1036
1085
  if (!lowLeafResult) {
@@ -1056,7 +1105,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1056
1105
  * @param blockNumber - The block number at which to get the data or 'latest'.
1057
1106
  * @returns Storage value at the given contract slot.
1058
1107
  */
1059
- public async getPublicStorageAt(blockNumber: L2BlockNumber, contract: AztecAddress, slot: Fr): Promise<Fr> {
1108
+ public async getPublicStorageAt(blockNumber: BlockParameter, contract: AztecAddress, slot: Fr): Promise<Fr> {
1060
1109
  const committedDb = await this.#getWorldState(blockNumber);
1061
1110
  const leafSlot = await computePublicDataTreeLeafSlot(contract, slot);
1062
1111
 
@@ -1075,10 +1124,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1075
1124
  * Returns the currently committed block header, or the initial header if no blocks have been produced.
1076
1125
  * @returns The current committed block header.
1077
1126
  */
1078
- public async getBlockHeader(blockNumber: L2BlockNumber = 'latest'): Promise<BlockHeader | undefined> {
1079
- return blockNumber === 0 || (blockNumber === 'latest' && (await this.blockSource.getBlockNumber()) === 0)
1127
+ public async getBlockHeader(blockNumber: BlockParameter = 'latest'): Promise<BlockHeader | undefined> {
1128
+ return blockNumber === BlockNumber.ZERO ||
1129
+ (blockNumber === 'latest' && (await this.blockSource.getBlockNumber()) === BlockNumber.ZERO)
1080
1130
  ? this.worldStateSynchronizer.getCommitted().getInitialHeader()
1081
- : this.blockSource.getBlockHeader(blockNumber);
1131
+ : this.blockSource.getBlockHeader(blockNumber === 'latest' ? blockNumber : (blockNumber as BlockNumber));
1082
1132
  }
1083
1133
 
1084
1134
  /**
@@ -1122,7 +1172,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1122
1172
  }
1123
1173
 
1124
1174
  const txHash = tx.getTxHash();
1125
- const blockNumber = (await this.blockSource.getBlockNumber()) + 1;
1175
+ const blockNumber = BlockNumber((await this.blockSource.getBlockNumber()) + 1);
1126
1176
 
1127
1177
  // If sequencer is not initialized, we just set these values to zero for simulation.
1128
1178
  const coinbase = EthAddress.ZERO;
@@ -1152,8 +1202,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1152
1202
  collectDebugLogs: true,
1153
1203
  collectHints: false,
1154
1204
  collectCallMetadata: true,
1155
- maxDebugLogMemoryReads: this.config.rpcSimulatePublicMaxDebugLogMemoryReads,
1156
1205
  collectStatistics: false,
1206
+ collectionLimits: CollectionLimitsConfig.from({
1207
+ maxDebugLogMemoryReads: this.config.rpcSimulatePublicMaxDebugLogMemoryReads,
1208
+ }),
1157
1209
  });
1158
1210
  const processor = publicProcessorFactory.create(merkleTreeFork, newGlobalVariables, config);
1159
1211
 
@@ -1187,7 +1239,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1187
1239
 
1188
1240
  // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1189
1241
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1190
- const blockNumber = (await this.blockSource.getBlockNumber()) + 1;
1242
+ const blockNumber = BlockNumber((await this.blockSource.getBlockNumber()) + 1);
1191
1243
  const validator = createValidatorForAcceptingTxs(db, this.contractDataSource, verifier, {
1192
1244
  timestamp: nextSlotTimestamp,
1193
1245
  blockNumber,
@@ -1294,7 +1346,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1294
1346
  return Promise.resolve();
1295
1347
  }
1296
1348
 
1297
- public async rollbackTo(targetBlock: number, force?: boolean): Promise<void> {
1349
+ public async rollbackTo(targetBlock: BlockNumber, force?: boolean): Promise<void> {
1298
1350
  const archiver = this.blockSource as Archiver;
1299
1351
  if (!('rollbackTo' in archiver)) {
1300
1352
  throw new Error('Archiver implementation does not support rollbacks.');
@@ -1366,12 +1418,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1366
1418
  * @param blockNumber - The block number at which to get the data.
1367
1419
  * @returns An instance of a committed MerkleTreeOperations
1368
1420
  */
1369
- async #getWorldState(blockNumber: L2BlockNumber) {
1421
+ async #getWorldState(blockNumber: BlockParameter) {
1370
1422
  if (typeof blockNumber === 'number' && blockNumber < INITIAL_L2_BLOCK_NUM - 1) {
1371
1423
  throw new Error('Invalid block number to get world state for: ' + blockNumber);
1372
1424
  }
1373
1425
 
1374
- let blockSyncedTo: number = 0;
1426
+ let blockSyncedTo: BlockNumber = BlockNumber.ZERO;
1375
1427
  try {
1376
1428
  // Attempt to sync the world state if necessary
1377
1429
  blockSyncedTo = await this.#syncWorldState();
@@ -1385,7 +1437,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1385
1437
  return this.worldStateSynchronizer.getCommitted();
1386
1438
  } else if (blockNumber <= blockSyncedTo) {
1387
1439
  this.log.debug(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
1388
- return this.worldStateSynchronizer.getSnapshot(blockNumber);
1440
+ return this.worldStateSynchronizer.getSnapshot(blockNumber as BlockNumber);
1389
1441
  } else {
1390
1442
  throw new Error(`Block ${blockNumber} not yet synced`);
1391
1443
  }
@@ -1395,8 +1447,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1395
1447
  * Ensure we fully sync the world state
1396
1448
  * @returns A promise that fulfils once the world state is synced
1397
1449
  */
1398
- async #syncWorldState(): Promise<number> {
1450
+ async #syncWorldState(): Promise<BlockNumber> {
1399
1451
  const blockSourceHeight = await this.blockSource.getBlockNumber();
1400
- return this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
1452
+ return await this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
1401
1453
  }
1402
1454
  }
@@ -1,5 +1,5 @@
1
1
  import type { EpochCache } from '@aztec/epoch-cache';
2
- import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
+ import { BlockNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
3
  import { countWhile, filterAsync, fromEntries, getEntries, mapValues } from '@aztec/foundation/collection';
4
4
  import { EthAddress } from '@aztec/foundation/eth-address';
5
5
  import { createLogger } from '@aztec/foundation/log';
@@ -44,7 +44,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
44
44
  protected initialSlot: SlotNumber | undefined;
45
45
  protected lastProcessedSlot: SlotNumber | undefined;
46
46
  // eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
47
- protected slotNumberToBlock: Map<SlotNumber, { blockNumber: number; archive: string; attestors: EthAddress[] }> =
47
+ protected slotNumberToBlock: Map<SlotNumber, { blockNumber: BlockNumber; archive: string; attestors: EthAddress[] }> =
48
48
  new Map();
49
49
 
50
50
  constructor(
@@ -76,7 +76,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
76
76
  /** Loads initial slot and initializes blockstream. We will not process anything at or before the initial slot. */
77
77
  protected async init() {
78
78
  this.initialSlot = this.epochCache.getEpochAndSlotNow().slot;
79
- const startingBlock = await this.archiver.getBlockNumber();
79
+ const startingBlock = BlockNumber(await this.archiver.getBlockNumber());
80
80
  this.logger.info(`Starting validator sentinel with initial slot ${this.initialSlot} and block ${startingBlock}`);
81
81
  this.blockStream = new L2BlockStream(this.archiver, this.l2TipsStore, this, this.logger, { startingBlock });
82
82
  }
@@ -91,7 +91,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
91
91
  // Store mapping from slot to archive, block number, and attestors
92
92
  for (const block of event.blocks) {
93
93
  this.slotNumberToBlock.set(block.block.header.getSlot(), {
94
- blockNumber: block.block.number,
94
+ blockNumber: BlockNumber(block.block.number),
95
95
  archive: block.block.archive.root.toString(),
96
96
  attestors: getAttestationInfoFromPublishedL2Block(block)
97
97
  .filter(a => a.status === 'recovered-from-signature')
@@ -118,7 +118,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
118
118
  if (event.type !== 'chain-proven') {
119
119
  return;
120
120
  }
121
- const blockNumber = event.block.number;
121
+ const blockNumber = BlockNumber(event.block.number);
122
122
  const block = await this.archiver.getBlock(blockNumber);
123
123
  if (!block) {
124
124
  this.logger.error(`Failed to get block ${blockNumber}`, { block });