@aztec/aztec-node 3.0.0-devnet.2 → 3.0.0-devnet.2-patch.1

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.
@@ -10,25 +10,25 @@ 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';
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, SlotNumber } from '@aztec/foundation/branded-types';
20
18
  import { compactArray, pick } from '@aztec/foundation/collection';
19
+ import { Fr } from '@aztec/foundation/curves/bn254';
21
20
  import { EthAddress } from '@aztec/foundation/eth-address';
22
- import { Fr } from '@aztec/foundation/fields';
23
21
  import { BadRequestError } from '@aztec/foundation/json-rpc';
24
22
  import { type Logger, createLogger } from '@aztec/foundation/log';
25
- import { SerialQueue } from '@aztec/foundation/queue';
26
23
  import { count } from '@aztec/foundation/string';
27
24
  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
34
  import {
@@ -46,12 +46,13 @@ import {
46
46
  type Watcher,
47
47
  createSlasher,
48
48
  } from '@aztec/slasher';
49
+ import { CollectionLimitsConfig, PublicSimulatorConfig } from '@aztec/stdlib/avm';
49
50
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
50
51
  import {
51
- type InBlock,
52
+ type BlockParameter,
53
+ type DataInBlock,
52
54
  type L2Block,
53
55
  L2BlockHash,
54
- type L2BlockNumber,
55
56
  type L2BlockSource,
56
57
  type PublishedL2Block,
57
58
  } from '@aztec/stdlib/block';
@@ -62,7 +63,7 @@ import type {
62
63
  NodeInfo,
63
64
  ProtocolContractAddresses,
64
65
  } from '@aztec/stdlib/contract';
65
- import type { GasFees } from '@aztec/stdlib/gas';
66
+ import { GasFees } from '@aztec/stdlib/gas';
66
67
  import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
67
68
  import {
68
69
  type AztecNode,
@@ -81,7 +82,7 @@ import {
81
82
  type WorldStateSynchronizer,
82
83
  tryStop,
83
84
  } from '@aztec/stdlib/interfaces/server';
84
- import type { LogFilter, PrivateLog, TxScopedL2Log } from '@aztec/stdlib/logs';
85
+ import type { LogFilter, TxScopedL2Log } from '@aztec/stdlib/logs';
85
86
  import { InboxLeaf, type L1ToL2MessageSource } from '@aztec/stdlib/messaging';
86
87
  import { P2PClientType } from '@aztec/stdlib/p2p';
87
88
  import type { Offense, SlashPayloadRound } from '@aztec/stdlib/slashing';
@@ -132,9 +133,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
132
133
  // Prevent two snapshot operations to happen simultaneously
133
134
  private isUploadingSnapshot = false;
134
135
 
135
- // Serial queue to ensure that we only send one tx at a time
136
- private txQueue: SerialQueue = new SerialQueue();
137
-
138
136
  public readonly tracer: Tracer;
139
137
 
140
138
  constructor(
@@ -160,7 +158,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
160
158
  ) {
161
159
  this.metrics = new NodeMetrics(telemetry, 'AztecNodeService');
162
160
  this.tracer = telemetry.getTracer('AztecNodeService');
163
- this.txQueue.start();
164
161
 
165
162
  this.log.info(`Aztec Node version: ${this.packageVersion}`);
166
163
  this.log.info(`Aztec Node started on chain 0x${l1ChainId.toString(16)}`, config.l1Contracts);
@@ -277,7 +274,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
277
274
  const archiver = await createArchiver(
278
275
  config,
279
276
  { blobSinkClient, epochCache, telemetry, dateProvider },
280
- { blockUntilSync: true },
277
+ { blockUntilSync: !config.skipArchiverInitialSync },
281
278
  );
282
279
 
283
280
  // now create the merkle trees and the world state synchronizer
@@ -287,7 +284,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
287
284
  options.prefilledPublicData,
288
285
  telemetry,
289
286
  );
290
- const circuitVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier();
287
+ const circuitVerifier =
288
+ config.realProofs || config.debugForceTxProofVerification
289
+ ? await BBCircuitVerifier.new(config)
290
+ : new TestCircuitVerifier(config.proverTestVerificationDelayMs);
291
291
  if (!config.realProofs) {
292
292
  log.warn(`Aztec node is accepting fake proofs`);
293
293
  }
@@ -365,12 +365,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
365
365
  await p2pClient.start();
366
366
 
367
367
  const validatorsSentinel = await createSentinel(epochCache, archiver, p2pClient, config);
368
- if (validatorsSentinel) {
369
- // we can run a sentinel without trying to slash.
370
- await validatorsSentinel.start();
371
- if (config.slashInactivityPenalty > 0n) {
372
- watchers.push(validatorsSentinel);
373
- }
368
+ if (validatorsSentinel && config.slashInactivityPenalty > 0n) {
369
+ watchers.push(validatorsSentinel);
374
370
  }
375
371
 
376
372
  let epochPruneWatcher: EpochPruneWatcher | undefined;
@@ -383,7 +379,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
383
379
  blockBuilder,
384
380
  config,
385
381
  );
386
- await epochPruneWatcher.start();
387
382
  watchers.push(epochPruneWatcher);
388
383
  }
389
384
 
@@ -391,16 +386,24 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
391
386
  let attestationsBlockWatcher: AttestationsBlockWatcher | undefined;
392
387
  if (config.slashProposeInvalidAttestationsPenalty > 0n || config.slashAttestDescendantOfInvalidPenalty > 0n) {
393
388
  attestationsBlockWatcher = new AttestationsBlockWatcher(archiver, epochCache, config);
394
- await attestationsBlockWatcher.start();
395
389
  watchers.push(attestationsBlockWatcher);
396
390
  }
397
391
 
398
- log.verbose(`All Aztec Node subsystems synced`);
392
+ // Start p2p-related services once the archiver has completed sync
393
+ void archiver
394
+ .waitForInitialSync()
395
+ .then(async () => {
396
+ await p2pClient.start();
397
+ await validatorsSentinel?.start();
398
+ await epochPruneWatcher?.start();
399
+ await attestationsBlockWatcher?.start();
400
+ log.info(`All p2p services started`);
401
+ })
402
+ .catch(err => log.error('Failed to start p2p services after archiver sync', err));
399
403
 
400
404
  // Validator enabled, create/start relevant service
401
405
  let sequencer: SequencerClient | undefined;
402
406
  let slasherClient: SlasherClientInterface | undefined;
403
-
404
407
  if (!config.disableValidator) {
405
408
  // We create a slasher only if we have a sequencer, since all slashing actions go through the sequencer publisher
406
409
  // as they are executed when the node is selected as proposer.
@@ -420,16 +423,23 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
420
423
  );
421
424
  await slasherClient.start();
422
425
 
423
- const l1TxUtils = await createL1TxUtilsWithBlobsFromEthSigner(
424
- publicClient,
425
- keyStoreManager!.createAllValidatorPublisherSigners(),
426
- { ...config, scope: 'sequencer' },
427
- { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
428
- );
429
-
426
+ const l1TxUtils = config.publisherForwarderAddress
427
+ ? await createForwarderL1TxUtilsFromEthSigner(
428
+ publicClient,
429
+ keyStoreManager!.createAllValidatorPublisherSigners(),
430
+ config.publisherForwarderAddress,
431
+ { ...config, scope: 'sequencer' },
432
+ { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
433
+ )
434
+ : await createL1TxUtilsWithBlobsFromEthSigner(
435
+ publicClient,
436
+ keyStoreManager!.createAllValidatorPublisherSigners(),
437
+ { ...config, scope: 'sequencer' },
438
+ { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
439
+ );
440
+
441
+ // Create and start the sequencer client
430
442
  sequencer = await SequencerClient.new(config, {
431
- // if deps were provided, they should override the defaults,
432
- // or things that we created in this function
433
443
  ...deps,
434
444
  epochCache,
435
445
  l1TxUtils,
@@ -548,8 +558,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
548
558
  * @param number - The block number being requested.
549
559
  * @returns The requested block.
550
560
  */
551
- public async getBlock(number: L2BlockNumber): Promise<L2Block | undefined> {
552
- const blockNumber = number === 'latest' ? await this.getBlockNumber() : number;
561
+ public async getBlock(number: BlockParameter): Promise<L2Block | undefined> {
562
+ const blockNumber = number === 'latest' ? await this.getBlockNumber() : (number as BlockNumber);
553
563
  return await this.blockSource.getBlock(blockNumber);
554
564
  }
555
565
 
@@ -579,11 +589,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
579
589
  * @param limit - The maximum number of blocks to obtain.
580
590
  * @returns The blocks requested.
581
591
  */
582
- public async getBlocks(from: number, limit: number): Promise<L2Block[]> {
592
+ public async getBlocks(from: BlockNumber, limit: number): Promise<L2Block[]> {
583
593
  return (await this.blockSource.getBlocks(from, limit)) ?? [];
584
594
  }
585
595
 
586
- public async getPublishedBlocks(from: number, limit: number): Promise<PublishedL2Block[]> {
596
+ public async getPublishedBlocks(from: BlockNumber, limit: number): Promise<PublishedL2Block[]> {
587
597
  return (await this.blockSource.getPublishedBlocks(from, limit)) ?? [];
588
598
  }
589
599
 
@@ -595,15 +605,23 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
595
605
  return await this.globalVariableBuilder.getCurrentBaseFees();
596
606
  }
597
607
 
608
+ public async getMaxPriorityFees(): Promise<GasFees> {
609
+ for await (const tx of this.p2pClient.iteratePendingTxs()) {
610
+ return tx.getGasSettings().maxPriorityFeesPerGas;
611
+ }
612
+
613
+ return GasFees.from({ feePerDaGas: 0n, feePerL2Gas: 0n });
614
+ }
615
+
598
616
  /**
599
617
  * Method to fetch the latest block number synchronized by the node.
600
618
  * @returns The block number.
601
619
  */
602
- public async getBlockNumber(): Promise<number> {
620
+ public async getBlockNumber(): Promise<BlockNumber> {
603
621
  return await this.blockSource.getBlockNumber();
604
622
  }
605
623
 
606
- public async getProvenBlockNumber(): Promise<number> {
624
+ public async getProvenBlockNumber(): Promise<BlockNumber> {
607
625
  return await this.blockSource.getProvenBlockNumber();
608
626
  }
609
627
 
@@ -639,16 +657,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
639
657
  return this.contractDataSource.getContract(address);
640
658
  }
641
659
 
642
- /**
643
- * Retrieves all private logs from up to `limit` blocks, starting from the block number `from`.
644
- * @param from - The block number from which to begin retrieving logs.
645
- * @param limit - The maximum number of blocks to retrieve logs from.
646
- * @returns An array of private logs from the specified range of blocks.
647
- */
648
- public getPrivateLogs(from: number, limit: number): Promise<PrivateLog[]> {
649
- return this.logsSource.getPrivateLogs(from, limit);
650
- }
651
-
652
660
  /**
653
661
  * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag).
654
662
  * @param tags - The tags to filter the logs by.
@@ -683,7 +691,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
683
691
  * @param tx - The transaction to be submitted.
684
692
  */
685
693
  public async sendTx(tx: Tx) {
686
- await this.txQueue.put(() => this.#sendTx(tx));
694
+ await this.#sendTx(tx);
687
695
  }
688
696
 
689
697
  async #sendTx(tx: Tx) {
@@ -730,7 +738,6 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
730
738
  */
731
739
  public async stop() {
732
740
  this.log.info(`Stopping Aztec Node`);
733
- await this.txQueue.end();
734
741
  await tryStop(this.validatorsSentinel);
735
742
  await tryStop(this.epochPruneWatcher);
736
743
  await tryStop(this.slasherClient);
@@ -784,10 +791,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
784
791
  * @returns The indices of leaves and the block metadata of a block in which the leaves were inserted.
785
792
  */
786
793
  public async findLeavesIndexes(
787
- blockNumber: L2BlockNumber,
794
+ blockNumber: BlockParameter,
788
795
  treeId: MerkleTreeId,
789
796
  leafValues: Fr[],
790
- ): Promise<(InBlock<bigint> | undefined)[]> {
797
+ ): Promise<(DataInBlock<bigint> | undefined)[]> {
791
798
  const committedDb = await this.#getWorldState(blockNumber);
792
799
  const maybeIndices = await committedDb.findLeafIndices(
793
800
  treeId,
@@ -813,7 +820,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
813
820
  // (note that block number corresponds to the leaf index in the archive tree).
814
821
  const blockHashes = await Promise.all(
815
822
  uniqueBlockNumbers.map(blockNumber => {
816
- return committedDb.getLeafValue(MerkleTreeId.ARCHIVE, blockNumber!);
823
+ return committedDb.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(blockNumber));
817
824
  }),
818
825
  );
819
826
 
@@ -824,7 +831,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
824
831
  }
825
832
  }
826
833
 
827
- // Create InBlock objects by combining indices, blockNumbers and blockHashes and return them.
834
+ // Create DataInBlock objects by combining indices, blockNumbers and blockHashes and return them.
828
835
  return maybeIndices.map((index, i) => {
829
836
  if (index === undefined) {
830
837
  return undefined;
@@ -839,7 +846,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
839
846
  return undefined;
840
847
  }
841
848
  return {
842
- l2BlockNumber: Number(blockNumber),
849
+ l2BlockNumber: BlockNumber(Number(blockNumber)),
843
850
  l2BlockHash: L2BlockHash.fromField(blockHash),
844
851
  data: index,
845
852
  };
@@ -853,7 +860,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
853
860
  * @returns The sibling path for the leaf index.
854
861
  */
855
862
  public async getNullifierSiblingPath(
856
- blockNumber: L2BlockNumber,
863
+ blockNumber: BlockParameter,
857
864
  leafIndex: bigint,
858
865
  ): Promise<SiblingPath<typeof NULLIFIER_TREE_HEIGHT>> {
859
866
  const committedDb = await this.#getWorldState(blockNumber);
@@ -867,7 +874,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
867
874
  * @returns The sibling path for the leaf index.
868
875
  */
869
876
  public async getNoteHashSiblingPath(
870
- blockNumber: L2BlockNumber,
877
+ blockNumber: BlockParameter,
871
878
  leafIndex: bigint,
872
879
  ): Promise<SiblingPath<typeof NOTE_HASH_TREE_HEIGHT>> {
873
880
  const committedDb = await this.#getWorldState(blockNumber);
@@ -875,7 +882,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
875
882
  }
876
883
 
877
884
  public async getArchiveMembershipWitness(
878
- blockNumber: L2BlockNumber,
885
+ blockNumber: BlockParameter,
879
886
  archive: Fr,
880
887
  ): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
881
888
  const committedDb = await this.#getWorldState(blockNumber);
@@ -886,7 +893,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
886
893
  }
887
894
 
888
895
  public async getNoteHashMembershipWitness(
889
- blockNumber: L2BlockNumber,
896
+ blockNumber: BlockParameter,
890
897
  noteHash: Fr,
891
898
  ): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
892
899
  const committedDb = await this.#getWorldState(blockNumber);
@@ -906,7 +913,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
906
913
  * @returns A tuple of the index and the sibling path of the L1ToL2Message (undefined if not found).
907
914
  */
908
915
  public async getL1ToL2MessageMembershipWitness(
909
- blockNumber: L2BlockNumber,
916
+ blockNumber: BlockParameter,
910
917
  l1ToL2Message: Fr,
911
918
  ): Promise<[bigint, SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>] | undefined> {
912
919
  const db = await this.#getWorldState(blockNumber);
@@ -919,9 +926,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
919
926
  return [witness.index, witness.path];
920
927
  }
921
928
 
922
- public async getL1ToL2MessageBlock(l1ToL2Message: Fr): Promise<number | undefined> {
929
+ public async getL1ToL2MessageBlock(l1ToL2Message: Fr): Promise<BlockNumber | undefined> {
923
930
  const messageIndex = await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message);
924
- return messageIndex ? InboxLeaf.l2BlockFromIndex(messageIndex) : undefined;
931
+ return messageIndex
932
+ ? BlockNumber.fromCheckpointNumber(InboxLeaf.checkpointNumberFromIndex(messageIndex))
933
+ : undefined;
925
934
  }
926
935
 
927
936
  /**
@@ -939,8 +948,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
939
948
  * @param blockNumber - The block number at which to get the data.
940
949
  * @returns The L2 to L1 messages (undefined if the block number is not found).
941
950
  */
942
- public async getL2ToL1Messages(blockNumber: L2BlockNumber): Promise<Fr[][] | undefined> {
943
- const block = await this.blockSource.getBlock(blockNumber === 'latest' ? await this.getBlockNumber() : blockNumber);
951
+ public async getL2ToL1Messages(blockNumber: BlockParameter): Promise<Fr[][] | undefined> {
952
+ const block = await this.blockSource.getBlock(
953
+ blockNumber === 'latest' ? await this.getBlockNumber() : (blockNumber as BlockNumber),
954
+ );
944
955
  return block?.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs);
945
956
  }
946
957
 
@@ -951,7 +962,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
951
962
  * @returns The sibling path.
952
963
  */
953
964
  public async getArchiveSiblingPath(
954
- blockNumber: L2BlockNumber,
965
+ blockNumber: BlockParameter,
955
966
  leafIndex: bigint,
956
967
  ): Promise<SiblingPath<typeof ARCHIVE_HEIGHT>> {
957
968
  const committedDb = await this.#getWorldState(blockNumber);
@@ -965,7 +976,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
965
976
  * @returns The sibling path.
966
977
  */
967
978
  public async getPublicDataSiblingPath(
968
- blockNumber: L2BlockNumber,
979
+ blockNumber: BlockParameter,
969
980
  leafIndex: bigint,
970
981
  ): Promise<SiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>> {
971
982
  const committedDb = await this.#getWorldState(blockNumber);
@@ -979,7 +990,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
979
990
  * @returns The nullifier membership witness (if found).
980
991
  */
981
992
  public async getNullifierMembershipWitness(
982
- blockNumber: L2BlockNumber,
993
+ blockNumber: BlockParameter,
983
994
  nullifier: Fr,
984
995
  ): Promise<NullifierMembershipWitness | undefined> {
985
996
  const db = await this.#getWorldState(blockNumber);
@@ -1012,7 +1023,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1012
1023
  * TODO: This is a confusing behavior and we should eventually address that.
1013
1024
  */
1014
1025
  public async getLowNullifierMembershipWitness(
1015
- blockNumber: L2BlockNumber,
1026
+ blockNumber: BlockParameter,
1016
1027
  nullifier: Fr,
1017
1028
  ): Promise<NullifierMembershipWitness | undefined> {
1018
1029
  const committedDb = await this.#getWorldState(blockNumber);
@@ -1030,7 +1041,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1030
1041
  return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath);
1031
1042
  }
1032
1043
 
1033
- async getPublicDataWitness(blockNumber: L2BlockNumber, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
1044
+ async getPublicDataWitness(blockNumber: BlockParameter, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
1034
1045
  const committedDb = await this.#getWorldState(blockNumber);
1035
1046
  const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
1036
1047
  if (!lowLeafResult) {
@@ -1056,7 +1067,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1056
1067
  * @param blockNumber - The block number at which to get the data or 'latest'.
1057
1068
  * @returns Storage value at the given contract slot.
1058
1069
  */
1059
- public async getPublicStorageAt(blockNumber: L2BlockNumber, contract: AztecAddress, slot: Fr): Promise<Fr> {
1070
+ public async getPublicStorageAt(blockNumber: BlockParameter, contract: AztecAddress, slot: Fr): Promise<Fr> {
1060
1071
  const committedDb = await this.#getWorldState(blockNumber);
1061
1072
  const leafSlot = await computePublicDataTreeLeafSlot(contract, slot);
1062
1073
 
@@ -1075,10 +1086,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1075
1086
  * Returns the currently committed block header, or the initial header if no blocks have been produced.
1076
1087
  * @returns The current committed block header.
1077
1088
  */
1078
- public async getBlockHeader(blockNumber: L2BlockNumber = 'latest'): Promise<BlockHeader | undefined> {
1079
- return blockNumber === 0 || (blockNumber === 'latest' && (await this.blockSource.getBlockNumber()) === 0)
1089
+ public async getBlockHeader(blockNumber: BlockParameter = 'latest'): Promise<BlockHeader | undefined> {
1090
+ return blockNumber === BlockNumber.ZERO ||
1091
+ (blockNumber === 'latest' && (await this.blockSource.getBlockNumber()) === BlockNumber.ZERO)
1080
1092
  ? this.worldStateSynchronizer.getCommitted().getInitialHeader()
1081
- : this.blockSource.getBlockHeader(blockNumber);
1093
+ : this.blockSource.getBlockHeader(blockNumber === 'latest' ? blockNumber : (blockNumber as BlockNumber));
1082
1094
  }
1083
1095
 
1084
1096
  /**
@@ -1122,7 +1134,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1122
1134
  }
1123
1135
 
1124
1136
  const txHash = tx.getTxHash();
1125
- const blockNumber = (await this.blockSource.getBlockNumber()) + 1;
1137
+ const blockNumber = BlockNumber((await this.blockSource.getBlockNumber()) + 1);
1126
1138
 
1127
1139
  // If sequencer is not initialized, we just set these values to zero for simulation.
1128
1140
  const coinbase = EthAddress.ZERO;
@@ -1147,11 +1159,17 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1147
1159
 
1148
1160
  const merkleTreeFork = await this.worldStateSynchronizer.fork();
1149
1161
  try {
1150
- const processor = publicProcessorFactory.create(merkleTreeFork, newGlobalVariables, {
1162
+ const config = PublicSimulatorConfig.from({
1151
1163
  skipFeeEnforcement,
1152
- clientInitiatedSimulation: true,
1153
- maxDebugLogMemoryReads: this.config.rpcSimulatePublicMaxDebugLogMemoryReads,
1164
+ collectDebugLogs: true,
1165
+ collectHints: false,
1166
+ collectCallMetadata: true,
1167
+ collectStatistics: false,
1168
+ collectionLimits: CollectionLimitsConfig.from({
1169
+ maxDebugLogMemoryReads: this.config.rpcSimulatePublicMaxDebugLogMemoryReads,
1170
+ }),
1154
1171
  });
1172
+ const processor = publicProcessorFactory.create(merkleTreeFork, newGlobalVariables, config);
1155
1173
 
1156
1174
  // REFACTOR: Consider merging ProcessReturnValues into ProcessedTx
1157
1175
  const [processedTxs, failedTxs, _usedTxs, returns] = await processor.process([tx]);
@@ -1183,7 +1201,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1183
1201
 
1184
1202
  // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1185
1203
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1186
- const blockNumber = (await this.blockSource.getBlockNumber()) + 1;
1204
+ const blockNumber = BlockNumber((await this.blockSource.getBlockNumber()) + 1);
1187
1205
  const validator = createValidatorForAcceptingTxs(db, this.contractDataSource, verifier, {
1188
1206
  timestamp: nextSlotTimestamp,
1189
1207
  blockNumber,
@@ -1240,8 +1258,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1240
1258
 
1241
1259
  public getValidatorStats(
1242
1260
  validatorAddress: EthAddress,
1243
- fromSlot?: bigint,
1244
- toSlot?: bigint,
1261
+ fromSlot?: SlotNumber,
1262
+ toSlot?: SlotNumber,
1245
1263
  ): Promise<SingleValidatorStats | undefined> {
1246
1264
  return this.validatorsSentinel?.getValidatorStats(validatorAddress, fromSlot, toSlot) ?? Promise.resolve(undefined);
1247
1265
  }
@@ -1251,39 +1269,46 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1251
1269
  // We break support for archiver running remotely to the node
1252
1270
  const archiver = this.blockSource as Archiver;
1253
1271
  if (!('backupTo' in archiver)) {
1272
+ this.metrics.recordSnapshotError();
1254
1273
  throw new Error('Archiver implementation does not support backups. Cannot generate snapshot.');
1255
1274
  }
1256
1275
 
1257
1276
  // Test that the archiver has done an initial sync.
1258
1277
  if (!archiver.isInitialSyncComplete()) {
1278
+ this.metrics.recordSnapshotError();
1259
1279
  throw new Error(`Archiver initial sync not complete. Cannot start snapshot.`);
1260
1280
  }
1261
1281
 
1262
1282
  // And it has an L2 block hash
1263
1283
  const l2BlockHash = await archiver.getL2Tips().then(tips => tips.latest.hash);
1264
1284
  if (!l2BlockHash) {
1285
+ this.metrics.recordSnapshotError();
1265
1286
  throw new Error(`Archiver has no latest L2 block hash downloaded. Cannot start snapshot.`);
1266
1287
  }
1267
1288
 
1268
1289
  if (this.isUploadingSnapshot) {
1290
+ this.metrics.recordSnapshotError();
1269
1291
  throw new Error(`Snapshot upload already in progress. Cannot start another one until complete.`);
1270
1292
  }
1271
1293
 
1272
1294
  // Do not wait for the upload to be complete to return to the caller, but flag that an operation is in progress
1273
1295
  this.isUploadingSnapshot = true;
1296
+ const timer = new Timer();
1274
1297
  void uploadSnapshot(location, this.blockSource as Archiver, this.worldStateSynchronizer, this.config, this.log)
1275
1298
  .then(() => {
1276
1299
  this.isUploadingSnapshot = false;
1300
+ this.metrics.recordSnapshot(timer.ms());
1277
1301
  })
1278
1302
  .catch(err => {
1279
1303
  this.isUploadingSnapshot = false;
1304
+ this.metrics.recordSnapshotError();
1280
1305
  this.log.error(`Error uploading snapshot: ${err}`);
1281
1306
  });
1282
1307
 
1283
1308
  return Promise.resolve();
1284
1309
  }
1285
1310
 
1286
- public async rollbackTo(targetBlock: number, force?: boolean): Promise<void> {
1311
+ public async rollbackTo(targetBlock: BlockNumber, force?: boolean): Promise<void> {
1287
1312
  const archiver = this.blockSource as Archiver;
1288
1313
  if (!('rollbackTo' in archiver)) {
1289
1314
  throw new Error('Archiver implementation does not support rollbacks.');
@@ -1355,12 +1380,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1355
1380
  * @param blockNumber - The block number at which to get the data.
1356
1381
  * @returns An instance of a committed MerkleTreeOperations
1357
1382
  */
1358
- async #getWorldState(blockNumber: L2BlockNumber) {
1383
+ async #getWorldState(blockNumber: BlockParameter) {
1359
1384
  if (typeof blockNumber === 'number' && blockNumber < INITIAL_L2_BLOCK_NUM - 1) {
1360
1385
  throw new Error('Invalid block number to get world state for: ' + blockNumber);
1361
1386
  }
1362
1387
 
1363
- let blockSyncedTo: number = 0;
1388
+ let blockSyncedTo: BlockNumber = BlockNumber.ZERO;
1364
1389
  try {
1365
1390
  // Attempt to sync the world state if necessary
1366
1391
  blockSyncedTo = await this.#syncWorldState();
@@ -1374,7 +1399,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1374
1399
  return this.worldStateSynchronizer.getCommitted();
1375
1400
  } else if (blockNumber <= blockSyncedTo) {
1376
1401
  this.log.debug(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
1377
- return this.worldStateSynchronizer.getSnapshot(blockNumber);
1402
+ return this.worldStateSynchronizer.getSnapshot(blockNumber as BlockNumber);
1378
1403
  } else {
1379
1404
  throw new Error(`Block ${blockNumber} not yet synced`);
1380
1405
  }
@@ -1384,8 +1409,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
1384
1409
  * Ensure we fully sync the world state
1385
1410
  * @returns A promise that fulfils once the world state is synced
1386
1411
  */
1387
- async #syncWorldState(): Promise<number> {
1412
+ async #syncWorldState(): Promise<BlockNumber> {
1388
1413
  const blockSourceHeight = await this.blockSource.getBlockNumber();
1389
- return this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
1414
+ return await this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
1390
1415
  }
1391
1416
  }