@aztec/sequencer-client 2.1.9 → 2.1.10-rc.2

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.
@@ -2,6 +2,7 @@ import type { L2Block } from '@aztec/aztec.js';
2
2
  import { type BlobSinkClientInterface } from '@aztec/blob-sink/client';
3
3
  import type { EpochCache } from '@aztec/epoch-cache';
4
4
  import { type EmpireSlashingProposerContract, FormattedViemError, type GovernanceProposerContract, type L1BlobInputs, type L1ContractsConfig, type L1TxConfig, type L1TxRequest, RollupContract, type TallySlashingProposerContract, type TransactionStats } from '@aztec/ethereum';
5
+ import { type L1FeeAnalysisResult, L1FeeAnalyzer } from '@aztec/ethereum/l1-fee-analysis';
5
6
  import type { L1TxUtilsWithBlobs } from '@aztec/ethereum/l1-tx-utils-with-blobs';
6
7
  import { EthAddress } from '@aztec/foundation/eth-address';
7
8
  import { Signature } from '@aztec/foundation/eth-signature';
@@ -51,6 +52,8 @@ export declare class SequencerPublisher {
51
52
  private blobSinkClient;
52
53
  /** Address to use for simulations in fisherman mode (actual proposer's address) */
53
54
  private proposerAddressForSimulation?;
55
+ /** L1 fee analyzer for fisherman mode */
56
+ private l1FeeAnalyzer?;
54
57
  static PROPOSE_GAS_GUESS: bigint;
55
58
  static MULTICALL_OVERHEAD_GAS_GUESS: bigint;
56
59
  static VOTE_GAS_GUESS: bigint;
@@ -76,6 +79,10 @@ export declare class SequencerPublisher {
76
79
  });
77
80
  getRollupContract(): RollupContract;
78
81
  getSenderAddress(): EthAddress;
82
+ /**
83
+ * Gets the L1 fee analyzer instance (only available in fisherman mode)
84
+ */
85
+ getL1FeeAnalyzer(): L1FeeAnalyzer | undefined;
79
86
  /**
80
87
  * Sets the proposer address to use for simulations in fisherman mode.
81
88
  * @param proposerAddress - The actual proposer's address to use for balance lookups in simulations
@@ -87,6 +94,14 @@ export declare class SequencerPublisher {
87
94
  * Clears all pending requests without sending them.
88
95
  */
89
96
  clearPendingRequests(): void;
97
+ /**
98
+ * Analyzes L1 fees for the pending requests without sending them.
99
+ * This is used in fisherman mode to validate fee calculations.
100
+ * @param l2SlotNumber - The L2 slot number for this analysis
101
+ * @param onComplete - Optional callback to invoke when analysis completes (after block is mined)
102
+ * @returns The analysis result (incomplete until block mines), or undefined if no requests
103
+ */
104
+ analyzeL1Fees(l2SlotNumber: bigint, onComplete?: (analysis: L1FeeAnalysisResult) => void): Promise<L1FeeAnalysisResult | undefined>;
90
105
  /**
91
106
  * Sends all requests that are still valid.
92
107
  * @returns one of:
@@ -1 +1 @@
1
- {"version":3,"file":"sequencer-publisher.d.ts","sourceRoot":"","sources":["../../src/publisher/sequencer-publisher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sequencer-publisher.d.ts","sourceRoot":"","sources":["../../src/publisher/sequencer-publisher.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { Blob } from '@aztec/blob-lib';
2
2
  import { createBlobSinkClient } from '@aztec/blob-sink/client';
3
3
  import { FormattedViemError, MULTI_CALL_3_ADDRESS, Multicall3, RollupContract, WEI_CONST, formatViemError, tryExtractEvent } from '@aztec/ethereum';
4
+ import { L1FeeAnalyzer } from '@aztec/ethereum/l1-fee-analysis';
4
5
  import { sumBigint } from '@aztec/foundation/bigint';
5
6
  import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
6
7
  import { EthAddress } from '@aztec/foundation/eth-address';
@@ -39,6 +40,7 @@ export class SequencerPublisher {
39
40
  ethereumSlotDuration;
40
41
  blobSinkClient;
41
42
  /** Address to use for simulations in fisherman mode (actual proposer's address) */ proposerAddressForSimulation;
43
+ /** L1 fee analyzer for fisherman mode */ l1FeeAnalyzer;
42
44
  // @note - with blobs, the below estimate seems too large.
43
45
  // Total used for full block from int_l1_pub e2e test: 1m (of which 86k is 1x blob)
44
46
  // Total used for emptier block from above test: 429k (of which 84k is 1x blob)
@@ -79,6 +81,10 @@ export class SequencerPublisher {
79
81
  this.slashingProposerContract = newSlashingProposer;
80
82
  });
81
83
  this.slashFactoryContract = deps.slashFactoryContract;
84
+ // Initialize L1 fee analyzer for fisherman mode
85
+ if (config.fishermanMode) {
86
+ this.l1FeeAnalyzer = new L1FeeAnalyzer(this.l1TxUtils.client, deps.dateProvider, createLogger('sequencer:publisher:fee-analyzer'));
87
+ }
82
88
  }
83
89
  getRollupContract() {
84
90
  return this.rollupContract;
@@ -87,6 +93,11 @@ export class SequencerPublisher {
87
93
  return this.l1TxUtils.getSenderAddress();
88
94
  }
89
95
  /**
96
+ * Gets the L1 fee analyzer instance (only available in fisherman mode)
97
+ */ getL1FeeAnalyzer() {
98
+ return this.l1FeeAnalyzer;
99
+ }
100
+ /**
90
101
  * Sets the proposer address to use for simulations in fisherman mode.
91
102
  * @param proposerAddress - The actual proposer's address to use for balance lookups in simulations
92
103
  */ setProposerAddressForSimulation(proposerAddress) {
@@ -108,6 +119,46 @@ export class SequencerPublisher {
108
119
  }
109
120
  }
110
121
  /**
122
+ * Analyzes L1 fees for the pending requests without sending them.
123
+ * This is used in fisherman mode to validate fee calculations.
124
+ * @param l2SlotNumber - The L2 slot number for this analysis
125
+ * @param onComplete - Optional callback to invoke when analysis completes (after block is mined)
126
+ * @returns The analysis result (incomplete until block mines), or undefined if no requests
127
+ */ async analyzeL1Fees(l2SlotNumber, onComplete) {
128
+ if (!this.l1FeeAnalyzer) {
129
+ this.log.warn('L1 fee analyzer not available (not in fisherman mode)');
130
+ return undefined;
131
+ }
132
+ const requestsToAnalyze = [
133
+ ...this.requests
134
+ ];
135
+ if (requestsToAnalyze.length === 0) {
136
+ this.log.debug('No requests to analyze for L1 fees');
137
+ return undefined;
138
+ }
139
+ // Extract blob config from requests (if any)
140
+ const blobConfigs = requestsToAnalyze.filter((request)=>request.blobConfig).map((request)=>request.blobConfig);
141
+ const blobConfig = blobConfigs[0];
142
+ // Get gas configs
143
+ const gasConfigs = requestsToAnalyze.filter((request)=>request.gasConfig).map((request)=>request.gasConfig);
144
+ const gasLimits = gasConfigs.map((g)=>g?.gasLimit).filter((g)=>g !== undefined);
145
+ const gasLimit = gasLimits.length > 0 ? gasLimits.reduce((sum, g)=>sum + g, 0n) : 0n;
146
+ // Get the transaction requests
147
+ const l1Requests = requestsToAnalyze.map((r)=>r.request);
148
+ // Start the analysis
149
+ const analysisId = await this.l1FeeAnalyzer.startAnalysis(l2SlotNumber, gasLimit > 0n ? gasLimit : SequencerPublisher.PROPOSE_GAS_GUESS, l1Requests, blobConfig, onComplete);
150
+ this.log.info('Started L1 fee analysis', {
151
+ analysisId,
152
+ l2SlotNumber: l2SlotNumber.toString(),
153
+ requestCount: requestsToAnalyze.length,
154
+ hasBlobConfig: !!blobConfig,
155
+ gasLimit: gasLimit.toString(),
156
+ actions: requestsToAnalyze.map((r)=>r.action)
157
+ });
158
+ // Return the analysis result (will be incomplete until block mines)
159
+ return this.l1FeeAnalyzer.getAnalysis(analysisId);
160
+ }
161
+ /**
111
162
  * Sends all requests that are still valid.
112
163
  * @returns one of:
113
164
  * - A receipt and stats if the tx succeeded
@@ -1,5 +1,6 @@
1
1
  import type { EthAddress } from '@aztec/aztec.js';
2
2
  import type { RollupContract } from '@aztec/ethereum';
3
+ import type { L1FeeAnalysisResult } from '@aztec/ethereum/l1-fee-analysis';
3
4
  import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
4
5
  import { type Hex } from 'viem';
5
6
  import type { SequencerState } from './utils.js';
@@ -23,6 +24,16 @@ export declare class SequencerMetrics {
23
24
  private blockProposalPrecheckFailed;
24
25
  private slashingAttempts;
25
26
  private lastSeenSlot?;
27
+ private fishermanWouldBeIncluded;
28
+ private fishermanTimeBeforeBlock;
29
+ private fishermanPendingBlobTxCount;
30
+ private fishermanIncludedBlobTxCount;
31
+ private fishermanCalculatedPriorityFee;
32
+ private fishermanPriorityFeeDelta;
33
+ private fishermanEstimatedCost;
34
+ private fishermanEstimatedOverpayment;
35
+ private fishermanMinedBlobTxPriorityFee;
36
+ private fishermanMinedBlobTxTotalCost;
26
37
  constructor(client: TelemetryClient, rollup: RollupContract, name?: string);
27
38
  recordRequiredAttestations(requiredAttestationsCount: number, allowanceMs: number): void;
28
39
  recordCollectedAttestations(count: number, durationMs: number): void;
@@ -35,5 +46,10 @@ export declare class SequencerMetrics {
35
46
  recordBlockProposalSuccess(): void;
36
47
  recordBlockProposalPrecheckFailed(checkType: string): void;
37
48
  recordSlashingAttempt(actionCount: number): void;
49
+ /**
50
+ * Records metrics for a completed fisherman fee analysis
51
+ * @param analysis - The completed fee analysis result
52
+ */
53
+ recordFishermanFeeAnalysis(analysis: L1FeeAnalysisResult): void;
38
54
  }
39
55
  //# sourceMappingURL=metrics.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/sequencer/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,MAAM,EAGZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,KAAK,GAAG,EAAe,MAAM,MAAM,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,gBAAgB;IA6BzB,OAAO,CAAC,MAAM;IA5BhB,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAQ;IAErB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,kBAAkB,CAAY;IACtC,OAAO,CAAC,uBAAuB,CAAQ;IACvC,OAAO,CAAC,6BAA6B,CAAY;IAGjD,OAAO,CAAC,yBAAyB,CAAQ;IACzC,OAAO,CAAC,8BAA8B,CAAQ;IAC9C,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,mBAAmB,CAAQ;IAEnC,OAAO,CAAC,OAAO,CAAQ;IAEvB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,WAAW,CAAgB;IAEnC,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,oBAAoB,CAAgB;IAC5C,OAAO,CAAC,2BAA2B,CAAgB;IACnD,OAAO,CAAC,gBAAgB,CAAgB;IAExC,OAAO,CAAC,YAAY,CAAC,CAAS;gBAG5B,MAAM,EAAE,eAAe,EACf,MAAM,EAAE,cAAc,EAC9B,IAAI,SAAc;IAyGb,0BAA0B,CAAC,yBAAyB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IASjF,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAKpE,gBAAgB,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAQ3D,iBAAiB;IAMjB,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc;IAMvE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAapC,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB5F,yBAAyB,CAAC,MAAM,CAAC,EAAE,MAAM;IAMzC,0BAA0B;IAI1B,iCAAiC,CAAC,SAAS,EAAE,MAAM;IAMnD,qBAAqB,CAAC,WAAW,EAAE,MAAM;CAG1C"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/sequencer/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,MAAM,EAGZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,KAAK,GAAG,EAAe,MAAM,MAAM,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,gBAAgB;IAyCzB,OAAO,CAAC,MAAM;IAxChB,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAQ;IAErB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,kBAAkB,CAAY;IACtC,OAAO,CAAC,uBAAuB,CAAQ;IACvC,OAAO,CAAC,6BAA6B,CAAY;IAGjD,OAAO,CAAC,yBAAyB,CAAQ;IACzC,OAAO,CAAC,8BAA8B,CAAQ;IAC9C,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,mBAAmB,CAAQ;IAEnC,OAAO,CAAC,OAAO,CAAQ;IAEvB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,WAAW,CAAgB;IAEnC,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,oBAAoB,CAAgB;IAC5C,OAAO,CAAC,2BAA2B,CAAgB;IACnD,OAAO,CAAC,gBAAgB,CAAgB;IAExC,OAAO,CAAC,YAAY,CAAC,CAAS;IAG9B,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,wBAAwB,CAAY;IAC5C,OAAO,CAAC,2BAA2B,CAAY;IAC/C,OAAO,CAAC,4BAA4B,CAAY;IAChD,OAAO,CAAC,8BAA8B,CAAY;IAClD,OAAO,CAAC,yBAAyB,CAAY;IAC7C,OAAO,CAAC,sBAAsB,CAAY;IAC1C,OAAO,CAAC,6BAA6B,CAAY;IACjD,OAAO,CAAC,+BAA+B,CAAY;IACnD,OAAO,CAAC,6BAA6B,CAAY;gBAG/C,MAAM,EAAE,eAAe,EACf,MAAM,EAAE,cAAc,EAC9B,IAAI,SAAc;IAqLb,0BAA0B,CAAC,yBAAyB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IASjF,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAKpE,gBAAgB,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAQ3D,iBAAiB;IAMjB,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc;IAMvE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAapC,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB5F,yBAAyB,CAAC,MAAM,CAAC,EAAE,MAAM;IAMzC,0BAA0B;IAI1B,iCAAiC,CAAC,SAAS,EAAE,MAAM;IAMnD,qBAAqB,CAAC,WAAW,EAAE,MAAM;IAIzC;;;OAGG;IACH,0BAA0B,CAAC,QAAQ,EAAE,mBAAmB;CAsFzD"}
@@ -21,6 +21,17 @@ export class SequencerMetrics {
21
21
  blockProposalPrecheckFailed;
22
22
  slashingAttempts;
23
23
  lastSeenSlot;
24
+ // Fisherman fee analysis metrics
25
+ fishermanWouldBeIncluded;
26
+ fishermanTimeBeforeBlock;
27
+ fishermanPendingBlobTxCount;
28
+ fishermanIncludedBlobTxCount;
29
+ fishermanCalculatedPriorityFee;
30
+ fishermanPriorityFeeDelta;
31
+ fishermanEstimatedCost;
32
+ fishermanEstimatedOverpayment;
33
+ fishermanMinedBlobTxPriorityFee;
34
+ fishermanMinedBlobTxTotalCost;
24
35
  constructor(client, rollup, name = 'Sequencer'){
25
36
  this.rollup = rollup;
26
37
  this.meter = client.getMeter(name);
@@ -97,6 +108,54 @@ export class SequencerMetrics {
97
108
  valueType: ValueType.INT,
98
109
  description: 'The number of slashing action attempts'
99
110
  });
111
+ // Fisherman fee analysis metrics
112
+ this.fishermanWouldBeIncluded = this.meter.createUpDownCounter(Metrics.FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED, {
113
+ valueType: ValueType.INT,
114
+ description: 'Whether the transaction would have been included in the block'
115
+ });
116
+ this.fishermanTimeBeforeBlock = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_TIME_BEFORE_BLOCK, {
117
+ unit: 'ms',
118
+ description: 'Time in ms between fee analysis and block being mined',
119
+ valueType: ValueType.INT
120
+ });
121
+ this.fishermanPendingBlobTxCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_TX_COUNT, {
122
+ description: 'Number of blob transactions seen in the pending block',
123
+ valueType: ValueType.INT
124
+ });
125
+ this.fishermanIncludedBlobTxCount = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_INCLUDED_BLOB_TX_COUNT, {
126
+ description: 'Number of blob transactions that got included in the mined block',
127
+ valueType: ValueType.INT
128
+ });
129
+ this.fishermanCalculatedPriorityFee = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_CALCULATED_PRIORITY_FEE, {
130
+ unit: 'gwei',
131
+ description: 'Priority fee calculated by each strategy',
132
+ valueType: ValueType.DOUBLE
133
+ });
134
+ this.fishermanPriorityFeeDelta = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PRIORITY_FEE_DELTA, {
135
+ unit: 'gwei',
136
+ description: 'Difference between our priority fee and minimum included priority fee',
137
+ valueType: ValueType.DOUBLE
138
+ });
139
+ this.fishermanEstimatedCost = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_COST, {
140
+ unit: 'eth',
141
+ description: 'Estimated total cost in ETH for the transaction with this strategy',
142
+ valueType: ValueType.DOUBLE
143
+ });
144
+ this.fishermanEstimatedOverpayment = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_OVERPAYMENT, {
145
+ unit: 'eth',
146
+ description: 'Estimated overpayment in ETH vs minimum required for inclusion',
147
+ valueType: ValueType.DOUBLE
148
+ });
149
+ this.fishermanMinedBlobTxPriorityFee = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_PRIORITY_FEE, {
150
+ unit: 'gwei',
151
+ description: 'Priority fee per gas for blob transactions in mined blocks',
152
+ valueType: ValueType.DOUBLE
153
+ });
154
+ this.fishermanMinedBlobTxTotalCost = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_TOTAL_COST, {
155
+ unit: 'eth',
156
+ description: 'Total cost in ETH for blob transactions in mined blocks',
157
+ valueType: ValueType.DOUBLE
158
+ });
100
159
  }
101
160
  recordRequiredAttestations(requiredAttestationsCount, allowanceMs) {
102
161
  this.requiredAttestions.record(requiredAttestationsCount);
@@ -171,4 +230,81 @@ export class SequencerMetrics {
171
230
  recordSlashingAttempt(actionCount) {
172
231
  this.slashingAttempts.add(actionCount);
173
232
  }
233
+ /**
234
+ * Records metrics for a completed fisherman fee analysis
235
+ * @param analysis - The completed fee analysis result
236
+ */ recordFishermanFeeAnalysis(analysis) {
237
+ // In fisherman mode, we should always have strategy results
238
+ if (!analysis.computedPrices.strategyResults || analysis.computedPrices.strategyResults.length === 0) {
239
+ // This should never happen in fisherman mode - log an error
240
+ // We don't record metrics without strategy IDs as that defeats the purpose
241
+ throw new Error(`No strategy results found in fisherman fee analysis ${analysis.id}. This indicates a bug in the fee analysis.`);
242
+ }
243
+ // Record metrics for each strategy separately
244
+ for (const strategyResult of analysis.computedPrices.strategyResults){
245
+ const strategyAttributes = {
246
+ [Attributes.FISHERMAN_FEE_STRATEGY_ID]: strategyResult.strategyId
247
+ };
248
+ // Record pending block snapshot data (once per strategy for comparison)
249
+ this.fishermanPendingBlobTxCount.record(analysis.pendingSnapshot.pendingBlobTxCount, strategyAttributes);
250
+ // Record mined block data if available
251
+ if (analysis.minedBlock) {
252
+ this.fishermanIncludedBlobTxCount.record(analysis.minedBlock.includedBlobTxCount, strategyAttributes);
253
+ // Record actual fees from blob transactions in the mined block
254
+ for (const blobTx of analysis.minedBlock.includedBlobTxs){
255
+ // Record priority fee per gas in Gwei
256
+ const priorityFeeGwei = Number(blobTx.maxPriorityFeePerGas) / 1e9;
257
+ this.fishermanMinedBlobTxPriorityFee.record(priorityFeeGwei, strategyAttributes);
258
+ // Calculate total cost in ETH
259
+ // Cost = (gas * (baseFee + priorityFee)) + (blobCount * blobGasPerBlob * blobBaseFee)
260
+ const baseFee = analysis.minedBlock.baseFeePerGas;
261
+ const effectiveGasPrice = baseFee + blobTx.maxPriorityFeePerGas;
262
+ // Calculate execution cost using actual gas limit from the transaction
263
+ const executionCost = blobTx.gas * effectiveGasPrice;
264
+ // Calculate blob cost using maxFeePerBlobGas * blobCount * GAS_PER_BLOB
265
+ const blobCost = blobTx.maxFeePerBlobGas * BigInt(blobTx.blobCount) * 131072n; // 128KB per blob
266
+ const totalCostWei = executionCost + blobCost;
267
+ const totalCostEth = Number(totalCostWei) / 1e18;
268
+ this.fishermanMinedBlobTxTotalCost.record(totalCostEth, strategyAttributes);
269
+ }
270
+ }
271
+ // Record the calculated priority fee for this strategy
272
+ const calculatedPriorityFeeGwei = Number(strategyResult.calculatedPriorityFee) / 1e9;
273
+ this.fishermanCalculatedPriorityFee.record(calculatedPriorityFeeGwei, strategyAttributes);
274
+ // Record analysis results if available
275
+ if (analysis.analysis) {
276
+ this.fishermanTimeBeforeBlock.record(Math.ceil(analysis.analysis.timeBeforeBlockMs), strategyAttributes);
277
+ // Record strategy-specific inclusion result
278
+ if (strategyResult.wouldBeIncluded !== undefined) {
279
+ if (strategyResult.wouldBeIncluded) {
280
+ this.fishermanWouldBeIncluded.add(1, {
281
+ ...strategyAttributes,
282
+ [Attributes.OK]: true
283
+ });
284
+ } else {
285
+ this.fishermanWouldBeIncluded.add(1, {
286
+ ...strategyAttributes,
287
+ [Attributes.OK]: false,
288
+ ...strategyResult.exclusionReason && {
289
+ [Attributes.ERROR_TYPE]: strategyResult.exclusionReason
290
+ }
291
+ });
292
+ }
293
+ }
294
+ // Record strategy-specific priority fee delta
295
+ if (strategyResult.priorityFeeDelta !== undefined) {
296
+ const priorityFeeDeltaGwei = Number(strategyResult.priorityFeeDelta) / 1e9;
297
+ this.fishermanPriorityFeeDelta.record(priorityFeeDeltaGwei, strategyAttributes);
298
+ }
299
+ // Record estimated cost if available
300
+ if (strategyResult.estimatedCostEth !== undefined) {
301
+ this.fishermanEstimatedCost.record(strategyResult.estimatedCostEth, strategyAttributes);
302
+ }
303
+ // Record estimated overpayment if available
304
+ if (strategyResult.estimatedOverpaymentEth !== undefined) {
305
+ this.fishermanEstimatedOverpayment.record(strategyResult.estimatedOverpaymentEth, strategyAttributes);
306
+ }
307
+ }
308
+ }
309
+ }
174
310
  }
@@ -93,6 +93,8 @@ export declare class Sequencer extends Sequencer_base {
93
93
  private lastSlotForVoteWhenSyncFailed;
94
94
  /** The last slot for which we built a validation block in fisherman mode, to prevent duplicate attempts. */
95
95
  private lastSlotForValidationBlock;
96
+ /** The last epoch for which we logged strategy comparison in fisherman mode. */
97
+ private lastEpochForStrategyComparison;
96
98
  /** The maximum number of seconds that the sequencer can be into a slot to transition to a particular state. */
97
99
  protected timetable: SequencerTimetable;
98
100
  protected enforceTimeTable: boolean;
@@ -216,6 +218,10 @@ export declare class Sequencer extends Sequencer_base {
216
218
  protected considerInvalidatingBlock(syncedTo: NonNullable<Awaited<ReturnType<Sequencer['checkSync']>>>, currentSlot: bigint): Promise<void>;
217
219
  private getSlotStartBuildTimestamp;
218
220
  private getSecondsIntoSlot;
221
+ /**
222
+ * Logs strategy comparison statistics at the end of each epoch in fisherman mode
223
+ */
224
+ private logStrategyComparison;
219
225
  get aztecSlotDuration(): number;
220
226
  get maxL2BlockGas(): number | undefined;
221
227
  getSlasherClient(): SlasherClientInterface | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"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"}
@@ -69,6 +69,7 @@ export { SequencerState };
69
69
  governanceProposerPayload;
70
70
  /** The last slot for which we attempted to vote when sync failed, to prevent duplicate attempts. */ lastSlotForVoteWhenSyncFailed;
71
71
  /** The last slot for which we built a validation block in fisherman mode, to prevent duplicate attempts. */ lastSlotForValidationBlock;
72
+ /** The last epoch for which we logged strategy comparison in fisherman mode. */ lastEpochForStrategyComparison;
72
73
  /** The maximum number of seconds that the sequencer can be into a slot to transition to a particular state. */ timetable;
73
74
  enforceTimeTable;
74
75
  // This shouldn't be here as this gets re-created each time we build/propose a block.
@@ -318,16 +319,28 @@ export { SequencerState };
318
319
  const block = await this.tryBuildBlockAndEnqueuePublish(slot, proposer, newBlockNumber, publisher, newGlobalVariables, chainTipArchive, invalidateBlock);
319
320
  // Wait until the voting promises have resolved, so all requests are enqueued
320
321
  await Promise.all(votesPromises);
321
- // In fisherman mode, we don't publish to L1
322
+ // In fisherman mode, we don't publish to L1 but analyze the fees
322
323
  if (this.config.fishermanMode) {
323
- // Clear pending requests
324
+ // Perform L1 fee analysis before clearing requests
325
+ // The callback is invoked asynchronously after the next block is mined
326
+ const feeAnalysis = await publisher.analyzeL1Fees(BigInt(slot), (analysis)=>{
327
+ this.metrics.recordFishermanFeeAnalysis(analysis);
328
+ });
329
+ // Check if we've moved to a new epoch and log strategy comparison
330
+ const currentEpoch = this.epochCache.getEpochAndSlotNow().epoch;
331
+ if (this.lastEpochForStrategyComparison === undefined || currentEpoch > this.lastEpochForStrategyComparison) {
332
+ this.logStrategyComparison(currentEpoch, publisher);
333
+ this.lastEpochForStrategyComparison = currentEpoch;
334
+ }
335
+ // Clear pending requests (we're not sending them)
324
336
  publisher.clearPendingRequests();
325
337
  if (block) {
326
338
  this.log.info(`Validation block building SUCCEEDED for slot ${slot}`, {
327
339
  blockNumber: newBlockNumber,
328
340
  slot: Number(slot),
329
341
  archive: block.archive.toString(),
330
- txCount: block.body.txEffects.length
342
+ txCount: block.body.txEffects.length,
343
+ feeAnalysisId: feeAnalysis?.id
331
344
  });
332
345
  this.lastBlockPublished = block;
333
346
  this.metrics.recordBlockProposalSuccess();
@@ -335,7 +348,8 @@ export { SequencerState };
335
348
  // Block building failed in fisherman mode
336
349
  this.log.warn(`Validation block building FAILED for slot ${slot}`, {
337
350
  blockNumber: newBlockNumber,
338
- slot: Number(slot)
351
+ slot: Number(slot),
352
+ feeAnalysisId: feeAnalysis?.id
339
353
  });
340
354
  this.metrics.recordBlockProposalFailed('block_build_failed');
341
355
  }
@@ -941,6 +955,34 @@ export { SequencerState };
941
955
  const slotStartTimestamp = this.getSlotStartBuildTimestamp(slotNumber);
942
956
  return Number((this.dateProvider.now() / 1000 - slotStartTimestamp).toFixed(3));
943
957
  }
958
+ /**
959
+ * Logs strategy comparison statistics at the end of each epoch in fisherman mode
960
+ */ logStrategyComparison(epoch, publisher) {
961
+ const feeAnalyzer = publisher.getL1FeeAnalyzer();
962
+ if (!feeAnalyzer) {
963
+ return;
964
+ }
965
+ const comparison = feeAnalyzer.getStrategyComparison();
966
+ if (comparison.length === 0) {
967
+ this.log.debug(`No strategy data available yet for epoch ${epoch}`);
968
+ return;
969
+ }
970
+ this.log.info(`L1 Fee Strategy Performance Report - End of Epoch ${epoch}`, {
971
+ epoch: Number(epoch),
972
+ totalAnalyses: comparison[0]?.totalAnalyses,
973
+ strategies: comparison.map((s)=>({
974
+ id: s.strategyId,
975
+ name: s.strategyName,
976
+ inclusionRate: `${(s.inclusionRate * 100).toFixed(1)}%`,
977
+ inclusionCount: `${s.inclusionCount}/${s.totalAnalyses}`,
978
+ avgCostEth: s.avgEstimatedCostEth.toFixed(6),
979
+ totalCostEth: s.totalEstimatedCostEth.toFixed(6),
980
+ avgOverpaymentEth: s.avgOverpaymentEth.toFixed(6),
981
+ totalOverpaymentEth: s.totalOverpaymentEth.toFixed(6),
982
+ avgPriorityFeeDeltaGwei: s.avgPriorityFeeDeltaGwei.toFixed(2)
983
+ }))
984
+ });
985
+ }
944
986
  get aztecSlotDuration() {
945
987
  return this.l1Constants.slotDuration;
946
988
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/sequencer-client",
3
- "version": "2.1.9",
3
+ "version": "2.1.10-rc.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -26,37 +26,37 @@
26
26
  "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
27
27
  },
28
28
  "dependencies": {
29
- "@aztec/aztec.js": "2.1.9",
30
- "@aztec/bb-prover": "2.1.9",
31
- "@aztec/blob-lib": "2.1.9",
32
- "@aztec/blob-sink": "2.1.9",
33
- "@aztec/constants": "2.1.9",
34
- "@aztec/epoch-cache": "2.1.9",
35
- "@aztec/ethereum": "2.1.9",
36
- "@aztec/foundation": "2.1.9",
37
- "@aztec/l1-artifacts": "2.1.9",
38
- "@aztec/merkle-tree": "2.1.9",
39
- "@aztec/node-keystore": "2.1.9",
40
- "@aztec/noir-acvm_js": "2.1.9",
41
- "@aztec/noir-contracts.js": "2.1.9",
42
- "@aztec/noir-protocol-circuits-types": "2.1.9",
43
- "@aztec/noir-types": "2.1.9",
44
- "@aztec/p2p": "2.1.9",
45
- "@aztec/protocol-contracts": "2.1.9",
46
- "@aztec/prover-client": "2.1.9",
47
- "@aztec/simulator": "2.1.9",
48
- "@aztec/slasher": "2.1.9",
49
- "@aztec/stdlib": "2.1.9",
50
- "@aztec/telemetry-client": "2.1.9",
51
- "@aztec/validator-client": "2.1.9",
52
- "@aztec/world-state": "2.1.9",
29
+ "@aztec/aztec.js": "2.1.10-rc.2",
30
+ "@aztec/bb-prover": "2.1.10-rc.2",
31
+ "@aztec/blob-lib": "2.1.10-rc.2",
32
+ "@aztec/blob-sink": "2.1.10-rc.2",
33
+ "@aztec/constants": "2.1.10-rc.2",
34
+ "@aztec/epoch-cache": "2.1.10-rc.2",
35
+ "@aztec/ethereum": "2.1.10-rc.2",
36
+ "@aztec/foundation": "2.1.10-rc.2",
37
+ "@aztec/l1-artifacts": "2.1.10-rc.2",
38
+ "@aztec/merkle-tree": "2.1.10-rc.2",
39
+ "@aztec/node-keystore": "2.1.10-rc.2",
40
+ "@aztec/noir-acvm_js": "2.1.10-rc.2",
41
+ "@aztec/noir-contracts.js": "2.1.10-rc.2",
42
+ "@aztec/noir-protocol-circuits-types": "2.1.10-rc.2",
43
+ "@aztec/noir-types": "2.1.10-rc.2",
44
+ "@aztec/p2p": "2.1.10-rc.2",
45
+ "@aztec/protocol-contracts": "2.1.10-rc.2",
46
+ "@aztec/prover-client": "2.1.10-rc.2",
47
+ "@aztec/simulator": "2.1.10-rc.2",
48
+ "@aztec/slasher": "2.1.10-rc.2",
49
+ "@aztec/stdlib": "2.1.10-rc.2",
50
+ "@aztec/telemetry-client": "2.1.10-rc.2",
51
+ "@aztec/validator-client": "2.1.10-rc.2",
52
+ "@aztec/world-state": "2.1.10-rc.2",
53
53
  "lodash.chunk": "^4.2.0",
54
54
  "tslib": "^2.4.0",
55
55
  "viem": "npm:@aztec/viem@2.38.2"
56
56
  },
57
57
  "devDependencies": {
58
- "@aztec/archiver": "2.1.9",
59
- "@aztec/kv-store": "2.1.9",
58
+ "@aztec/archiver": "2.1.10-rc.2",
59
+ "@aztec/kv-store": "2.1.10-rc.2",
60
60
  "@jest/globals": "^30.0.0",
61
61
  "@types/jest": "^30.0.0",
62
62
  "@types/lodash.chunk": "^4.2.7",
@@ -23,6 +23,7 @@ import {
23
23
  formatViemError,
24
24
  tryExtractEvent,
25
25
  } from '@aztec/ethereum';
26
+ import { type L1FeeAnalysisResult, L1FeeAnalyzer } from '@aztec/ethereum/l1-fee-analysis';
26
27
  import type { L1TxUtilsWithBlobs } from '@aztec/ethereum/l1-tx-utils-with-blobs';
27
28
  import { sumBigint } from '@aztec/foundation/bigint';
28
29
  import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
@@ -117,6 +118,9 @@ export class SequencerPublisher {
117
118
 
118
119
  /** Address to use for simulations in fisherman mode (actual proposer's address) */
119
120
  private proposerAddressForSimulation?: EthAddress;
121
+
122
+ /** L1 fee analyzer for fisherman mode */
123
+ private l1FeeAnalyzer?: L1FeeAnalyzer;
120
124
  // @note - with blobs, the below estimate seems too large.
121
125
  // Total used for full block from int_l1_pub e2e test: 1m (of which 86k is 1x blob)
122
126
  // Total used for emptier block from above test: 429k (of which 84k is 1x blob)
@@ -176,6 +180,15 @@ export class SequencerPublisher {
176
180
  this.slashingProposerContract = newSlashingProposer;
177
181
  });
178
182
  this.slashFactoryContract = deps.slashFactoryContract;
183
+
184
+ // Initialize L1 fee analyzer for fisherman mode
185
+ if (config.fishermanMode) {
186
+ this.l1FeeAnalyzer = new L1FeeAnalyzer(
187
+ this.l1TxUtils.client,
188
+ deps.dateProvider,
189
+ createLogger('sequencer:publisher:fee-analyzer'),
190
+ );
191
+ }
179
192
  }
180
193
 
181
194
  public getRollupContract(): RollupContract {
@@ -186,6 +199,13 @@ export class SequencerPublisher {
186
199
  return this.l1TxUtils.getSenderAddress();
187
200
  }
188
201
 
202
+ /**
203
+ * Gets the L1 fee analyzer instance (only available in fisherman mode)
204
+ */
205
+ public getL1FeeAnalyzer(): L1FeeAnalyzer | undefined {
206
+ return this.l1FeeAnalyzer;
207
+ }
208
+
189
209
  /**
190
210
  * Sets the proposer address to use for simulations in fisherman mode.
191
211
  * @param proposerAddress - The actual proposer's address to use for balance lookups in simulations
@@ -213,6 +233,62 @@ export class SequencerPublisher {
213
233
  }
214
234
  }
215
235
 
236
+ /**
237
+ * Analyzes L1 fees for the pending requests without sending them.
238
+ * This is used in fisherman mode to validate fee calculations.
239
+ * @param l2SlotNumber - The L2 slot number for this analysis
240
+ * @param onComplete - Optional callback to invoke when analysis completes (after block is mined)
241
+ * @returns The analysis result (incomplete until block mines), or undefined if no requests
242
+ */
243
+ public async analyzeL1Fees(
244
+ l2SlotNumber: bigint,
245
+ onComplete?: (analysis: L1FeeAnalysisResult) => void,
246
+ ): Promise<L1FeeAnalysisResult | undefined> {
247
+ if (!this.l1FeeAnalyzer) {
248
+ this.log.warn('L1 fee analyzer not available (not in fisherman mode)');
249
+ return undefined;
250
+ }
251
+
252
+ const requestsToAnalyze = [...this.requests];
253
+ if (requestsToAnalyze.length === 0) {
254
+ this.log.debug('No requests to analyze for L1 fees');
255
+ return undefined;
256
+ }
257
+
258
+ // Extract blob config from requests (if any)
259
+ const blobConfigs = requestsToAnalyze.filter(request => request.blobConfig).map(request => request.blobConfig);
260
+ const blobConfig = blobConfigs[0];
261
+
262
+ // Get gas configs
263
+ const gasConfigs = requestsToAnalyze.filter(request => request.gasConfig).map(request => request.gasConfig);
264
+ const gasLimits = gasConfigs.map(g => g?.gasLimit).filter((g): g is bigint => g !== undefined);
265
+ const gasLimit = gasLimits.length > 0 ? gasLimits.reduce((sum, g) => sum + g, 0n) : 0n;
266
+
267
+ // Get the transaction requests
268
+ const l1Requests = requestsToAnalyze.map(r => r.request);
269
+
270
+ // Start the analysis
271
+ const analysisId = await this.l1FeeAnalyzer.startAnalysis(
272
+ l2SlotNumber,
273
+ gasLimit > 0n ? gasLimit : SequencerPublisher.PROPOSE_GAS_GUESS,
274
+ l1Requests,
275
+ blobConfig,
276
+ onComplete,
277
+ );
278
+
279
+ this.log.info('Started L1 fee analysis', {
280
+ analysisId,
281
+ l2SlotNumber: l2SlotNumber.toString(),
282
+ requestCount: requestsToAnalyze.length,
283
+ hasBlobConfig: !!blobConfig,
284
+ gasLimit: gasLimit.toString(),
285
+ actions: requestsToAnalyze.map(r => r.action),
286
+ });
287
+
288
+ // Return the analysis result (will be incomplete until block mines)
289
+ return this.l1FeeAnalyzer.getAnalysis(analysisId);
290
+ }
291
+
216
292
  /**
217
293
  * Sends all requests that are still valid.
218
294
  * @returns one of:
@@ -1,5 +1,6 @@
1
1
  import type { EthAddress } from '@aztec/aztec.js';
2
2
  import type { RollupContract } from '@aztec/ethereum';
3
+ import type { L1FeeAnalysisResult } from '@aztec/ethereum/l1-fee-analysis';
3
4
  import {
4
5
  Attributes,
5
6
  type Gauge,
@@ -43,6 +44,18 @@ export class SequencerMetrics {
43
44
 
44
45
  private lastSeenSlot?: bigint;
45
46
 
47
+ // Fisherman fee analysis metrics
48
+ private fishermanWouldBeIncluded: UpDownCounter;
49
+ private fishermanTimeBeforeBlock: Histogram;
50
+ private fishermanPendingBlobTxCount: Histogram;
51
+ private fishermanIncludedBlobTxCount: Histogram;
52
+ private fishermanCalculatedPriorityFee: Histogram;
53
+ private fishermanPriorityFeeDelta: Histogram;
54
+ private fishermanEstimatedCost: Histogram;
55
+ private fishermanEstimatedOverpayment: Histogram;
56
+ private fishermanMinedBlobTxPriorityFee: Histogram;
57
+ private fishermanMinedBlobTxTotalCost: Histogram;
58
+
46
59
  constructor(
47
60
  client: TelemetryClient,
48
61
  private rollup: RollupContract,
@@ -149,6 +162,82 @@ export class SequencerMetrics {
149
162
  valueType: ValueType.INT,
150
163
  description: 'The number of slashing action attempts',
151
164
  });
165
+
166
+ // Fisherman fee analysis metrics
167
+ this.fishermanWouldBeIncluded = this.meter.createUpDownCounter(Metrics.FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED, {
168
+ valueType: ValueType.INT,
169
+ description: 'Whether the transaction would have been included in the block',
170
+ });
171
+
172
+ this.fishermanTimeBeforeBlock = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_TIME_BEFORE_BLOCK, {
173
+ unit: 'ms',
174
+ description: 'Time in ms between fee analysis and block being mined',
175
+ valueType: ValueType.INT,
176
+ });
177
+
178
+ this.fishermanPendingBlobTxCount = this.meter.createHistogram(
179
+ Metrics.FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_TX_COUNT,
180
+ {
181
+ description: 'Number of blob transactions seen in the pending block',
182
+ valueType: ValueType.INT,
183
+ },
184
+ );
185
+
186
+ this.fishermanIncludedBlobTxCount = this.meter.createHistogram(
187
+ Metrics.FISHERMAN_FEE_ANALYSIS_INCLUDED_BLOB_TX_COUNT,
188
+ {
189
+ description: 'Number of blob transactions that got included in the mined block',
190
+ valueType: ValueType.INT,
191
+ },
192
+ );
193
+
194
+ this.fishermanCalculatedPriorityFee = this.meter.createHistogram(
195
+ Metrics.FISHERMAN_FEE_ANALYSIS_CALCULATED_PRIORITY_FEE,
196
+ {
197
+ unit: 'gwei',
198
+ description: 'Priority fee calculated by each strategy',
199
+ valueType: ValueType.DOUBLE,
200
+ },
201
+ );
202
+
203
+ this.fishermanPriorityFeeDelta = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_PRIORITY_FEE_DELTA, {
204
+ unit: 'gwei',
205
+ description: 'Difference between our priority fee and minimum included priority fee',
206
+ valueType: ValueType.DOUBLE,
207
+ });
208
+
209
+ this.fishermanEstimatedCost = this.meter.createHistogram(Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_COST, {
210
+ unit: 'eth',
211
+ description: 'Estimated total cost in ETH for the transaction with this strategy',
212
+ valueType: ValueType.DOUBLE,
213
+ });
214
+
215
+ this.fishermanEstimatedOverpayment = this.meter.createHistogram(
216
+ Metrics.FISHERMAN_FEE_ANALYSIS_ESTIMATED_OVERPAYMENT,
217
+ {
218
+ unit: 'eth',
219
+ description: 'Estimated overpayment in ETH vs minimum required for inclusion',
220
+ valueType: ValueType.DOUBLE,
221
+ },
222
+ );
223
+
224
+ this.fishermanMinedBlobTxPriorityFee = this.meter.createHistogram(
225
+ Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_PRIORITY_FEE,
226
+ {
227
+ unit: 'gwei',
228
+ description: 'Priority fee per gas for blob transactions in mined blocks',
229
+ valueType: ValueType.DOUBLE,
230
+ },
231
+ );
232
+
233
+ this.fishermanMinedBlobTxTotalCost = this.meter.createHistogram(
234
+ Metrics.FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_TOTAL_COST,
235
+ {
236
+ unit: 'eth',
237
+ description: 'Total cost in ETH for blob transactions in mined blocks',
238
+ valueType: ValueType.DOUBLE,
239
+ },
240
+ );
152
241
  }
153
242
 
154
243
  public recordRequiredAttestations(requiredAttestationsCount: number, allowanceMs: number) {
@@ -236,4 +325,95 @@ export class SequencerMetrics {
236
325
  recordSlashingAttempt(actionCount: number) {
237
326
  this.slashingAttempts.add(actionCount);
238
327
  }
328
+
329
+ /**
330
+ * Records metrics for a completed fisherman fee analysis
331
+ * @param analysis - The completed fee analysis result
332
+ */
333
+ recordFishermanFeeAnalysis(analysis: L1FeeAnalysisResult) {
334
+ // In fisherman mode, we should always have strategy results
335
+ if (!analysis.computedPrices.strategyResults || analysis.computedPrices.strategyResults.length === 0) {
336
+ // This should never happen in fisherman mode - log an error
337
+ // We don't record metrics without strategy IDs as that defeats the purpose
338
+ throw new Error(
339
+ `No strategy results found in fisherman fee analysis ${analysis.id}. This indicates a bug in the fee analysis.`,
340
+ );
341
+ }
342
+
343
+ // Record metrics for each strategy separately
344
+ for (const strategyResult of analysis.computedPrices.strategyResults) {
345
+ const strategyAttributes = {
346
+ [Attributes.FISHERMAN_FEE_STRATEGY_ID]: strategyResult.strategyId,
347
+ };
348
+
349
+ // Record pending block snapshot data (once per strategy for comparison)
350
+ this.fishermanPendingBlobTxCount.record(analysis.pendingSnapshot.pendingBlobTxCount, strategyAttributes);
351
+
352
+ // Record mined block data if available
353
+ if (analysis.minedBlock) {
354
+ this.fishermanIncludedBlobTxCount.record(analysis.minedBlock.includedBlobTxCount, strategyAttributes);
355
+
356
+ // Record actual fees from blob transactions in the mined block
357
+ for (const blobTx of analysis.minedBlock.includedBlobTxs) {
358
+ // Record priority fee per gas in Gwei
359
+ const priorityFeeGwei = Number(blobTx.maxPriorityFeePerGas) / 1e9;
360
+ this.fishermanMinedBlobTxPriorityFee.record(priorityFeeGwei, strategyAttributes);
361
+
362
+ // Calculate total cost in ETH
363
+ // Cost = (gas * (baseFee + priorityFee)) + (blobCount * blobGasPerBlob * blobBaseFee)
364
+ const baseFee = analysis.minedBlock.baseFeePerGas;
365
+ const effectiveGasPrice = baseFee + blobTx.maxPriorityFeePerGas;
366
+
367
+ // Calculate execution cost using actual gas limit from the transaction
368
+ const executionCost = blobTx.gas * effectiveGasPrice;
369
+
370
+ // Calculate blob cost using maxFeePerBlobGas * blobCount * GAS_PER_BLOB
371
+ const blobCost = blobTx.maxFeePerBlobGas * BigInt(blobTx.blobCount) * 131072n; // 128KB per blob
372
+
373
+ const totalCostWei = executionCost + blobCost;
374
+ const totalCostEth = Number(totalCostWei) / 1e18;
375
+
376
+ this.fishermanMinedBlobTxTotalCost.record(totalCostEth, strategyAttributes);
377
+ }
378
+ }
379
+
380
+ // Record the calculated priority fee for this strategy
381
+ const calculatedPriorityFeeGwei = Number(strategyResult.calculatedPriorityFee) / 1e9;
382
+ this.fishermanCalculatedPriorityFee.record(calculatedPriorityFeeGwei, strategyAttributes);
383
+
384
+ // Record analysis results if available
385
+ if (analysis.analysis) {
386
+ this.fishermanTimeBeforeBlock.record(Math.ceil(analysis.analysis.timeBeforeBlockMs), strategyAttributes);
387
+
388
+ // Record strategy-specific inclusion result
389
+ if (strategyResult.wouldBeIncluded !== undefined) {
390
+ if (strategyResult.wouldBeIncluded) {
391
+ this.fishermanWouldBeIncluded.add(1, { ...strategyAttributes, [Attributes.OK]: true });
392
+ } else {
393
+ this.fishermanWouldBeIncluded.add(1, {
394
+ ...strategyAttributes,
395
+ [Attributes.OK]: false,
396
+ ...(strategyResult.exclusionReason && { [Attributes.ERROR_TYPE]: strategyResult.exclusionReason }),
397
+ });
398
+ }
399
+ }
400
+
401
+ // Record strategy-specific priority fee delta
402
+ if (strategyResult.priorityFeeDelta !== undefined) {
403
+ const priorityFeeDeltaGwei = Number(strategyResult.priorityFeeDelta) / 1e9;
404
+ this.fishermanPriorityFeeDelta.record(priorityFeeDeltaGwei, strategyAttributes);
405
+ }
406
+
407
+ // Record estimated cost if available
408
+ if (strategyResult.estimatedCostEth !== undefined) {
409
+ this.fishermanEstimatedCost.record(strategyResult.estimatedCostEth, strategyAttributes);
410
+ }
411
+
412
+ // Record estimated overpayment if available
413
+ if (strategyResult.estimatedOverpaymentEth !== undefined) {
414
+ this.fishermanEstimatedOverpayment.record(strategyResult.estimatedOverpaymentEth, strategyAttributes);
415
+ }
416
+ }
417
+ }
418
+ }
239
419
  }
@@ -103,6 +103,9 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
103
103
  /** The last slot for which we built a validation block in fisherman mode, to prevent duplicate attempts. */
104
104
  private lastSlotForValidationBlock: bigint | undefined;
105
105
 
106
+ /** The last epoch for which we logged strategy comparison in fisherman mode. */
107
+ private lastEpochForStrategyComparison: bigint | undefined;
108
+
106
109
  /** The maximum number of seconds that the sequencer can be into a slot to transition to a particular state. */
107
110
  protected timetable!: SequencerTimetable;
108
111
  protected enforceTimeTable: boolean = false;
@@ -422,9 +425,22 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
422
425
  // Wait until the voting promises have resolved, so all requests are enqueued
423
426
  await Promise.all(votesPromises);
424
427
 
425
- // In fisherman mode, we don't publish to L1
428
+ // In fisherman mode, we don't publish to L1 but analyze the fees
426
429
  if (this.config.fishermanMode) {
427
- // Clear pending requests
430
+ // Perform L1 fee analysis before clearing requests
431
+ // The callback is invoked asynchronously after the next block is mined
432
+ const feeAnalysis = await publisher.analyzeL1Fees(BigInt(slot), analysis => {
433
+ this.metrics.recordFishermanFeeAnalysis(analysis);
434
+ });
435
+
436
+ // Check if we've moved to a new epoch and log strategy comparison
437
+ const currentEpoch = this.epochCache.getEpochAndSlotNow().epoch;
438
+ if (this.lastEpochForStrategyComparison === undefined || currentEpoch > this.lastEpochForStrategyComparison) {
439
+ this.logStrategyComparison(currentEpoch, publisher);
440
+ this.lastEpochForStrategyComparison = currentEpoch;
441
+ }
442
+
443
+ // Clear pending requests (we're not sending them)
428
444
  publisher.clearPendingRequests();
429
445
 
430
446
  if (block) {
@@ -433,6 +449,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
433
449
  slot: Number(slot),
434
450
  archive: block.archive.toString(),
435
451
  txCount: block.body.txEffects.length,
452
+ feeAnalysisId: feeAnalysis?.id,
436
453
  });
437
454
  this.lastBlockPublished = block;
438
455
  this.metrics.recordBlockProposalSuccess();
@@ -441,6 +458,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
441
458
  this.log.warn(`Validation block building FAILED for slot ${slot}`, {
442
459
  blockNumber: newBlockNumber,
443
460
  slot: Number(slot),
461
+ feeAnalysisId: feeAnalysis?.id,
444
462
  });
445
463
  this.metrics.recordBlockProposalFailed('block_build_failed');
446
464
  }
@@ -1234,6 +1252,38 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
1234
1252
  return Number((this.dateProvider.now() / 1000 - slotStartTimestamp).toFixed(3));
1235
1253
  }
1236
1254
 
1255
+ /**
1256
+ * Logs strategy comparison statistics at the end of each epoch in fisherman mode
1257
+ */
1258
+ private logStrategyComparison(epoch: bigint, publisher: SequencerPublisher): void {
1259
+ const feeAnalyzer = publisher.getL1FeeAnalyzer();
1260
+ if (!feeAnalyzer) {
1261
+ return;
1262
+ }
1263
+
1264
+ const comparison = feeAnalyzer.getStrategyComparison();
1265
+ if (comparison.length === 0) {
1266
+ this.log.debug(`No strategy data available yet for epoch ${epoch}`);
1267
+ return;
1268
+ }
1269
+
1270
+ this.log.info(`L1 Fee Strategy Performance Report - End of Epoch ${epoch}`, {
1271
+ epoch: Number(epoch),
1272
+ totalAnalyses: comparison[0]?.totalAnalyses,
1273
+ strategies: comparison.map(s => ({
1274
+ id: s.strategyId,
1275
+ name: s.strategyName,
1276
+ inclusionRate: `${(s.inclusionRate * 100).toFixed(1)}%`,
1277
+ inclusionCount: `${s.inclusionCount}/${s.totalAnalyses}`,
1278
+ avgCostEth: s.avgEstimatedCostEth.toFixed(6),
1279
+ totalCostEth: s.totalEstimatedCostEth.toFixed(6),
1280
+ avgOverpaymentEth: s.avgOverpaymentEth.toFixed(6),
1281
+ totalOverpaymentEth: s.totalOverpaymentEth.toFixed(6),
1282
+ avgPriorityFeeDeltaGwei: s.avgPriorityFeeDeltaGwei.toFixed(2),
1283
+ })),
1284
+ });
1285
+ }
1286
+
1237
1287
  get aztecSlotDuration() {
1238
1288
  return this.l1Constants.slotDuration;
1239
1289
  }