@aztec/aztec-node 4.0.0-nightly.20250907 → 4.0.0-nightly.20260108

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,48 +1,424 @@
1
- function _ts_decorate(decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1
+ function applyDecs2203RFactory() {
2
+ function createAddInitializerMethod(initializers, decoratorFinishedRef) {
3
+ return function addInitializer(initializer) {
4
+ assertNotFinished(decoratorFinishedRef, "addInitializer");
5
+ assertCallable(initializer, "An initializer");
6
+ initializers.push(initializer);
7
+ };
8
+ }
9
+ function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) {
10
+ var kindStr;
11
+ switch(kind){
12
+ case 1:
13
+ kindStr = "accessor";
14
+ break;
15
+ case 2:
16
+ kindStr = "method";
17
+ break;
18
+ case 3:
19
+ kindStr = "getter";
20
+ break;
21
+ case 4:
22
+ kindStr = "setter";
23
+ break;
24
+ default:
25
+ kindStr = "field";
26
+ }
27
+ var ctx = {
28
+ kind: kindStr,
29
+ name: isPrivate ? "#" + name : name,
30
+ static: isStatic,
31
+ private: isPrivate,
32
+ metadata: metadata
33
+ };
34
+ var decoratorFinishedRef = {
35
+ v: false
36
+ };
37
+ ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef);
38
+ var get, set;
39
+ if (kind === 0) {
40
+ if (isPrivate) {
41
+ get = desc.get;
42
+ set = desc.set;
43
+ } else {
44
+ get = function() {
45
+ return this[name];
46
+ };
47
+ set = function(v) {
48
+ this[name] = v;
49
+ };
50
+ }
51
+ } else if (kind === 2) {
52
+ get = function() {
53
+ return desc.value;
54
+ };
55
+ } else {
56
+ if (kind === 1 || kind === 3) {
57
+ get = function() {
58
+ return desc.get.call(this);
59
+ };
60
+ }
61
+ if (kind === 1 || kind === 4) {
62
+ set = function(v) {
63
+ desc.set.call(this, v);
64
+ };
65
+ }
66
+ }
67
+ ctx.access = get && set ? {
68
+ get: get,
69
+ set: set
70
+ } : get ? {
71
+ get: get
72
+ } : {
73
+ set: set
74
+ };
75
+ try {
76
+ return dec(value, ctx);
77
+ } finally{
78
+ decoratorFinishedRef.v = true;
79
+ }
80
+ }
81
+ function assertNotFinished(decoratorFinishedRef, fnName) {
82
+ if (decoratorFinishedRef.v) {
83
+ throw new Error("attempted to call " + fnName + " after decoration was finished");
84
+ }
85
+ }
86
+ function assertCallable(fn, hint) {
87
+ if (typeof fn !== "function") {
88
+ throw new TypeError(hint + " must be a function");
89
+ }
90
+ }
91
+ function assertValidReturnValue(kind, value) {
92
+ var type = typeof value;
93
+ if (kind === 1) {
94
+ if (type !== "object" || value === null) {
95
+ throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
96
+ }
97
+ if (value.get !== undefined) {
98
+ assertCallable(value.get, "accessor.get");
99
+ }
100
+ if (value.set !== undefined) {
101
+ assertCallable(value.set, "accessor.set");
102
+ }
103
+ if (value.init !== undefined) {
104
+ assertCallable(value.init, "accessor.init");
105
+ }
106
+ } else if (type !== "function") {
107
+ var hint;
108
+ if (kind === 0) {
109
+ hint = "field";
110
+ } else if (kind === 10) {
111
+ hint = "class";
112
+ } else {
113
+ hint = "method";
114
+ }
115
+ throw new TypeError(hint + " decorators must return a function or void 0");
116
+ }
117
+ }
118
+ function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) {
119
+ var decs = decInfo[0];
120
+ var desc, init, value;
121
+ if (isPrivate) {
122
+ if (kind === 0 || kind === 1) {
123
+ desc = {
124
+ get: decInfo[3],
125
+ set: decInfo[4]
126
+ };
127
+ } else if (kind === 3) {
128
+ desc = {
129
+ get: decInfo[3]
130
+ };
131
+ } else if (kind === 4) {
132
+ desc = {
133
+ set: decInfo[3]
134
+ };
135
+ } else {
136
+ desc = {
137
+ value: decInfo[3]
138
+ };
139
+ }
140
+ } else if (kind !== 0) {
141
+ desc = Object.getOwnPropertyDescriptor(base, name);
142
+ }
143
+ if (kind === 1) {
144
+ value = {
145
+ get: desc.get,
146
+ set: desc.set
147
+ };
148
+ } else if (kind === 2) {
149
+ value = desc.value;
150
+ } else if (kind === 3) {
151
+ value = desc.get;
152
+ } else if (kind === 4) {
153
+ value = desc.set;
154
+ }
155
+ var newValue, get, set;
156
+ if (typeof decs === "function") {
157
+ newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
158
+ if (newValue !== void 0) {
159
+ assertValidReturnValue(kind, newValue);
160
+ if (kind === 0) {
161
+ init = newValue;
162
+ } else if (kind === 1) {
163
+ init = newValue.init;
164
+ get = newValue.get || value.get;
165
+ set = newValue.set || value.set;
166
+ value = {
167
+ get: get,
168
+ set: set
169
+ };
170
+ } else {
171
+ value = newValue;
172
+ }
173
+ }
174
+ } else {
175
+ for(var i = decs.length - 1; i >= 0; i--){
176
+ var dec = decs[i];
177
+ newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
178
+ if (newValue !== void 0) {
179
+ assertValidReturnValue(kind, newValue);
180
+ var newInit;
181
+ if (kind === 0) {
182
+ newInit = newValue;
183
+ } else if (kind === 1) {
184
+ newInit = newValue.init;
185
+ get = newValue.get || value.get;
186
+ set = newValue.set || value.set;
187
+ value = {
188
+ get: get,
189
+ set: set
190
+ };
191
+ } else {
192
+ value = newValue;
193
+ }
194
+ if (newInit !== void 0) {
195
+ if (init === void 0) {
196
+ init = newInit;
197
+ } else if (typeof init === "function") {
198
+ init = [
199
+ init,
200
+ newInit
201
+ ];
202
+ } else {
203
+ init.push(newInit);
204
+ }
205
+ }
206
+ }
207
+ }
208
+ }
209
+ if (kind === 0 || kind === 1) {
210
+ if (init === void 0) {
211
+ init = function(instance, init) {
212
+ return init;
213
+ };
214
+ } else if (typeof init !== "function") {
215
+ var ownInitializers = init;
216
+ init = function(instance, init) {
217
+ var value = init;
218
+ for(var i = 0; i < ownInitializers.length; i++){
219
+ value = ownInitializers[i].call(instance, value);
220
+ }
221
+ return value;
222
+ };
223
+ } else {
224
+ var originalInitializer = init;
225
+ init = function(instance, init) {
226
+ return originalInitializer.call(instance, init);
227
+ };
228
+ }
229
+ ret.push(init);
230
+ }
231
+ if (kind !== 0) {
232
+ if (kind === 1) {
233
+ desc.get = value.get;
234
+ desc.set = value.set;
235
+ } else if (kind === 2) {
236
+ desc.value = value;
237
+ } else if (kind === 3) {
238
+ desc.get = value;
239
+ } else if (kind === 4) {
240
+ desc.set = value;
241
+ }
242
+ if (isPrivate) {
243
+ if (kind === 1) {
244
+ ret.push(function(instance, args) {
245
+ return value.get.call(instance, args);
246
+ });
247
+ ret.push(function(instance, args) {
248
+ return value.set.call(instance, args);
249
+ });
250
+ } else if (kind === 2) {
251
+ ret.push(value);
252
+ } else {
253
+ ret.push(function(instance, args) {
254
+ return value.call(instance, args);
255
+ });
256
+ }
257
+ } else {
258
+ Object.defineProperty(base, name, desc);
259
+ }
260
+ }
261
+ }
262
+ function applyMemberDecs(Class, decInfos, metadata) {
263
+ var ret = [];
264
+ var protoInitializers;
265
+ var staticInitializers;
266
+ var existingProtoNonFields = new Map();
267
+ var existingStaticNonFields = new Map();
268
+ for(var i = 0; i < decInfos.length; i++){
269
+ var decInfo = decInfos[i];
270
+ if (!Array.isArray(decInfo)) continue;
271
+ var kind = decInfo[1];
272
+ var name = decInfo[2];
273
+ var isPrivate = decInfo.length > 3;
274
+ var isStatic = kind >= 5;
275
+ var base;
276
+ var initializers;
277
+ if (isStatic) {
278
+ base = Class;
279
+ kind = kind - 5;
280
+ staticInitializers = staticInitializers || [];
281
+ initializers = staticInitializers;
282
+ } else {
283
+ base = Class.prototype;
284
+ protoInitializers = protoInitializers || [];
285
+ initializers = protoInitializers;
286
+ }
287
+ if (kind !== 0 && !isPrivate) {
288
+ var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields;
289
+ var existingKind = existingNonFields.get(name) || 0;
290
+ if (existingKind === true || existingKind === 3 && kind !== 4 || existingKind === 4 && kind !== 3) {
291
+ throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
292
+ } else if (!existingKind && kind > 2) {
293
+ existingNonFields.set(name, kind);
294
+ } else {
295
+ existingNonFields.set(name, true);
296
+ }
297
+ }
298
+ applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata);
299
+ }
300
+ pushInitializers(ret, protoInitializers);
301
+ pushInitializers(ret, staticInitializers);
302
+ return ret;
303
+ }
304
+ function pushInitializers(ret, initializers) {
305
+ if (initializers) {
306
+ ret.push(function(instance) {
307
+ for(var i = 0; i < initializers.length; i++){
308
+ initializers[i].call(instance);
309
+ }
310
+ return instance;
311
+ });
312
+ }
313
+ }
314
+ function applyClassDecs(targetClass, classDecs, metadata) {
315
+ if (classDecs.length > 0) {
316
+ var initializers = [];
317
+ var newClass = targetClass;
318
+ var name = targetClass.name;
319
+ for(var i = classDecs.length - 1; i >= 0; i--){
320
+ var decoratorFinishedRef = {
321
+ v: false
322
+ };
323
+ try {
324
+ var nextNewClass = classDecs[i](newClass, {
325
+ kind: "class",
326
+ name: name,
327
+ addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef),
328
+ metadata
329
+ });
330
+ } finally{
331
+ decoratorFinishedRef.v = true;
332
+ }
333
+ if (nextNewClass !== undefined) {
334
+ assertValidReturnValue(10, nextNewClass);
335
+ newClass = nextNewClass;
336
+ }
337
+ }
338
+ return [
339
+ defineMetadata(newClass, metadata),
340
+ function() {
341
+ for(var i = 0; i < initializers.length; i++){
342
+ initializers[i].call(newClass);
343
+ }
344
+ }
345
+ ];
346
+ }
347
+ }
348
+ function defineMetadata(Class, metadata) {
349
+ return Object.defineProperty(Class, Symbol.metadata || Symbol.for("Symbol.metadata"), {
350
+ configurable: true,
351
+ enumerable: true,
352
+ value: metadata
353
+ });
354
+ }
355
+ return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) {
356
+ if (parentClass !== void 0) {
357
+ var parentMetadata = parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")];
358
+ }
359
+ var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata);
360
+ var e = applyMemberDecs(targetClass, memberDecs, metadata);
361
+ if (!classDecs.length) defineMetadata(targetClass, metadata);
362
+ return {
363
+ e: e,
364
+ get c () {
365
+ return applyClassDecs(targetClass, classDecs, metadata);
366
+ }
367
+ };
368
+ };
6
369
  }
370
+ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
371
+ return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
372
+ }
373
+ var _dec, _initProto;
7
374
  import { createArchiver } from '@aztec/archiver';
8
375
  import { BBCircuitVerifier, QueuedIVCVerifier, TestCircuitVerifier } from '@aztec/bb-prover';
9
- import { createBlobSinkClient } from '@aztec/blob-sink/client';
376
+ import { createBlobClientWithFileStores } from '@aztec/blob-client/client';
10
377
  import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
11
378
  import { EpochCache } from '@aztec/epoch-cache';
12
- import { RegistryContract, RollupContract, createEthereumChain, getPublicClient } from '@aztec/ethereum';
13
- import { createL1TxUtilsWithBlobsFromEthSigner } from '@aztec/ethereum/l1-tx-utils-with-blobs';
379
+ import { createEthereumChain } from '@aztec/ethereum/chain';
380
+ import { getPublicClient } from '@aztec/ethereum/client';
381
+ import { RegistryContract, RollupContract } from '@aztec/ethereum/contracts';
382
+ import { BlockNumber } from '@aztec/foundation/branded-types';
14
383
  import { compactArray, pick } from '@aztec/foundation/collection';
384
+ import { Fr } from '@aztec/foundation/curves/bn254';
15
385
  import { EthAddress } from '@aztec/foundation/eth-address';
16
- import { Fr } from '@aztec/foundation/fields';
17
386
  import { BadRequestError } from '@aztec/foundation/json-rpc';
18
387
  import { createLogger } from '@aztec/foundation/log';
19
- import { SerialQueue } from '@aztec/foundation/queue';
20
388
  import { count } from '@aztec/foundation/string';
21
389
  import { DateProvider, Timer } from '@aztec/foundation/timer';
22
390
  import { MembershipWitness } from '@aztec/foundation/trees';
23
391
  import { KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore';
24
392
  import { trySnapshotSync, uploadSnapshot } from '@aztec/node-lib/actions';
393
+ import { createForwarderL1TxUtilsFromEthSigner, createL1TxUtilsWithBlobsFromEthSigner } from '@aztec/node-lib/factories';
25
394
  import { createP2PClient, getDefaultAllowedSetupFunctions } from '@aztec/p2p';
26
395
  import { ProtocolContractAddress } from '@aztec/protocol-contracts';
27
396
  import { BlockBuilder, GlobalVariableBuilder, SequencerClient, createValidatorForAcceptingTxs } from '@aztec/sequencer-client';
397
+ import { CheckpointsBuilder } from '@aztec/sequencer-client';
28
398
  import { PublicProcessorFactory } from '@aztec/simulator/server';
29
399
  import { AttestationsBlockWatcher, EpochPruneWatcher, createSlasher } from '@aztec/slasher';
400
+ import { CollectionLimitsConfig, PublicSimulatorConfig } from '@aztec/stdlib/avm';
30
401
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
31
402
  import { L2BlockHash } from '@aztec/stdlib/block';
403
+ import { GasFees } from '@aztec/stdlib/gas';
32
404
  import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
33
405
  import { AztecNodeAdminConfigSchema } from '@aztec/stdlib/interfaces/client';
34
406
  import { tryStop } from '@aztec/stdlib/interfaces/server';
407
+ import { InboxLeaf } from '@aztec/stdlib/messaging';
35
408
  import { P2PClientType } from '@aztec/stdlib/p2p';
36
409
  import { MerkleTreeId, NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
37
410
  import { PublicSimulationOutput, TxReceipt, TxStatus } from '@aztec/stdlib/tx';
38
411
  import { getPackageVersion } from '@aztec/stdlib/update-checker';
39
412
  import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
40
- import { NodeKeystoreAdapter, ValidatorClient, createValidatorClient } from '@aztec/validator-client';
413
+ import { NodeKeystoreAdapter, ValidatorClient, createBlockProposalHandler, createValidatorClient } from '@aztec/validator-client';
41
414
  import { createWorldStateSynchronizer } from '@aztec/world-state';
42
415
  import { createPublicClient, fallback, http } from 'viem';
43
416
  import { createSentinel } from '../sentinel/factory.js';
44
417
  import { createKeyStoreForValidator } from './config.js';
45
418
  import { NodeMetrics } from './node_metrics.js';
419
+ _dec = trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
420
+ [Attributes.TX_HASH]: tx.getTxHash().toString()
421
+ }));
46
422
  /**
47
423
  * The aztec node.
48
424
  */ export class AztecNodeService {
@@ -65,13 +441,21 @@ import { NodeMetrics } from './node_metrics.js';
65
441
  proofVerifier;
66
442
  telemetry;
67
443
  log;
444
+ blobClient;
445
+ static{
446
+ ({ e: [_initProto] } = _apply_decs_2203_r(this, [
447
+ [
448
+ _dec,
449
+ 2,
450
+ "simulatePublicCalls"
451
+ ]
452
+ ], []));
453
+ }
68
454
  metrics;
69
455
  // Prevent two snapshot operations to happen simultaneously
70
456
  isUploadingSnapshot;
71
- // Serial queue to ensure that we only send one tx at a time
72
- txQueue;
73
457
  tracer;
74
- constructor(config, p2pClient, blockSource, logsSource, contractDataSource, l1ToL2MessageSource, worldStateSynchronizer, sequencer, slasherClient, validatorsSentinel, epochPruneWatcher, l1ChainId, version, globalVariableBuilder, epochCache, packageVersion, proofVerifier, telemetry = getTelemetryClient(), log = createLogger('node')){
458
+ constructor(config, p2pClient, blockSource, logsSource, contractDataSource, l1ToL2MessageSource, worldStateSynchronizer, sequencer, slasherClient, validatorsSentinel, epochPruneWatcher, l1ChainId, version, globalVariableBuilder, epochCache, packageVersion, proofVerifier, telemetry = getTelemetryClient(), log = createLogger('node'), blobClient){
75
459
  this.config = config;
76
460
  this.p2pClient = p2pClient;
77
461
  this.blockSource = blockSource;
@@ -91,11 +475,10 @@ import { NodeMetrics } from './node_metrics.js';
91
475
  this.proofVerifier = proofVerifier;
92
476
  this.telemetry = telemetry;
93
477
  this.log = log;
94
- this.isUploadingSnapshot = false;
95
- this.txQueue = new SerialQueue();
478
+ this.blobClient = blobClient;
479
+ this.isUploadingSnapshot = (_initProto(this), false);
96
480
  this.metrics = new NodeMetrics(telemetry, 'AztecNodeService');
97
481
  this.tracer = telemetry.getTracer('AztecNodeService');
98
- this.txQueue.start();
99
482
  this.log.info(`Aztec Node version: ${this.packageVersion}`);
100
483
  this.log.info(`Aztec Node started on chain 0x${l1ChainId.toString(16)}`, config.l1Contracts);
101
484
  }
@@ -118,9 +501,6 @@ import { NodeMetrics } from './node_metrics.js';
118
501
  const packageVersion = getPackageVersion() ?? '';
119
502
  const telemetry = deps.telemetry ?? getTelemetryClient();
120
503
  const dateProvider = deps.dateProvider ?? new DateProvider();
121
- const blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config, {
122
- logger: createLogger('node:blob-sink:client')
123
- });
124
504
  const ethereumChain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
125
505
  // Build a key store from file if given or from environment otherwise
126
506
  let keyStoreManager;
@@ -134,6 +514,7 @@ import { NodeMetrics } from './node_metrics.js';
134
514
  keyStoreManager = new KeystoreManager(keyStore);
135
515
  }
136
516
  }
517
+ await keyStoreManager?.validateSigners();
137
518
  // If we are a validator, verify our configuration before doing too much more.
138
519
  if (!config.disableValidator) {
139
520
  if (keyStoreManager === undefined) {
@@ -142,7 +523,7 @@ import { NodeMetrics } from './node_metrics.js';
142
523
  if (!keyStoreProvided) {
143
524
  log.warn('KEY STORE CREATED FROM ENVIRONMENT, IT IS RECOMMENDED TO USE A FILE-BASED KEY STORE IN PRODUCTION ENVIRONMENTS');
144
525
  }
145
- ValidatorClient.validateKeyStoreConfiguration(keyStoreManager);
526
+ ValidatorClient.validateKeyStoreConfiguration(keyStoreManager, log);
146
527
  }
147
528
  // validate that the actual chain id matches that specified in configuration
148
529
  if (config.l1ChainId !== ethereumChain.chainInfo.id) {
@@ -150,7 +531,9 @@ import { NodeMetrics } from './node_metrics.js';
150
531
  }
151
532
  const publicClient = createPublicClient({
152
533
  chain: ethereumChain.chainInfo,
153
- transport: fallback(config.l1RpcUrls.map((url)=>http(url))),
534
+ transport: fallback(config.l1RpcUrls.map((url)=>http(url, {
535
+ batch: false
536
+ }))),
154
537
  pollingInterval: config.viemPollingIntervalMS
155
538
  });
156
539
  const l1ContractsAddresses = await RegistryContract.collectAddresses(publicClient, config.l1Contracts.registryAddress, config.rollupVersion ?? 'canonical');
@@ -169,89 +552,131 @@ import { NodeMetrics } from './node_metrics.js';
169
552
  if (config.rollupVersion !== Number(rollupVersionFromRollup)) {
170
553
  log.warn(`Registry looked up and returned a rollup with version (${config.rollupVersion}), but this does not match with version detected from the rollup directly: (${rollupVersionFromRollup}).`);
171
554
  }
555
+ const blobClient = await createBlobClientWithFileStores(config, createLogger('node:blob-client:client'));
172
556
  // attempt snapshot sync if possible
173
557
  await trySnapshotSync(config, log);
174
558
  const epochCache = await EpochCache.create(config.l1Contracts.rollupAddress, config, {
175
559
  dateProvider
176
560
  });
177
561
  const archiver = await createArchiver(config, {
178
- blobSinkClient,
562
+ blobClient,
179
563
  epochCache,
180
564
  telemetry,
181
565
  dateProvider
182
566
  }, {
183
- blockUntilSync: true
567
+ blockUntilSync: !config.skipArchiverInitialSync
184
568
  });
185
569
  // now create the merkle trees and the world state synchronizer
186
570
  const worldStateSynchronizer = await createWorldStateSynchronizer(config, archiver, options.prefilledPublicData, telemetry);
187
- const circuitVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier();
571
+ const circuitVerifier = config.realProofs || config.debugForceTxProofVerification ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(config.proverTestVerificationDelayMs);
188
572
  if (!config.realProofs) {
189
573
  log.warn(`Aztec node is accepting fake proofs`);
190
574
  }
191
575
  const proofVerifier = new QueuedIVCVerifier(config, circuitVerifier);
192
576
  // create the tx pool and the p2p client, which will need the l2 block source
193
577
  const p2pClient = await createP2PClient(P2PClientType.Full, config, archiver, proofVerifier, worldStateSynchronizer, epochCache, packageVersion, dateProvider, telemetry, deps.p2pClientDeps);
194
- // Start world state and wait for it to sync to the archiver.
195
- await worldStateSynchronizer.start();
196
- // Start p2p. Note that it depends on world state to be running.
197
- await p2pClient.start();
578
+ // We should really not be modifying the config object
198
579
  config.txPublicSetupAllowList = config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
199
580
  const blockBuilder = new BlockBuilder({
200
581
  ...config,
201
582
  l1GenesisTime,
202
583
  slotDuration: Number(slotDuration)
203
584
  }, worldStateSynchronizer, archiver, dateProvider, telemetry);
585
+ // We'll accumulate sentinel watchers here
204
586
  const watchers = [];
205
- const validatorsSentinel = await createSentinel(epochCache, archiver, p2pClient, config);
206
- if (validatorsSentinel) {
207
- // we can run a sentinel without trying to slash.
208
- await validatorsSentinel.start();
209
- if (config.slashInactivityPenalty > 0n) {
210
- watchers.push(validatorsSentinel);
587
+ // Create validator client if required
588
+ const validatorClient = createValidatorClient(config, {
589
+ p2pClient,
590
+ telemetry,
591
+ dateProvider,
592
+ epochCache,
593
+ blockBuilder,
594
+ blockSource: archiver,
595
+ l1ToL2MessageSource: archiver,
596
+ keyStoreManager,
597
+ blobClient
598
+ });
599
+ // If we have a validator client, register it as a source of offenses for the slasher,
600
+ // and have it register callbacks on the p2p client *before* we start it, otherwise messages
601
+ // like attestations or auths will fail.
602
+ if (validatorClient) {
603
+ watchers.push(validatorClient);
604
+ if (!options.dontStartSequencer) {
605
+ await validatorClient.registerHandlers();
211
606
  }
212
607
  }
608
+ // If there's no validator client but alwaysReexecuteBlockProposals is enabled,
609
+ // create a BlockProposalHandler to reexecute block proposals for monitoring
610
+ if (!validatorClient && config.alwaysReexecuteBlockProposals) {
611
+ log.info('Setting up block proposal reexecution for monitoring');
612
+ createBlockProposalHandler(config, {
613
+ blockBuilder,
614
+ epochCache,
615
+ blockSource: archiver,
616
+ l1ToL2MessageSource: archiver,
617
+ p2pClient,
618
+ dateProvider,
619
+ telemetry
620
+ }).registerForReexecution(p2pClient);
621
+ }
622
+ // Start world state and wait for it to sync to the archiver.
623
+ await worldStateSynchronizer.start();
624
+ // Start p2p. Note that it depends on world state to be running.
625
+ await p2pClient.start();
626
+ const validatorsSentinel = await createSentinel(epochCache, archiver, p2pClient, config);
627
+ if (validatorsSentinel && config.slashInactivityPenalty > 0n) {
628
+ watchers.push(validatorsSentinel);
629
+ }
213
630
  let epochPruneWatcher;
214
631
  if (config.slashPrunePenalty > 0n || config.slashDataWithholdingPenalty > 0n) {
215
632
  epochPruneWatcher = new EpochPruneWatcher(archiver, archiver, epochCache, p2pClient.getTxProvider(), blockBuilder, config);
216
- await epochPruneWatcher.start();
217
633
  watchers.push(epochPruneWatcher);
218
634
  }
219
635
  // We assume we want to slash for invalid attestations unless all max penalties are set to 0
220
636
  let attestationsBlockWatcher;
221
637
  if (config.slashProposeInvalidAttestationsPenalty > 0n || config.slashAttestDescendantOfInvalidPenalty > 0n) {
222
638
  attestationsBlockWatcher = new AttestationsBlockWatcher(archiver, epochCache, config);
223
- await attestationsBlockWatcher.start();
224
639
  watchers.push(attestationsBlockWatcher);
225
640
  }
226
- const validatorClient = createValidatorClient(config, {
227
- p2pClient,
228
- telemetry,
229
- dateProvider,
230
- epochCache,
231
- blockBuilder,
232
- blockSource: archiver,
233
- l1ToL2MessageSource: archiver,
234
- keyStoreManager
235
- });
236
- if (validatorClient) {
237
- watchers.push(validatorClient);
238
- }
239
- log.verbose(`All Aztec Node subsystems synced`);
641
+ // Start p2p-related services once the archiver has completed sync
642
+ void archiver.waitForInitialSync().then(async ()=>{
643
+ await p2pClient.start();
644
+ await validatorsSentinel?.start();
645
+ await epochPruneWatcher?.start();
646
+ await attestationsBlockWatcher?.start();
647
+ log.info(`All p2p services started`);
648
+ }).catch((err)=>log.error('Failed to start p2p services after archiver sync', err));
240
649
  // Validator enabled, create/start relevant service
241
650
  let sequencer;
242
651
  let slasherClient;
243
- if (!config.disableValidator) {
652
+ if (!config.disableValidator && validatorClient) {
244
653
  // We create a slasher only if we have a sequencer, since all slashing actions go through the sequencer publisher
245
654
  // as they are executed when the node is selected as proposer.
246
655
  const validatorAddresses = keyStoreManager ? NodeKeystoreAdapter.fromKeyStoreManager(keyStoreManager).getAddresses() : [];
247
656
  slasherClient = await createSlasher(config, config.l1Contracts, getPublicClient(config), watchers, dateProvider, epochCache, validatorAddresses, undefined);
248
657
  await slasherClient.start();
249
- const l1TxUtils = keyStoreManager.createAllValidatorPublisherSigners().map((signer)=>{
250
- return createL1TxUtilsWithBlobsFromEthSigner(publicClient, signer, log, dateProvider, config);
658
+ const l1TxUtils = config.publisherForwarderAddress ? await createForwarderL1TxUtilsFromEthSigner(publicClient, keyStoreManager.createAllValidatorPublisherSigners(), config.publisherForwarderAddress, {
659
+ ...config,
660
+ scope: 'sequencer'
661
+ }, {
662
+ telemetry,
663
+ logger: log.createChild('l1-tx-utils'),
664
+ dateProvider
665
+ }) : await createL1TxUtilsWithBlobsFromEthSigner(publicClient, keyStoreManager.createAllValidatorPublisherSigners(), {
666
+ ...config,
667
+ scope: 'sequencer'
668
+ }, {
669
+ telemetry,
670
+ logger: log.createChild('l1-tx-utils'),
671
+ dateProvider
251
672
  });
673
+ // Create and start the sequencer client
674
+ const checkpointsBuilder = new CheckpointsBuilder({
675
+ ...config,
676
+ l1GenesisTime,
677
+ slotDuration: Number(slotDuration)
678
+ }, archiver, dateProvider, telemetry);
252
679
  sequencer = await SequencerClient.new(config, {
253
- // if deps were provided, they should override the defaults,
254
- // or things that we created in this function
255
680
  ...deps,
256
681
  epochCache,
257
682
  l1TxUtils,
@@ -259,20 +684,28 @@ import { NodeMetrics } from './node_metrics.js';
259
684
  p2pClient,
260
685
  worldStateSynchronizer,
261
686
  slasherClient,
262
- blockBuilder,
687
+ checkpointsBuilder,
263
688
  l2BlockSource: archiver,
264
689
  l1ToL2MessageSource: archiver,
265
690
  telemetry,
266
691
  dateProvider,
267
- blobSinkClient,
692
+ blobClient,
268
693
  nodeKeyStore: keyStoreManager
269
694
  });
270
695
  }
271
696
  if (!options.dontStartSequencer && sequencer) {
272
697
  await sequencer.start();
273
698
  log.verbose(`Sequencer started`);
699
+ } else if (sequencer) {
700
+ log.warn(`Sequencer created but not started`);
274
701
  }
275
- return new AztecNodeService(config, p2pClient, archiver, archiver, archiver, archiver, worldStateSynchronizer, sequencer, slasherClient, validatorsSentinel, epochPruneWatcher, ethereumChain.chainInfo.id, config.rollupVersion, new GlobalVariableBuilder(config), epochCache, packageVersion, proofVerifier, telemetry, log);
702
+ const globalVariableBuilder = new GlobalVariableBuilder({
703
+ ...config,
704
+ rollupVersion: BigInt(config.rollupVersion),
705
+ l1GenesisTime,
706
+ slotDuration: Number(slotDuration)
707
+ });
708
+ return new AztecNodeService(config, p2pClient, archiver, archiver, archiver, archiver, worldStateSynchronizer, sequencer, slasherClient, validatorsSentinel, epochPruneWatcher, ethereumChain.chainInfo.id, config.rollupVersion, globalVariableBuilder, epochCache, packageVersion, proofVerifier, telemetry, log, blobClient);
276
709
  }
277
710
  /**
278
711
  * Returns the sequencer client instance.
@@ -298,6 +731,9 @@ import { NodeMetrics } from './node_metrics.js';
298
731
  getEncodedEnr() {
299
732
  return Promise.resolve(this.p2pClient.getEnr()?.encodeTxt());
300
733
  }
734
+ async getAllowedPublicSetup() {
735
+ return this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
736
+ }
301
737
  /**
302
738
  * Method to determine if the node is ready to accept transactions.
303
739
  * @returns - Flag indicating the readiness for tx submission.
@@ -328,7 +764,24 @@ import { NodeMetrics } from './node_metrics.js';
328
764
  * @param number - The block number being requested.
329
765
  * @returns The requested block.
330
766
  */ async getBlock(number) {
331
- return await this.blockSource.getBlock(number);
767
+ const blockNumber = number === 'latest' ? await this.getBlockNumber() : number;
768
+ return await this.blockSource.getBlock(blockNumber);
769
+ }
770
+ /**
771
+ * Get a block specified by its hash.
772
+ * @param blockHash - The block hash being requested.
773
+ * @returns The requested block.
774
+ */ async getBlockByHash(blockHash) {
775
+ const publishedBlock = await this.blockSource.getPublishedBlockByHash(blockHash);
776
+ return publishedBlock?.block;
777
+ }
778
+ /**
779
+ * Get a block specified by its archive root.
780
+ * @param archive - The archive root being requested.
781
+ * @returns The requested block.
782
+ */ async getBlockByArchive(archive) {
783
+ const publishedBlock = await this.blockSource.getPublishedBlockByArchive(archive);
784
+ return publishedBlock?.block;
332
785
  }
333
786
  /**
334
787
  * Method to request blocks. Will attempt to return all requested blocks but will return only those available.
@@ -342,10 +795,19 @@ import { NodeMetrics } from './node_metrics.js';
342
795
  return await this.blockSource.getPublishedBlocks(from, limit) ?? [];
343
796
  }
344
797
  /**
345
- * Method to fetch the current base fees.
346
- * @returns The current base fees.
347
- */ async getCurrentBaseFees() {
348
- return await this.globalVariableBuilder.getCurrentBaseFees();
798
+ * Method to fetch the current min L2 fees.
799
+ * @returns The current min L2 fees.
800
+ */ async getCurrentMinFees() {
801
+ return await this.globalVariableBuilder.getCurrentMinFees();
802
+ }
803
+ async getMaxPriorityFees() {
804
+ for await (const tx of this.p2pClient.iteratePendingTxs()){
805
+ return tx.getGasSettings().maxPriorityFeesPerGas;
806
+ }
807
+ return GasFees.from({
808
+ feePerDaGas: 0n,
809
+ feePerL2Gas: 0n
810
+ });
349
811
  }
350
812
  /**
351
813
  * Method to fetch the latest block number synchronized by the node.
@@ -380,22 +842,11 @@ import { NodeMetrics } from './node_metrics.js';
380
842
  getContract(address) {
381
843
  return this.contractDataSource.getContract(address);
382
844
  }
383
- /**
384
- * Retrieves all private logs from up to `limit` blocks, starting from the block number `from`.
385
- * @param from - The block number from which to begin retrieving logs.
386
- * @param limit - The maximum number of blocks to retrieve logs from.
387
- * @returns An array of private logs from the specified range of blocks.
388
- */ getPrivateLogs(from, limit) {
389
- return this.logsSource.getPrivateLogs(from, limit);
845
+ getPrivateLogsByTags(tags) {
846
+ return this.logsSource.getPrivateLogsByTags(tags);
390
847
  }
391
- /**
392
- * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag).
393
- * @param tags - The tags to filter the logs by.
394
- * @param logsPerTag - The maximum number of logs to return for each tag. By default no limit is set
395
- * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
396
- * that tag.
397
- */ getLogsByTags(tags, logsPerTag) {
398
- return this.logsSource.getLogsByTags(tags, logsPerTag);
848
+ getPublicLogsByTagsFromContract(contractAddress, tags) {
849
+ return this.logsSource.getPublicLogsByTagsFromContract(contractAddress, tags);
399
850
  }
400
851
  /**
401
852
  * Gets public logs based on the provided filter.
@@ -415,7 +866,7 @@ import { NodeMetrics } from './node_metrics.js';
415
866
  * Method to submit a transaction to the p2p pool.
416
867
  * @param tx - The transaction to be submitted.
417
868
  */ async sendTx(tx) {
418
- await this.txQueue.put(()=>this.#sendTx(tx));
869
+ await this.#sendTx(tx);
419
870
  }
420
871
  async #sendTx(tx) {
421
872
  const timer = new Timer();
@@ -456,7 +907,6 @@ import { NodeMetrics } from './node_metrics.js';
456
907
  * Method to stop the aztec node.
457
908
  */ async stop() {
458
909
  this.log.info(`Stopping Aztec Node`);
459
- await this.txQueue.end();
460
910
  await tryStop(this.validatorsSentinel);
461
911
  await tryStop(this.epochPruneWatcher);
462
912
  await tryStop(this.slasherClient);
@@ -465,10 +915,17 @@ import { NodeMetrics } from './node_metrics.js';
465
915
  await tryStop(this.p2pClient);
466
916
  await tryStop(this.worldStateSynchronizer);
467
917
  await tryStop(this.blockSource);
918
+ await tryStop(this.blobClient);
468
919
  await tryStop(this.telemetry);
469
920
  this.log.info(`Stopped Aztec Node`);
470
921
  }
471
922
  /**
923
+ * Returns the blob client used by this node.
924
+ * @internal - Exposed for testing purposes only.
925
+ */ getBlobClient() {
926
+ return this.blobClient;
927
+ }
928
+ /**
472
929
  * Method to retrieve pending txs.
473
930
  * @param limit - The number of items to returns
474
931
  * @param after - The last known pending tx. Used for pagination
@@ -520,7 +977,7 @@ import { NodeMetrics } from './node_metrics.js';
520
977
  // Now we obtain the block hashes from the archive tree by calling await `committedDb.getLeafValue(treeId, index)`
521
978
  // (note that block number corresponds to the leaf index in the archive tree).
522
979
  const blockHashes = await Promise.all(uniqueBlockNumbers.map((blockNumber)=>{
523
- return committedDb.getLeafValue(MerkleTreeId.ARCHIVE, blockNumber);
980
+ return committedDb.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(blockNumber));
524
981
  }));
525
982
  // If any of the block hashes are undefined, we throw an error.
526
983
  for(let i = 0; i < uniqueBlockNumbers.length; i++){
@@ -528,7 +985,7 @@ import { NodeMetrics } from './node_metrics.js';
528
985
  throw new Error(`Block hash is undefined for block number ${uniqueBlockNumbers[i]}`);
529
986
  }
530
987
  }
531
- // Create InBlock objects by combining indices, blockNumbers and blockHashes and return them.
988
+ // Create DataInBlock objects by combining indices, blockNumbers and blockHashes and return them.
532
989
  return maybeIndices.map((index, i)=>{
533
990
  if (index === undefined) {
534
991
  return undefined;
@@ -543,7 +1000,7 @@ import { NodeMetrics } from './node_metrics.js';
543
1000
  return undefined;
544
1001
  }
545
1002
  return {
546
- l2BlockNumber: Number(blockNumber),
1003
+ l2BlockNumber: BlockNumber(Number(blockNumber)),
547
1004
  l2BlockHash: L2BlockHash.fromField(blockHash),
548
1005
  data: index
549
1006
  };
@@ -600,12 +1057,17 @@ import { NodeMetrics } from './node_metrics.js';
600
1057
  witness.path
601
1058
  ];
602
1059
  }
1060
+ async getL1ToL2MessageBlock(l1ToL2Message) {
1061
+ const messageIndex = await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message);
1062
+ return messageIndex ? BlockNumber.fromCheckpointNumber(InboxLeaf.checkpointNumberFromIndex(messageIndex)) : undefined;
1063
+ }
603
1064
  /**
604
1065
  * Returns whether an L1 to L2 message is synced by archiver and if it's ready to be included in a block.
605
1066
  * @param l1ToL2Message - The L1 to L2 message to check.
606
1067
  * @returns Whether the message is synced and ready to be included in a block.
607
1068
  */ async isL1ToL2MessageSynced(l1ToL2Message) {
608
- return await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message) !== undefined;
1069
+ const messageIndex = await this.l1ToL2MessageSource.getL1ToL2MessageIndex(l1ToL2Message);
1070
+ return messageIndex !== undefined;
609
1071
  }
610
1072
  /**
611
1073
  * Returns all the L2 to L1 messages in a block.
@@ -715,7 +1177,21 @@ import { NodeMetrics } from './node_metrics.js';
715
1177
  * Returns the currently committed block header, or the initial header if no blocks have been produced.
716
1178
  * @returns The current committed block header.
717
1179
  */ async getBlockHeader(blockNumber = 'latest') {
718
- return blockNumber === 0 || blockNumber === 'latest' && await this.blockSource.getBlockNumber() === 0 ? this.worldStateSynchronizer.getCommitted().getInitialHeader() : this.blockSource.getBlockHeader(blockNumber);
1180
+ return blockNumber === BlockNumber.ZERO || blockNumber === 'latest' && await this.blockSource.getBlockNumber() === BlockNumber.ZERO ? this.worldStateSynchronizer.getCommitted().getInitialHeader() : this.blockSource.getBlockHeader(blockNumber === 'latest' ? blockNumber : blockNumber);
1181
+ }
1182
+ /**
1183
+ * Get a block header specified by its hash.
1184
+ * @param blockHash - The block hash being requested.
1185
+ * @returns The requested block header.
1186
+ */ async getBlockHeaderByHash(blockHash) {
1187
+ return await this.blockSource.getBlockHeaderByHash(blockHash);
1188
+ }
1189
+ /**
1190
+ * Get a block header specified by its archive root.
1191
+ * @param archive - The archive root being requested.
1192
+ * @returns The requested block header.
1193
+ */ async getBlockHeaderByArchive(archive) {
1194
+ return await this.blockSource.getBlockHeaderByArchive(archive);
719
1195
  }
720
1196
  /**
721
1197
  * Simulates the public part of a transaction with the current state.
@@ -729,7 +1205,7 @@ import { NodeMetrics } from './node_metrics.js';
729
1205
  throw new BadRequestError(`Transaction total gas limit ${txGasLimit + teardownGasLimit} (${txGasLimit} + ${teardownGasLimit}) exceeds maximum gas limit ${this.config.rpcSimulatePublicMaxGasLimit} for simulation`);
730
1206
  }
731
1207
  const txHash = tx.getTxHash();
732
- const blockNumber = await this.blockSource.getBlockNumber() + 1;
1208
+ const blockNumber = BlockNumber(await this.blockSource.getBlockNumber() + 1);
733
1209
  // If sequencer is not initialized, we just set these values to zero for simulation.
734
1210
  const coinbase = EthAddress.ZERO;
735
1211
  const feeRecipient = AztecAddress.ZERO;
@@ -742,7 +1218,17 @@ import { NodeMetrics } from './node_metrics.js';
742
1218
  });
743
1219
  const merkleTreeFork = await this.worldStateSynchronizer.fork();
744
1220
  try {
745
- const processor = publicProcessorFactory.create(merkleTreeFork, newGlobalVariables, skipFeeEnforcement, /*clientInitiatedSimulation*/ true);
1221
+ const config = PublicSimulatorConfig.from({
1222
+ skipFeeEnforcement,
1223
+ collectDebugLogs: true,
1224
+ collectHints: false,
1225
+ collectCallMetadata: true,
1226
+ collectStatistics: false,
1227
+ collectionLimits: CollectionLimitsConfig.from({
1228
+ maxDebugLogMemoryReads: this.config.rpcSimulatePublicMaxDebugLogMemoryReads
1229
+ })
1230
+ });
1231
+ const processor = publicProcessorFactory.create(merkleTreeFork, newGlobalVariables, config);
746
1232
  // REFACTOR: Consider merging ProcessReturnValues into ProcessedTx
747
1233
  const [processedTxs, failedTxs, _usedTxs, returns] = await processor.process([
748
1234
  tx
@@ -765,14 +1251,14 @@ import { NodeMetrics } from './node_metrics.js';
765
1251
  const verifier = isSimulation ? undefined : this.proofVerifier;
766
1252
  // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
767
1253
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
768
- const blockNumber = await this.blockSource.getBlockNumber() + 1;
1254
+ const blockNumber = BlockNumber(await this.blockSource.getBlockNumber() + 1);
769
1255
  const validator = createValidatorForAcceptingTxs(db, this.contractDataSource, verifier, {
770
1256
  timestamp: nextSlotTimestamp,
771
1257
  blockNumber,
772
1258
  l1ChainId: this.l1ChainId,
773
1259
  rollupVersion: this.version,
774
1260
  setupAllowList: this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions(),
775
- gasFees: await this.getCurrentBaseFees(),
1261
+ gasFees: await this.getCurrentMinFees(),
776
1262
  skipFeeEnforcement,
777
1263
  txsPermitted: !this.config.disableTransactions
778
1264
  });
@@ -791,8 +1277,11 @@ import { NodeMetrics } from './node_metrics.js';
791
1277
  this.sequencer?.updateConfig(config);
792
1278
  this.slasherClient?.updateConfig(config);
793
1279
  this.validatorsSentinel?.updateConfig(config);
794
- // this.blockBuilder.updateConfig(config); // TODO: Spyros has a PR to add the builder to `this`, so we can do this
795
1280
  await this.p2pClient.updateP2PConfig(config);
1281
+ const archiver = this.blockSource;
1282
+ if ('updateConfig' in archiver) {
1283
+ archiver.updateConfig(config);
1284
+ }
796
1285
  if (newConfig.realProofs !== this.config.realProofs) {
797
1286
  this.proofVerifier = config.realProofs ? await BBCircuitVerifier.new(newConfig) : new TestCircuitVerifier();
798
1287
  }
@@ -823,26 +1312,33 @@ import { NodeMetrics } from './node_metrics.js';
823
1312
  // We break support for archiver running remotely to the node
824
1313
  const archiver = this.blockSource;
825
1314
  if (!('backupTo' in archiver)) {
1315
+ this.metrics.recordSnapshotError();
826
1316
  throw new Error('Archiver implementation does not support backups. Cannot generate snapshot.');
827
1317
  }
828
1318
  // Test that the archiver has done an initial sync.
829
1319
  if (!archiver.isInitialSyncComplete()) {
1320
+ this.metrics.recordSnapshotError();
830
1321
  throw new Error(`Archiver initial sync not complete. Cannot start snapshot.`);
831
1322
  }
832
1323
  // And it has an L2 block hash
833
1324
  const l2BlockHash = await archiver.getL2Tips().then((tips)=>tips.latest.hash);
834
1325
  if (!l2BlockHash) {
1326
+ this.metrics.recordSnapshotError();
835
1327
  throw new Error(`Archiver has no latest L2 block hash downloaded. Cannot start snapshot.`);
836
1328
  }
837
1329
  if (this.isUploadingSnapshot) {
1330
+ this.metrics.recordSnapshotError();
838
1331
  throw new Error(`Snapshot upload already in progress. Cannot start another one until complete.`);
839
1332
  }
840
1333
  // Do not wait for the upload to be complete to return to the caller, but flag that an operation is in progress
841
1334
  this.isUploadingSnapshot = true;
1335
+ const timer = new Timer();
842
1336
  void uploadSnapshot(location, this.blockSource, this.worldStateSynchronizer, this.config, this.log).then(()=>{
843
1337
  this.isUploadingSnapshot = false;
1338
+ this.metrics.recordSnapshot(timer.ms());
844
1339
  }).catch((err)=>{
845
1340
  this.isUploadingSnapshot = false;
1341
+ this.metrics.recordSnapshotError();
846
1342
  this.log.error(`Error uploading snapshot: ${err}`);
847
1343
  });
848
1344
  return Promise.resolve();
@@ -915,7 +1411,7 @@ import { NodeMetrics } from './node_metrics.js';
915
1411
  if (typeof blockNumber === 'number' && blockNumber < INITIAL_L2_BLOCK_NUM - 1) {
916
1412
  throw new Error('Invalid block number to get world state for: ' + blockNumber);
917
1413
  }
918
- let blockSyncedTo = 0;
1414
+ let blockSyncedTo = BlockNumber.ZERO;
919
1415
  try {
920
1416
  // Attempt to sync the world state if necessary
921
1417
  blockSyncedTo = await this.#syncWorldState();
@@ -938,11 +1434,6 @@ import { NodeMetrics } from './node_metrics.js';
938
1434
  * @returns A promise that fulfils once the world state is synced
939
1435
  */ async #syncWorldState() {
940
1436
  const blockSourceHeight = await this.blockSource.getBlockNumber();
941
- return this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
1437
+ return await this.worldStateSynchronizer.syncImmediate(blockSourceHeight);
942
1438
  }
943
1439
  }
944
- _ts_decorate([
945
- trackSpan('AztecNodeService.simulatePublicCalls', (tx)=>({
946
- [Attributes.TX_HASH]: tx.getTxHash().toString()
947
- }))
948
- ], AztecNodeService.prototype, "simulatePublicCalls", null);