Skip to content

Commit 0492bf0

Browse files
spalladinoclaude
andcommitted
fix(p2p): use projected next-block fees in gossip validator instead of stale block header
The gossip validator was checking tx maxFeePerGas against the last block's header fees, while the wallet and tx pool already use projected next-block fees from L1. When the L1 fee oracle transitions from high to low values (e.g. after a time warp in tests), this caused a large discrepancy where valid transactions were rejected at the gossip layer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 809ca2f commit 0492bf0

6 files changed

Lines changed: 20 additions & 13 deletions

File tree

yarn-project/p2p/src/client/factory.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ export async function createP2PClient(
142142
proofVerifier,
143143
worldStateSynchronizer,
144144
epochCache,
145+
blockMinFeesProvider,
145146
store,
146147
peerStore,
147148
mempools,
@@ -218,6 +219,7 @@ async function createP2PService(
218219
proofVerifier: ClientProtocolCircuitVerifier,
219220
worldStateSynchronizer: WorldStateSynchronizer,
220221
epochCache: EpochCacheInterface,
222+
blockMinFeesProvider: BlockMinFeesProvider,
221223
store: AztecAsyncKVStore,
222224
peerStore: AztecLMDBStoreV2,
223225
mempools: MemPools,
@@ -245,6 +247,7 @@ async function createP2PService(
245247
proofVerifier,
246248
worldStateSynchronizer,
247249
peerStore,
250+
blockMinFeesProvider,
248251
telemetry,
249252
logger: logger.createChild(`libp2p_service`),
250253
});

yarn-project/p2p/src/services/libp2p/libp2p_service.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
88
import { openTmpStore } from '@aztec/kv-store/lmdb';
99
import { L2Block, type L2BlockSource } from '@aztec/stdlib/block';
1010
import type { ContractDataSource } from '@aztec/stdlib/contract';
11+
import { GasFees } from '@aztec/stdlib/gas';
1112
import type { ClientProtocolCircuitVerifier } from '@aztec/stdlib/interfaces/server';
1213
import { BlockProposal, PeerErrorSeverity } from '@aztec/stdlib/p2p';
1314
import {
@@ -1117,6 +1118,7 @@ describe('LibP2PService', () => {
11171118
epochCache,
11181119
mockProofVerifier,
11191120
mockWorldStateSynchronizer,
1121+
{ getCurrentMinFees: () => Promise.resolve(GasFees.empty()) },
11201122
getTelemetryClient(),
11211123
createLogger('p2p:test:queryForIp'),
11221124
);
@@ -1264,6 +1266,7 @@ class TestLibP2PService extends LibP2PService {
12641266
epochCache,
12651267
mockProofVerifier,
12661268
mockWorldStateSynchronizer,
1269+
{ getCurrentMinFees: () => Promise.resolve(GasFees.empty()) },
12671270
telemetry,
12681271
logger,
12691272
);

yarn-project/p2p/src/services/libp2p/libp2p_service.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { AztecAsyncKVStore } from '@aztec/kv-store';
99
import { protocolContractsHash } from '@aztec/protocol-contracts';
1010
import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
1111
import type { ContractDataSource } from '@aztec/stdlib/contract';
12-
import { GasFees } from '@aztec/stdlib/gas';
12+
import { type BlockMinFeesProvider, GasFees } from '@aztec/stdlib/gas';
1313
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
1414
import {
1515
BlockProposal,
@@ -148,8 +148,6 @@ export class LibP2PService extends WithTracer implements P2PService {
148148
private protocolVersion = '';
149149
private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
150150

151-
private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
152-
153151
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */
154152
private duplicateProposalCallback?: (info: {
155153
slot: SlotNumber;
@@ -197,6 +195,7 @@ export class LibP2PService extends WithTracer implements P2PService {
197195
private epochCache: EpochCacheInterface,
198196
private proofVerifier: ClientProtocolCircuitVerifier,
199197
private worldStateSynchronizer: WorldStateSynchronizer,
198+
private blockMinFeesProvider: BlockMinFeesProvider,
200199
telemetry: TelemetryClient,
201200
logger: Logger = createLogger('p2p:libp2p_service'),
202201
) {
@@ -278,6 +277,7 @@ export class LibP2PService extends WithTracer implements P2PService {
278277
proofVerifier: ClientProtocolCircuitVerifier;
279278
worldStateSynchronizer: WorldStateSynchronizer;
280279
peerStore: AztecAsyncKVStore;
280+
blockMinFeesProvider: BlockMinFeesProvider;
281281
telemetry: TelemetryClient;
282282
logger: Logger;
283283
packageVersion: string;
@@ -290,6 +290,7 @@ export class LibP2PService extends WithTracer implements P2PService {
290290
mempools,
291291
proofVerifier,
292292
peerStore,
293+
blockMinFeesProvider,
293294
telemetry,
294295
logger,
295296
packageVersion,
@@ -491,6 +492,7 @@ export class LibP2PService extends WithTracer implements P2PService {
491492
epochCache,
492493
proofVerifier,
493494
worldStateSynchronizer,
495+
blockMinFeesProvider,
494496
telemetry,
495497
logger,
496498
);
@@ -1664,15 +1666,8 @@ export class LibP2PService extends WithTracer implements P2PService {
16641666
});
16651667
}
16661668

1667-
private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
1668-
if (blockNumber === this.feesCache?.blockNumber) {
1669-
return this.feesCache.gasFees;
1670-
}
1671-
1672-
const header = await this.archiver.getBlockHeader(blockNumber);
1673-
const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
1674-
this.feesCache = { blockNumber, gasFees };
1675-
return gasFees;
1669+
private getGasFees(): Promise<GasFees> {
1670+
return this.blockMinFeesProvider.getCurrentMinFees();
16761671
}
16771672

16781673
/**
@@ -1714,7 +1709,7 @@ export class LibP2PService extends WithTracer implements P2PService {
17141709
currentBlockNumber: BlockNumber,
17151710
nextSlotTimestamp: UInt64,
17161711
): Promise<Record<string, TransactionValidator>> {
1717-
const gasFees = await this.getGasFees(currentBlockNumber);
1712+
const gasFees = await this.getGasFees();
17181713
const allowedInSetup = [
17191714
...(await getDefaultAllowedSetupFunctions()),
17201715
...(this.config.txPublicSetupAllowListExtend ?? []),

yarn-project/p2p/src/test-helpers/mock-pubsub.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
33
import type { AztecAsyncKVStore } from '@aztec/kv-store';
44
import type { L2BlockSource } from '@aztec/stdlib/block';
55
import type { ContractDataSource } from '@aztec/stdlib/contract';
6+
import type { BlockMinFeesProvider } from '@aztec/stdlib/gas';
67
import type { ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
78
import type { TelemetryClient } from '@aztec/telemetry-client';
89

@@ -56,6 +57,7 @@ export function getMockPubSubP2PServiceFactory(
5657
proofVerifier: ClientProtocolCircuitVerifier;
5758
worldStateSynchronizer: WorldStateSynchronizer;
5859
peerStore: AztecAsyncKVStore;
60+
blockMinFeesProvider: BlockMinFeesProvider;
5961
telemetry: TelemetryClient;
6062
logger: Logger;
6163
},
@@ -76,6 +78,7 @@ export function getMockPubSubP2PServiceFactory(
7678
deps.epochCache,
7779
deps.proofVerifier,
7880
deps.worldStateSynchronizer,
81+
deps.blockMinFeesProvider,
7982
deps.telemetry,
8083
deps.logger,
8184
);

yarn-project/p2p/src/test-helpers/reqresp-nodes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
66
import type { L2BlockSource } from '@aztec/stdlib/block';
77
import { type ChainConfig, emptyChainConfig } from '@aztec/stdlib/config';
88
import type { ContractDataSource } from '@aztec/stdlib/contract';
9+
import { GasFees } from '@aztec/stdlib/gas';
910
import type {
1011
ClientProtocolCircuitVerifier,
1112
IVCProofVerificationResult,
@@ -168,6 +169,7 @@ export async function createTestLibP2PService(
168169
epochCache,
169170
proofVerifier,
170171
worldStateSynchronizer,
172+
{ getCurrentMinFees: () => Promise.resolve(GasFees.empty()) },
171173
telemetry,
172174
);
173175
}

yarn-project/p2p/src/testbench/p2p_client_testbench_worker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class TestLibP2PService extends LibP2PService {
117117
epochCache,
118118
proofVerifier,
119119
worldStateSynchronizer,
120+
{ getCurrentMinFees: () => Promise.resolve(GasFees.empty()) },
120121
telemetry,
121122
logger,
122123
);

0 commit comments

Comments
 (0)