@aztec/sequencer-client 0.0.1-commit.6c91f13 → 0.0.1-commit.96bb3f7

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 (67) hide show
  1. package/dest/client/sequencer-client.d.ts +4 -5
  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-metrics.d.ts +1 -1
  13. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
  14. package/dest/publisher/sequencer-publisher-metrics.js +15 -86
  15. package/dest/publisher/sequencer-publisher.d.ts +17 -16
  16. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  17. package/dest/publisher/sequencer-publisher.js +442 -49
  18. package/dest/sequencer/block_builder.d.ts +1 -1
  19. package/dest/sequencer/block_builder.d.ts.map +1 -1
  20. package/dest/sequencer/block_builder.js +1 -1
  21. package/dest/sequencer/checkpoint_proposal_job.d.ts +11 -8
  22. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
  23. package/dest/sequencer/checkpoint_proposal_job.js +475 -28
  24. package/dest/sequencer/index.d.ts +1 -2
  25. package/dest/sequencer/index.d.ts.map +1 -1
  26. package/dest/sequencer/index.js +0 -1
  27. package/dest/sequencer/metrics.d.ts +3 -3
  28. package/dest/sequencer/metrics.d.ts.map +1 -1
  29. package/dest/sequencer/metrics.js +30 -121
  30. package/dest/sequencer/sequencer.d.ts +13 -11
  31. package/dest/sequencer/sequencer.d.ts.map +1 -1
  32. package/dest/sequencer/sequencer.js +425 -37
  33. package/dest/test/index.d.ts +2 -3
  34. package/dest/test/index.d.ts.map +1 -1
  35. package/dest/test/mock_checkpoint_builder.d.ts +10 -2
  36. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
  37. package/dest/test/mock_checkpoint_builder.js +23 -0
  38. package/dest/test/utils.d.ts +8 -4
  39. package/dest/test/utils.d.ts.map +1 -1
  40. package/dest/test/utils.js +21 -12
  41. package/package.json +27 -27
  42. package/src/client/sequencer-client.ts +3 -4
  43. package/src/config.ts +7 -0
  44. package/src/global_variable_builder/global_builder.ts +12 -12
  45. package/src/index.ts +0 -3
  46. package/src/publisher/sequencer-publisher-metrics.ts +14 -70
  47. package/src/publisher/sequencer-publisher.ts +84 -73
  48. package/src/sequencer/block_builder.ts +1 -2
  49. package/src/sequencer/checkpoint_proposal_job.ts +75 -39
  50. package/src/sequencer/index.ts +0 -1
  51. package/src/sequencer/metrics.ts +23 -131
  52. package/src/sequencer/sequencer.ts +46 -35
  53. package/src/test/index.ts +1 -2
  54. package/src/test/mock_checkpoint_builder.ts +34 -2
  55. package/src/test/utils.ts +39 -19
  56. package/dest/sequencer/checkpoint_builder.d.ts +0 -63
  57. package/dest/sequencer/checkpoint_builder.d.ts.map +0 -1
  58. package/dest/sequencer/checkpoint_builder.js +0 -131
  59. package/dest/tx_validator/nullifier_cache.d.ts +0 -14
  60. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  61. package/dest/tx_validator/nullifier_cache.js +0 -24
  62. package/dest/tx_validator/tx_validator_factory.d.ts +0 -18
  63. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
  64. package/dest/tx_validator/tx_validator_factory.js +0 -53
  65. package/src/sequencer/checkpoint_builder.ts +0 -217
  66. package/src/tx_validator/nullifier_cache.ts +0 -30
  67. 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
@@ -132,6 +136,13 @@ export class CheckpointProposalJob {
132
136
  }
133
137
  }
134
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
+ })
135
146
  private async proposeCheckpoint(): Promise<Checkpoint | undefined> {
136
147
  try {
137
148
  // Get operator configured coinbase and fee recipient for this attestor
@@ -142,9 +153,9 @@ export class CheckpointProposalJob {
142
153
  this.setStateFn(SequencerState.INITIALIZING_CHECKPOINT, this.slot);
143
154
  this.metrics.incOpenSlot(this.slot, this.proposer?.toString() ?? 'unknown');
144
155
 
145
- // Enqueues block invalidation (constant for the whole slot)
146
- if (this.invalidateBlock && !this.config.skipInvalidateBlockAsProposer) {
147
- 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);
148
159
  }
149
160
 
150
161
  // Create checkpoint builder for the slot
@@ -154,8 +165,9 @@ export class CheckpointProposalJob {
154
165
  this.slot,
155
166
  );
156
167
 
157
- // Collect L1 to L2 messages for the checkpoint
168
+ // Collect L1 to L2 messages for the checkpoint and compute their hash
158
169
  const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(this.checkpointNumber);
170
+ const inHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
159
171
 
160
172
  // Create a long-lived forked world state for the checkpoint builder
161
173
  using fork = await this.worldState.fork(this.syncedToBlockNumber, { closeDelayMs: 12_000 });
@@ -174,10 +186,16 @@ export class CheckpointProposalJob {
174
186
  broadcastInvalidBlockProposal: this.config.broadcastInvalidBlockProposal,
175
187
  };
176
188
 
189
+ const checkpointProposalOptions: CheckpointProposalOptions = {
190
+ publishFullTxs: !!this.config.publishTxsWithProposals,
191
+ broadcastInvalidCheckpointProposal: this.config.broadcastInvalidBlockProposal,
192
+ };
193
+
177
194
  // Main loop: build blocks for the checkpoint
178
- const { blocksInCheckpoint, pendingBroadcast } = await this.buildBlocksForCheckpoint(
195
+ const { blocksInCheckpoint, blockPendingBroadcast } = await this.buildBlocksForCheckpoint(
179
196
  checkpointBuilder,
180
197
  checkpointGlobalVariables.timestamp,
198
+ inHash,
181
199
  blockProposalOptions,
182
200
  );
183
201
 
@@ -207,22 +225,30 @@ export class CheckpointProposalJob {
207
225
  return checkpoint;
208
226
  }
209
227
 
210
- // 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
211
236
  const proposal = await this.validatorClient.createCheckpointProposal(
212
237
  checkpoint.header,
213
238
  checkpoint.archive.root,
214
- pendingBroadcast?.txs ?? [],
239
+ lastBlock,
215
240
  this.proposer,
216
- blockProposalOptions,
241
+ checkpointProposalOptions,
217
242
  );
243
+
218
244
  const blockProposedAt = this.dateProvider.now();
219
- await this.p2pClient.broadcastProposal(proposal);
245
+ await this.p2pClient.broadcastCheckpointProposal(proposal);
220
246
 
221
247
  this.setStateFn(SequencerState.COLLECTING_ATTESTATIONS, this.slot);
222
248
  const attestations = await this.waitForAttestations(proposal);
223
249
  const blockAttestedAt = this.dateProvider.now();
224
250
 
225
- this.metrics.recordBlockAttestationDelay(blockAttestedAt - blockProposedAt);
251
+ this.metrics.recordCheckpointAttestationDelay(blockAttestedAt - blockProposedAt);
226
252
 
227
253
  // Proposer must sign over the attestations before pushing them to L1
228
254
  const signer = this.proposer ?? this.publisher.getSenderAddress();
@@ -235,7 +261,7 @@ export class CheckpointProposalJob {
235
261
  const txTimeoutAt = new Date((slotStartBuildTimestamp + aztecSlotDuration) * 1000);
236
262
  await this.publisher.enqueueProposeCheckpoint(checkpoint, attestations, attestationsSignature, {
237
263
  txTimeoutAt,
238
- forcePendingBlockNumber: this.invalidateBlock?.forcePendingBlockNumber,
264
+ forcePendingCheckpointNumber: this.invalidateCheckpoint?.forcePendingCheckpointNumber,
239
265
  });
240
266
 
241
267
  return checkpoint;
@@ -248,20 +274,22 @@ export class CheckpointProposalJob {
248
274
  /**
249
275
  * Builds blocks for a checkpoint within the current slot.
250
276
  */
277
+ @trackSpan('CheckpointProposalJob.buildBlocksForCheckpoint')
251
278
  private async buildBlocksForCheckpoint(
252
279
  checkpointBuilder: CheckpointBuilder,
253
280
  timestamp: bigint,
281
+ inHash: Fr,
254
282
  blockProposalOptions: BlockProposalOptions,
255
283
  ): Promise<{
256
284
  blocksInCheckpoint: L2BlockNew[];
257
- pendingBroadcast: { block: L2BlockNew; txs: Tx[] } | undefined;
285
+ blockPendingBroadcast: { block: L2BlockNew; txs: Tx[] } | undefined;
258
286
  }> {
259
287
  const blocksInCheckpoint: L2BlockNew[] = [];
260
288
  const txHashesAlreadyIncluded = new Set<string>();
261
289
  const initialBlockNumber = BlockNumber(this.syncedToBlockNumber + 1);
262
290
 
263
291
  // Last block in the checkpoint will usually be flagged as pending broadcast, so we send it along with the checkpoint proposal
264
- let pendingBroadcast: { block: L2BlockNew; txs: Tx[] } | undefined = undefined;
292
+ let blockPendingBroadcast: { block: L2BlockNew; txs: Tx[] } | undefined = undefined;
265
293
 
266
294
  while (true) {
267
295
  const blocksBuilt = blocksInCheckpoint.length;
@@ -331,17 +359,17 @@ export class CheckpointProposalJob {
331
359
  blockNumber,
332
360
  blocksBuilt,
333
361
  });
334
- pendingBroadcast = { block, txs: usedTxs };
362
+ blockPendingBroadcast = { block, txs: usedTxs };
335
363
  break;
336
364
  }
337
365
 
338
366
  // For non-last blocks, broadcast the block proposal (unless we're in fisherman mode)
339
367
  // If the block is the last one, we'll broadcast it along with the checkpoint at the end of the loop
340
368
  if (!this.config.fishermanMode) {
341
- // TODO(palla/mbps): Wire this to the new p2p API once available
342
369
  const proposal = await this.validatorClient.createBlockProposal(
343
- block.header.globalVariables.blockNumber,
344
- (await checkpointBuilder.getCheckpoint()).header,
370
+ block.header,
371
+ block.indexWithinCheckpoint,
372
+ inHash,
345
373
  block.archive.root,
346
374
  usedTxs,
347
375
  this.proposer,
@@ -359,13 +387,11 @@ export class CheckpointProposalJob {
359
387
  blocksBuilt: blocksInCheckpoint.length,
360
388
  });
361
389
 
362
- return {
363
- blocksInCheckpoint,
364
- pendingBroadcast,
365
- };
390
+ return { blocksInCheckpoint, blockPendingBroadcast };
366
391
  }
367
392
 
368
393
  /** Sleeps until it is time to produce the next block in the slot */
394
+ @trackSpan('CheckpointProposalJob.waitUntilNextSubslot')
369
395
  private async waitUntilNextSubslot(nextSubslotStart: number) {
370
396
  this.setStateFn(SequencerState.WAITING_UNTIL_NEXT_BLOCK, this.slot);
371
397
  this.log.verbose(`Waiting until time for the next block at ${nextSubslotStart}s into slot`, { slot: this.slot });
@@ -373,6 +399,7 @@ export class CheckpointProposalJob {
373
399
  }
374
400
 
375
401
  /** Builds a single block. Called from the main block building loop. */
402
+ @trackSpan('CheckpointProposalJob.buildSingleBlock')
376
403
  private async buildSingleBlock(
377
404
  checkpointBuilder: CheckpointBuilder,
378
405
  opts: {
@@ -484,6 +511,7 @@ export class CheckpointProposalJob {
484
511
  }
485
512
 
486
513
  /** Waits until minTxs are available on the pool for building a block. */
514
+ @trackSpan('CheckpointProposalJob.waitForMinTxs')
487
515
  private async waitForMinTxs(opts: {
488
516
  forceCreate?: boolean;
489
517
  blockNumber: BlockNumber;
@@ -524,7 +552,8 @@ export class CheckpointProposalJob {
524
552
  * Waits for enough attestations to be collected via p2p.
525
553
  * This is run after all blocks for the checkpoint have been built.
526
554
  */
527
- private async waitForAttestations(proposal: BlockProposal): Promise<CommitteeAttestationsAndSigners> {
555
+ @trackSpan('CheckpointProposalJob.waitForAttestations')
556
+ private async waitForAttestations(proposal: CheckpointProposal): Promise<CommitteeAttestationsAndSigners> {
528
557
  if (this.config.fishermanMode) {
529
558
  this.log.debug('Skipping attestation collection in fisherman mode');
530
559
  return CommitteeAttestationsAndSigners.empty();
@@ -573,8 +602,7 @@ export class CheckpointProposalJob {
573
602
 
574
603
  // Manipulate the attestations if we've been configured to do so
575
604
  if (this.config.injectFakeAttestation || this.config.shuffleAttestationOrdering) {
576
- const checkpoint = proposal.payload.header;
577
- return this.manipulateAttestations(checkpoint, epoch, seed, committee, sorted);
605
+ return this.manipulateAttestations(proposal.slotNumber, epoch, seed, committee, sorted);
578
606
  }
579
607
 
580
608
  return new CommitteeAttestationsAndSigners(sorted);
@@ -590,7 +618,7 @@ export class CheckpointProposalJob {
590
618
 
591
619
  /** Breaks the attestations before publishing based on attack configs */
592
620
  private manipulateAttestations(
593
- checkpoint: CheckpointHeader,
621
+ slotNumber: SlotNumber,
594
622
  epoch: EpochNumber,
595
623
  seed: bigint,
596
624
  committee: EthAddress[],
@@ -598,7 +626,6 @@ export class CheckpointProposalJob {
598
626
  ) {
599
627
  // Compute the proposer index in the committee, since we dont want to tweak it.
600
628
  // Otherwise, the L1 rollup contract will reject the block outright.
601
- const { slotNumber } = checkpoint;
602
629
  const proposerIndex = Number(
603
630
  this.epochCache.computeProposerIndex(slotNumber, epoch, seed, BigInt(committee.length)),
604
631
  );
@@ -647,16 +674,24 @@ export class CheckpointProposalJob {
647
674
  }
648
675
 
649
676
  /**
650
- * Placeholder for pushing block to archiver and waiting for sync.
651
- * 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.
652
680
  */
653
681
  private async syncProposedBlockToArchiver(block: L2BlockNew): Promise<void> {
654
- 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`, {
655
691
  blockNumber: block.number,
656
692
  slot: block.header.globalVariables.slotNumber,
657
693
  });
658
- // TODO(palla/mbps): Implement actual sync to archiver and world-state
659
- await Promise.resolve();
694
+ await this.blockSink.addBlock(block);
660
695
  }
661
696
 
662
697
  /** Runs fee analysis and logs checkpoint outcome as fisherman */
@@ -685,6 +720,7 @@ export class CheckpointProposalJob {
685
720
  }
686
721
 
687
722
  /** Waits until a specific time within the current slot */
723
+ @trackSpan('CheckpointProposalJob.waitUntilTimeInSlot')
688
724
  protected async waitUntilTimeInSlot(targetSecondsIntoSlot: number): Promise<void> {
689
725
  const slotStartTimestamp = this.getSlotStartBuildTimestamp();
690
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) {