@aztec/sequencer-client 4.0.0-nightly.20260107 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/sequencer-client",
3
- "version": "4.0.0-nightly.20260107",
3
+ "version": "4.0.0-nightly.20260108",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -26,37 +26,37 @@
26
26
  "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
27
27
  },
28
28
  "dependencies": {
29
- "@aztec/aztec.js": "4.0.0-nightly.20260107",
30
- "@aztec/bb-prover": "4.0.0-nightly.20260107",
31
- "@aztec/blob-client": "4.0.0-nightly.20260107",
32
- "@aztec/blob-lib": "4.0.0-nightly.20260107",
33
- "@aztec/constants": "4.0.0-nightly.20260107",
34
- "@aztec/epoch-cache": "4.0.0-nightly.20260107",
35
- "@aztec/ethereum": "4.0.0-nightly.20260107",
36
- "@aztec/foundation": "4.0.0-nightly.20260107",
37
- "@aztec/l1-artifacts": "4.0.0-nightly.20260107",
38
- "@aztec/merkle-tree": "4.0.0-nightly.20260107",
39
- "@aztec/node-keystore": "4.0.0-nightly.20260107",
40
- "@aztec/noir-acvm_js": "4.0.0-nightly.20260107",
41
- "@aztec/noir-contracts.js": "4.0.0-nightly.20260107",
42
- "@aztec/noir-protocol-circuits-types": "4.0.0-nightly.20260107",
43
- "@aztec/noir-types": "4.0.0-nightly.20260107",
44
- "@aztec/p2p": "4.0.0-nightly.20260107",
45
- "@aztec/protocol-contracts": "4.0.0-nightly.20260107",
46
- "@aztec/prover-client": "4.0.0-nightly.20260107",
47
- "@aztec/simulator": "4.0.0-nightly.20260107",
48
- "@aztec/slasher": "4.0.0-nightly.20260107",
49
- "@aztec/stdlib": "4.0.0-nightly.20260107",
50
- "@aztec/telemetry-client": "4.0.0-nightly.20260107",
51
- "@aztec/validator-client": "4.0.0-nightly.20260107",
52
- "@aztec/world-state": "4.0.0-nightly.20260107",
29
+ "@aztec/aztec.js": "4.0.0-nightly.20260108",
30
+ "@aztec/bb-prover": "4.0.0-nightly.20260108",
31
+ "@aztec/blob-client": "4.0.0-nightly.20260108",
32
+ "@aztec/blob-lib": "4.0.0-nightly.20260108",
33
+ "@aztec/constants": "4.0.0-nightly.20260108",
34
+ "@aztec/epoch-cache": "4.0.0-nightly.20260108",
35
+ "@aztec/ethereum": "4.0.0-nightly.20260108",
36
+ "@aztec/foundation": "4.0.0-nightly.20260108",
37
+ "@aztec/l1-artifacts": "4.0.0-nightly.20260108",
38
+ "@aztec/merkle-tree": "4.0.0-nightly.20260108",
39
+ "@aztec/node-keystore": "4.0.0-nightly.20260108",
40
+ "@aztec/noir-acvm_js": "4.0.0-nightly.20260108",
41
+ "@aztec/noir-contracts.js": "4.0.0-nightly.20260108",
42
+ "@aztec/noir-protocol-circuits-types": "4.0.0-nightly.20260108",
43
+ "@aztec/noir-types": "4.0.0-nightly.20260108",
44
+ "@aztec/p2p": "4.0.0-nightly.20260108",
45
+ "@aztec/protocol-contracts": "4.0.0-nightly.20260108",
46
+ "@aztec/prover-client": "4.0.0-nightly.20260108",
47
+ "@aztec/simulator": "4.0.0-nightly.20260108",
48
+ "@aztec/slasher": "4.0.0-nightly.20260108",
49
+ "@aztec/stdlib": "4.0.0-nightly.20260108",
50
+ "@aztec/telemetry-client": "4.0.0-nightly.20260108",
51
+ "@aztec/validator-client": "4.0.0-nightly.20260108",
52
+ "@aztec/world-state": "4.0.0-nightly.20260108",
53
53
  "lodash.chunk": "^4.2.0",
54
54
  "tslib": "^2.4.0",
55
55
  "viem": "npm:@aztec/viem@2.38.2"
56
56
  },
57
57
  "devDependencies": {
58
- "@aztec/archiver": "4.0.0-nightly.20260107",
59
- "@aztec/kv-store": "4.0.0-nightly.20260107",
58
+ "@aztec/archiver": "4.0.0-nightly.20260108",
59
+ "@aztec/kv-store": "4.0.0-nightly.20260108",
60
60
  "@jest/globals": "^30.0.0",
61
61
  "@types/jest": "^30.0.0",
62
62
  "@types/lodash.chunk": "^4.2.7",
@@ -23,7 +23,7 @@ import { createPublicClient, fallback, http } from 'viem';
23
23
  */
24
24
  export class GlobalVariableBuilder implements GlobalVariableBuilderInterface {
25
25
  private log = createLogger('sequencer:global_variable_builder');
26
- private currentBaseFees: Promise<GasFees> = Promise.resolve(new GasFees(0, 0));
26
+ private currentMinFees: Promise<GasFees> = Promise.resolve(new GasFees(0, 0));
27
27
  private currentL1BlockNumber: bigint | undefined = undefined;
28
28
 
29
29
  private readonly rollupContract: RollupContract;
@@ -61,10 +61,10 @@ export class GlobalVariableBuilder implements GlobalVariableBuilderInterface {
61
61
  }
62
62
 
63
63
  /**
64
- * Computes the "current" base fees, e.g., the price that you currently should pay to get include in the next block
65
- * @returns Base fees for the next block
64
+ * Computes the "current" min fees, e.g., the price that you currently should pay to get include in the next block
65
+ * @returns Min fees for the next block
66
66
  */
67
- private async computeCurrentBaseFees(): Promise<GasFees> {
67
+ private async computeCurrentMinFees(): Promise<GasFees> {
68
68
  // Since this might be called in the middle of a slot where a block might have been published,
69
69
  // we need to fetch the last block written, and estimate the earliest timestamp for the next block.
70
70
  // The timestamp of that last block will act as a lower bound for the next block.
@@ -76,19 +76,19 @@ export class GlobalVariableBuilder implements GlobalVariableBuilderInterface {
76
76
  const nextEthTimestamp = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(this.ethereumSlotDuration));
77
77
  const timestamp = earliestTimestamp > nextEthTimestamp ? earliestTimestamp : nextEthTimestamp;
78
78
 
79
- return new GasFees(0, await this.rollupContract.getManaBaseFeeAt(timestamp, true));
79
+ return new GasFees(0, await this.rollupContract.getManaMinFeeAt(timestamp, true));
80
80
  }
81
81
 
82
- public async getCurrentBaseFees(): Promise<GasFees> {
82
+ public async getCurrentMinFees(): Promise<GasFees> {
83
83
  // Get the current block number
84
84
  const blockNumber = await this.publicClient.getBlockNumber();
85
85
 
86
- // If the L1 block number has changed then chain a new promise to get the current base fees
86
+ // If the L1 block number has changed then chain a new promise to get the current min fees
87
87
  if (this.currentL1BlockNumber === undefined || blockNumber > this.currentL1BlockNumber) {
88
88
  this.currentL1BlockNumber = blockNumber;
89
- this.currentBaseFees = this.currentBaseFees.then(() => this.computeCurrentBaseFees());
89
+ this.currentMinFees = this.currentMinFees.then(() => this.computeCurrentMinFees());
90
90
  }
91
- return this.currentBaseFees;
91
+ return this.currentMinFees;
92
92
  }
93
93
 
94
94
  /**
@@ -128,9 +128,9 @@ export class GlobalVariableBuilder implements GlobalVariableBuilderInterface {
128
128
  l1GenesisTime: this.l1GenesisTime,
129
129
  });
130
130
 
131
- // We can skip much of the logic in getCurrentBaseFees since it we already check that we are not within a slot elsewhere.
131
+ // We can skip much of the logic in getCurrentMinFees since it we already check that we are not within a slot elsewhere.
132
132
  // TODO(palla/mbps): Can we use a cached value here?
133
- const gasFees = new GasFees(0, await this.rollupContract.getManaBaseFeeAt(timestamp, true));
133
+ const gasFees = new GasFees(0, await this.rollupContract.getManaMinFeeAt(timestamp, true));
134
134
 
135
135
  return { chainId, version, slotNumber, timestamp, coinbase, feeRecipient, gasFees };
136
136
  }
@@ -40,7 +40,7 @@ import type { Checkpoint } from '@aztec/stdlib/checkpoint';
40
40
  import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
41
41
  import type { CheckpointHeader } from '@aztec/stdlib/rollup';
42
42
  import type { L1PublishCheckpointStats } from '@aztec/stdlib/stats';
43
- import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
43
+ import { type TelemetryClient, type Tracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
44
44
 
45
45
  import { type StateOverride, type TransactionReceipt, type TypedDataDefinition, encodeFunctionData, toHex } from 'viem';
46
46
 
@@ -139,6 +139,8 @@ export class SequencerPublisher {
139
139
  public slashingProposerContract: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
140
140
  public slashFactoryContract: SlashFactoryContract;
141
141
 
142
+ public readonly tracer: Tracer;
143
+
142
144
  protected requests: RequestWithExpiry[] = [];
143
145
 
144
146
  constructor(
@@ -167,6 +169,7 @@ export class SequencerPublisher {
167
169
 
168
170
  const telemetry = deps.telemetry ?? getTelemetryClient();
169
171
  this.metrics = deps.metrics ?? new SequencerPublisherMetrics(telemetry, 'SequencerPublisher');
172
+ this.tracer = telemetry.getTracer('SequencerPublisher');
170
173
  this.l1TxUtils = deps.l1TxUtils;
171
174
 
172
175
  this.rollupContract = deps.rollupContract;
@@ -296,6 +299,7 @@ export class SequencerPublisher {
296
299
  * - a receipt and errorMsg if it failed on L1
297
300
  * - undefined if no valid requests are found OR the tx failed to send.
298
301
  */
302
+ @trackSpan('SequencerPublisher.sendRequests')
299
303
  public async sendRequests() {
300
304
  const requestsToProcess = [...this.requests];
301
305
  this.requests = [];
@@ -442,10 +446,11 @@ export class SequencerPublisher {
442
446
  * It will throw if the block header is invalid.
443
447
  * @param header - The block header to validate
444
448
  */
449
+ @trackSpan('SequencerPublisher.validateBlockHeader')
445
450
  public async validateBlockHeader(
446
451
  header: CheckpointHeader,
447
452
  opts?: { forcePendingBlockNumber: BlockNumber | undefined },
448
- ) {
453
+ ): Promise<void> {
449
454
  const flags = { ignoreDA: true, ignoreSignatures: true };
450
455
 
451
456
  const args = [
@@ -588,6 +593,7 @@ export class SequencerPublisher {
588
593
  }
589
594
 
590
595
  /** Simulates `propose` to make sure that the checkpoint is valid for submission */
596
+ @trackSpan('SequencerPublisher.validateCheckpointForSubmission')
591
597
  public async validateCheckpointForSubmission(
592
598
  checkpoint: Checkpoint,
593
599
  attestationsAndSigners: CommitteeAttestationsAndSigners,
@@ -32,6 +32,7 @@ import { CheckpointHeader } from '@aztec/stdlib/rollup';
32
32
  import type { L2BlockBuiltStats } from '@aztec/stdlib/stats';
33
33
  import { type FailedTx, Tx } from '@aztec/stdlib/tx';
34
34
  import { AttestationTimeoutError } from '@aztec/stdlib/validators';
35
+ import { Attributes, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
35
36
  import type { ValidatorClient } from '@aztec/validator-client';
36
37
 
37
38
  import type { GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
@@ -54,7 +55,7 @@ const TXS_POLLING_MS = 500;
54
55
  * as well as enqueueing votes for slashing and governance proposals. This class is created from
55
56
  * the Sequencer once the check for being the proposer for the slot has succeeded.
56
57
  */
57
- export class CheckpointProposalJob {
58
+ export class CheckpointProposalJob implements Traceable {
58
59
  constructor(
59
60
  private readonly slot: SlotNumber,
60
61
  private readonly checkpointNumber: CheckpointNumber,
@@ -80,12 +81,14 @@ export class CheckpointProposalJob {
80
81
  private readonly eventEmitter: TypedEventEmitter<SequencerEvents>,
81
82
  private readonly setStateFn: (state: SequencerState, slot?: SlotNumber) => void,
82
83
  protected readonly log: Logger,
84
+ public readonly tracer: Tracer,
83
85
  ) {}
84
86
 
85
87
  /**
86
88
  * Executes the checkpoint proposal job.
87
89
  * Returns the published checkpoint if successful, undefined otherwise.
88
90
  */
91
+ @trackSpan('CheckpointProposalJob.execute')
89
92
  public async execute(): Promise<Checkpoint | undefined> {
90
93
  // Enqueue governance and slashing votes (returns promises that will be awaited later)
91
94
  // In fisherman mode, we simulate slashing but don't actually publish to L1
@@ -132,6 +135,13 @@ export class CheckpointProposalJob {
132
135
  }
133
136
  }
134
137
 
138
+ @trackSpan('CheckpointProposalJob.proposeCheckpoint', function () {
139
+ return {
140
+ // nullish operator needed for tests
141
+ [Attributes.COINBASE]: this.validatorClient.getCoinbaseForAttestor(this.attestorAddress)?.toString(),
142
+ [Attributes.SLOT_NUMBER]: this.slot,
143
+ };
144
+ })
135
145
  private async proposeCheckpoint(): Promise<Checkpoint | undefined> {
136
146
  try {
137
147
  // Get operator configured coinbase and fee recipient for this attestor
@@ -248,6 +258,7 @@ export class CheckpointProposalJob {
248
258
  /**
249
259
  * Builds blocks for a checkpoint within the current slot.
250
260
  */
261
+ @trackSpan('CheckpointProposalJob.buildBlocksForCheckpoint')
251
262
  private async buildBlocksForCheckpoint(
252
263
  checkpointBuilder: CheckpointBuilder,
253
264
  timestamp: bigint,
@@ -366,6 +377,7 @@ export class CheckpointProposalJob {
366
377
  }
367
378
 
368
379
  /** Sleeps until it is time to produce the next block in the slot */
380
+ @trackSpan('CheckpointProposalJob.waitUntilNextSubslot')
369
381
  private async waitUntilNextSubslot(nextSubslotStart: number) {
370
382
  this.setStateFn(SequencerState.WAITING_UNTIL_NEXT_BLOCK, this.slot);
371
383
  this.log.verbose(`Waiting until time for the next block at ${nextSubslotStart}s into slot`, { slot: this.slot });
@@ -373,6 +385,7 @@ export class CheckpointProposalJob {
373
385
  }
374
386
 
375
387
  /** Builds a single block. Called from the main block building loop. */
388
+ @trackSpan('CheckpointProposalJob.buildSingleBlock')
376
389
  private async buildSingleBlock(
377
390
  checkpointBuilder: CheckpointBuilder,
378
391
  opts: {
@@ -484,6 +497,7 @@ export class CheckpointProposalJob {
484
497
  }
485
498
 
486
499
  /** Waits until minTxs are available on the pool for building a block. */
500
+ @trackSpan('CheckpointProposalJob.waitForMinTxs')
487
501
  private async waitForMinTxs(opts: {
488
502
  forceCreate?: boolean;
489
503
  blockNumber: BlockNumber;
@@ -524,6 +538,7 @@ export class CheckpointProposalJob {
524
538
  * Waits for enough attestations to be collected via p2p.
525
539
  * This is run after all blocks for the checkpoint have been built.
526
540
  */
541
+ @trackSpan('CheckpointProposalJob.waitForAttestations')
527
542
  private async waitForAttestations(proposal: BlockProposal): Promise<CommitteeAttestationsAndSigners> {
528
543
  if (this.config.fishermanMode) {
529
544
  this.log.debug('Skipping attestation collection in fisherman mode');
@@ -685,6 +700,7 @@ export class CheckpointProposalJob {
685
700
  }
686
701
 
687
702
  /** Waits until a specific time within the current slot */
703
+ @trackSpan('CheckpointProposalJob.waitUntilTimeInSlot')
688
704
  protected async waitUntilTimeInSlot(targetSecondsIntoSlot: number): Promise<void> {
689
705
  const slotStartTimestamp = this.getSlotStartBuildTimestamp();
690
706
  const targetTimestamp = slotStartTimestamp + targetSecondsIntoSlot;
@@ -24,7 +24,7 @@ import {
24
24
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
25
25
  import { pickFromSchema } from '@aztec/stdlib/schemas';
26
26
  import { MerkleTreeId } from '@aztec/stdlib/trees';
27
- import { type TelemetryClient, type Tracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
27
+ import { Attributes, type TelemetryClient, type Tracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
28
28
  import type { ValidatorClient } from '@aztec/validator-client';
29
29
 
30
30
  import EventEmitter from 'node:events';
@@ -160,7 +160,6 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
160
160
  this.log.info('Stopped sequencer');
161
161
  }
162
162
 
163
- @trackSpan('Sequencer.work')
164
163
  /** Main sequencer loop with a try/catch */
165
164
  protected async safeWork() {
166
165
  try {
@@ -198,6 +197,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
198
197
  * - Collect attestations for the final block
199
198
  * - Submit checkpoint
200
199
  */
200
+ @trackSpan('Sequencer.work')
201
201
  protected async work() {
202
202
  this.setState(SequencerState.SYNCHRONIZING, undefined);
203
203
  const { slot, ts, now, epoch } = this.epochCache.getEpochAndSlotInNextL1Slot();
@@ -233,6 +233,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
233
233
  * This is the initial step in the main loop.
234
234
  * @returns CheckpointProposalJob if successful, undefined if we are not yet synced or are not the proposer.
235
235
  */
236
+ @trackSpan('Sequencer.prepareCheckpointProposal')
236
237
  private async prepareCheckpointProposal(
237
238
  slot: SlotNumber,
238
239
  ts: bigint,
@@ -401,6 +402,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
401
402
  this,
402
403
  this.setState.bind(this),
403
404
  this.log,
405
+ this.tracer,
404
406
  );
405
407
  }
406
408
 
@@ -555,6 +557,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
555
557
  * Tries to vote on slashing actions and governance when the sync check fails but we're past the max time for initializing a proposal.
556
558
  * This allows the sequencer to participate in governance/slashing votes even when it cannot build blocks.
557
559
  */
560
+ @trackSpan('Seqeuencer.tryVoteWhenSyncFails', ({ slot }) => ({ [Attributes.SLOT_NUMBER]: slot }))
558
561
  protected async tryVoteWhenSyncFails(args: { slot: SlotNumber; ts: bigint }): Promise<void> {
559
562
  const { slot } = args;
560
563