@aztec/sequencer-client 0.0.1-commit.03f7ef2 → 0.0.1-commit.1142ef1

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.
Files changed (70) hide show
  1. package/dest/client/sequencer-client.d.ts +5 -6
  2. package/dest/client/sequencer-client.d.ts.map +1 -1
  3. package/dest/config.d.ts +1 -1
  4. package/dest/config.d.ts.map +1 -1
  5. package/dest/config.js +8 -1
  6. package/dest/global_variable_builder/global_builder.d.ts +4 -4
  7. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  8. package/dest/global_variable_builder/global_builder.js +12 -12
  9. package/dest/index.d.ts +2 -3
  10. package/dest/index.d.ts.map +1 -1
  11. package/dest/index.js +1 -2
  12. package/dest/publisher/sequencer-publisher-factory.d.ts +2 -2
  13. package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
  14. package/dest/publisher/sequencer-publisher-metrics.d.ts +1 -1
  15. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
  16. package/dest/publisher/sequencer-publisher-metrics.js +15 -86
  17. package/dest/publisher/sequencer-publisher.d.ts +19 -18
  18. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  19. package/dest/publisher/sequencer-publisher.js +443 -53
  20. package/dest/sequencer/block_builder.d.ts +1 -1
  21. package/dest/sequencer/block_builder.d.ts.map +1 -1
  22. package/dest/sequencer/block_builder.js +1 -1
  23. package/dest/sequencer/checkpoint_proposal_job.d.ts +11 -8
  24. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
  25. package/dest/sequencer/checkpoint_proposal_job.js +478 -29
  26. package/dest/sequencer/index.d.ts +1 -2
  27. package/dest/sequencer/index.d.ts.map +1 -1
  28. package/dest/sequencer/index.js +0 -1
  29. package/dest/sequencer/metrics.d.ts +3 -3
  30. package/dest/sequencer/metrics.d.ts.map +1 -1
  31. package/dest/sequencer/metrics.js +30 -121
  32. package/dest/sequencer/sequencer.d.ts +13 -11
  33. package/dest/sequencer/sequencer.d.ts.map +1 -1
  34. package/dest/sequencer/sequencer.js +425 -37
  35. package/dest/test/index.d.ts +2 -3
  36. package/dest/test/index.d.ts.map +1 -1
  37. package/dest/test/mock_checkpoint_builder.d.ts +10 -2
  38. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
  39. package/dest/test/mock_checkpoint_builder.js +23 -0
  40. package/dest/test/utils.d.ts +8 -4
  41. package/dest/test/utils.d.ts.map +1 -1
  42. package/dest/test/utils.js +21 -12
  43. package/package.json +27 -27
  44. package/src/client/sequencer-client.ts +4 -5
  45. package/src/config.ts +7 -0
  46. package/src/global_variable_builder/global_builder.ts +12 -12
  47. package/src/index.ts +0 -3
  48. package/src/publisher/sequencer-publisher-factory.ts +1 -1
  49. package/src/publisher/sequencer-publisher-metrics.ts +14 -70
  50. package/src/publisher/sequencer-publisher.ts +87 -77
  51. package/src/sequencer/block_builder.ts +1 -2
  52. package/src/sequencer/checkpoint_proposal_job.ts +79 -40
  53. package/src/sequencer/index.ts +0 -1
  54. package/src/sequencer/metrics.ts +23 -131
  55. package/src/sequencer/sequencer.ts +46 -35
  56. package/src/test/index.ts +1 -2
  57. package/src/test/mock_checkpoint_builder.ts +34 -2
  58. package/src/test/utils.ts +39 -19
  59. package/dest/sequencer/checkpoint_builder.d.ts +0 -63
  60. package/dest/sequencer/checkpoint_builder.d.ts.map +0 -1
  61. package/dest/sequencer/checkpoint_builder.js +0 -131
  62. package/dest/tx_validator/nullifier_cache.d.ts +0 -14
  63. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  64. package/dest/tx_validator/nullifier_cache.js +0 -24
  65. package/dest/tx_validator/tx_validator_factory.d.ts +0 -18
  66. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
  67. package/dest/tx_validator/tx_validator_factory.js +0 -53
  68. package/src/sequencer/checkpoint_builder.ts +0 -217
  69. package/src/tx_validator/nullifier_cache.ts +0 -30
  70. package/src/tx_validator/tx_validator_factory.ts +0 -133
@@ -2,6 +2,7 @@ import { BLOBS_PER_CHECKPOINT, FIELDS_PER_BLOB } from '@aztec/constants';
2
2
  import type { EpochCache } from '@aztec/epoch-cache';
3
3
  import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
4
4
  import { randomInt } from '@aztec/foundation/crypto/random';
5
+ import { Fr } from '@aztec/foundation/curves/bn254';
5
6
  import { EthAddress } from '@aztec/foundation/eth-address';
6
7
  import { Signature } from '@aztec/foundation/eth-signature';
7
8
  import { filter } from '@aztec/foundation/iterator';
@@ -15,6 +16,7 @@ import {
15
16
  CommitteeAttestation,
16
17
  CommitteeAttestationsAndSigners,
17
18
  L2BlockNew,
19
+ type L2BlockSink,
18
20
  MaliciousCommitteeAttestationsAndSigners,
19
21
  } from '@aztec/stdlib/block';
20
22
  import type { Checkpoint } from '@aztec/stdlib/checkpoint';
@@ -25,18 +27,17 @@ import type {
25
27
  ResolvedSequencerConfig,
26
28
  WorldStateSynchronizer,
27
29
  } from '@aztec/stdlib/interfaces/server';
28
- import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
29
- import type { BlockProposal, BlockProposalOptions } from '@aztec/stdlib/p2p';
30
+ import { type L1ToL2MessageSource, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
31
+ import type { BlockProposalOptions, CheckpointProposal, CheckpointProposalOptions } from '@aztec/stdlib/p2p';
30
32
  import { orderAttestations } from '@aztec/stdlib/p2p';
31
- import { CheckpointHeader } from '@aztec/stdlib/rollup';
32
33
  import type { L2BlockBuiltStats } from '@aztec/stdlib/stats';
33
34
  import { type FailedTx, Tx } from '@aztec/stdlib/tx';
34
35
  import { AttestationTimeoutError } from '@aztec/stdlib/validators';
35
- import type { ValidatorClient } from '@aztec/validator-client';
36
+ import { Attributes, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
37
+ import { CheckpointBuilder, type FullNodeCheckpointsBuilder, type ValidatorClient } from '@aztec/validator-client';
36
38
 
37
39
  import type { GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
38
- import type { InvalidateBlockRequest, SequencerPublisher } from '../publisher/sequencer-publisher.js';
39
- import { CheckpointBuilder, type FullNodeCheckpointsBuilder } from './checkpoint_builder.js';
40
+ import type { InvalidateCheckpointRequest, SequencerPublisher } from '../publisher/sequencer-publisher.js';
40
41
  import { CheckpointVoter } from './checkpoint_voter.js';
41
42
  import { SequencerInterruptedError } from './errors.js';
42
43
  import type { SequencerEvents } from './events.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,
@@ -63,13 +64,14 @@ export class CheckpointProposalJob {
63
64
  private readonly proposer: EthAddress | undefined,
64
65
  private readonly publisher: SequencerPublisher,
65
66
  private readonly attestorAddress: EthAddress,
66
- private readonly invalidateBlock: InvalidateBlockRequest | undefined,
67
+ private readonly invalidateCheckpoint: InvalidateCheckpointRequest | undefined,
67
68
  private readonly validatorClient: ValidatorClient,
68
69
  private readonly globalsBuilder: GlobalVariableBuilder,
69
70
  private readonly p2pClient: P2P,
70
71
  private readonly worldState: WorldStateSynchronizer,
71
72
  private readonly l1ToL2MessageSource: L1ToL2MessageSource,
72
73
  private readonly checkpointsBuilder: FullNodeCheckpointsBuilder,
74
+ private readonly blockSink: L2BlockSink,
73
75
  private readonly l1Constants: SequencerRollupConstants,
74
76
  protected config: ResolvedSequencerConfig,
75
77
  protected timetable: SequencerTimetable,
@@ -80,12 +82,14 @@ export class CheckpointProposalJob {
80
82
  private readonly eventEmitter: TypedEventEmitter<SequencerEvents>,
81
83
  private readonly setStateFn: (state: SequencerState, slot?: SlotNumber) => void,
82
84
  protected readonly log: Logger,
85
+ public readonly tracer: Tracer,
83
86
  ) {}
84
87
 
85
88
  /**
86
89
  * Executes the checkpoint proposal job.
87
90
  * Returns the published checkpoint if successful, undefined otherwise.
88
91
  */
92
+ @trackSpan('CheckpointProposalJob.execute')
89
93
  public async execute(): Promise<Checkpoint | undefined> {
90
94
  // Enqueue governance and slashing votes (returns promises that will be awaited later)
91
95
  // In fisherman mode, we simulate slashing but don't actually publish to L1
@@ -108,6 +112,10 @@ export class CheckpointProposalJob {
108
112
  // Wait until the voting promises have resolved, so all requests are enqueued (not sent)
109
113
  await Promise.all(votesPromises);
110
114
 
115
+ if (checkpoint) {
116
+ this.metrics.recordBlockProposalSuccess();
117
+ }
118
+
111
119
  // Do not post anything to L1 if we are fishermen, but do perform L1 fee analysis
112
120
  if (this.config.fishermanMode) {
113
121
  await this.handleCheckpointEndAsFisherman(checkpoint);
@@ -128,6 +136,13 @@ export class CheckpointProposalJob {
128
136
  }
129
137
  }
130
138
 
139
+ @trackSpan('CheckpointProposalJob.proposeCheckpoint', function () {
140
+ return {
141
+ // nullish operator needed for tests
142
+ [Attributes.COINBASE]: this.validatorClient.getCoinbaseForAttestor(this.attestorAddress)?.toString(),
143
+ [Attributes.SLOT_NUMBER]: this.slot,
144
+ };
145
+ })
131
146
  private async proposeCheckpoint(): Promise<Checkpoint | undefined> {
132
147
  try {
133
148
  // Get operator configured coinbase and fee recipient for this attestor
@@ -138,9 +153,9 @@ export class CheckpointProposalJob {
138
153
  this.setStateFn(SequencerState.INITIALIZING_CHECKPOINT, this.slot);
139
154
  this.metrics.incOpenSlot(this.slot, this.proposer?.toString() ?? 'unknown');
140
155
 
141
- // Enqueues block invalidation (constant for the whole slot)
142
- if (this.invalidateBlock && !this.config.skipInvalidateBlockAsProposer) {
143
- this.publisher.enqueueInvalidateBlock(this.invalidateBlock);
156
+ // Enqueues checkpoint invalidation (constant for the whole slot)
157
+ if (this.invalidateCheckpoint && !this.config.skipInvalidateBlockAsProposer) {
158
+ this.publisher.enqueueInvalidateCheckpoint(this.invalidateCheckpoint);
144
159
  }
145
160
 
146
161
  // Create checkpoint builder for the slot
@@ -150,8 +165,9 @@ export class CheckpointProposalJob {
150
165
  this.slot,
151
166
  );
152
167
 
153
- // Collect L1 to L2 messages for the checkpoint
168
+ // Collect L1 to L2 messages for the checkpoint and compute their hash
154
169
  const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(this.checkpointNumber);
170
+ const inHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
155
171
 
156
172
  // Create a long-lived forked world state for the checkpoint builder
157
173
  using fork = await this.worldState.fork(this.syncedToBlockNumber, { closeDelayMs: 12_000 });
@@ -170,10 +186,16 @@ export class CheckpointProposalJob {
170
186
  broadcastInvalidBlockProposal: this.config.broadcastInvalidBlockProposal,
171
187
  };
172
188
 
189
+ const checkpointProposalOptions: CheckpointProposalOptions = {
190
+ publishFullTxs: !!this.config.publishTxsWithProposals,
191
+ broadcastInvalidCheckpointProposal: this.config.broadcastInvalidBlockProposal,
192
+ };
193
+
173
194
  // Main loop: build blocks for the checkpoint
174
- const { blocksInCheckpoint, pendingBroadcast } = await this.buildBlocksForCheckpoint(
195
+ const { blocksInCheckpoint, blockPendingBroadcast } = await this.buildBlocksForCheckpoint(
175
196
  checkpointBuilder,
176
197
  checkpointGlobalVariables.timestamp,
198
+ inHash,
177
199
  blockProposalOptions,
178
200
  );
179
201
 
@@ -203,22 +225,30 @@ export class CheckpointProposalJob {
203
225
  return checkpoint;
204
226
  }
205
227
 
206
- // TODO(palla/mbps): Wire this to the new p2p API once available, including the pendingBroadcast.block
228
+ // Include the block pending broadcast in the checkpoint proposal if any
229
+ const lastBlock = blockPendingBroadcast && {
230
+ blockHeader: blockPendingBroadcast.block.header,
231
+ indexWithinCheckpoint: blockPendingBroadcast.block.indexWithinCheckpoint,
232
+ txs: blockPendingBroadcast.txs,
233
+ };
234
+
235
+ // Create the checkpoint proposal and broadcast it
207
236
  const proposal = await this.validatorClient.createCheckpointProposal(
208
237
  checkpoint.header,
209
238
  checkpoint.archive.root,
210
- pendingBroadcast?.txs ?? [],
239
+ lastBlock,
211
240
  this.proposer,
212
- blockProposalOptions,
241
+ checkpointProposalOptions,
213
242
  );
243
+
214
244
  const blockProposedAt = this.dateProvider.now();
215
- await this.p2pClient.broadcastProposal(proposal);
245
+ await this.p2pClient.broadcastCheckpointProposal(proposal);
216
246
 
217
247
  this.setStateFn(SequencerState.COLLECTING_ATTESTATIONS, this.slot);
218
248
  const attestations = await this.waitForAttestations(proposal);
219
249
  const blockAttestedAt = this.dateProvider.now();
220
250
 
221
- this.metrics.recordBlockAttestationDelay(blockAttestedAt - blockProposedAt);
251
+ this.metrics.recordCheckpointAttestationDelay(blockAttestedAt - blockProposedAt);
222
252
 
223
253
  // Proposer must sign over the attestations before pushing them to L1
224
254
  const signer = this.proposer ?? this.publisher.getSenderAddress();
@@ -231,7 +261,7 @@ export class CheckpointProposalJob {
231
261
  const txTimeoutAt = new Date((slotStartBuildTimestamp + aztecSlotDuration) * 1000);
232
262
  await this.publisher.enqueueProposeCheckpoint(checkpoint, attestations, attestationsSignature, {
233
263
  txTimeoutAt,
234
- forcePendingBlockNumber: this.invalidateBlock?.forcePendingBlockNumber,
264
+ forcePendingCheckpointNumber: this.invalidateCheckpoint?.forcePendingCheckpointNumber,
235
265
  });
236
266
 
237
267
  return checkpoint;
@@ -244,20 +274,22 @@ export class CheckpointProposalJob {
244
274
  /**
245
275
  * Builds blocks for a checkpoint within the current slot.
246
276
  */
277
+ @trackSpan('CheckpointProposalJob.buildBlocksForCheckpoint')
247
278
  private async buildBlocksForCheckpoint(
248
279
  checkpointBuilder: CheckpointBuilder,
249
280
  timestamp: bigint,
281
+ inHash: Fr,
250
282
  blockProposalOptions: BlockProposalOptions,
251
283
  ): Promise<{
252
284
  blocksInCheckpoint: L2BlockNew[];
253
- pendingBroadcast: { block: L2BlockNew; txs: Tx[] } | undefined;
285
+ blockPendingBroadcast: { block: L2BlockNew; txs: Tx[] } | undefined;
254
286
  }> {
255
287
  const blocksInCheckpoint: L2BlockNew[] = [];
256
288
  const txHashesAlreadyIncluded = new Set<string>();
257
289
  const initialBlockNumber = BlockNumber(this.syncedToBlockNumber + 1);
258
290
 
259
291
  // Last block in the checkpoint will usually be flagged as pending broadcast, so we send it along with the checkpoint proposal
260
- let pendingBroadcast: { block: L2BlockNew; txs: Tx[] } | undefined = undefined;
292
+ let blockPendingBroadcast: { block: L2BlockNew; txs: Tx[] } | undefined = undefined;
261
293
 
262
294
  while (true) {
263
295
  const blocksBuilt = blocksInCheckpoint.length;
@@ -327,17 +359,17 @@ export class CheckpointProposalJob {
327
359
  blockNumber,
328
360
  blocksBuilt,
329
361
  });
330
- pendingBroadcast = { block, txs: usedTxs };
362
+ blockPendingBroadcast = { block, txs: usedTxs };
331
363
  break;
332
364
  }
333
365
 
334
366
  // For non-last blocks, broadcast the block proposal (unless we're in fisherman mode)
335
367
  // If the block is the last one, we'll broadcast it along with the checkpoint at the end of the loop
336
368
  if (!this.config.fishermanMode) {
337
- // TODO(palla/mbps): Wire this to the new p2p API once available
338
369
  const proposal = await this.validatorClient.createBlockProposal(
339
- block.header.globalVariables.blockNumber,
340
- (await checkpointBuilder.getCheckpoint()).header,
370
+ block.header,
371
+ block.indexWithinCheckpoint,
372
+ inHash,
341
373
  block.archive.root,
342
374
  usedTxs,
343
375
  this.proposer,
@@ -355,13 +387,11 @@ export class CheckpointProposalJob {
355
387
  blocksBuilt: blocksInCheckpoint.length,
356
388
  });
357
389
 
358
- return {
359
- blocksInCheckpoint,
360
- pendingBroadcast,
361
- };
390
+ return { blocksInCheckpoint, blockPendingBroadcast };
362
391
  }
363
392
 
364
393
  /** Sleeps until it is time to produce the next block in the slot */
394
+ @trackSpan('CheckpointProposalJob.waitUntilNextSubslot')
365
395
  private async waitUntilNextSubslot(nextSubslotStart: number) {
366
396
  this.setStateFn(SequencerState.WAITING_UNTIL_NEXT_BLOCK, this.slot);
367
397
  this.log.verbose(`Waiting until time for the next block at ${nextSubslotStart}s into slot`, { slot: this.slot });
@@ -369,6 +399,7 @@ export class CheckpointProposalJob {
369
399
  }
370
400
 
371
401
  /** Builds a single block. Called from the main block building loop. */
402
+ @trackSpan('CheckpointProposalJob.buildSingleBlock')
372
403
  private async buildSingleBlock(
373
404
  checkpointBuilder: CheckpointBuilder,
374
405
  opts: {
@@ -480,6 +511,7 @@ export class CheckpointProposalJob {
480
511
  }
481
512
 
482
513
  /** Waits until minTxs are available on the pool for building a block. */
514
+ @trackSpan('CheckpointProposalJob.waitForMinTxs')
483
515
  private async waitForMinTxs(opts: {
484
516
  forceCreate?: boolean;
485
517
  blockNumber: BlockNumber;
@@ -520,7 +552,8 @@ export class CheckpointProposalJob {
520
552
  * Waits for enough attestations to be collected via p2p.
521
553
  * This is run after all blocks for the checkpoint have been built.
522
554
  */
523
- private async waitForAttestations(proposal: BlockProposal): Promise<CommitteeAttestationsAndSigners> {
555
+ @trackSpan('CheckpointProposalJob.waitForAttestations')
556
+ private async waitForAttestations(proposal: CheckpointProposal): Promise<CommitteeAttestationsAndSigners> {
524
557
  if (this.config.fishermanMode) {
525
558
  this.log.debug('Skipping attestation collection in fisherman mode');
526
559
  return CommitteeAttestationsAndSigners.empty();
@@ -569,8 +602,7 @@ export class CheckpointProposalJob {
569
602
 
570
603
  // Manipulate the attestations if we've been configured to do so
571
604
  if (this.config.injectFakeAttestation || this.config.shuffleAttestationOrdering) {
572
- const checkpoint = proposal.payload.header;
573
- return this.manipulateAttestations(checkpoint, epoch, seed, committee, sorted);
605
+ return this.manipulateAttestations(proposal.slotNumber, epoch, seed, committee, sorted);
574
606
  }
575
607
 
576
608
  return new CommitteeAttestationsAndSigners(sorted);
@@ -586,7 +618,7 @@ export class CheckpointProposalJob {
586
618
 
587
619
  /** Breaks the attestations before publishing based on attack configs */
588
620
  private manipulateAttestations(
589
- checkpoint: CheckpointHeader,
621
+ slotNumber: SlotNumber,
590
622
  epoch: EpochNumber,
591
623
  seed: bigint,
592
624
  committee: EthAddress[],
@@ -594,7 +626,6 @@ export class CheckpointProposalJob {
594
626
  ) {
595
627
  // Compute the proposer index in the committee, since we dont want to tweak it.
596
628
  // Otherwise, the L1 rollup contract will reject the block outright.
597
- const { slotNumber } = checkpoint;
598
629
  const proposerIndex = Number(
599
630
  this.epochCache.computeProposerIndex(slotNumber, epoch, seed, BigInt(committee.length)),
600
631
  );
@@ -643,16 +674,24 @@ export class CheckpointProposalJob {
643
674
  }
644
675
 
645
676
  /**
646
- * Placeholder for pushing block to archiver and waiting for sync.
647
- * To be implemented when archiver and world-state support proposed blocks.
677
+ * Adds the proposed block to the archiver so it's available via P2P.
678
+ * Gossip doesn't echo messages back to the sender, so the proposer's archiver/world-state
679
+ * would never receive its own block without this explicit sync.
648
680
  */
649
681
  private async syncProposedBlockToArchiver(block: L2BlockNew): Promise<void> {
650
- this.log.debug(`Syncing proposed block ${block.number}`, {
682
+ // TODO(palla/mbps): Change default to false once block sync is stable.
683
+ if (this.config.skipPushProposedBlocksToArchiver !== false) {
684
+ this.log.warn(`Skipping push of proposed block ${block.number} to archiver`, {
685
+ blockNumber: block.number,
686
+ slot: block.header.globalVariables.slotNumber,
687
+ });
688
+ return;
689
+ }
690
+ this.log.debug(`Syncing proposed block ${block.number} to archiver`, {
651
691
  blockNumber: block.number,
652
692
  slot: block.header.globalVariables.slotNumber,
653
693
  });
654
- // TODO(palla/mbps): Implement actual sync to archiver and world-state
655
- await Promise.resolve();
694
+ await this.blockSink.addBlock(block);
656
695
  }
657
696
 
658
697
  /** Runs fee analysis and logs checkpoint outcome as fisherman */
@@ -669,7 +708,6 @@ export class CheckpointProposalJob {
669
708
  ...checkpoint.getStats(),
670
709
  feeAnalysisId: feeAnalysis?.id,
671
710
  });
672
- this.metrics.recordBlockProposalSuccess();
673
711
  } else {
674
712
  this.log.warn(`Validation block building FAILED for slot ${this.slot}`, {
675
713
  slot: this.slot,
@@ -682,6 +720,7 @@ export class CheckpointProposalJob {
682
720
  }
683
721
 
684
722
  /** Waits until a specific time within the current slot */
723
+ @trackSpan('CheckpointProposalJob.waitUntilTimeInSlot')
685
724
  protected async waitUntilTimeInSlot(targetSecondsIntoSlot: number): Promise<void> {
686
725
  const slotStartTimestamp = this.getSlotStartBuildTimestamp();
687
726
  const targetTimestamp = slotStartTimestamp + targetSecondsIntoSlot;
@@ -1,5 +1,4 @@
1
1
  export * from './block_builder.js';
2
- export * from './checkpoint_builder.js';
3
2
  export * from './checkpoint_proposal_job.js';
4
3
  export * from './checkpoint_voter.js';
5
4
  export * from './config.js';
@@ -11,7 +11,6 @@ import {
11
11
  type TelemetryClient,
12
12
  type Tracer,
13
13
  type UpDownCounter,
14
- ValueType,
15
14
  } from '@aztec/telemetry-client';
16
15
 
17
16
  import { type Hex, formatUnits } from 'viem';
@@ -44,7 +43,7 @@ export class SequencerMetrics {
44
43
  private blockProposalPrecheckFailed: UpDownCounter;
45
44
  private checkpointSuccess: UpDownCounter;
46
45
  private slashingAttempts: UpDownCounter;
47
- private blockAttestationDelay: Histogram;
46
+ private checkpointAttestationDelay: Histogram;
48
47
 
49
48
  // Fisherman fee analysis metrics
50
49
  private fishermanWouldBeIncluded: UpDownCounter;
@@ -70,33 +69,13 @@ export class SequencerMetrics {
70
69
 
71
70
  this.blockCounter = this.meter.createUpDownCounter(Metrics.SEQUENCER_BLOCK_COUNT);
72
71
 
73
- this.blockBuildDuration = this.meter.createHistogram(Metrics.SEQUENCER_BLOCK_BUILD_DURATION, {
74
- unit: 'ms',
75
- description: 'Duration to build a block',
76
- valueType: ValueType.INT,
77
- });
72
+ this.blockBuildDuration = this.meter.createHistogram(Metrics.SEQUENCER_BLOCK_BUILD_DURATION);
78
73
 
79
- this.blockBuildManaPerSecond = this.meter.createGauge(Metrics.SEQUENCER_BLOCK_BUILD_MANA_PER_SECOND, {
80
- unit: 'mana/s',
81
- description: 'Mana per second when building a block',
82
- valueType: ValueType.INT,
83
- });
74
+ this.blockBuildManaPerSecond = this.meter.createGauge(Metrics.SEQUENCER_BLOCK_BUILD_MANA_PER_SECOND);
84
75
 
85
- this.stateTransitionBufferDuration = this.meter.createHistogram(
86
- Metrics.SEQUENCER_STATE_TRANSITION_BUFFER_DURATION,
87
- {
88
- unit: 'ms',
89
- description:
90
- 'The time difference between when the sequencer needed to transition to a new state and when it actually did.',
91
- valueType: ValueType.INT,
92
- },
93
- );
76
+ this.stateTransitionBufferDuration = this.meter.createHistogram(Metrics.SEQUENCER_STATE_TRANSITION_BUFFER_DURATION);
94
77
 
95
- this.blockAttestationDelay = this.meter.createHistogram(Metrics.SEQUENCER_BLOCK_ATTESTATION_DELAY, {
96
- unit: 'ms',
97
- description: 'The time difference between block proposal and minimal attestation count reached,',
98
- valueType: ValueType.INT,
99
- });
78
+ this.checkpointAttestationDelay = this.meter.createHistogram(Metrics.SEQUENCER_CHECKPOINT_ATTESTATION_DELAY);
100
79
 
101
80
  // Init gauges and counters
102
81
  this.blockCounter.add(0, {
@@ -106,152 +85,65 @@ export class SequencerMetrics {
106
85
  [Attributes.STATUS]: 'built',
107
86
  });
108
87
 
109
- this.rewards = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_REWARDS, {
110
- valueType: ValueType.DOUBLE,
111
- description: 'The rewards earned',
112
- });
88
+ this.rewards = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_REWARDS);
113
89
 
114
- this.slots = this.meter.createUpDownCounter(Metrics.SEQUENCER_SLOT_COUNT, {
115
- valueType: ValueType.INT,
116
- description: 'The number of slots this sequencer was selected for',
117
- });
90
+ this.slots = this.meter.createUpDownCounter(Metrics.SEQUENCER_SLOT_COUNT);
118
91
 
119
92
  /**
120
93
  * NOTE: we do not track missed slots as a separate metric. That would be difficult to determine
121
94
  * Instead, use a computed metric, `slots - filledSlots` to get the number of slots a sequencer has missed.
122
95
  */
123
- this.filledSlots = this.meter.createUpDownCounter(Metrics.SEQUENCER_FILLED_SLOT_COUNT, {
124
- valueType: ValueType.INT,
125
- description: 'The number of slots this sequencer has filled',
126
- });
96
+ this.filledSlots = this.meter.createUpDownCounter(Metrics.SEQUENCER_FILLED_SLOT_COUNT);
127
97
 
128
- this.timeToCollectAttestations = this.meter.createGauge(Metrics.SEQUENCER_COLLECT_ATTESTATIONS_DURATION, {
129
- description: 'The time spent collecting attestations from committee members',
130
- unit: 'ms',
131
- valueType: ValueType.INT,
132
- });
98
+ this.timeToCollectAttestations = this.meter.createGauge(Metrics.SEQUENCER_COLLECT_ATTESTATIONS_DURATION);
133
99
 
134
- this.allowanceToCollectAttestations = this.meter.createGauge(
135
- Metrics.SEQUENCER_COLLECT_ATTESTATIONS_TIME_ALLOWANCE,
136
- {
137
- description: 'Maximum amount of time to collect attestations',
138
- unit: 'ms',
139
- valueType: ValueType.INT,
140
- },
141
- );
100
+ this.allowanceToCollectAttestations = this.meter.createGauge(Metrics.SEQUENCER_COLLECT_ATTESTATIONS_TIME_ALLOWANCE);
142
101
 
143
- this.requiredAttestions = this.meter.createGauge(Metrics.SEQUENCER_REQUIRED_ATTESTATIONS_COUNT, {
144
- valueType: ValueType.INT,
145
- description: 'The minimum number of attestations required to publish a block',
146
- });
102
+ this.requiredAttestions = this.meter.createGauge(Metrics.SEQUENCER_REQUIRED_ATTESTATIONS_COUNT);
147
103
 
148
- this.collectedAttestions = this.meter.createGauge(Metrics.SEQUENCER_COLLECTED_ATTESTATIONS_COUNT, {
149
- valueType: ValueType.INT,
150
- description: 'The minimum number of attestations required to publish a block',
151
- });
104
+ this.collectedAttestions = this.meter.createGauge(Metrics.SEQUENCER_COLLECTED_ATTESTATIONS_COUNT);
152
105
 
153
- this.blockProposalFailed = this.meter.createUpDownCounter(Metrics.SEQUENCER_BLOCK_PROPOSAL_FAILED_COUNT, {
154
- valueType: ValueType.INT,
155
- description: 'The number of times block proposal failed (including validation builds)',
156
- });
106
+ this.blockProposalFailed = this.meter.createUpDownCounter(Metrics.SEQUENCER_BLOCK_PROPOSAL_FAILED_COUNT);
157
107
 
158
- this.blockProposalSuccess = this.meter.createUpDownCounter(Metrics.SEQUENCER_BLOCK_PROPOSAL_SUCCESS_COUNT, {
159
- valueType: ValueType.INT,
160
- description: 'The number of times block proposal succeeded (including validation builds)',
161
- });
108
+ this.blockProposalSuccess = this.meter.createUpDownCounter(Metrics.SEQUENCER_BLOCK_PROPOSAL_SUCCESS_COUNT);
162
109
 
163
- this.checkpointSuccess = this.meter.createUpDownCounter(Metrics.SEQUENCER_CHECKPOINT_SUCCESS_COUNT, {
164
- valueType: ValueType.INT,
165
- description: 'The number of times checkpoint publishing succeeded',
166
- });
110
+ this.checkpointSuccess = this.meter.createUpDownCounter(Metrics.SEQUENCER_CHECKPOINT_SUCCESS_COUNT);
167
111
 
168
112
  this.blockProposalPrecheckFailed = this.meter.createUpDownCounter(
169
113
  Metrics.SEQUENCER_BLOCK_PROPOSAL_PRECHECK_FAILED_COUNT,
170
- {
171
- valueType: ValueType.INT,
172
- description: 'The number of times block proposal pre-build checks failed',
173
- },
174
114
  );
175
115
 
176
- this.slashingAttempts = this.meter.createUpDownCounter(Metrics.SEQUENCER_SLASHING_ATTEMPTS_COUNT, {
177
- valueType: ValueType.INT,
178
- description: 'The number of slashing action attempts',
179
- });
116
+ this.slashingAttempts = this.meter.createUpDownCounter(Metrics.SEQUENCER_SLASHING_ATTEMPTS_COUNT);
180
117
 
181
118
  // Fisherman fee analysis metrics
182
- this.fishermanWouldBeIncluded = this.meter.createUpDownCounter(Metrics.FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED, {
183
- valueType: ValueType.INT,
184
- description: 'Whether the transaction would have been included in the block',
185
- });
119
+ this.fishermanWouldBeIncluded = this.meter.createUpDownCounter(Metrics.FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED);
186
120
 
187
- this.fishermanTimeBeforeBlock = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_TIME_BEFORE_BLOCK, {
188
- unit: 'ms',
189
- description: 'Time in ms between fee analysis and block being mined',
190
- valueType: ValueType.INT,
191
- });
121
+ this.fishermanTimeBeforeBlock = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_TIME_BEFORE_BLOCK);
192
122
 
193
- this.fishermanPendingBlobTxCount = this.meter.createHistogram(
194
- Metrics.FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_TX_COUNT,
195
- {
196
- description: 'Number of blob transactions seen in the pending block',
197
- valueType: ValueType.INT,
198
- },
199
- );
123
+ this.fishermanPendingBlobTxCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_TX_COUNT);
200
124
 
201
125
  this.fishermanIncludedBlobTxCount = this.meter.createHistogram(
202
126
  Metrics.FISHERMAN_FEE_ANALYSIS_INCLUDED_BLOB_TX_COUNT,
203
- {
204
- description: 'Number of blob transactions that got included in the mined block',
205
- valueType: ValueType.INT,
206
- },
207
127
  );
208
128
 
209
129
  this.fishermanCalculatedPriorityFee = this.meter.createHistogram(
210
130
  Metrics.FISHERMAN_FEE_ANALYSIS_CALCULATED_PRIORITY_FEE,
211
- {
212
- unit: 'gwei',
213
- description: 'Priority fee calculated by each strategy',
214
- valueType: ValueType.DOUBLE,
215
- },
216
131
  );
217
132
 
218
- this.fishermanPriorityFeeDelta = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PRIORITY_FEE_DELTA, {
219
- unit: 'gwei',
220
- description: 'Difference between our priority fee and minimum included priority fee',
221
- valueType: ValueType.DOUBLE,
222
- });
133
+ this.fishermanPriorityFeeDelta = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PRIORITY_FEE_DELTA);
223
134
 
224
- this.fishermanEstimatedCost = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_COST, {
225
- unit: 'eth',
226
- description: 'Estimated total cost in ETH for the transaction with this strategy',
227
- valueType: ValueType.DOUBLE,
228
- });
135
+ this.fishermanEstimatedCost = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_COST);
229
136
 
230
137
  this.fishermanEstimatedOverpayment = this.meter.createHistogram(
231
138
  Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_OVERPAYMENT,
232
- {
233
- unit: 'eth',
234
- description: 'Estimated overpayment in ETH vs minimum required for inclusion',
235
- valueType: ValueType.DOUBLE,
236
- },
237
139
  );
238
140
 
239
141
  this.fishermanMinedBlobTxPriorityFee = this.meter.createHistogram(
240
142
  Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_PRIORITY_FEE,
241
- {
242
- unit: 'gwei',
243
- description: 'Priority fee per gas for blob transactions in mined blocks',
244
- valueType: ValueType.DOUBLE,
245
- },
246
143
  );
247
144
 
248
145
  this.fishermanMinedBlobTxTotalCost = this.meter.createHistogram(
249
146
  Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_TOTAL_COST,
250
- {
251
- unit: 'eth',
252
- description: 'Total cost in ETH for blob transactions in mined blocks',
253
- valueType: ValueType.DOUBLE,
254
- },
255
147
  );
256
148
  }
257
149
 
@@ -264,8 +156,8 @@ export class SequencerMetrics {
264
156
  this.timeToCollectAttestations.record(0);
265
157
  }
266
158
 
267
- public recordBlockAttestationDelay(duration: number) {
268
- this.blockAttestationDelay.record(duration);
159
+ public recordCheckpointAttestationDelay(duration: number) {
160
+ this.checkpointAttestationDelay.record(duration);
269
161
  }
270
162
 
271
163
  public recordCollectedAttestations(count: number, durationMs: number) {