@aztec/p2p 0.0.1-commit.f5d02921e → 0.0.1-commit.f7ea82942
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 +16 -15
- package/dest/client/p2p_client.d.ts +1 -1
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +9 -2
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +4 -1
- package/dest/config.d.ts +103 -99
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +11 -6
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -2
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +5 -3
- 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/eviction/invalid_txs_after_reorg_rule.js +2 -2
- 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 +8 -5
- 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 +17 -9
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +4 -2
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +2 -2
- package/dest/msg_validators/clock_tolerance.d.ts +12 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +50 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +2 -1
- 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 +2 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +3 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +16 -8
- package/dest/msg_validators/tx_validator/archive_cache.js +1 -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 +50 -33
- package/dest/services/data_store.d.ts +1 -1
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/data_store.js +5 -5
- package/dest/services/dummy_service.d.ts +2 -1
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +1 -0
- package/dest/services/gossipsub/topic_score_params.d.ts +13 -2
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +21 -4
- 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 -17
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +37 -73
- package/dest/services/peer-manager/peer_manager.d.ts +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +15 -2
- package/dest/services/peer-manager/peer_scoring.d.ts +3 -1
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +4 -0
- package/dest/services/reqresp/config.d.ts +3 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/interface.d.ts +14 -9
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +10 -11
- package/dest/services/reqresp/metrics.d.ts +1 -1
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.js +0 -1
- package/dest/services/reqresp/protocols/index.d.ts +1 -2
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.js +0 -1
- package/dest/services/reqresp/protocols/tx.d.ts +1 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +1 -3
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +0 -10
- package/dest/services/reqresp/reqresp.d.ts +4 -2
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +11 -2
- 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 +11 -3
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +36 -11
- 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 +5 -3
- package/dest/test-helpers/testbench-utils.d.ts +1 -1
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +1 -0
- 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 +29 -2
- package/dest/testbench/worker_client_manager.d.ts +8 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +49 -0
- package/package.json +14 -14
- package/src/client/factory.ts +23 -18
- package/src/client/p2p_client.ts +11 -3
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +2 -0
- package/src/config.ts +19 -7
- package/src/mem_pools/attestation_pool/attestation_pool.ts +5 -3
- 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/eviction/invalid_txs_after_reorg_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/interfaces.ts +3 -0
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +13 -7
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +2 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +18 -7
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +4 -1
- package/src/msg_validators/clock_tolerance.ts +68 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +4 -1
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +4 -1
- package/src/msg_validators/proposal_validator/proposal_validator.ts +13 -7
- package/src/msg_validators/tx_validator/README.md +11 -3
- package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
- package/src/msg_validators/tx_validator/factory.ts +3 -1
- package/src/msg_validators/tx_validator/gas_validator.ts +82 -33
- package/src/services/data_store.ts +5 -13
- package/src/services/dummy_service.ts +1 -0
- package/src/services/gossipsub/topic_score_params.ts +36 -4
- package/src/services/libp2p/instrumentation.ts +14 -0
- package/src/services/libp2p/libp2p_service.ts +32 -68
- package/src/services/peer-manager/peer_manager.ts +17 -2
- package/src/services/peer-manager/peer_scoring.ts +6 -0
- package/src/services/reqresp/config.ts +2 -2
- package/src/services/reqresp/interface.ts +21 -11
- package/src/services/reqresp/metrics.ts +0 -1
- package/src/services/reqresp/protocols/index.ts +0 -1
- package/src/services/reqresp/protocols/tx.ts +1 -3
- package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
- package/src/services/reqresp/reqresp.ts +18 -1
- package/src/test-helpers/make-test-p2p-clients.ts +2 -0
- package/src/test-helpers/mock-pubsub.ts +34 -5
- package/src/test-helpers/reqresp-nodes.ts +4 -2
- package/src/test-helpers/testbench-utils.ts +1 -0
- package/src/testbench/p2p_client_testbench_worker.ts +30 -0
- package/src/testbench/worker_client_manager.ts +55 -0
- package/dest/services/reqresp/protocols/block.d.ts +0 -9
- package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
- package/dest/services/reqresp/protocols/block.js +0 -32
- package/src/services/reqresp/protocols/block.ts +0 -37
package/src/client/factory.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { AztecLMDBStoreV2, createStore } from '@aztec/kv-store/lmdb-v2';
|
|
|
7
7
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
8
8
|
import type { ChainConfig } from '@aztec/stdlib/config';
|
|
9
9
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
10
|
+
import type { BlockMinFeesProvider } from '@aztec/stdlib/gas';
|
|
10
11
|
import type { AztecNode, ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
11
12
|
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
12
13
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
@@ -52,6 +53,7 @@ export async function createP2PClient(
|
|
|
52
53
|
proofVerifier: ClientProtocolCircuitVerifier,
|
|
53
54
|
worldStateSynchronizer: WorldStateSynchronizer,
|
|
54
55
|
epochCache: EpochCacheInterface,
|
|
56
|
+
blockMinFeesProvider: BlockMinFeesProvider,
|
|
55
57
|
packageVersion: string,
|
|
56
58
|
dateProvider: DateProvider = new DateProvider(),
|
|
57
59
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
@@ -90,23 +92,6 @@ export async function createP2PClient(
|
|
|
90
92
|
() => epochCache.getEpochAndSlotInNextL1Slot().ts,
|
|
91
93
|
);
|
|
92
94
|
|
|
93
|
-
const createTxValidator = async () => {
|
|
94
|
-
// We accept transactions if they are not expired by the next slot and block number (checked based on the ExpirationTimestamp field)
|
|
95
|
-
const currentBlockNumber = await archiver.getBlockNumber();
|
|
96
|
-
const { ts: nextSlotTimestamp } = epochCache.getEpochAndSlotInNextL1Slot();
|
|
97
|
-
const l1Constants = await archiver.getL1Constants();
|
|
98
|
-
return createTxValidatorForTransactionsEnteringPendingTxPool(
|
|
99
|
-
worldStateSynchronizer,
|
|
100
|
-
nextSlotTimestamp,
|
|
101
|
-
BlockNumber(currentBlockNumber + 1),
|
|
102
|
-
{
|
|
103
|
-
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
104
|
-
maxBlockL2Gas: config.validateMaxL2BlockGas,
|
|
105
|
-
maxBlockDAGas: config.validateMaxDABlockGas,
|
|
106
|
-
},
|
|
107
|
-
);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
95
|
const txPool =
|
|
111
96
|
deps.txPool ??
|
|
112
97
|
new AztecKVTxPoolV2(
|
|
@@ -116,7 +101,24 @@ export async function createP2PClient(
|
|
|
116
101
|
l2BlockSource: archiver,
|
|
117
102
|
worldStateSynchronizer,
|
|
118
103
|
checkAllowedSetupCalls,
|
|
119
|
-
createTxValidator
|
|
104
|
+
createTxValidator: async () => {
|
|
105
|
+
const currentBlockNumber = await archiver.getBlockNumber();
|
|
106
|
+
const { ts: nextSlotTimestamp } = epochCache.getEpochAndSlotInNextL1Slot();
|
|
107
|
+
const l1Constants = await archiver.getL1Constants();
|
|
108
|
+
const gasFees = await blockMinFeesProvider.getCurrentMinFees();
|
|
109
|
+
return createTxValidatorForTransactionsEnteringPendingTxPool(
|
|
110
|
+
worldStateSynchronizer,
|
|
111
|
+
nextSlotTimestamp,
|
|
112
|
+
BlockNumber(currentBlockNumber + 1),
|
|
113
|
+
{
|
|
114
|
+
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
115
|
+
maxBlockL2Gas: config.validateMaxL2BlockGas,
|
|
116
|
+
maxBlockDAGas: config.validateMaxDABlockGas,
|
|
117
|
+
},
|
|
118
|
+
gasFees,
|
|
119
|
+
);
|
|
120
|
+
},
|
|
121
|
+
blockMinFeesProvider,
|
|
120
122
|
},
|
|
121
123
|
telemetry,
|
|
122
124
|
{
|
|
@@ -140,6 +142,7 @@ export async function createP2PClient(
|
|
|
140
142
|
proofVerifier,
|
|
141
143
|
worldStateSynchronizer,
|
|
142
144
|
epochCache,
|
|
145
|
+
blockMinFeesProvider,
|
|
143
146
|
store,
|
|
144
147
|
peerStore,
|
|
145
148
|
mempools,
|
|
@@ -216,6 +219,7 @@ async function createP2PService(
|
|
|
216
219
|
proofVerifier: ClientProtocolCircuitVerifier,
|
|
217
220
|
worldStateSynchronizer: WorldStateSynchronizer,
|
|
218
221
|
epochCache: EpochCacheInterface,
|
|
222
|
+
blockMinFeesProvider: BlockMinFeesProvider,
|
|
219
223
|
store: AztecAsyncKVStore,
|
|
220
224
|
peerStore: AztecLMDBStoreV2,
|
|
221
225
|
mempools: MemPools,
|
|
@@ -243,6 +247,7 @@ async function createP2PService(
|
|
|
243
247
|
proofVerifier,
|
|
244
248
|
worldStateSynchronizer,
|
|
245
249
|
peerStore,
|
|
250
|
+
blockMinFeesProvider,
|
|
246
251
|
telemetry,
|
|
247
252
|
logger: logger.createChild(`libp2p_service`),
|
|
248
253
|
});
|
package/src/client/p2p_client.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { GENESIS_BLOCK_HEADER_HASH } from '@aztec/constants';
|
|
2
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
3
2
|
import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -9,6 +8,7 @@ import { L2TipsKVStore } from '@aztec/kv-store/stores';
|
|
|
9
8
|
import {
|
|
10
9
|
type CheckpointId,
|
|
11
10
|
type EthAddress,
|
|
11
|
+
GENESIS_BLOCK_HEADER_HASH,
|
|
12
12
|
type L2Block,
|
|
13
13
|
type L2BlockId,
|
|
14
14
|
type L2BlockSource,
|
|
@@ -257,7 +257,11 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
257
257
|
});
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
|
|
260
|
+
// Should never happen: all branches above call initBlockStream()
|
|
261
|
+
if (!this.blockStream) {
|
|
262
|
+
throw new Error('Block stream not initialized');
|
|
263
|
+
}
|
|
264
|
+
this.blockStream.start();
|
|
261
265
|
await this.txCollection.start();
|
|
262
266
|
this.txFileStore?.start();
|
|
263
267
|
|
|
@@ -319,7 +323,11 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
319
323
|
/** Triggers a sync to the archiver. Used for testing. */
|
|
320
324
|
public async sync() {
|
|
321
325
|
this.initBlockStream();
|
|
322
|
-
|
|
326
|
+
// Should never happen: initBlockStream() creates blockStream if absent
|
|
327
|
+
if (!this.blockStream) {
|
|
328
|
+
throw new Error('Block stream not initialized');
|
|
329
|
+
}
|
|
330
|
+
await this.blockStream.sync();
|
|
323
331
|
}
|
|
324
332
|
|
|
325
333
|
@trackSpan('p2pClient.broadcastProposal', async proposal => ({
|
|
@@ -6,6 +6,7 @@ import { DateProvider, Timer, executeTimeout } from '@aztec/foundation/timer';
|
|
|
6
6
|
import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
|
|
7
7
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
8
8
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
9
|
+
import { GasFees } from '@aztec/stdlib/gas';
|
|
9
10
|
import type { ClientProtocolCircuitVerifier } from '@aztec/stdlib/interfaces/server';
|
|
10
11
|
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
11
12
|
import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
@@ -119,6 +120,7 @@ async function startClient(config: P2PConfig, clientIndex: number) {
|
|
|
119
120
|
proofVerifier as ClientProtocolCircuitVerifier,
|
|
120
121
|
worldState,
|
|
121
122
|
epochCache,
|
|
123
|
+
{ getCurrentMinFees: () => Promise.resolve(GasFees.empty()) },
|
|
122
124
|
'proposal-tx-collector-bench-worker',
|
|
123
125
|
new DateProvider(),
|
|
124
126
|
telemetry as TelemetryClient,
|
package/src/config.ts
CHANGED
|
@@ -39,7 +39,14 @@ export interface P2PConfig
|
|
|
39
39
|
ChainConfig,
|
|
40
40
|
TxCollectionConfig,
|
|
41
41
|
TxFileStoreConfig,
|
|
42
|
-
Pick<
|
|
42
|
+
Pick<
|
|
43
|
+
SequencerConfig,
|
|
44
|
+
| 'blockDurationMs'
|
|
45
|
+
| 'expectedBlockProposalsPerSlot'
|
|
46
|
+
| 'l1PublishingTime'
|
|
47
|
+
| 'maxTxsPerBlock'
|
|
48
|
+
| 'attestationPropagationTime'
|
|
49
|
+
> {
|
|
43
50
|
/** Maximum transactions per block for validation. Overrides maxTxsPerBlock for gossip validation when set. */
|
|
44
51
|
validateMaxTxsPerBlock?: number;
|
|
45
52
|
|
|
@@ -218,23 +225,23 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
|
218
225
|
env: 'VALIDATOR_MAX_TX_PER_BLOCK',
|
|
219
226
|
description:
|
|
220
227
|
'Maximum transactions per block for validation. Overrides maxTxsPerBlock for gossip validation when set.',
|
|
221
|
-
parseEnv: (val: string) =>
|
|
228
|
+
parseEnv: (val: string) => parseInt(val, 10),
|
|
222
229
|
},
|
|
223
230
|
validateMaxTxsPerCheckpoint: {
|
|
224
231
|
env: 'VALIDATOR_MAX_TX_PER_CHECKPOINT',
|
|
225
232
|
description:
|
|
226
233
|
'Maximum transactions per checkpoint for validation. Used as fallback for maxTxsPerBlock when that is not set.',
|
|
227
|
-
parseEnv: (val: string) =>
|
|
234
|
+
parseEnv: (val: string) => parseInt(val, 10),
|
|
228
235
|
},
|
|
229
236
|
validateMaxL2BlockGas: {
|
|
230
237
|
env: 'VALIDATOR_MAX_L2_BLOCK_GAS',
|
|
231
238
|
description: 'Maximum L2 gas per block for validation. When set, txs exceeding this limit are rejected.',
|
|
232
|
-
parseEnv: (val: string) =>
|
|
239
|
+
parseEnv: (val: string) => parseInt(val, 10),
|
|
233
240
|
},
|
|
234
241
|
validateMaxDABlockGas: {
|
|
235
242
|
env: 'VALIDATOR_MAX_DA_BLOCK_GAS',
|
|
236
243
|
description: 'Maximum DA gas per block for validation. When set, txs exceeding this limit are rejected.',
|
|
237
|
-
parseEnv: (val: string) =>
|
|
244
|
+
parseEnv: (val: string) => parseInt(val, 10),
|
|
238
245
|
},
|
|
239
246
|
p2pEnabled: {
|
|
240
247
|
env: 'P2P_ENABLED',
|
|
@@ -364,7 +371,7 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
|
364
371
|
gossipsubMcacheLength: {
|
|
365
372
|
env: 'P2P_GOSSIPSUB_MCACHE_LENGTH',
|
|
366
373
|
description: 'The number of gossipsub interval message cache windows to keep.',
|
|
367
|
-
...numberConfigHelper(
|
|
374
|
+
...numberConfigHelper(12),
|
|
368
375
|
},
|
|
369
376
|
gossipsubMcacheGossip: {
|
|
370
377
|
env: 'P2P_GOSSIPSUB_MCACHE_GOSSIP',
|
|
@@ -436,7 +443,7 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
|
436
443
|
},
|
|
437
444
|
p2pStoreMapSizeKb: {
|
|
438
445
|
env: 'P2P_STORE_MAP_SIZE_KB',
|
|
439
|
-
parseEnv: (val: string
|
|
446
|
+
parseEnv: (val: string) => +val,
|
|
440
447
|
description: 'The maximum possible size of the P2P DB in KB. Overwrites the general dataStoreMapSizeKb.',
|
|
441
448
|
},
|
|
442
449
|
txPublicSetupAllowListExtend: {
|
|
@@ -495,6 +502,11 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
|
495
502
|
description: 'Alters the format of p2p messages to include things like broadcast timestamp FOR TESTING ONLY',
|
|
496
503
|
...booleanConfigHelper(false),
|
|
497
504
|
},
|
|
505
|
+
l1PublishingTime: {
|
|
506
|
+
env: 'SEQ_L1_PUBLISHING_TIME_ALLOWANCE_IN_SLOT',
|
|
507
|
+
description: 'How much time (in seconds) we allow in the slot for publishing the L1 tx (defaults to 1 L1 slot).',
|
|
508
|
+
parseEnv: (val: string) => parseInt(val, 10),
|
|
509
|
+
},
|
|
498
510
|
fishermanMode: {
|
|
499
511
|
env: 'FISHERMAN_MODE',
|
|
500
512
|
description:
|
|
@@ -154,14 +154,16 @@ export class AttestationPool {
|
|
|
154
154
|
/** Maximum indexWithinCheckpoint value (2^10 - 1 = 1023). */
|
|
155
155
|
private static readonly MAX_INDEX = (1 << AttestationPool.INDEX_BITS) - 1;
|
|
156
156
|
|
|
157
|
-
/** Creates a position key for block proposals:
|
|
157
|
+
/** Creates a position key for block proposals: slot * 1024 + indexWithinCheckpoint.
|
|
158
|
+
* Uses multiplication instead of bit-shift to avoid 32-bit signed integer overflow
|
|
159
|
+
* (bit-shift overflows after slot ~2^21, roughly 278 days of uptime). */
|
|
158
160
|
private getBlockPositionKey(slot: number, indexWithinCheckpoint: number): number {
|
|
159
161
|
if (indexWithinCheckpoint > AttestationPool.MAX_INDEX) {
|
|
160
162
|
throw new Error(
|
|
161
163
|
`Value for indexWithinCheckpoint ${indexWithinCheckpoint} exceeds maximum ${AttestationPool.MAX_INDEX}`,
|
|
162
164
|
);
|
|
163
165
|
}
|
|
164
|
-
return
|
|
166
|
+
return slot * (1 << AttestationPool.INDEX_BITS) + indexWithinCheckpoint;
|
|
165
167
|
}
|
|
166
168
|
|
|
167
169
|
/**
|
|
@@ -454,7 +456,7 @@ export class AttestationPool {
|
|
|
454
456
|
|
|
455
457
|
// Delete block proposals for slots < oldestSlot, using blockProposalsForSlotAndIndex as index
|
|
456
458
|
// Key format: (slot << INDEX_BITS) | indexWithinCheckpoint
|
|
457
|
-
const blockPositionEndKey = oldestSlot << AttestationPool.INDEX_BITS;
|
|
459
|
+
const blockPositionEndKey = oldestSlot * (1 << AttestationPool.INDEX_BITS);
|
|
458
460
|
for await (const positionKey of this.blockProposalsForSlotAndIndex.keysAsync({ end: blockPositionEndKey })) {
|
|
459
461
|
const proposalIds = await toArray(this.blockProposalsForSlotAndIndex.getValuesAsync(positionKey));
|
|
460
462
|
for (const proposalId of proposalIds) {
|
|
@@ -21,6 +21,7 @@ export { FeePayerBalancePreAddRule } from './fee_payer_balance_pre_add_rule.js';
|
|
|
21
21
|
export { LowPriorityPreAddRule } from './low_priority_pre_add_rule.js';
|
|
22
22
|
|
|
23
23
|
// Post-event eviction rules
|
|
24
|
+
export { InsufficientFeePerGasEvictionRule } from './insufficient_fee_per_gas_eviction_rule.js';
|
|
24
25
|
export { InvalidTxsAfterMiningRule } from './invalid_txs_after_mining_rule.js';
|
|
25
26
|
export { InvalidTxsAfterReorgRule } from './invalid_txs_after_reorg_rule.js';
|
|
26
27
|
export { FeePayerBalanceEvictionRule } from './fee_payer_balance_eviction_rule.js';
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import type { BlockMinFeesProvider } from '@aztec/stdlib/gas';
|
|
3
|
+
|
|
4
|
+
import type { EvictionContext, EvictionResult, EvictionRule, PoolOperations } from './interfaces.js';
|
|
5
|
+
import { EvictionEvent } from './interfaces.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Eviction rule that removes transactions whose maxFeesPerGas no longer meets
|
|
9
|
+
* the projected minimum gas fees after a new block is mined.
|
|
10
|
+
* Uses the BlockMinFeesProvider (forward-looking) to get the projected minimum fees.
|
|
11
|
+
* Only triggers on BLOCK_MINED events.
|
|
12
|
+
*/
|
|
13
|
+
export class InsufficientFeePerGasEvictionRule implements EvictionRule {
|
|
14
|
+
public readonly name = 'InsufficientFeePerGas';
|
|
15
|
+
|
|
16
|
+
private log = createLogger('p2p:tx_pool_v2:insufficient_fee_per_gas_eviction_rule');
|
|
17
|
+
|
|
18
|
+
constructor(private blockMinFeesProvider: BlockMinFeesProvider) {}
|
|
19
|
+
|
|
20
|
+
async evict(context: EvictionContext, pool: PoolOperations): Promise<EvictionResult> {
|
|
21
|
+
if (context.event !== EvictionEvent.BLOCK_MINED) {
|
|
22
|
+
return {
|
|
23
|
+
reason: 'insufficient_fee_per_gas',
|
|
24
|
+
success: true,
|
|
25
|
+
txsEvicted: [],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const gasFees = await this.blockMinFeesProvider.getCurrentMinFees();
|
|
31
|
+
const txsToEvict: string[] = [];
|
|
32
|
+
const pendingTxs = pool.getPendingTxs();
|
|
33
|
+
|
|
34
|
+
for (const meta of pendingTxs) {
|
|
35
|
+
const maxFeesPerGas = meta.data.constants.txContext.gasSettings.maxFeesPerGas;
|
|
36
|
+
if (maxFeesPerGas.feePerDaGas < gasFees.feePerDaGas || maxFeesPerGas.feePerL2Gas < gasFees.feePerL2Gas) {
|
|
37
|
+
this.log.verbose(`Evicting tx ${meta.txHash} from pool due to insufficient fee per gas`, {
|
|
38
|
+
txMaxFeesPerGas: maxFeesPerGas.toInspect(),
|
|
39
|
+
blockGasFees: gasFees.toInspect(),
|
|
40
|
+
});
|
|
41
|
+
txsToEvict.push(meta.txHash);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (txsToEvict.length > 0) {
|
|
46
|
+
this.log.info(`Evicted ${txsToEvict.length} txs with insufficient fee per gas after block mined`);
|
|
47
|
+
await pool.deleteTxs(txsToEvict, this.name);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
reason: 'insufficient_fee_per_gas',
|
|
52
|
+
success: true,
|
|
53
|
+
txsEvicted: txsToEvict,
|
|
54
|
+
};
|
|
55
|
+
} catch (err) {
|
|
56
|
+
this.log.error('Failed to evict transactions with insufficient fee per gas', { err });
|
|
57
|
+
return {
|
|
58
|
+
reason: 'insufficient_fee_per_gas',
|
|
59
|
+
success: false,
|
|
60
|
+
txsEvicted: [],
|
|
61
|
+
error: new Error('Failed to evict txs with insufficient fee per gas', { cause: err }),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import { BlockHash } from '@aztec/stdlib/block';
|
|
3
3
|
import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
4
4
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
5
5
|
|
|
@@ -33,14 +33,14 @@ export class InvalidTxsAfterReorgRule implements EvictionRule {
|
|
|
33
33
|
const pendingTxs = pool.getPendingTxs();
|
|
34
34
|
|
|
35
35
|
// Deduplicate block hashes to reduce redundant DB lookups
|
|
36
|
-
const uniqueBlockHashes = new Map<string,
|
|
36
|
+
const uniqueBlockHashes = new Map<string, BlockHash>();
|
|
37
37
|
const txsByBlockHash = new Map<string, string[]>();
|
|
38
38
|
|
|
39
39
|
for (const meta of pendingTxs) {
|
|
40
40
|
const blockHashStr = meta.anchorBlockHeaderHash;
|
|
41
41
|
if (!txsByBlockHash.has(blockHashStr)) {
|
|
42
42
|
txsByBlockHash.set(blockHashStr, []);
|
|
43
|
-
uniqueBlockHashes.set(blockHashStr,
|
|
43
|
+
uniqueBlockHashes.set(blockHashStr, BlockHash.fromString(blockHashStr));
|
|
44
44
|
}
|
|
45
45
|
txsByBlockHash.get(blockHashStr)!.push(meta.txHash);
|
|
46
46
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import type { TypedEventEmitter } from '@aztec/foundation/types';
|
|
3
3
|
import type { L2Block, L2BlockId, L2BlockSource } from '@aztec/stdlib/block';
|
|
4
|
+
import type { BlockMinFeesProvider } from '@aztec/stdlib/gas';
|
|
4
5
|
import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
5
6
|
import type { BlockHeader, Tx, TxHash, TxValidator } from '@aztec/stdlib/tx';
|
|
6
7
|
|
|
@@ -74,6 +75,8 @@ export type TxPoolV2Dependencies = {
|
|
|
74
75
|
createTxValidator: () => Promise<TxValidator<TxMetaData>>;
|
|
75
76
|
/** Checks whether a tx's setup-phase calls are on the allow list. Precomputed at receipt time. */
|
|
76
77
|
checkAllowedSetupCalls: (tx: Tx) => Promise<boolean>;
|
|
78
|
+
/** Provides projected minimum fees for the next block. Used by eviction rules instead of stale block header fees. */
|
|
79
|
+
blockMinFeesProvider: BlockMinFeesProvider;
|
|
77
80
|
};
|
|
78
81
|
|
|
79
82
|
/**
|
|
@@ -3,7 +3,7 @@ import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
|
3
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
4
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
5
5
|
import { BlockHash, type L2BlockId } from '@aztec/stdlib/block';
|
|
6
|
-
import { Gas } from '@aztec/stdlib/gas';
|
|
6
|
+
import { Gas, GasFees } from '@aztec/stdlib/gas';
|
|
7
7
|
import { type Tx, TxHash } from '@aztec/stdlib/tx';
|
|
8
8
|
|
|
9
9
|
import { getFeePayerBalanceDelta } from '../../msg_validators/tx_validator/fee_payer_balance.js';
|
|
@@ -23,7 +23,7 @@ export type TxMetaValidationData = {
|
|
|
23
23
|
};
|
|
24
24
|
};
|
|
25
25
|
txContext: {
|
|
26
|
-
gasSettings: { gasLimits: Gas };
|
|
26
|
+
gasSettings: { gasLimits: Gas; maxFeesPerGas: GasFees };
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
29
|
};
|
|
@@ -132,7 +132,10 @@ export async function buildTxMetaData(tx: Tx, allowedSetupCalls: boolean = true)
|
|
|
132
132
|
globalVariables: { blockNumber: anchorBlockNumber },
|
|
133
133
|
},
|
|
134
134
|
txContext: {
|
|
135
|
-
gasSettings: {
|
|
135
|
+
gasSettings: {
|
|
136
|
+
gasLimits: tx.data.constants.txContext.gasSettings.gasLimits,
|
|
137
|
+
maxFeesPerGas: tx.data.constants.txContext.gasSettings.maxFeesPerGas,
|
|
138
|
+
},
|
|
136
139
|
},
|
|
137
140
|
},
|
|
138
141
|
},
|
|
@@ -285,17 +288,19 @@ export function checkNullifierConflict(
|
|
|
285
288
|
}
|
|
286
289
|
|
|
287
290
|
/** Creates a stub TxMetaValidationData for tests that don't exercise validators. */
|
|
288
|
-
export function stubTxMetaValidationData(
|
|
291
|
+
export function stubTxMetaValidationData(
|
|
292
|
+
overrides: { expirationTimestamp?: bigint; maxFeesPerGas?: GasFees } = {},
|
|
293
|
+
): TxMetaValidationData {
|
|
289
294
|
return {
|
|
290
295
|
getNonEmptyNullifiers: () => [],
|
|
291
296
|
expirationTimestamp: overrides.expirationTimestamp ?? 0n,
|
|
292
297
|
constants: {
|
|
293
298
|
anchorBlockHeader: {
|
|
294
|
-
hash: () => Promise.resolve(
|
|
299
|
+
hash: () => Promise.resolve(BlockHash.ZERO),
|
|
295
300
|
globalVariables: { blockNumber: BlockNumber(0) },
|
|
296
301
|
},
|
|
297
302
|
txContext: {
|
|
298
|
-
gasSettings: { gasLimits: Gas.empty() },
|
|
303
|
+
gasSettings: { gasLimits: Gas.empty(), maxFeesPerGas: overrides.maxFeesPerGas ?? GasFees.empty() },
|
|
299
304
|
},
|
|
300
305
|
},
|
|
301
306
|
};
|
|
@@ -313,6 +318,7 @@ export function stubTxMetaData(
|
|
|
313
318
|
expirationTimestamp?: bigint;
|
|
314
319
|
anchorBlockHeaderHash?: string;
|
|
315
320
|
allowedSetupCalls?: boolean;
|
|
321
|
+
maxFeesPerGas?: GasFees;
|
|
316
322
|
} = {},
|
|
317
323
|
): TxMetaData {
|
|
318
324
|
const txHashBigInt = Fr.fromHexString(txHash).toBigInt();
|
|
@@ -332,7 +338,7 @@ export function stubTxMetaData(
|
|
|
332
338
|
allowedSetupCalls: overrides.allowedSetupCalls ?? true,
|
|
333
339
|
receivedAt: 0,
|
|
334
340
|
estimatedSizeBytes: 0,
|
|
335
|
-
data: stubTxMetaValidationData({ expirationTimestamp }),
|
|
341
|
+
data: stubTxMetaValidationData({ expirationTimestamp, maxFeesPerGas: overrides.maxFeesPerGas }),
|
|
336
342
|
};
|
|
337
343
|
}
|
|
338
344
|
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
EvictionManager,
|
|
18
18
|
FeePayerBalanceEvictionRule,
|
|
19
19
|
FeePayerBalancePreAddRule,
|
|
20
|
+
InsufficientFeePerGasEvictionRule,
|
|
20
21
|
InvalidTxsAfterMiningRule,
|
|
21
22
|
InvalidTxsAfterReorgRule,
|
|
22
23
|
LowPriorityEvictionRule,
|
|
@@ -116,6 +117,7 @@ export class TxPoolV2Impl {
|
|
|
116
117
|
|
|
117
118
|
// Post-event eviction rules (run after events to check ALL pending txs)
|
|
118
119
|
this.#evictionManager.registerRule(new InvalidTxsAfterMiningRule());
|
|
120
|
+
this.#evictionManager.registerRule(new InsufficientFeePerGasEvictionRule(deps.blockMinFeesProvider));
|
|
119
121
|
this.#evictionManager.registerRule(new InvalidTxsAfterReorgRule(deps.worldStateSynchronizer));
|
|
120
122
|
this.#evictionManager.registerRule(new FeePayerBalanceEvictionRule(deps.worldStateSynchronizer));
|
|
121
123
|
// LowPriorityEvictionRule handles cases where txs become pending via prepareForSlot (unprotect)
|
|
@@ -8,14 +8,21 @@ import {
|
|
|
8
8
|
type ValidationResult,
|
|
9
9
|
} from '@aztec/stdlib/p2p';
|
|
10
10
|
|
|
11
|
-
import { isWithinClockTolerance } from '../clock_tolerance.js';
|
|
11
|
+
import { PipeliningWindow, isWithinClockTolerance } from '../clock_tolerance.js';
|
|
12
12
|
|
|
13
13
|
export class CheckpointAttestationValidator implements P2PValidator<CheckpointAttestation> {
|
|
14
14
|
protected epochCache: EpochCacheInterface;
|
|
15
15
|
protected logger: Logger;
|
|
16
|
+
private readonly pipeliningWindow: PipeliningWindow;
|
|
16
17
|
|
|
17
|
-
constructor(
|
|
18
|
+
constructor(
|
|
19
|
+
epochCache: EpochCacheInterface,
|
|
20
|
+
opts: {
|
|
21
|
+
l1PublishingTime?: number;
|
|
22
|
+
},
|
|
23
|
+
) {
|
|
18
24
|
this.epochCache = epochCache;
|
|
25
|
+
this.pipeliningWindow = new PipeliningWindow(epochCache, { l1PublishingTime: opts.l1PublishingTime });
|
|
19
26
|
this.logger = createLogger('p2p:checkpoint-attestation-validator');
|
|
20
27
|
}
|
|
21
28
|
|
|
@@ -23,19 +30,23 @@ export class CheckpointAttestationValidator implements P2PValidator<CheckpointAt
|
|
|
23
30
|
const slotNumber = message.payload.header.slotNumber;
|
|
24
31
|
|
|
25
32
|
try {
|
|
26
|
-
// Use target slots since proposals target pipeline slots (slot + 1 when pipelining)
|
|
33
|
+
// Use target slots since proposals target pipeline slots (slot + 1 when pipelining).
|
|
27
34
|
const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
|
|
28
35
|
|
|
29
36
|
if (slotNumber !== targetSlot && slotNumber !== nextSlot) {
|
|
30
|
-
//
|
|
31
|
-
|
|
37
|
+
// When pipelining, accept attestations for the current slot (built in the previous slot)
|
|
38
|
+
// until the target slot reaches its L1 publish cutoff.
|
|
39
|
+
if (this.pipeliningWindow.acceptsAttestation(slotNumber)) {
|
|
40
|
+
// Fall through to remaining validation (signature, committee, etc.)
|
|
41
|
+
} else if (!isWithinClockTolerance(slotNumber, targetSlot, this.epochCache)) {
|
|
32
42
|
this.logger.warn(
|
|
33
43
|
`Checkpoint attestation slot ${slotNumber} is not current (${targetSlot}) or next (${nextSlot}) slot`,
|
|
34
44
|
);
|
|
35
45
|
return { result: 'reject', severity: PeerErrorSeverity.HighToleranceError };
|
|
46
|
+
} else {
|
|
47
|
+
this.logger.debug(`Ignoring checkpoint attestation for previous slot ${slotNumber} within clock tolerance`);
|
|
48
|
+
return { result: 'ignore' };
|
|
36
49
|
}
|
|
37
|
-
this.logger.debug(`Ignoring checkpoint attestation for previous slot ${slotNumber} within clock tolerance`);
|
|
38
|
-
return { result: 'ignore' };
|
|
39
50
|
}
|
|
40
51
|
|
|
41
52
|
// Verify the signature is valid
|
|
@@ -20,8 +20,11 @@ export class FishermanAttestationValidator extends CheckpointAttestationValidato
|
|
|
20
20
|
epochCache: EpochCacheInterface,
|
|
21
21
|
private attestationPool: AttestationPoolApi,
|
|
22
22
|
telemetryClient: TelemetryClient,
|
|
23
|
+
opts: {
|
|
24
|
+
l1PublishingTime?: number;
|
|
25
|
+
} = {},
|
|
23
26
|
) {
|
|
24
|
-
super(epochCache);
|
|
27
|
+
super(epochCache, opts);
|
|
25
28
|
this.logger = this.logger.createChild('[FISHERMAN]');
|
|
26
29
|
|
|
27
30
|
const meter = telemetryClient.getMeter('FishermanAttestationValidator');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
2
|
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { DEFAULT_P2P_PROPAGATION_TIME, createPipelinedCheckpointTimingModel } from '@aztec/stdlib/timetable';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Maximum clock disparity tolerance for P2P message validation (in milliseconds).
|
|
@@ -50,3 +51,70 @@ export function isWithinClockTolerance(
|
|
|
50
51
|
|
|
51
52
|
return elapsedMs < MAXIMUM_GOSSIP_CLOCK_DISPARITY_MS;
|
|
52
53
|
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Checks if a message should be accepted under the pipelining grace period.
|
|
57
|
+
*
|
|
58
|
+
* When pipelining is enabled, `targetSlot = slotNow + 1`. A proposal built in slot N-1
|
|
59
|
+
* for slot N arrives when validators are in slot N, so their `targetSlot = N+1`.
|
|
60
|
+
* This function accepts proposals for the current wallclock slot if we're within the
|
|
61
|
+
* first `windowSeconds` seconds of the slot (the pipelining grace period). - see stdlib/timetable/index.ts
|
|
62
|
+
*
|
|
63
|
+
* @param messageSlot - The slot number from the received message
|
|
64
|
+
* @param epochCache - EpochCache to get timing and pipelining state
|
|
65
|
+
* @param windowSeconds - The window grace period allowed for attestations into the next slot
|
|
66
|
+
* @returns true if pipelining is enabled, the message is for the current slot, and we're within the grace period
|
|
67
|
+
*/
|
|
68
|
+
function isWithinPipeliningWindow(
|
|
69
|
+
messageSlot: SlotNumber,
|
|
70
|
+
epochCache: EpochCacheInterface,
|
|
71
|
+
windowSeconds: number,
|
|
72
|
+
): boolean {
|
|
73
|
+
if (!epochCache.isProposerPipeliningEnabled()) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const currentSlot = epochCache.getSlotNow();
|
|
78
|
+
if (messageSlot !== currentSlot) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const { ts: slotStartTs, nowMs } = epochCache.getEpochAndSlotNow();
|
|
83
|
+
const slotStartMs = slotStartTs * 1000n;
|
|
84
|
+
const elapsedMs = Number(nowMs - slotStartMs);
|
|
85
|
+
const windowMs = windowSeconds * 1000 + MAXIMUM_GOSSIP_CLOCK_DISPARITY_MS;
|
|
86
|
+
|
|
87
|
+
return elapsedMs < windowMs;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export class PipeliningWindow {
|
|
91
|
+
private readonly proposalWindowIntoTargetSlot: number;
|
|
92
|
+
private readonly attestationWindowIntoTargetSlot: number;
|
|
93
|
+
|
|
94
|
+
constructor(
|
|
95
|
+
private readonly epochCache: EpochCacheInterface,
|
|
96
|
+
opts: {
|
|
97
|
+
p2pPropagationTime?: number;
|
|
98
|
+
l1PublishingTime?: number;
|
|
99
|
+
} = {},
|
|
100
|
+
) {
|
|
101
|
+
const l1Constants = epochCache.getL1Constants();
|
|
102
|
+
const checkpointTiming = createPipelinedCheckpointTimingModel({
|
|
103
|
+
aztecSlotDuration: l1Constants.slotDuration,
|
|
104
|
+
ethereumSlotDuration: l1Constants.ethereumSlotDuration,
|
|
105
|
+
l1PublishingTime: opts.l1PublishingTime ?? l1Constants.ethereumSlotDuration,
|
|
106
|
+
p2pPropagationTime: opts.p2pPropagationTime ?? DEFAULT_P2P_PROPAGATION_TIME,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
this.proposalWindowIntoTargetSlot = checkpointTiming.proposalWindowIntoTargetSlot;
|
|
110
|
+
this.attestationWindowIntoTargetSlot = checkpointTiming.attestationWindowIntoTargetSlot;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public acceptsProposal(messageSlot: SlotNumber): boolean {
|
|
114
|
+
return isWithinPipeliningWindow(messageSlot, this.epochCache, this.proposalWindowIntoTargetSlot);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public acceptsAttestation(messageSlot: SlotNumber): boolean {
|
|
118
|
+
return isWithinPipeliningWindow(messageSlot, this.epochCache, this.attestationWindowIntoTargetSlot);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -6,7 +6,10 @@ import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
|
|
|
6
6
|
export class BlockProposalValidator implements P2PValidator<BlockProposal> {
|
|
7
7
|
private proposalValidator: ProposalValidator;
|
|
8
8
|
|
|
9
|
-
constructor(
|
|
9
|
+
constructor(
|
|
10
|
+
epochCache: EpochCacheInterface,
|
|
11
|
+
opts: { txsPermitted: boolean; maxTxsPerBlock?: number; p2pPropagationTime?: number },
|
|
12
|
+
) {
|
|
10
13
|
this.proposalValidator = new ProposalValidator(epochCache, opts, 'p2p:block_proposal_validator');
|
|
11
14
|
}
|
|
12
15
|
|
|
@@ -6,7 +6,10 @@ import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
|
|
|
6
6
|
export class CheckpointProposalValidator implements P2PValidator<CheckpointProposal> {
|
|
7
7
|
private proposalValidator: ProposalValidator;
|
|
8
8
|
|
|
9
|
-
constructor(
|
|
9
|
+
constructor(
|
|
10
|
+
epochCache: EpochCacheInterface,
|
|
11
|
+
opts: { txsPermitted: boolean; maxTxsPerBlock?: number; p2pPropagationTime?: number },
|
|
12
|
+
) {
|
|
10
13
|
this.proposalValidator = new ProposalValidator(epochCache, opts, 'p2p:checkpoint_proposal_validator');
|
|
11
14
|
}
|
|
12
15
|
|