@aztec/p2p 0.0.1-commit.2b2662070 → 0.0.1-commit.2c0ee1788
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/factory.d.ts +3 -2
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +17 -16
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +4 -1
- package/dest/config.d.ts +6 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +12 -8
- package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +6 -4
- package/dest/mem_pools/instrumentation.d.ts +1 -1
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +17 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +4 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +5 -2
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +7 -4
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +2 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +5 -2
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +18 -2
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -3
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +1 -1
- package/dest/msg_validators/clock_tolerance.d.ts +1 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +14 -7
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +4 -2
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +4 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +6 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +25 -1
- package/dest/msg_validators/tx_validator/factory.d.ts +2 -2
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +3 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +36 -4
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +46 -31
- package/dest/services/libp2p/instrumentation.d.ts +3 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +14 -0
- package/dest/services/libp2p/libp2p_service.d.ts +6 -4
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +41 -25
- package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +4 -1
- package/dest/test-helpers/mock-pubsub.d.ts +1 -1
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +4 -1
- package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +7 -2
- package/package.json +14 -14
- package/src/client/factory.ts +24 -19
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +2 -0
- package/src/config.ts +16 -7
- package/src/mem_pools/attestation_pool/mocks.ts +13 -8
- package/src/mem_pools/instrumentation.ts +5 -1
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
- package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +3 -0
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +12 -6
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +2 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +21 -1
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +9 -2
- package/src/msg_validators/clock_tolerance.ts +14 -7
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +8 -2
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -2
- package/src/msg_validators/proposal_validator/proposal_validator.ts +35 -1
- package/src/msg_validators/tx_validator/README.md +11 -3
- package/src/msg_validators/tx_validator/factory.ts +3 -1
- package/src/msg_validators/tx_validator/gas_validator.ts +64 -31
- package/src/services/libp2p/instrumentation.ts +14 -0
- package/src/services/libp2p/libp2p_service.ts +43 -19
- package/src/test-helpers/make-test-p2p-clients.ts +2 -0
- package/src/test-helpers/mock-pubsub.ts +3 -0
- package/src/test-helpers/reqresp-nodes.ts +2 -0
- package/src/testbench/p2p_client_testbench_worker.ts +3 -0
|
@@ -3,9 +3,11 @@ import { NoCommitteeError } from '@aztec/ethereum/contracts';
|
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import {
|
|
5
5
|
type CheckpointAttestation,
|
|
6
|
+
type CoordinationSignatureContext,
|
|
6
7
|
type P2PValidator,
|
|
7
8
|
PeerErrorSeverity,
|
|
8
9
|
type ValidationResult,
|
|
10
|
+
hasValidSignatureContext,
|
|
9
11
|
} from '@aztec/stdlib/p2p';
|
|
10
12
|
|
|
11
13
|
import { PipeliningWindow, isWithinClockTolerance } from '../clock_tolerance.js';
|
|
@@ -14,15 +16,22 @@ export class CheckpointAttestationValidator implements P2PValidator<CheckpointAt
|
|
|
14
16
|
protected epochCache: EpochCacheInterface;
|
|
15
17
|
protected logger: Logger;
|
|
16
18
|
private readonly pipeliningWindow: PipeliningWindow;
|
|
19
|
+
protected readonly signatureContext: CoordinationSignatureContext;
|
|
17
20
|
|
|
18
21
|
constructor(
|
|
19
22
|
epochCache: EpochCacheInterface,
|
|
20
23
|
opts: {
|
|
21
24
|
l1PublishingTime?: number;
|
|
25
|
+
p2pPropagationTime?: number;
|
|
26
|
+
signatureContext: CoordinationSignatureContext;
|
|
22
27
|
},
|
|
23
28
|
) {
|
|
24
29
|
this.epochCache = epochCache;
|
|
25
|
-
this.pipeliningWindow = new PipeliningWindow(epochCache, {
|
|
30
|
+
this.pipeliningWindow = new PipeliningWindow(epochCache, {
|
|
31
|
+
l1PublishingTime: opts.l1PublishingTime,
|
|
32
|
+
p2pPropagationTime: opts.p2pPropagationTime,
|
|
33
|
+
});
|
|
34
|
+
this.signatureContext = opts.signatureContext;
|
|
26
35
|
this.logger = createLogger('p2p:checkpoint-attestation-validator');
|
|
27
36
|
}
|
|
28
37
|
|
|
@@ -30,6 +39,17 @@ export class CheckpointAttestationValidator implements P2PValidator<CheckpointAt
|
|
|
30
39
|
const slotNumber = message.payload.header.slotNumber;
|
|
31
40
|
|
|
32
41
|
try {
|
|
42
|
+
// Cross-chain replay check: reject attestations that carry a foreign signing domain.
|
|
43
|
+
if (!hasValidSignatureContext(message.payload, this.signatureContext)) {
|
|
44
|
+
this.logger.warn(`Rejecting checkpoint attestation with foreign signature context for slot ${slotNumber}`, {
|
|
45
|
+
chainId: message.payload.signatureContext.chainId,
|
|
46
|
+
rollupAddress: message.payload.signatureContext.rollupAddress.toString(),
|
|
47
|
+
expectedChainId: this.signatureContext.chainId,
|
|
48
|
+
expectedRollupAddress: this.signatureContext.rollupAddress.toString(),
|
|
49
|
+
});
|
|
50
|
+
return { result: 'reject', severity: PeerErrorSeverity.LowToleranceError };
|
|
51
|
+
}
|
|
52
|
+
|
|
33
53
|
// Use target slots since proposals target pipeline slots (slot + 1 when pipelining).
|
|
34
54
|
const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
|
|
35
55
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type CheckpointAttestation,
|
|
4
|
+
type CoordinationSignatureContext,
|
|
5
|
+
PeerErrorSeverity,
|
|
6
|
+
type ValidationResult,
|
|
7
|
+
} from '@aztec/stdlib/p2p';
|
|
3
8
|
import { Attributes, Metrics, type TelemetryClient, createUpDownCounterWithDefault } from '@aztec/telemetry-client';
|
|
4
9
|
|
|
5
10
|
import type { AttestationPoolApi } from '../../mem_pools/attestation_pool/attestation_pool.js';
|
|
@@ -22,7 +27,9 @@ export class FishermanAttestationValidator extends CheckpointAttestationValidato
|
|
|
22
27
|
telemetryClient: TelemetryClient,
|
|
23
28
|
opts: {
|
|
24
29
|
l1PublishingTime?: number;
|
|
25
|
-
|
|
30
|
+
p2pPropagationTime?: number;
|
|
31
|
+
signatureContext: CoordinationSignatureContext;
|
|
32
|
+
},
|
|
26
33
|
) {
|
|
27
34
|
super(epochCache, opts);
|
|
28
35
|
this.logger = this.logger.createChild('[FISHERMAN]');
|
|
@@ -53,17 +53,24 @@ export function isWithinClockTolerance(
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
* Checks if a message
|
|
56
|
+
* Checks if a straggler message for the previous target slot should be accepted.
|
|
57
57
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
58
|
+
* Under pipelining, proposals and attestations carry the target slot N. Most of the
|
|
59
|
+
* time the receiver is either still in the build slot N-1 (accepted via the main
|
|
60
|
+
* `slotNumber === targetSlot` match) or in the target slot N (accepted via
|
|
61
|
+
* `slotNumber === nextSlot` when pipelining is disabled, or again via `targetSlot`
|
|
62
|
+
* when the receiver itself is pipelining). Stragglers that arrive after the receiver
|
|
63
|
+
* has rolled past the target slot fall to this check: accept `messageSlot === slotNow`
|
|
64
|
+
* while we're still within the first `windowSeconds + clock-disparity` of the slot.
|
|
65
|
+
*
|
|
66
|
+
* Under the early-pipelining schedule `windowSeconds` is small (0 for proposals,
|
|
67
|
+
* `2*p2pPropagationTime` for attestations) since the proposer collects everything
|
|
68
|
+
* before the slot boundary.
|
|
62
69
|
*
|
|
63
70
|
* @param messageSlot - The slot number from the received message
|
|
64
71
|
* @param epochCache - EpochCache to get timing and pipelining state
|
|
65
|
-
* @param windowSeconds -
|
|
66
|
-
* @returns true if pipelining is enabled, the message is for the current slot, and we're within the grace period
|
|
72
|
+
* @param windowSeconds - How far into the current slot we still accept previous-target messages
|
|
73
|
+
* @returns true if pipelining is enabled, the message is for the current wallclock slot, and we're within the grace period
|
|
67
74
|
*/
|
|
68
75
|
function isWithinPipeliningWindow(
|
|
69
76
|
messageSlot: SlotNumber,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import type { BlockProposal, P2PValidator, ValidationResult } from '@aztec/stdlib/p2p';
|
|
2
|
+
import type { BlockProposal, CoordinationSignatureContext, P2PValidator, ValidationResult } from '@aztec/stdlib/p2p';
|
|
3
3
|
|
|
4
4
|
import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
|
|
5
5
|
|
|
@@ -8,7 +8,13 @@ export class BlockProposalValidator implements P2PValidator<BlockProposal> {
|
|
|
8
8
|
|
|
9
9
|
constructor(
|
|
10
10
|
epochCache: EpochCacheInterface,
|
|
11
|
-
opts: {
|
|
11
|
+
opts: {
|
|
12
|
+
txsPermitted: boolean;
|
|
13
|
+
maxTxsPerBlock?: number;
|
|
14
|
+
maxBlocksPerCheckpoint?: number;
|
|
15
|
+
p2pPropagationTime?: number;
|
|
16
|
+
signatureContext: CoordinationSignatureContext;
|
|
17
|
+
},
|
|
12
18
|
) {
|
|
13
19
|
this.proposalValidator = new ProposalValidator(epochCache, opts, 'p2p:block_proposal_validator');
|
|
14
20
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
CheckpointProposal,
|
|
4
|
+
CoordinationSignatureContext,
|
|
5
|
+
P2PValidator,
|
|
6
|
+
ValidationResult,
|
|
7
|
+
} from '@aztec/stdlib/p2p';
|
|
3
8
|
|
|
4
9
|
import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
|
|
5
10
|
|
|
@@ -8,7 +13,13 @@ export class CheckpointProposalValidator implements P2PValidator<CheckpointPropo
|
|
|
8
13
|
|
|
9
14
|
constructor(
|
|
10
15
|
epochCache: EpochCacheInterface,
|
|
11
|
-
opts: {
|
|
16
|
+
opts: {
|
|
17
|
+
txsPermitted: boolean;
|
|
18
|
+
maxTxsPerBlock?: number;
|
|
19
|
+
maxBlocksPerCheckpoint?: number;
|
|
20
|
+
p2pPropagationTime?: number;
|
|
21
|
+
signatureContext: CoordinationSignatureContext;
|
|
22
|
+
},
|
|
12
23
|
) {
|
|
13
24
|
this.proposalValidator = new ProposalValidator(epochCache, opts, 'p2p:checkpoint_proposal_validator');
|
|
14
25
|
}
|
|
@@ -4,8 +4,10 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
|
4
4
|
import {
|
|
5
5
|
type BlockProposal,
|
|
6
6
|
type CheckpointProposalCore,
|
|
7
|
+
type CoordinationSignatureContext,
|
|
7
8
|
PeerErrorSeverity,
|
|
8
9
|
type ValidationResult,
|
|
10
|
+
hasValidSignatureContext,
|
|
9
11
|
} from '@aztec/stdlib/p2p';
|
|
10
12
|
|
|
11
13
|
import { PipeliningWindow, isWithinClockTolerance } from '../clock_tolerance.js';
|
|
@@ -16,23 +18,44 @@ export class ProposalValidator {
|
|
|
16
18
|
private logger: Logger;
|
|
17
19
|
private txsPermitted: boolean;
|
|
18
20
|
private maxTxsPerBlock?: number;
|
|
21
|
+
private maxBlocksPerCheckpoint?: number;
|
|
19
22
|
private pipeliningWindow: PipeliningWindow;
|
|
23
|
+
private signatureContext: CoordinationSignatureContext;
|
|
20
24
|
|
|
21
25
|
constructor(
|
|
22
26
|
epochCache: EpochCacheInterface,
|
|
23
|
-
opts: {
|
|
27
|
+
opts: {
|
|
28
|
+
txsPermitted: boolean;
|
|
29
|
+
maxTxsPerBlock?: number;
|
|
30
|
+
maxBlocksPerCheckpoint?: number;
|
|
31
|
+
p2pPropagationTime?: number;
|
|
32
|
+
signatureContext: CoordinationSignatureContext;
|
|
33
|
+
},
|
|
24
34
|
loggerName: string,
|
|
25
35
|
) {
|
|
26
36
|
this.epochCache = epochCache;
|
|
27
37
|
this.txsPermitted = opts.txsPermitted;
|
|
28
38
|
this.maxTxsPerBlock = opts.maxTxsPerBlock;
|
|
39
|
+
this.maxBlocksPerCheckpoint = opts.maxBlocksPerCheckpoint;
|
|
29
40
|
this.pipeliningWindow = new PipeliningWindow(epochCache, { p2pPropagationTime: opts.p2pPropagationTime });
|
|
41
|
+
this.signatureContext = opts.signatureContext;
|
|
30
42
|
this.logger = createLogger(loggerName);
|
|
31
43
|
}
|
|
32
44
|
|
|
33
45
|
/** Validates header-level fields: slot, signature, and proposer. */
|
|
34
46
|
public async validate(proposal: BlockProposal | CheckpointProposalCore): Promise<ValidationResult> {
|
|
35
47
|
try {
|
|
48
|
+
// Cross-chain replay check: reject proposals that carry a foreign signing domain.
|
|
49
|
+
if (!hasValidSignatureContext(proposal, this.signatureContext)) {
|
|
50
|
+
this.logger.warn(`Penalizing peer for proposal with foreign signature context`, {
|
|
51
|
+
chainId: proposal.signatureContext.chainId,
|
|
52
|
+
rollupAddress: proposal.signatureContext.rollupAddress.toString(),
|
|
53
|
+
expectedChainId: this.signatureContext.chainId,
|
|
54
|
+
expectedRollupAddress: this.signatureContext.rollupAddress.toString(),
|
|
55
|
+
});
|
|
56
|
+
return { result: 'reject', severity: PeerErrorSeverity.LowToleranceError };
|
|
57
|
+
}
|
|
58
|
+
|
|
36
59
|
// Slot check: use target slots since proposals target pipeline slots (slot + 1 when pipelining).
|
|
37
60
|
const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
|
|
38
61
|
|
|
@@ -68,6 +91,17 @@ export class ProposalValidator {
|
|
|
68
91
|
return { result: 'reject', severity: PeerErrorSeverity.MidToleranceError };
|
|
69
92
|
}
|
|
70
93
|
|
|
94
|
+
if (
|
|
95
|
+
this.maxBlocksPerCheckpoint !== undefined &&
|
|
96
|
+
'indexWithinCheckpoint' in proposal &&
|
|
97
|
+
proposal.indexWithinCheckpoint >= this.maxBlocksPerCheckpoint
|
|
98
|
+
) {
|
|
99
|
+
this.logger.warn(
|
|
100
|
+
`Penalizing peer for proposal with indexWithinCheckpoint ${proposal.indexWithinCheckpoint} >= max ${this.maxBlocksPerCheckpoint}`,
|
|
101
|
+
);
|
|
102
|
+
return { result: 'reject', severity: PeerErrorSeverity.MidToleranceError };
|
|
103
|
+
}
|
|
104
|
+
|
|
71
105
|
return { result: 'accept' };
|
|
72
106
|
} catch (e) {
|
|
73
107
|
if (e instanceof NoCommitteeError) {
|
|
@@ -75,7 +75,7 @@ This validator is invoked on **every** transaction potentially entering the pend
|
|
|
75
75
|
- Startup hydration — revalidating persisted non-mined txs on node restart
|
|
76
76
|
|
|
77
77
|
Runs:
|
|
78
|
-
- DoubleSpend, BlockHeader, GasLimits, Timestamp, AllowedSetupCalls
|
|
78
|
+
- DoubleSpend, BlockHeader, GasLimits, MaxFeePerGas, Timestamp, AllowedSetupCalls
|
|
79
79
|
|
|
80
80
|
Operates on `TxMetaData` (pre-built by the pool) rather than full `Tx` objects.
|
|
81
81
|
|
|
@@ -91,8 +91,9 @@ The `AllowedSetupCallsMetaValidator` checks a precomputed boolean flag (`TxMetaD
|
|
|
91
91
|
| `MetadataTxValidator` | Chain ID, rollup version, protocol contracts hash, VK tree root | 4.18 us |
|
|
92
92
|
| `TimestampTxValidator` | Transaction has not expired (expiration timestamp vs next slot) | 1.56 us |
|
|
93
93
|
| `DoubleSpendTxValidator` | Nullifiers do not already exist in the nullifier tree | 106.08 us |
|
|
94
|
-
| `GasTxValidator` | Gas limits are within bounds (delegates to `GasLimitsValidator`), max fee per gas meets current block fees, and fee payer has sufficient FeeJuice balance | 1.02 ms |
|
|
94
|
+
| `GasTxValidator` | Gas limits are within bounds (delegates to `GasLimitsValidator`), max fee per gas meets current block fees (delegates to `MaxFeePerGasValidator`), and fee payer has sufficient FeeJuice balance | 1.02 ms |
|
|
95
95
|
| `GasLimitsValidator` | Gas limits are >= fixed minimums and <= AVM max processable L2 gas. Used standalone in pool migration; also called internally by `GasTxValidator` | 3–10 us |
|
|
96
|
+
| `MaxFeePerGasValidator` | Max fee per gas >= current block gas fees on both dimensions (DA and L2). Used standalone in pool migration; also called internally by `GasTxValidator` | 3–10 us |
|
|
96
97
|
| `PhasesTxValidator` | Public function calls in setup phase are on the allow list | 10.12–13.12 us |
|
|
97
98
|
| `AllowedSetupCallsMetaValidator` | Checks the precomputed `allowedSetupCalls` flag on `TxMetaData`. Used in pool migration instead of the full `PhasesTxValidator` | — |
|
|
98
99
|
| `BlockHeaderTxValidator` | Transaction's anchor block hash exists in the archive tree | 98.88 us |
|
|
@@ -110,10 +111,17 @@ The `AllowedSetupCallsMetaValidator` checks a precomputed boolean flag (`TxMetaD
|
|
|
110
111
|
| DoubleSpend | Stage 1 | Yes | — | Yes | Yes |
|
|
111
112
|
| Gas (balance + limits) | Stage 1 | Optional* | — | Yes | — |
|
|
112
113
|
| GasLimits (standalone) | — | — | — | — | Yes |
|
|
114
|
+
| MaxFeePerGas (standalone) | — | — | — | — | Yes |
|
|
113
115
|
| Phases | Stage 1 | Yes | — | Yes | — |
|
|
114
116
|
| AllowedSetupCalls | — | — | — | — | Yes |
|
|
115
117
|
| BlockHeader | Stage 1 | Yes | — | Yes | Yes |
|
|
116
118
|
| Proof | Stage 2 | Optional** | Yes | — | — |
|
|
117
119
|
|
|
118
|
-
\* Gas balance check is skipped when `skipFeeEnforcement` is set (testing/dev). `GasTxValidator` internally delegates to `GasLimitsValidator` as its first
|
|
120
|
+
\* Gas balance check is skipped when `skipFeeEnforcement` is set (testing/dev). `GasTxValidator` internally delegates to `GasLimitsValidator` and `MaxFeePerGasValidator` as its first steps, so gas limits and fee-per-gas are checked wherever `GasTxValidator` runs. Pool migration uses `GasLimitsValidator` and `MaxFeePerGasValidator` standalone because it doesn't need the balance check.
|
|
119
121
|
\** Proof verification is skipped for simulations (no verifier provided).
|
|
122
|
+
|
|
123
|
+
## Fee-Per-Gas Rejection Strategy
|
|
124
|
+
|
|
125
|
+
The `MaxFeePerGasValidator` and `InsufficientFeePerGasEvictionRule` reject and evict transactions whose `maxFeesPerGas` falls below the current block's gas fees. This is a simple strategy: if a tx can't pay the current fees, it gets rejected on entry and evicted after each new block.
|
|
126
|
+
|
|
127
|
+
**Caveat**: This may evict transactions that would become valid again if block fees drop. A more nuanced approach would be to define a threshold (e.g., 50%) and only reject/evict when the tx's max fee falls below that fraction of the current fees. The current approach is simpler and ensures the pool doesn't accumulate transactions with low max fees that are unlikely to be mined soon.
|
|
@@ -56,7 +56,7 @@ import { type ArchiveSource, BlockHeaderTxValidator } from './block_header_valid
|
|
|
56
56
|
import { ContractInstanceTxValidator } from './contract_instance_validator.js';
|
|
57
57
|
import { DataTxValidator } from './data_validator.js';
|
|
58
58
|
import { DoubleSpendTxValidator, type NullifierSource } from './double_spend_validator.js';
|
|
59
|
-
import { GasLimitsValidator, GasTxValidator } from './gas_validator.js';
|
|
59
|
+
import { GasLimitsValidator, GasTxValidator, MaxFeePerGasValidator } from './gas_validator.js';
|
|
60
60
|
import { MetadataTxValidator } from './metadata_validator.js';
|
|
61
61
|
import { NullifierCache } from './nullifier_cache.js';
|
|
62
62
|
import { AllowedSetupCallsMetaValidator, PhasesTxValidator } from './phases_validator.js';
|
|
@@ -423,6 +423,7 @@ export async function createTxValidatorForTransactionsEnteringPendingTxPool(
|
|
|
423
423
|
timestamp: bigint,
|
|
424
424
|
blockNumber: BlockNumber,
|
|
425
425
|
gasLimitOpts: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number },
|
|
426
|
+
gasFees: GasFees,
|
|
426
427
|
bindings?: LoggerBindings,
|
|
427
428
|
): Promise<TxValidator<TxMetaData>> {
|
|
428
429
|
await worldStateSynchronizer.syncImmediate();
|
|
@@ -440,6 +441,7 @@ export async function createTxValidatorForTransactionsEnteringPendingTxPool(
|
|
|
440
441
|
};
|
|
441
442
|
return new AggregateTxValidator<TxMetaData>(
|
|
442
443
|
new GasLimitsValidator<TxMetaData>({ ...gasLimitOpts, bindings }),
|
|
444
|
+
new MaxFeePerGasValidator<TxMetaData>(gasFees, bindings),
|
|
443
445
|
new TimestampTxValidator<TxMetaData>({ timestamp, blockNumber }, bindings),
|
|
444
446
|
new DoubleSpendTxValidator<TxMetaData>(nullifierSource, bindings),
|
|
445
447
|
new BlockHeaderTxValidator<TxMetaData>(archiveSource, bindings),
|
|
@@ -36,6 +36,18 @@ export interface HasGasLimitData {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/** Structural interface for types that carry max fee per gas data, used by {@link MaxFeePerGasValidator}. */
|
|
40
|
+
export interface HasMaxFeePerGasData {
|
|
41
|
+
txHash: { toString(): string };
|
|
42
|
+
data: {
|
|
43
|
+
constants: {
|
|
44
|
+
txContext: {
|
|
45
|
+
gasSettings: { maxFeesPerGas: GasFees };
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
39
51
|
/**
|
|
40
52
|
* Validates that a transaction's gas limits are within acceptable bounds.
|
|
41
53
|
*
|
|
@@ -124,15 +136,60 @@ export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidato
|
|
|
124
136
|
}
|
|
125
137
|
}
|
|
126
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Validates that a transaction's max fee per gas meets the current block's gas fees.
|
|
141
|
+
*
|
|
142
|
+
* Rejects transactions whose maxFeesPerGas is below the current block's gas fees
|
|
143
|
+
* on either dimension (DA or L2). This is a cheap, stateless check.
|
|
144
|
+
*
|
|
145
|
+
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
146
|
+
* (used during pending pool migration).
|
|
147
|
+
*
|
|
148
|
+
* Used by: pending pool migration (via factory), and indirectly by {@link GasTxValidator}.
|
|
149
|
+
*/
|
|
150
|
+
export class MaxFeePerGasValidator<T extends HasMaxFeePerGasData> implements TxValidator<T> {
|
|
151
|
+
#log: Logger;
|
|
152
|
+
#gasFees: GasFees;
|
|
153
|
+
|
|
154
|
+
constructor(gasFees: GasFees, bindings?: LoggerBindings) {
|
|
155
|
+
this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
|
|
156
|
+
this.#gasFees = gasFees;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
validateTx(tx: T): Promise<TxValidationResult> {
|
|
160
|
+
return Promise.resolve(this.validateMaxFeePerGas(tx));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Checks maxFeesPerGas >= current block gas fees on both dimensions. */
|
|
164
|
+
validateMaxFeePerGas(tx: T): TxValidationResult {
|
|
165
|
+
const maxFeesPerGas = tx.data.constants.txContext.gasSettings.maxFeesPerGas;
|
|
166
|
+
const notEnoughMaxFees =
|
|
167
|
+
maxFeesPerGas.feePerDaGas < this.#gasFees.feePerDaGas || maxFeesPerGas.feePerL2Gas < this.#gasFees.feePerL2Gas;
|
|
168
|
+
|
|
169
|
+
if (notEnoughMaxFees) {
|
|
170
|
+
this.#log.verbose(`Rejecting transaction ${tx.txHash.toString()} due to insufficient fee per gas`, {
|
|
171
|
+
txMaxFeesPerGas: maxFeesPerGas.toInspect(),
|
|
172
|
+
currentGasFees: this.#gasFees.toInspect(),
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
result: 'invalid',
|
|
176
|
+
reason: [
|
|
177
|
+
`${TX_ERROR_INSUFFICIENT_FEE_PER_GAS} (maxFee=da:${maxFeesPerGas.feePerDaGas},l2:${maxFeesPerGas.feePerL2Gas} required=da:${this.#gasFees.feePerDaGas},l2:${this.#gasFees.feePerL2Gas})`,
|
|
178
|
+
],
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return { result: 'valid' };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
127
185
|
/**
|
|
128
186
|
* Validates that a transaction can pay its gas fees.
|
|
129
187
|
*
|
|
130
188
|
* Runs three checks in order:
|
|
131
189
|
* 1. **Gas limits** (delegates to {@link GasLimitsValidator}) — rejects if limits are
|
|
132
190
|
* out of bounds.
|
|
133
|
-
* 2. **Max fee per gas** —
|
|
134
|
-
* the current block's gas fees.
|
|
135
|
-
* become eligible in a later block with lower fees.
|
|
191
|
+
* 2. **Max fee per gas** — rejects the tx if its maxFeesPerGas is below
|
|
192
|
+
* the current block's gas fees.
|
|
136
193
|
* 3. **Fee payer balance** — reads the fee payer's FeeJuice balance from public state,
|
|
137
194
|
* adds any pending claim from a setup-phase `_increase_public_balance` call, and
|
|
138
195
|
* rejects if the total is less than the tx's fee limit (gasLimits * maxFeePerGas).
|
|
@@ -166,39 +223,15 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
166
223
|
bindings: this.bindings,
|
|
167
224
|
}).validateGasLimit(tx);
|
|
168
225
|
if (gasLimitValidation.result === 'invalid') {
|
|
169
|
-
return
|
|
226
|
+
return gasLimitValidation;
|
|
170
227
|
}
|
|
171
|
-
const
|
|
172
|
-
if (
|
|
173
|
-
return
|
|
228
|
+
const maxFeeValidation = new MaxFeePerGasValidator(this.#gasFees, this.bindings).validateMaxFeePerGas(tx);
|
|
229
|
+
if (maxFeeValidation.result === 'invalid') {
|
|
230
|
+
return maxFeeValidation;
|
|
174
231
|
}
|
|
175
232
|
return await this.validateTxFee(tx);
|
|
176
233
|
}
|
|
177
234
|
|
|
178
|
-
/**
|
|
179
|
-
* Check whether the tx's max fees are valid for the current block, and return a skip reason if not.
|
|
180
|
-
* We skip instead of invalidating since the tx may become eligible later.
|
|
181
|
-
* Note that circuits check max fees even if fee payer is unset, so we
|
|
182
|
-
* keep this validation even if the tx does not pay fees.
|
|
183
|
-
*/
|
|
184
|
-
#getSkipReason(tx: Tx): string | undefined {
|
|
185
|
-
const gasSettings = tx.data.constants.txContext.gasSettings;
|
|
186
|
-
|
|
187
|
-
// Skip the tx if its max fees are not enough for the current block's gas fees.
|
|
188
|
-
const maxFeesPerGas = gasSettings.maxFeesPerGas;
|
|
189
|
-
const notEnoughMaxFees =
|
|
190
|
-
maxFeesPerGas.feePerDaGas < this.#gasFees.feePerDaGas || maxFeesPerGas.feePerL2Gas < this.#gasFees.feePerL2Gas;
|
|
191
|
-
|
|
192
|
-
if (notEnoughMaxFees) {
|
|
193
|
-
this.#log.verbose(`Skipping transaction ${tx.getTxHash().toString()} due to insufficient fee per gas`, {
|
|
194
|
-
txMaxFeesPerGas: maxFeesPerGas.toInspect(),
|
|
195
|
-
currentGasFees: this.#gasFees.toInspect(),
|
|
196
|
-
});
|
|
197
|
-
return `${TX_ERROR_INSUFFICIENT_FEE_PER_GAS} (maxFee=da:${maxFeesPerGas.feePerDaGas},l2:${maxFeesPerGas.feePerL2Gas} required=da:${this.#gasFees.feePerDaGas},l2:${this.#gasFees.feePerL2Gas})`;
|
|
198
|
-
}
|
|
199
|
-
return undefined;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
235
|
/**
|
|
203
236
|
* Checks the fee payer has enough FeeJuice balance to cover the tx's fee limit.
|
|
204
237
|
* Accounts for any pending claim from a setup-phase `_increase_public_balance` call.
|
|
@@ -18,6 +18,7 @@ export class P2PInstrumentation {
|
|
|
18
18
|
private messagePrevalidationCount: UpDownCounter;
|
|
19
19
|
private messageLatency: Histogram;
|
|
20
20
|
private txReceivedCount: UpDownCounter;
|
|
21
|
+
private slowValidationCount: UpDownCounter;
|
|
21
22
|
|
|
22
23
|
private aggLatencyHisto = new Map<TopicType, RecordableHistogram>();
|
|
23
24
|
private aggValidationHisto = new Map<TopicType, RecordableHistogram>();
|
|
@@ -48,6 +49,15 @@ export class P2PInstrumentation {
|
|
|
48
49
|
|
|
49
50
|
this.txReceivedCount = createUpDownCounterWithDefault(meter, Metrics.P2P_GOSSIP_TX_RECEIVED_COUNT);
|
|
50
51
|
|
|
52
|
+
this.slowValidationCount = createUpDownCounterWithDefault(meter, Metrics.P2P_GOSSIP_SLOW_VALIDATION_COUNT, {
|
|
53
|
+
[Attributes.TOPIC_NAME]: [
|
|
54
|
+
TopicType.tx,
|
|
55
|
+
TopicType.block_proposal,
|
|
56
|
+
TopicType.checkpoint_proposal,
|
|
57
|
+
TopicType.checkpoint_attestation,
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
|
|
51
61
|
this.aggLatencyMetrics = {
|
|
52
62
|
avg: meter.createObservableGauge(Metrics.P2P_GOSSIP_AGG_MESSAGE_LATENCY_AVG),
|
|
53
63
|
max: meter.createObservableGauge(Metrics.P2P_GOSSIP_AGG_MESSAGE_LATENCY_MAX),
|
|
@@ -87,6 +97,10 @@ export class P2PInstrumentation {
|
|
|
87
97
|
this.txReceivedCount.add(count);
|
|
88
98
|
}
|
|
89
99
|
|
|
100
|
+
public incSlowValidation(topicName: TopicType) {
|
|
101
|
+
this.slowValidationCount.add(1, { [Attributes.TOPIC_NAME]: topicName });
|
|
102
|
+
}
|
|
103
|
+
|
|
90
104
|
public incMessagePrevalidationStatus(passed: boolean, topicName: TopicType | undefined) {
|
|
91
105
|
this.messagePrevalidationCount.add(1, { [Attributes.TOPIC_NAME]: topicName, [Attributes.OK]: passed });
|
|
92
106
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
2
|
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
-
import { maxBy } from '@aztec/foundation/collection';
|
|
3
|
+
import { maxBy, merge } from '@aztec/foundation/collection';
|
|
4
4
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
5
5
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
6
6
|
import { Timer } from '@aztec/foundation/timer';
|
|
@@ -8,7 +8,7 @@ import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
|
8
8
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
9
9
|
import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
|
|
10
10
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
11
|
-
import { GasFees } from '@aztec/stdlib/gas';
|
|
11
|
+
import { type BlockMinFeesProvider, GasFees } from '@aztec/stdlib/gas';
|
|
12
12
|
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
13
13
|
import {
|
|
14
14
|
BlockProposal,
|
|
@@ -146,8 +146,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
146
146
|
private protocolVersion = '';
|
|
147
147
|
private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
|
|
148
148
|
|
|
149
|
-
private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
|
|
150
|
-
|
|
151
149
|
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */
|
|
152
150
|
private duplicateProposalCallback?: (info: {
|
|
153
151
|
slot: SlotNumber;
|
|
@@ -197,6 +195,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
197
195
|
private epochCache: EpochCacheInterface,
|
|
198
196
|
private proofVerifier: ClientProtocolCircuitVerifier,
|
|
199
197
|
private worldStateSynchronizer: WorldStateSynchronizer,
|
|
198
|
+
private blockMinFeesProvider: BlockMinFeesProvider,
|
|
200
199
|
telemetry: TelemetryClient,
|
|
201
200
|
logger: Logger = createLogger('p2p:libp2p_service'),
|
|
202
201
|
) {
|
|
@@ -232,15 +231,23 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
232
231
|
const proposalValidatorOpts = {
|
|
233
232
|
txsPermitted: !config.disableTransactions,
|
|
234
233
|
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
234
|
+
maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint,
|
|
235
235
|
p2pPropagationTime,
|
|
236
|
+
signatureContext: {
|
|
237
|
+
chainId: config.l1ChainId,
|
|
238
|
+
rollupAddress: config.l1Contracts.rollupAddress,
|
|
239
|
+
},
|
|
236
240
|
};
|
|
237
241
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
|
|
238
242
|
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
243
|
+
const attestationValidatorOpts = {
|
|
244
|
+
l1PublishingTime: config.l1PublishingTime,
|
|
245
|
+
p2pPropagationTime,
|
|
246
|
+
signatureContext: proposalValidatorOpts.signatureContext,
|
|
247
|
+
};
|
|
239
248
|
this.checkpointAttestationValidator = config.fishermanMode
|
|
240
|
-
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry,
|
|
241
|
-
|
|
242
|
-
})
|
|
243
|
-
: new CheckpointAttestationValidator(epochCache, { l1PublishingTime: config.l1PublishingTime });
|
|
249
|
+
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry, attestationValidatorOpts)
|
|
250
|
+
: new CheckpointAttestationValidator(epochCache, attestationValidatorOpts);
|
|
244
251
|
|
|
245
252
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
246
253
|
|
|
@@ -265,8 +272,9 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
265
272
|
};
|
|
266
273
|
}
|
|
267
274
|
|
|
268
|
-
public updateConfig(config: Partial<P2PReqRespConfig
|
|
275
|
+
public updateConfig(config: Partial<P2PReqRespConfig & Pick<P2PConfig, 'skipIncomingProposals'>>) {
|
|
269
276
|
this.reqresp.updateConfig(config);
|
|
277
|
+
this.config = merge(this.config, config);
|
|
270
278
|
}
|
|
271
279
|
|
|
272
280
|
/**
|
|
@@ -285,6 +293,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
285
293
|
proofVerifier: ClientProtocolCircuitVerifier;
|
|
286
294
|
worldStateSynchronizer: WorldStateSynchronizer;
|
|
287
295
|
peerStore: AztecAsyncKVStore;
|
|
296
|
+
blockMinFeesProvider: BlockMinFeesProvider;
|
|
288
297
|
telemetry: TelemetryClient;
|
|
289
298
|
logger: Logger;
|
|
290
299
|
packageVersion: string;
|
|
@@ -297,6 +306,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
297
306
|
mempools,
|
|
298
307
|
proofVerifier,
|
|
299
308
|
peerStore,
|
|
309
|
+
blockMinFeesProvider,
|
|
300
310
|
telemetry,
|
|
301
311
|
logger,
|
|
302
312
|
packageVersion,
|
|
@@ -503,6 +513,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
503
513
|
epochCache,
|
|
504
514
|
proofVerifier,
|
|
505
515
|
worldStateSynchronizer,
|
|
516
|
+
blockMinFeesProvider,
|
|
506
517
|
telemetry,
|
|
507
518
|
logger,
|
|
508
519
|
);
|
|
@@ -840,6 +851,15 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
840
851
|
|
|
841
852
|
// Process the message, optionally within a linked span for trace propagation
|
|
842
853
|
const processMessage = async () => {
|
|
854
|
+
if (
|
|
855
|
+
this.config.skipIncomingProposals &&
|
|
856
|
+
(msg.topic === this.topicStrings[TopicType.block_proposal] ||
|
|
857
|
+
msg.topic === this.topicStrings[TopicType.checkpoint_proposal])
|
|
858
|
+
) {
|
|
859
|
+
this.logger.warn(`Ignoring incoming proposal (skipIncomingProposals is set)`, { topic: msg.topic });
|
|
860
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
843
863
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
844
864
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
845
865
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
@@ -917,6 +937,17 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
917
937
|
this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
|
|
918
938
|
}
|
|
919
939
|
|
|
940
|
+
const validationTimeMs = timer.ms();
|
|
941
|
+
const mcacheWindowMs = this.config.gossipsubMcacheLength * this.config.gossipsubInterval;
|
|
942
|
+
if (validationTimeMs > mcacheWindowMs * 0.75) {
|
|
943
|
+
this.instrumentation.incSlowValidation(topicType);
|
|
944
|
+
this.logger.warn(
|
|
945
|
+
`Gossip validation for ${topicType} took ${validationTimeMs}ms, approaching mcache eviction window of ${mcacheWindowMs}ms. ` +
|
|
946
|
+
`Message forwarding may be skipped if validation exceeds the window.`,
|
|
947
|
+
{ msgId, source: source.toString(), topicType, validationTimeMs, mcacheWindowMs },
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
|
|
920
951
|
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
921
952
|
this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
|
|
922
953
|
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
@@ -1605,15 +1636,8 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1605
1636
|
});
|
|
1606
1637
|
}
|
|
1607
1638
|
|
|
1608
|
-
private
|
|
1609
|
-
|
|
1610
|
-
return this.feesCache.gasFees;
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1613
|
-
const header = await this.archiver.getBlockHeader(blockNumber);
|
|
1614
|
-
const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
|
|
1615
|
-
this.feesCache = { blockNumber, gasFees };
|
|
1616
|
-
return gasFees;
|
|
1639
|
+
private getGasFees(): Promise<GasFees> {
|
|
1640
|
+
return this.blockMinFeesProvider.getCurrentMinFees();
|
|
1617
1641
|
}
|
|
1618
1642
|
|
|
1619
1643
|
/**
|
|
@@ -1655,7 +1679,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1655
1679
|
currentBlockNumber: BlockNumber,
|
|
1656
1680
|
nextSlotTimestamp: UInt64,
|
|
1657
1681
|
): Promise<Record<string, TransactionValidator>> {
|
|
1658
|
-
const gasFees = await this.getGasFees(
|
|
1682
|
+
const gasFees = await this.getGasFees();
|
|
1659
1683
|
const allowedInSetup = [
|
|
1660
1684
|
...(await getDefaultAllowedSetupFunctions()),
|
|
1661
1685
|
...(this.config.txPublicSetupAllowListExtend ?? []),
|
|
@@ -5,6 +5,7 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
|
5
5
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
6
6
|
import { sleep } from '@aztec/foundation/sleep';
|
|
7
7
|
import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
|
|
8
|
+
import { GasFees } from '@aztec/stdlib/gas';
|
|
8
9
|
import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
9
10
|
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
10
11
|
|
|
@@ -102,6 +103,7 @@ export async function makeTestP2PClient(
|
|
|
102
103
|
proofVerifier,
|
|
103
104
|
mockWorldState,
|
|
104
105
|
mockEpochCache,
|
|
106
|
+
{ getCurrentMinFees: () => Promise.resolve(GasFees.empty()) },
|
|
105
107
|
'test-p2p-client',
|
|
106
108
|
undefined,
|
|
107
109
|
undefined,
|
|
@@ -4,6 +4,7 @@ import { sleep } from '@aztec/foundation/sleep';
|
|
|
4
4
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
5
5
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
6
6
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
7
|
+
import type { BlockMinFeesProvider } from '@aztec/stdlib/gas';
|
|
7
8
|
import type { ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
8
9
|
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
9
10
|
|
|
@@ -56,6 +57,7 @@ export function getMockPubSubP2PServiceFactory(
|
|
|
56
57
|
proofVerifier: ClientProtocolCircuitVerifier;
|
|
57
58
|
worldStateSynchronizer: WorldStateSynchronizer;
|
|
58
59
|
peerStore: AztecAsyncKVStore;
|
|
60
|
+
blockMinFeesProvider: BlockMinFeesProvider;
|
|
59
61
|
telemetry: TelemetryClient;
|
|
60
62
|
logger: Logger;
|
|
61
63
|
},
|
|
@@ -76,6 +78,7 @@ export function getMockPubSubP2PServiceFactory(
|
|
|
76
78
|
deps.epochCache,
|
|
77
79
|
deps.proofVerifier,
|
|
78
80
|
deps.worldStateSynchronizer,
|
|
81
|
+
deps.blockMinFeesProvider,
|
|
79
82
|
deps.telemetry,
|
|
80
83
|
deps.logger,
|
|
81
84
|
);
|