@aztec/sequencer-client 0.0.1-commit.6d3c34e → 0.0.1-commit.7035c9bd6
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/dest/client/sequencer-client.d.ts +12 -7
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +56 -17
- package/dest/config.d.ts +26 -7
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +47 -30
- package/dest/global_variable_builder/global_builder.d.ts +2 -4
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +7 -6
- package/dest/index.d.ts +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/publisher/config.d.ts +35 -17
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +106 -42
- package/dest/publisher/index.d.ts +2 -1
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/l1_tx_failed_store/factory.d.ts +11 -0
- package/dest/publisher/l1_tx_failed_store/factory.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/factory.js +22 -0
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts +59 -0
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.js +1 -0
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts +15 -0
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.js +34 -0
- package/dest/publisher/l1_tx_failed_store/index.d.ts +4 -0
- package/dest/publisher/l1_tx_failed_store/index.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/index.js +2 -0
- package/dest/publisher/sequencer-publisher-factory.d.ts +11 -3
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +27 -2
- package/dest/publisher/sequencer-publisher-metrics.d.ts +1 -1
- package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-metrics.js +12 -4
- package/dest/publisher/sequencer-publisher.d.ts +30 -10
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +362 -56
- package/dest/sequencer/checkpoint_proposal_job.d.ts +42 -11
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +322 -122
- package/dest/sequencer/checkpoint_voter.d.ts +3 -2
- package/dest/sequencer/checkpoint_voter.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_voter.js +34 -10
- package/dest/sequencer/events.d.ts +2 -1
- package/dest/sequencer/events.d.ts.map +1 -1
- package/dest/sequencer/index.d.ts +1 -2
- package/dest/sequencer/index.d.ts.map +1 -1
- package/dest/sequencer/index.js +0 -1
- package/dest/sequencer/metrics.d.ts +21 -5
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +122 -30
- package/dest/sequencer/sequencer.d.ts +43 -20
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +151 -82
- package/dest/sequencer/timetable.d.ts +4 -6
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +7 -11
- package/dest/sequencer/types.d.ts +2 -2
- package/dest/sequencer/types.d.ts.map +1 -1
- package/dest/test/index.d.ts +3 -5
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.d.ts +23 -19
- package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.js +67 -38
- package/dest/test/utils.d.ts +8 -8
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +12 -11
- package/package.json +29 -28
- package/src/client/sequencer-client.ts +77 -18
- package/src/config.ts +66 -41
- package/src/global_variable_builder/global_builder.ts +6 -5
- package/src/index.ts +1 -6
- package/src/publisher/config.ts +121 -43
- package/src/publisher/index.ts +3 -0
- package/src/publisher/l1_tx_failed_store/factory.ts +32 -0
- package/src/publisher/l1_tx_failed_store/failed_tx_store.ts +55 -0
- package/src/publisher/l1_tx_failed_store/file_store_failed_tx_store.ts +46 -0
- package/src/publisher/l1_tx_failed_store/index.ts +3 -0
- package/src/publisher/sequencer-publisher-factory.ts +38 -6
- package/src/publisher/sequencer-publisher-metrics.ts +7 -3
- package/src/publisher/sequencer-publisher.ts +360 -69
- package/src/sequencer/checkpoint_proposal_job.ts +449 -142
- package/src/sequencer/checkpoint_voter.ts +32 -7
- package/src/sequencer/events.ts +1 -1
- package/src/sequencer/index.ts +0 -1
- package/src/sequencer/metrics.ts +138 -32
- package/src/sequencer/sequencer.ts +200 -91
- package/src/sequencer/timetable.ts +13 -12
- package/src/sequencer/types.ts +1 -1
- package/src/test/index.ts +2 -4
- package/src/test/mock_checkpoint_builder.ts +122 -78
- package/src/test/utils.ts +24 -14
- package/dest/sequencer/block_builder.d.ts +0 -26
- package/dest/sequencer/block_builder.d.ts.map +0 -1
- package/dest/sequencer/block_builder.js +0 -129
- package/src/sequencer/block_builder.ts +0 -216
|
@@ -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
|
|
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
|
-
|
|
35
|
-
|
|
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.
|
|
82
|
+
this.governanceSigner,
|
|
72
83
|
);
|
|
73
84
|
} catch (err) {
|
|
74
|
-
|
|
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.
|
|
116
|
+
this.slashingSigner,
|
|
99
117
|
);
|
|
100
118
|
} catch (err) {
|
|
101
|
-
|
|
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
|
}
|
package/src/sequencer/events.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type SequencerEvents = {
|
|
|
13
13
|
['proposer-rollup-check-failed']: (args: { reason: string; slot: SlotNumber }) => void;
|
|
14
14
|
['block-tx-count-check-failed']: (args: { minTxs: number; availableTxs: number; slot: SlotNumber }) => void;
|
|
15
15
|
['block-build-failed']: (args: { reason: string; slot: SlotNumber }) => void;
|
|
16
|
-
['block-proposed']: (args: { blockNumber: BlockNumber; slot: SlotNumber }) => void;
|
|
16
|
+
['block-proposed']: (args: { blockNumber: BlockNumber; slot: SlotNumber; buildSlot: SlotNumber }) => void;
|
|
17
17
|
['checkpoint-empty']: (args: { slot: SlotNumber }) => void;
|
|
18
18
|
['checkpoint-publish-failed']: (args: {
|
|
19
19
|
slot: SlotNumber;
|
package/src/sequencer/index.ts
CHANGED
package/src/sequencer/metrics.ts
CHANGED
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
type TelemetryClient,
|
|
12
12
|
type Tracer,
|
|
13
13
|
type UpDownCounter,
|
|
14
|
+
createUpDownCounterWithDefault,
|
|
14
15
|
} from '@aztec/telemetry-client';
|
|
15
16
|
|
|
16
17
|
import { type Hex, formatUnits } from 'viem';
|
|
17
18
|
|
|
18
19
|
import type { SequencerState } from './utils.js';
|
|
19
20
|
|
|
20
|
-
// TODO(palla/mbps): Review all metrics and add any missing ones per checkpoint
|
|
21
21
|
export class SequencerMetrics {
|
|
22
22
|
public readonly tracer: Tracer;
|
|
23
23
|
private meter: Meter;
|
|
@@ -39,17 +39,28 @@ export class SequencerMetrics {
|
|
|
39
39
|
private filledSlots: UpDownCounter;
|
|
40
40
|
|
|
41
41
|
private blockProposalFailed: UpDownCounter;
|
|
42
|
-
private
|
|
43
|
-
private
|
|
42
|
+
private checkpointProposalSuccess: UpDownCounter;
|
|
43
|
+
private checkpointPrecheckFailed: UpDownCounter;
|
|
44
|
+
private checkpointProposalFailed: UpDownCounter;
|
|
44
45
|
private checkpointSuccess: UpDownCounter;
|
|
45
46
|
private slashingAttempts: UpDownCounter;
|
|
46
47
|
private checkpointAttestationDelay: Histogram;
|
|
48
|
+
private checkpointBuildDuration: Histogram;
|
|
49
|
+
private checkpointBlockCount: Gauge;
|
|
50
|
+
private checkpointTxCount: Gauge;
|
|
51
|
+
private checkpointTotalMana: Gauge;
|
|
52
|
+
private pipelineDepth: Gauge;
|
|
53
|
+
private pipelineDiscards: UpDownCounter;
|
|
47
54
|
|
|
48
55
|
// Fisherman fee analysis metrics
|
|
49
56
|
private fishermanWouldBeIncluded: UpDownCounter;
|
|
50
57
|
private fishermanTimeBeforeBlock: Histogram;
|
|
51
58
|
private fishermanPendingBlobTxCount: Histogram;
|
|
52
59
|
private fishermanIncludedBlobTxCount: Histogram;
|
|
60
|
+
private fishermanPendingBlobCount: Histogram;
|
|
61
|
+
private fishermanIncludedBlobCount: Histogram;
|
|
62
|
+
private fishermanBlockBlobsFull: UpDownCounter;
|
|
63
|
+
private fishermanMaxBlobCapacity: Histogram;
|
|
53
64
|
private fishermanCalculatedPriorityFee: Histogram;
|
|
54
65
|
private fishermanPriorityFeeDelta: Histogram;
|
|
55
66
|
private fishermanEstimatedCost: Histogram;
|
|
@@ -67,7 +78,9 @@ export class SequencerMetrics {
|
|
|
67
78
|
this.meter = client.getMeter(name);
|
|
68
79
|
this.tracer = client.getTracer(name);
|
|
69
80
|
|
|
70
|
-
this.blockCounter = this.meter
|
|
81
|
+
this.blockCounter = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_BLOCK_COUNT, {
|
|
82
|
+
[Attributes.STATUS]: ['failed', 'built'],
|
|
83
|
+
});
|
|
71
84
|
|
|
72
85
|
this.blockBuildDuration = this.meter.createHistogram(Metrics.SEQUENCER_BLOCK_BUILD_DURATION);
|
|
73
86
|
|
|
@@ -77,23 +90,15 @@ export class SequencerMetrics {
|
|
|
77
90
|
|
|
78
91
|
this.checkpointAttestationDelay = this.meter.createHistogram(Metrics.SEQUENCER_CHECKPOINT_ATTESTATION_DELAY);
|
|
79
92
|
|
|
80
|
-
|
|
81
|
-
this.blockCounter.add(0, {
|
|
82
|
-
[Attributes.STATUS]: 'failed',
|
|
83
|
-
});
|
|
84
|
-
this.blockCounter.add(0, {
|
|
85
|
-
[Attributes.STATUS]: 'built',
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
this.rewards = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_REWARDS);
|
|
93
|
+
this.rewards = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_SLOT_REWARDS);
|
|
89
94
|
|
|
90
|
-
this.slots = this.meter
|
|
95
|
+
this.slots = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_SLOT_COUNT);
|
|
91
96
|
|
|
92
97
|
/**
|
|
93
98
|
* NOTE: we do not track missed slots as a separate metric. That would be difficult to determine
|
|
94
99
|
* Instead, use a computed metric, `slots - filledSlots` to get the number of slots a sequencer has missed.
|
|
95
100
|
*/
|
|
96
|
-
this.filledSlots = this.meter
|
|
101
|
+
this.filledSlots = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_FILLED_SLOT_COUNT);
|
|
97
102
|
|
|
98
103
|
this.timeToCollectAttestations = this.meter.createGauge(Metrics.SEQUENCER_COLLECT_ATTESTATIONS_DURATION);
|
|
99
104
|
|
|
@@ -103,20 +108,56 @@ export class SequencerMetrics {
|
|
|
103
108
|
|
|
104
109
|
this.collectedAttestions = this.meter.createGauge(Metrics.SEQUENCER_COLLECTED_ATTESTATIONS_COUNT);
|
|
105
110
|
|
|
106
|
-
this.blockProposalFailed =
|
|
111
|
+
this.blockProposalFailed = createUpDownCounterWithDefault(
|
|
112
|
+
this.meter,
|
|
113
|
+
Metrics.SEQUENCER_BLOCK_PROPOSAL_FAILED_COUNT,
|
|
114
|
+
);
|
|
107
115
|
|
|
108
|
-
this.
|
|
116
|
+
this.checkpointProposalSuccess = createUpDownCounterWithDefault(
|
|
117
|
+
this.meter,
|
|
118
|
+
Metrics.SEQUENCER_CHECKPOINT_PROPOSAL_SUCCESS_COUNT,
|
|
119
|
+
);
|
|
109
120
|
|
|
110
|
-
this.checkpointSuccess = this.meter
|
|
121
|
+
this.checkpointSuccess = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_CHECKPOINT_SUCCESS_COUNT);
|
|
122
|
+
|
|
123
|
+
this.checkpointPrecheckFailed = createUpDownCounterWithDefault(
|
|
124
|
+
this.meter,
|
|
125
|
+
Metrics.SEQUENCER_CHECKPOINT_PRECHECK_FAILED_COUNT,
|
|
126
|
+
{
|
|
127
|
+
[Attributes.ERROR_TYPE]: [
|
|
128
|
+
'slot_already_taken',
|
|
129
|
+
'rollup_contract_check_failed',
|
|
130
|
+
'slot_mismatch',
|
|
131
|
+
'block_number_mismatch',
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
);
|
|
111
135
|
|
|
112
|
-
this.
|
|
113
|
-
|
|
136
|
+
this.checkpointProposalFailed = createUpDownCounterWithDefault(
|
|
137
|
+
this.meter,
|
|
138
|
+
Metrics.SEQUENCER_CHECKPOINT_PROPOSAL_FAILED_COUNT,
|
|
114
139
|
);
|
|
115
140
|
|
|
116
|
-
this.
|
|
141
|
+
this.checkpointBuildDuration = this.meter.createHistogram(Metrics.SEQUENCER_CHECKPOINT_BUILD_DURATION);
|
|
142
|
+
this.checkpointBlockCount = this.meter.createGauge(Metrics.SEQUENCER_CHECKPOINT_BLOCK_COUNT);
|
|
143
|
+
this.checkpointTxCount = this.meter.createGauge(Metrics.SEQUENCER_CHECKPOINT_TX_COUNT);
|
|
144
|
+
this.checkpointTotalMana = this.meter.createGauge(Metrics.SEQUENCER_CHECKPOINT_TOTAL_MANA);
|
|
145
|
+
|
|
146
|
+
this.slashingAttempts = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_SLASHING_ATTEMPTS_COUNT);
|
|
147
|
+
|
|
148
|
+
this.pipelineDepth = this.meter.createGauge(Metrics.SEQUENCER_PIPELINE_DEPTH);
|
|
149
|
+
this.pipelineDiscards = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_PIPELINE_DISCARDS_COUNT);
|
|
150
|
+
this.pipelineDepth.record(0);
|
|
117
151
|
|
|
118
152
|
// Fisherman fee analysis metrics
|
|
119
|
-
this.fishermanWouldBeIncluded =
|
|
153
|
+
this.fishermanWouldBeIncluded = createUpDownCounterWithDefault(
|
|
154
|
+
this.meter,
|
|
155
|
+
Metrics.FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED,
|
|
156
|
+
{
|
|
157
|
+
[Attributes.OK]: [true, false],
|
|
158
|
+
[Attributes.BLOCK_FULL]: ['true', 'false'],
|
|
159
|
+
},
|
|
160
|
+
);
|
|
120
161
|
|
|
121
162
|
this.fishermanTimeBeforeBlock = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_TIME_BEFORE_BLOCK);
|
|
122
163
|
|
|
@@ -145,6 +186,20 @@ export class SequencerMetrics {
|
|
|
145
186
|
this.fishermanMinedBlobTxTotalCost = this.meter.createHistogram(
|
|
146
187
|
Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_TOTAL_COST,
|
|
147
188
|
);
|
|
189
|
+
|
|
190
|
+
this.fishermanPendingBlobCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_COUNT);
|
|
191
|
+
|
|
192
|
+
this.fishermanIncludedBlobCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_INCLUDED_BLOB_COUNT);
|
|
193
|
+
|
|
194
|
+
this.fishermanBlockBlobsFull = createUpDownCounterWithDefault(
|
|
195
|
+
this.meter,
|
|
196
|
+
Metrics.FISHERMAN_FEE_ANALYSIS_BLOCK_BLOBS_FULL,
|
|
197
|
+
{
|
|
198
|
+
[Attributes.OK]: [true, false],
|
|
199
|
+
},
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
this.fishermanMaxBlobCapacity = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_MAX_BLOB_CAPACITY);
|
|
148
203
|
}
|
|
149
204
|
|
|
150
205
|
public recordRequiredAttestations(requiredAttestationsCount: number, allowanceMs: number) {
|
|
@@ -185,6 +240,14 @@ export class SequencerMetrics {
|
|
|
185
240
|
});
|
|
186
241
|
}
|
|
187
242
|
|
|
243
|
+
recordPipelineDepth(depth: number) {
|
|
244
|
+
this.pipelineDepth.record(depth);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
recordPipelineDiscard(count = 1) {
|
|
248
|
+
this.pipelineDiscards.add(count);
|
|
249
|
+
}
|
|
250
|
+
|
|
188
251
|
incOpenSlot(slot: SlotNumber, proposer: string) {
|
|
189
252
|
// sequencer went through the loop a second time. Noop
|
|
190
253
|
if (slot === this.lastSeenSlot) {
|
|
@@ -227,16 +290,30 @@ export class SequencerMetrics {
|
|
|
227
290
|
});
|
|
228
291
|
}
|
|
229
292
|
|
|
230
|
-
|
|
231
|
-
this.
|
|
293
|
+
recordCheckpointProposalSuccess() {
|
|
294
|
+
this.checkpointProposalSuccess.add(1);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
recordCheckpointPrecheckFailed(
|
|
298
|
+
checkType: 'slot_already_taken' | 'rollup_contract_check_failed' | 'slot_mismatch' | 'block_number_mismatch',
|
|
299
|
+
) {
|
|
300
|
+
this.checkpointPrecheckFailed.add(1, { [Attributes.ERROR_TYPE]: checkType });
|
|
232
301
|
}
|
|
233
302
|
|
|
234
|
-
|
|
235
|
-
this.
|
|
236
|
-
[Attributes.ERROR_TYPE]:
|
|
303
|
+
recordCheckpointProposalFailed(reason?: string) {
|
|
304
|
+
this.checkpointProposalFailed.add(1, {
|
|
305
|
+
...(reason && { [Attributes.ERROR_TYPE]: reason }),
|
|
237
306
|
});
|
|
238
307
|
}
|
|
239
308
|
|
|
309
|
+
/** Records aggregate metrics for a completed checkpoint build. */
|
|
310
|
+
recordCheckpointBuild(durationMs: number, blockCount: number, txCount: number, totalMana: number) {
|
|
311
|
+
this.checkpointBuildDuration.record(Math.ceil(durationMs));
|
|
312
|
+
this.checkpointBlockCount.record(blockCount);
|
|
313
|
+
this.checkpointTxCount.record(txCount);
|
|
314
|
+
this.checkpointTotalMana.record(totalMana);
|
|
315
|
+
}
|
|
316
|
+
|
|
240
317
|
recordSlashingAttempt(actionCount: number) {
|
|
241
318
|
this.slashingAttempts.add(actionCount);
|
|
242
319
|
}
|
|
@@ -263,10 +340,12 @@ export class SequencerMetrics {
|
|
|
263
340
|
|
|
264
341
|
// Record pending block snapshot data (once per strategy for comparison)
|
|
265
342
|
this.fishermanPendingBlobTxCount.record(analysis.pendingSnapshot.pendingBlobTxCount, strategyAttributes);
|
|
343
|
+
this.fishermanPendingBlobCount.record(analysis.pendingSnapshot.pendingBlobCount, strategyAttributes);
|
|
266
344
|
|
|
267
345
|
// Record mined block data if available
|
|
268
346
|
if (analysis.minedBlock) {
|
|
269
347
|
this.fishermanIncludedBlobTxCount.record(analysis.minedBlock.includedBlobTxCount, strategyAttributes);
|
|
348
|
+
this.fishermanIncludedBlobCount.record(analysis.minedBlock.includedBlobCount, strategyAttributes);
|
|
270
349
|
|
|
271
350
|
// Record actual fees from blob transactions in the mined block
|
|
272
351
|
for (const blobTx of analysis.minedBlock.includedBlobTxs) {
|
|
@@ -300,13 +379,28 @@ export class SequencerMetrics {
|
|
|
300
379
|
if (analysis.analysis) {
|
|
301
380
|
this.fishermanTimeBeforeBlock.record(Math.ceil(analysis.analysis.timeBeforeBlockMs), strategyAttributes);
|
|
302
381
|
|
|
382
|
+
// Record whether the block reached 100% blob capacity
|
|
383
|
+
if (analysis.analysis.blockBlobsFull) {
|
|
384
|
+
this.fishermanBlockBlobsFull.add(1, { ...strategyAttributes, [Attributes.OK]: true });
|
|
385
|
+
} else {
|
|
386
|
+
this.fishermanBlockBlobsFull.add(1, { ...strategyAttributes, [Attributes.OK]: false });
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Record the max blob capacity for this block
|
|
390
|
+
this.fishermanMaxBlobCapacity.record(analysis.analysis.maxBlobCapacity, strategyAttributes);
|
|
391
|
+
|
|
303
392
|
// Record strategy-specific inclusion result
|
|
304
393
|
if (strategyResult.wouldBeIncluded !== undefined) {
|
|
394
|
+
const inclusionAttributes = {
|
|
395
|
+
...strategyAttributes,
|
|
396
|
+
[Attributes.BLOCK_FULL]: analysis.analysis.blockBlobsFull ? 'true' : 'false',
|
|
397
|
+
};
|
|
398
|
+
|
|
305
399
|
if (strategyResult.wouldBeIncluded) {
|
|
306
|
-
this.fishermanWouldBeIncluded.add(1, { ...
|
|
400
|
+
this.fishermanWouldBeIncluded.add(1, { ...inclusionAttributes, [Attributes.OK]: true });
|
|
307
401
|
} else {
|
|
308
402
|
this.fishermanWouldBeIncluded.add(1, {
|
|
309
|
-
...
|
|
403
|
+
...inclusionAttributes,
|
|
310
404
|
[Attributes.OK]: false,
|
|
311
405
|
...(strategyResult.exclusionReason && { [Attributes.ERROR_TYPE]: strategyResult.exclusionReason }),
|
|
312
406
|
});
|
|
@@ -316,17 +410,29 @@ export class SequencerMetrics {
|
|
|
316
410
|
// Record strategy-specific priority fee delta
|
|
317
411
|
if (strategyResult.priorityFeeDelta !== undefined) {
|
|
318
412
|
const priorityFeeDeltaGwei = Number(strategyResult.priorityFeeDelta) / 1e9;
|
|
319
|
-
|
|
413
|
+
const deltaAttributes = {
|
|
414
|
+
...strategyAttributes,
|
|
415
|
+
[Attributes.BLOCK_FULL]: analysis.analysis.blockBlobsFull ? 'true' : 'false',
|
|
416
|
+
};
|
|
417
|
+
this.fishermanPriorityFeeDelta.record(priorityFeeDeltaGwei, deltaAttributes);
|
|
320
418
|
}
|
|
321
419
|
|
|
322
420
|
// Record estimated cost if available
|
|
323
421
|
if (strategyResult.estimatedCostEth !== undefined) {
|
|
324
|
-
|
|
422
|
+
const costAttributes = {
|
|
423
|
+
...strategyAttributes,
|
|
424
|
+
[Attributes.BLOCK_FULL]: analysis.analysis.blockBlobsFull ? 'true' : 'false',
|
|
425
|
+
};
|
|
426
|
+
this.fishermanEstimatedCost.record(strategyResult.estimatedCostEth, costAttributes);
|
|
325
427
|
}
|
|
326
428
|
|
|
327
429
|
// Record estimated overpayment if available
|
|
328
430
|
if (strategyResult.estimatedOverpaymentEth !== undefined) {
|
|
329
|
-
|
|
431
|
+
const overpaymentAttributes = {
|
|
432
|
+
...strategyAttributes,
|
|
433
|
+
[Attributes.BLOCK_FULL]: analysis.analysis.blockBlobsFull ? 'true' : 'false',
|
|
434
|
+
};
|
|
435
|
+
this.fishermanEstimatedOverpayment.record(strategyResult.estimatedOverpaymentEth, overpaymentAttributes);
|
|
330
436
|
}
|
|
331
437
|
}
|
|
332
438
|
}
|