@aztec/sequencer-client 0.0.1-commit.03f7ef2 → 0.0.1-commit.08c5969dc

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 (79) 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/client/sequencer-client.js +1 -1
  4. package/dest/config.d.ts +1 -2
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +10 -9
  7. package/dest/global_variable_builder/global_builder.d.ts +4 -4
  8. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  9. package/dest/global_variable_builder/global_builder.js +13 -13
  10. package/dest/index.d.ts +2 -3
  11. package/dest/index.d.ts.map +1 -1
  12. package/dest/index.js +1 -2
  13. package/dest/publisher/sequencer-publisher-factory.d.ts +2 -2
  14. package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
  15. package/dest/publisher/sequencer-publisher-metrics.d.ts +1 -1
  16. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
  17. package/dest/publisher/sequencer-publisher-metrics.js +23 -86
  18. package/dest/publisher/sequencer-publisher.d.ts +19 -19
  19. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  20. package/dest/publisher/sequencer-publisher.js +482 -71
  21. package/dest/sequencer/checkpoint_proposal_job.d.ts +40 -12
  22. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
  23. package/dest/sequencer/checkpoint_proposal_job.js +610 -59
  24. package/dest/sequencer/checkpoint_voter.d.ts +3 -2
  25. package/dest/sequencer/checkpoint_voter.d.ts.map +1 -1
  26. package/dest/sequencer/checkpoint_voter.js +34 -10
  27. package/dest/sequencer/index.d.ts +1 -3
  28. package/dest/sequencer/index.d.ts.map +1 -1
  29. package/dest/sequencer/index.js +0 -2
  30. package/dest/sequencer/metrics.d.ts +7 -4
  31. package/dest/sequencer/metrics.d.ts.map +1 -1
  32. package/dest/sequencer/metrics.js +72 -128
  33. package/dest/sequencer/sequencer.d.ts +27 -15
  34. package/dest/sequencer/sequencer.d.ts.map +1 -1
  35. package/dest/sequencer/sequencer.js +492 -43
  36. package/dest/sequencer/timetable.d.ts +1 -4
  37. package/dest/sequencer/timetable.d.ts.map +1 -1
  38. package/dest/sequencer/timetable.js +1 -4
  39. package/dest/test/index.d.ts +2 -3
  40. package/dest/test/index.d.ts.map +1 -1
  41. package/dest/test/mock_checkpoint_builder.d.ts +23 -11
  42. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
  43. package/dest/test/mock_checkpoint_builder.js +50 -9
  44. package/dest/test/utils.d.ts +13 -9
  45. package/dest/test/utils.d.ts.map +1 -1
  46. package/dest/test/utils.js +27 -17
  47. package/package.json +30 -28
  48. package/src/client/sequencer-client.ts +5 -6
  49. package/src/config.ts +14 -11
  50. package/src/global_variable_builder/global_builder.ts +13 -13
  51. package/src/index.ts +1 -9
  52. package/src/publisher/sequencer-publisher-factory.ts +1 -1
  53. package/src/publisher/sequencer-publisher-metrics.ts +17 -69
  54. package/src/publisher/sequencer-publisher.ts +121 -95
  55. package/src/sequencer/checkpoint_proposal_job.ts +263 -89
  56. package/src/sequencer/checkpoint_voter.ts +32 -7
  57. package/src/sequencer/index.ts +0 -2
  58. package/src/sequencer/metrics.ts +70 -136
  59. package/src/sequencer/sequencer.ts +133 -43
  60. package/src/sequencer/timetable.ts +6 -5
  61. package/src/test/index.ts +1 -2
  62. package/src/test/mock_checkpoint_builder.ts +91 -29
  63. package/src/test/utils.ts +56 -28
  64. package/dest/sequencer/block_builder.d.ts +0 -26
  65. package/dest/sequencer/block_builder.d.ts.map +0 -1
  66. package/dest/sequencer/block_builder.js +0 -129
  67. package/dest/sequencer/checkpoint_builder.d.ts +0 -63
  68. package/dest/sequencer/checkpoint_builder.d.ts.map +0 -1
  69. package/dest/sequencer/checkpoint_builder.js +0 -131
  70. package/dest/tx_validator/nullifier_cache.d.ts +0 -14
  71. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  72. package/dest/tx_validator/nullifier_cache.js +0 -24
  73. package/dest/tx_validator/tx_validator_factory.d.ts +0 -18
  74. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
  75. package/dest/tx_validator/tx_validator_factory.js +0 -53
  76. package/src/sequencer/block_builder.ts +0 -217
  77. package/src/sequencer/checkpoint_builder.ts +0 -217
  78. package/src/tx_validator/nullifier_cache.ts +0 -30
  79. package/src/tx_validator/tx_validator_factory.ts +0 -133
@@ -5,6 +5,8 @@ import type { SlasherClientInterface } from '@aztec/slasher';
5
5
  import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
6
6
  import type { ResolvedSequencerConfig } from '@aztec/stdlib/interfaces/server';
7
7
  import type { ValidatorClient } from '@aztec/validator-client';
8
+ import { DutyAlreadySignedError } from '@aztec/validator-ha-signer/errors';
9
+ import { DutyType, type SigningContext } from '@aztec/validator-ha-signer/types';
8
10
 
9
11
  import type { TypedDataDefinition } from 'viem';
10
12
 
@@ -17,7 +19,8 @@ import type { SequencerRollupConstants } from './types.js';
17
19
  */
18
20
  export class CheckpointVoter {
19
21
  private slotTimestamp: bigint;
20
- private signer: (msg: TypedDataDefinition) => Promise<`0x${string}`>;
22
+ private governanceSigner: (msg: TypedDataDefinition) => Promise<`0x${string}`>;
23
+ private slashingSigner: (msg: TypedDataDefinition) => Promise<`0x${string}`>;
21
24
 
22
25
  constructor(
23
26
  private readonly slot: SlotNumber,
@@ -31,8 +34,16 @@ export class CheckpointVoter {
31
34
  private readonly log: Logger,
32
35
  ) {
33
36
  this.slotTimestamp = getTimestampForSlot(this.slot, this.l1Constants);
34
- this.signer = (msg: TypedDataDefinition) =>
35
- this.validatorClient.signWithAddress(this.attestorAddress, msg).then(s => s.toString());
37
+
38
+ // Create separate signers with appropriate duty contexts for governance and slashing votes
39
+ // These use HA protection to ensure only one node signs per slot/duty
40
+ const governanceContext: SigningContext = { slot: this.slot, dutyType: DutyType.GOVERNANCE_VOTE };
41
+ this.governanceSigner = (msg: TypedDataDefinition) =>
42
+ this.validatorClient.signWithAddress(this.attestorAddress, msg, governanceContext).then(s => s.toString());
43
+
44
+ const slashingContext: SigningContext = { slot: this.slot, dutyType: DutyType.SLASHING_VOTE };
45
+ this.slashingSigner = (msg: TypedDataDefinition) =>
46
+ this.validatorClient.signWithAddress(this.attestorAddress, msg, slashingContext).then(s => s.toString());
36
47
  }
37
48
 
38
49
  /**
@@ -68,10 +79,17 @@ export class CheckpointVoter {
68
79
  this.slot,
69
80
  this.slotTimestamp,
70
81
  this.attestorAddress,
71
- this.signer,
82
+ this.governanceSigner,
72
83
  );
73
84
  } catch (err) {
74
- this.log.error(`Error enqueuing governance vote`, err, { slot: this.slot });
85
+ if (err instanceof DutyAlreadySignedError) {
86
+ this.log.info(`Governance vote already signed by another node`, {
87
+ slot: this.slot,
88
+ signedByNode: err.signedByNode,
89
+ });
90
+ } else {
91
+ this.log.error(`Error enqueueing governance vote`, err);
92
+ }
75
93
  return false;
76
94
  }
77
95
  }
@@ -95,10 +113,17 @@ export class CheckpointVoter {
95
113
  this.slot,
96
114
  this.slotTimestamp,
97
115
  this.attestorAddress,
98
- this.signer,
116
+ this.slashingSigner,
99
117
  );
100
118
  } catch (err) {
101
- this.log.error(`Error enqueuing slashing vote`, err, { slot: this.slot });
119
+ if (err instanceof DutyAlreadySignedError) {
120
+ this.log.info(`Slashing vote already signed by another node`, {
121
+ slot: this.slot,
122
+ signedByNode: err.signedByNode,
123
+ });
124
+ } else {
125
+ this.log.error(`Error enqueueing slashing vote`, err);
126
+ }
102
127
  return false;
103
128
  }
104
129
  }
@@ -1,5 +1,3 @@
1
- export * from './block_builder.js';
2
- export * from './checkpoint_builder.js';
3
1
  export * from './checkpoint_proposal_job.js';
4
2
  export * from './checkpoint_voter.js';
5
3
  export * from './config.js';
@@ -11,7 +11,7 @@ import {
11
11
  type TelemetryClient,
12
12
  type Tracer,
13
13
  type UpDownCounter,
14
- ValueType,
14
+ createUpDownCounterWithDefault,
15
15
  } from '@aztec/telemetry-client';
16
16
 
17
17
  import { type Hex, formatUnits } from 'viem';
@@ -44,13 +44,16 @@ export class SequencerMetrics {
44
44
  private blockProposalPrecheckFailed: UpDownCounter;
45
45
  private checkpointSuccess: UpDownCounter;
46
46
  private slashingAttempts: UpDownCounter;
47
- private blockAttestationDelay: Histogram;
47
+ private checkpointAttestationDelay: Histogram;
48
48
 
49
49
  // Fisherman fee analysis metrics
50
50
  private fishermanWouldBeIncluded: UpDownCounter;
51
51
  private fishermanTimeBeforeBlock: Histogram;
52
52
  private fishermanPendingBlobTxCount: Histogram;
53
53
  private fishermanIncludedBlobTxCount: Histogram;
54
+ private fishermanPendingBlobCount: Histogram;
55
+ private fishermanIncludedBlobCount: Histogram;
56
+ private fishermanBlockBlobsFull: UpDownCounter;
54
57
  private fishermanCalculatedPriorityFee: Histogram;
55
58
  private fishermanPriorityFeeDelta: Histogram;
56
59
  private fishermanEstimatedCost: Histogram;
@@ -68,189 +71,109 @@ export class SequencerMetrics {
68
71
  this.meter = client.getMeter(name);
69
72
  this.tracer = client.getTracer(name);
70
73
 
71
- this.blockCounter = this.meter.createUpDownCounter(Metrics.SEQUENCER_BLOCK_COUNT);
72
-
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,
74
+ this.blockCounter = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_BLOCK_COUNT, {
75
+ [Attributes.STATUS]: ['failed', 'built'],
77
76
  });
78
77
 
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
- });
78
+ this.blockBuildDuration = this.meter.createHistogram(Metrics.SEQUENCER_BLOCK_BUILD_DURATION);
84
79
 
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
- );
80
+ this.blockBuildManaPerSecond = this.meter.createGauge(Metrics.SEQUENCER_BLOCK_BUILD_MANA_PER_SECOND);
94
81
 
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
- });
82
+ this.stateTransitionBufferDuration = this.meter.createHistogram(Metrics.SEQUENCER_STATE_TRANSITION_BUFFER_DURATION);
100
83
 
101
- // Init gauges and counters
102
- this.blockCounter.add(0, {
103
- [Attributes.STATUS]: 'failed',
104
- });
105
- this.blockCounter.add(0, {
106
- [Attributes.STATUS]: 'built',
107
- });
84
+ this.checkpointAttestationDelay = this.meter.createHistogram(Metrics.SEQUENCER_CHECKPOINT_ATTESTATION_DELAY);
108
85
 
109
- this.rewards = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_REWARDS, {
110
- valueType: ValueType.DOUBLE,
111
- description: 'The rewards earned',
112
- });
86
+ this.rewards = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_REWARDS);
113
87
 
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
- });
88
+ this.slots = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_SLOT_COUNT);
118
89
 
119
90
  /**
120
91
  * NOTE: we do not track missed slots as a separate metric. That would be difficult to determine
121
92
  * Instead, use a computed metric, `slots - filledSlots` to get the number of slots a sequencer has missed.
122
93
  */
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
- });
94
+ this.filledSlots = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_FILLED_SLOT_COUNT);
127
95
 
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
- });
96
+ this.timeToCollectAttestations = this.meter.createGauge(Metrics.SEQUENCER_COLLECT_ATTESTATIONS_DURATION);
133
97
 
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
- );
98
+ this.allowanceToCollectAttestations = this.meter.createGauge(Metrics.SEQUENCER_COLLECT_ATTESTATIONS_TIME_ALLOWANCE);
142
99
 
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
- });
100
+ this.requiredAttestions = this.meter.createGauge(Metrics.SEQUENCER_REQUIRED_ATTESTATIONS_COUNT);
147
101
 
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
- });
102
+ this.collectedAttestions = this.meter.createGauge(Metrics.SEQUENCER_COLLECTED_ATTESTATIONS_COUNT);
152
103
 
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
- });
104
+ this.blockProposalFailed = createUpDownCounterWithDefault(
105
+ this.meter,
106
+ Metrics.SEQUENCER_BLOCK_PROPOSAL_FAILED_COUNT,
107
+ );
157
108
 
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
- });
109
+ this.blockProposalSuccess = createUpDownCounterWithDefault(
110
+ this.meter,
111
+ Metrics.SEQUENCER_BLOCK_PROPOSAL_SUCCESS_COUNT,
112
+ );
162
113
 
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
- });
114
+ this.checkpointSuccess = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_CHECKPOINT_SUCCESS_COUNT);
167
115
 
168
- this.blockProposalPrecheckFailed = this.meter.createUpDownCounter(
116
+ this.blockProposalPrecheckFailed = createUpDownCounterWithDefault(
117
+ this.meter,
169
118
  Metrics.SEQUENCER_BLOCK_PROPOSAL_PRECHECK_FAILED_COUNT,
170
119
  {
171
- valueType: ValueType.INT,
172
- description: 'The number of times block proposal pre-build checks failed',
120
+ [Attributes.ERROR_TYPE]: [
121
+ 'slot_already_taken',
122
+ 'rollup_contract_check_failed',
123
+ 'slot_mismatch',
124
+ 'block_number_mismatch',
125
+ ],
173
126
  },
174
127
  );
175
128
 
176
- this.slashingAttempts = this.meter.createUpDownCounter(Metrics.SEQUENCER_SLASHING_ATTEMPTS_COUNT, {
177
- valueType: ValueType.INT,
178
- description: 'The number of slashing action attempts',
179
- });
129
+ this.slashingAttempts = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_SLASHING_ATTEMPTS_COUNT);
180
130
 
181
131
  // 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
- });
186
-
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
- });
192
-
193
- this.fishermanPendingBlobTxCount = this.meter.createHistogram(
194
- Metrics.FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_TX_COUNT,
132
+ this.fishermanWouldBeIncluded = createUpDownCounterWithDefault(
133
+ this.meter,
134
+ Metrics.FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED,
195
135
  {
196
- description: 'Number of blob transactions seen in the pending block',
197
- valueType: ValueType.INT,
136
+ [Attributes.OK]: [true, false],
198
137
  },
199
138
  );
200
139
 
140
+ this.fishermanTimeBeforeBlock = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_TIME_BEFORE_BLOCK);
141
+
142
+ this.fishermanPendingBlobTxCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_TX_COUNT);
143
+
201
144
  this.fishermanIncludedBlobTxCount = this.meter.createHistogram(
202
145
  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
146
  );
208
147
 
209
148
  this.fishermanCalculatedPriorityFee = this.meter.createHistogram(
210
149
  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
150
  );
217
151
 
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
- });
152
+ this.fishermanPriorityFeeDelta = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PRIORITY_FEE_DELTA);
223
153
 
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
- });
154
+ this.fishermanEstimatedCost = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_COST);
229
155
 
230
156
  this.fishermanEstimatedOverpayment = this.meter.createHistogram(
231
157
  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
158
  );
238
159
 
239
160
  this.fishermanMinedBlobTxPriorityFee = this.meter.createHistogram(
240
161
  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
162
  );
247
163
 
248
164
  this.fishermanMinedBlobTxTotalCost = this.meter.createHistogram(
249
165
  Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_TOTAL_COST,
166
+ );
167
+
168
+ this.fishermanPendingBlobCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_COUNT);
169
+
170
+ this.fishermanIncludedBlobCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_INCLUDED_BLOB_COUNT);
171
+
172
+ this.fishermanBlockBlobsFull = createUpDownCounterWithDefault(
173
+ this.meter,
174
+ Metrics.FISHERMAN_FEE_ANALYSIS_BLOCK_BLOBS_FULL,
250
175
  {
251
- unit: 'eth',
252
- description: 'Total cost in ETH for blob transactions in mined blocks',
253
- valueType: ValueType.DOUBLE,
176
+ [Attributes.OK]: [true, false],
254
177
  },
255
178
  );
256
179
  }
@@ -264,8 +187,8 @@ export class SequencerMetrics {
264
187
  this.timeToCollectAttestations.record(0);
265
188
  }
266
189
 
267
- public recordBlockAttestationDelay(duration: number) {
268
- this.blockAttestationDelay.record(duration);
190
+ public recordCheckpointAttestationDelay(duration: number) {
191
+ this.checkpointAttestationDelay.record(duration);
269
192
  }
270
193
 
271
194
  public recordCollectedAttestations(count: number, durationMs: number) {
@@ -339,7 +262,9 @@ export class SequencerMetrics {
339
262
  this.blockProposalSuccess.add(1);
340
263
  }
341
264
 
342
- recordBlockProposalPrecheckFailed(checkType: string) {
265
+ recordBlockProposalPrecheckFailed(
266
+ checkType: 'slot_already_taken' | 'rollup_contract_check_failed' | 'slot_mismatch' | 'block_number_mismatch',
267
+ ) {
343
268
  this.blockProposalPrecheckFailed.add(1, {
344
269
  [Attributes.ERROR_TYPE]: checkType,
345
270
  });
@@ -371,10 +296,12 @@ export class SequencerMetrics {
371
296
 
372
297
  // Record pending block snapshot data (once per strategy for comparison)
373
298
  this.fishermanPendingBlobTxCount.record(analysis.pendingSnapshot.pendingBlobTxCount, strategyAttributes);
299
+ this.fishermanPendingBlobCount.record(analysis.pendingSnapshot.pendingBlobCount, strategyAttributes);
374
300
 
375
301
  // Record mined block data if available
376
302
  if (analysis.minedBlock) {
377
303
  this.fishermanIncludedBlobTxCount.record(analysis.minedBlock.includedBlobTxCount, strategyAttributes);
304
+ this.fishermanIncludedBlobCount.record(analysis.minedBlock.includedBlobCount, strategyAttributes);
378
305
 
379
306
  // Record actual fees from blob transactions in the mined block
380
307
  for (const blobTx of analysis.minedBlock.includedBlobTxs) {
@@ -408,6 +335,13 @@ export class SequencerMetrics {
408
335
  if (analysis.analysis) {
409
336
  this.fishermanTimeBeforeBlock.record(Math.ceil(analysis.analysis.timeBeforeBlockMs), strategyAttributes);
410
337
 
338
+ // Record whether the block reached 100% blob capacity
339
+ if (analysis.analysis.blockBlobsFull) {
340
+ this.fishermanBlockBlobsFull.add(1, { ...strategyAttributes, [Attributes.OK]: true });
341
+ } else {
342
+ this.fishermanBlockBlobsFull.add(1, { ...strategyAttributes, [Attributes.OK]: false });
343
+ }
344
+
411
345
  // Record strategy-specific inclusion result
412
346
  if (strategyResult.wouldBeIncluded !== undefined) {
413
347
  if (strategyResult.wouldBeIncluded) {