@aztec/p2p 0.0.1-commit.35158ae7e → 0.0.1-commit.3750d92a7
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 +1 -1
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +6 -5
- package/dest/client/interface.d.ts +9 -2
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +3 -2
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +30 -10
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +14 -3
- package/dest/config.d.ts +103 -99
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +10 -5
- package/dest/errors/p2p-service.error.d.ts +9 -0
- package/dest/errors/p2p-service.error.d.ts.map +1 -0
- package/dest/errors/p2p-service.error.js +10 -0
- package/dest/index.d.ts +1 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +0 -1
- 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 +8 -5
- package/dest/mem_pools/index.d.ts +1 -2
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +6 -2
- 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/gas_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +11 -9
- 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/discv5/discV5_service.d.ts +1 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +2 -4
- package/dest/services/dummy_service.d.ts +6 -3
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +6 -1
- 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/libp2p_service.d.ts +12 -20
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +42 -97
- package/dest/services/peer-manager/peer_manager.d.ts +6 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +33 -8
- package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +32 -10
- 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_limiter.d.ts +5 -4
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
- 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/services/service.d.ts +5 -8
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +39 -29
- package/dest/services/tx_collection/tx_source.d.ts +6 -5
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +9 -7
- package/dest/test-helpers/mock-pubsub.d.ts +11 -8
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +36 -19
- 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 +1 -2
- 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.js +63 -12
- 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 -1
- package/dest/util.d.ts +3 -8
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +9 -2
- package/package.json +14 -14
- package/src/client/factory.ts +8 -3
- package/src/client/interface.ts +9 -1
- package/src/client/p2p_client.ts +34 -11
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +15 -3
- package/src/config.ts +18 -6
- package/src/errors/p2p-service.error.ts +11 -0
- package/src/index.ts +0 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +9 -5
- package/src/mem_pools/index.ts +0 -3
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +8 -2
- 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/README.md +1 -1
- 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/archive_cache.ts +1 -1
- package/src/msg_validators/tx_validator/gas_validator.ts +25 -9
- package/src/services/data_store.ts +5 -13
- package/src/services/discv5/discV5_service.ts +2 -4
- package/src/services/dummy_service.ts +8 -2
- package/src/services/gossipsub/topic_score_params.ts +36 -4
- package/src/services/libp2p/libp2p_service.ts +47 -106
- package/src/services/peer-manager/peer_manager.ts +38 -8
- package/src/services/peer-manager/peer_scoring.ts +27 -5
- 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_limiter.ts +13 -9
- package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
- package/src/services/reqresp/reqresp.ts +18 -1
- package/src/services/service.ts +6 -8
- package/src/services/tx_collection/file_store_tx_source.ts +43 -31
- package/src/services/tx_collection/tx_source.ts +8 -7
- package/src/test-helpers/mock-pubsub.ts +31 -14
- package/src/test-helpers/reqresp-nodes.ts +2 -2
- package/src/test-helpers/testbench-utils.ts +1 -0
- package/src/testbench/p2p_client_testbench_worker.ts +67 -9
- package/src/testbench/worker_client_manager.ts +55 -1
- package/src/util.ts +12 -8
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -123
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
- package/dest/mem_pools/tx_pool/index.d.ts +0 -3
- package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/index.js +0 -2
- package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
- package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/priority.js +0 -15
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -402
- 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/mem_pools/tx_pool/README.md +0 -270
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -163
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
- package/src/mem_pools/tx_pool/index.ts +0 -2
- package/src/mem_pools/tx_pool/priority.ts +0 -20
- package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -321
- package/src/services/reqresp/protocols/block.ts +0 -37
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TopicType, createTopicString } from '@aztec/stdlib/p2p';
|
|
2
|
-
import {
|
|
2
|
+
import { createCheckpointTimingModel } from '@aztec/stdlib/timetable';
|
|
3
3
|
|
|
4
4
|
import { createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
5
5
|
|
|
@@ -9,12 +9,18 @@ import { createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
|
9
9
|
export type TopicScoringNetworkParams = {
|
|
10
10
|
/** L2 slot duration in milliseconds */
|
|
11
11
|
slotDurationMs: number;
|
|
12
|
+
/** L1 slot duration in seconds */
|
|
13
|
+
ethereumSlotDuration: number;
|
|
12
14
|
/** Gossipsub heartbeat interval in milliseconds */
|
|
13
15
|
heartbeatIntervalMs: number;
|
|
14
16
|
/** Target committee size (number of validators expected to attest per slot) */
|
|
15
17
|
targetCommitteeSize: number;
|
|
16
18
|
/** Duration per block in milliseconds when building multiple blocks per slot. If undefined, single block mode. */
|
|
17
19
|
blockDurationMs?: number;
|
|
20
|
+
/** Time budget in seconds reserved for L1 publishing. Defaults to ethereumSlotDuration. */
|
|
21
|
+
l1PublishingTime?: number;
|
|
22
|
+
/** One-way proposal/attestation propagation budget in seconds. */
|
|
23
|
+
p2pPropagationTime?: number;
|
|
18
24
|
/** Expected number of block proposals per slot for scoring override. 0 disables scoring, undefined falls back to blocksPerSlot - 1. */
|
|
19
25
|
expectedBlockProposalsPerSlot?: number;
|
|
20
26
|
};
|
|
@@ -25,10 +31,32 @@ export type TopicScoringNetworkParams = {
|
|
|
25
31
|
*
|
|
26
32
|
* @param slotDurationMs - L2 slot duration in milliseconds
|
|
27
33
|
* @param blockDurationMs - Duration per block in milliseconds (undefined = single block mode)
|
|
34
|
+
* @param opts - Shared checkpoint timing inputs used by the sequencer and validators
|
|
28
35
|
* @returns Number of blocks per slot
|
|
29
36
|
*/
|
|
30
|
-
export function calculateBlocksPerSlot(
|
|
31
|
-
|
|
37
|
+
export function calculateBlocksPerSlot(
|
|
38
|
+
slotDurationMs: number,
|
|
39
|
+
blockDurationMs: number | undefined,
|
|
40
|
+
opts?: {
|
|
41
|
+
ethereumSlotDuration: number;
|
|
42
|
+
l1PublishingTime?: number;
|
|
43
|
+
p2pPropagationTime?: number;
|
|
44
|
+
},
|
|
45
|
+
): number {
|
|
46
|
+
if (!opts) {
|
|
47
|
+
return createCheckpointTimingModel({
|
|
48
|
+
aztecSlotDuration: slotDurationMs / 1000,
|
|
49
|
+
blockDuration: blockDurationMs ? blockDurationMs / 1000 : undefined,
|
|
50
|
+
}).calculateMaxBlocksPerSlot();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return createCheckpointTimingModel({
|
|
54
|
+
aztecSlotDuration: slotDurationMs / 1000,
|
|
55
|
+
ethereumSlotDuration: opts.ethereumSlotDuration,
|
|
56
|
+
blockDuration: blockDurationMs ? blockDurationMs / 1000 : undefined,
|
|
57
|
+
l1PublishingTime: opts.l1PublishingTime ?? opts.ethereumSlotDuration,
|
|
58
|
+
p2pPropagationTime: opts.p2pPropagationTime,
|
|
59
|
+
}).calculateMaxBlocksPerSlot();
|
|
32
60
|
}
|
|
33
61
|
|
|
34
62
|
/**
|
|
@@ -279,7 +307,11 @@ export class TopicScoreParamsFactory {
|
|
|
279
307
|
const { slotDurationMs, heartbeatIntervalMs, blockDurationMs } = params;
|
|
280
308
|
|
|
281
309
|
// Compute values that are the same for all topics
|
|
282
|
-
this.blocksPerSlot = calculateBlocksPerSlot(slotDurationMs, blockDurationMs
|
|
310
|
+
this.blocksPerSlot = calculateBlocksPerSlot(slotDurationMs, blockDurationMs, {
|
|
311
|
+
ethereumSlotDuration: params.ethereumSlotDuration,
|
|
312
|
+
l1PublishingTime: params.l1PublishingTime,
|
|
313
|
+
p2pPropagationTime: params.p2pPropagationTime,
|
|
314
|
+
});
|
|
283
315
|
this.heartbeatsPerSlot = slotDurationMs / heartbeatIntervalMs;
|
|
284
316
|
this.invalidDecay = computeDecay(heartbeatIntervalMs, slotDurationMs, INVALID_DECAY_WINDOW_SLOTS);
|
|
285
317
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
2
|
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { maxBy } from '@aztec/foundation/collection';
|
|
4
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
4
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
6
5
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
7
6
|
import { Timer } from '@aztec/foundation/timer';
|
|
8
7
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
9
8
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
10
|
-
import type { EthAddress,
|
|
9
|
+
import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
|
|
11
10
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
12
11
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
13
12
|
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
@@ -51,14 +50,14 @@ import { yamux } from '@chainsafe/libp2p-yamux';
|
|
|
51
50
|
import { bootstrap } from '@libp2p/bootstrap';
|
|
52
51
|
import { identify } from '@libp2p/identify';
|
|
53
52
|
import { type Message, type MultiaddrConnection, type PeerId, TopicValidatorResult } from '@libp2p/interface';
|
|
54
|
-
import type {
|
|
53
|
+
import type { ConnectionManager } from '@libp2p/interface-internal';
|
|
55
54
|
import { mplex } from '@libp2p/mplex';
|
|
56
55
|
import { tcp } from '@libp2p/tcp';
|
|
57
|
-
import { multiaddr } from '@multiformats/multiaddr';
|
|
58
56
|
import { ENR } from '@nethermindeth/enr';
|
|
59
57
|
import { createLibp2p } from 'libp2p';
|
|
60
58
|
|
|
61
59
|
import type { P2PConfig } from '../../config.js';
|
|
60
|
+
import { CheckpointProposalReceivedCallbackNotRegisteredError } from '../../errors/p2p-service.error.js';
|
|
62
61
|
import type { MemPools } from '../../mem_pools/interface.js';
|
|
63
62
|
import {
|
|
64
63
|
BlockProposalValidator,
|
|
@@ -105,7 +104,6 @@ import {
|
|
|
105
104
|
ValidationError,
|
|
106
105
|
pingHandler,
|
|
107
106
|
reqGoodbyeHandler,
|
|
108
|
-
reqRespBlockHandler,
|
|
109
107
|
reqRespBlockTxsHandler,
|
|
110
108
|
reqRespStatusHandler,
|
|
111
109
|
reqRespTxHandler,
|
|
@@ -172,13 +170,15 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
172
170
|
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
173
171
|
* @returns The attestations for the checkpoint, if any.
|
|
174
172
|
*/
|
|
175
|
-
private
|
|
173
|
+
private allNodesCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
174
|
+
/**
|
|
175
|
+
* Callback for when a checkpoint proposal is received - specifically for validators - from a peer.
|
|
176
|
+
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
177
|
+
* @returns The attestations for the checkpoint, if any.
|
|
178
|
+
*/
|
|
179
|
+
private validatorCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
176
180
|
|
|
177
181
|
private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
|
|
178
|
-
private ipChangedHandler?: (ip: string) => void;
|
|
179
|
-
|
|
180
|
-
/** Discovered public IP address (set when queryForIp is enabled and no static IP was configured). */
|
|
181
|
-
private discoveredP2pIp?: string;
|
|
182
182
|
|
|
183
183
|
private instrumentation: P2PInstrumentation;
|
|
184
184
|
|
|
@@ -228,15 +228,19 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
228
228
|
this.protocolVersion,
|
|
229
229
|
);
|
|
230
230
|
|
|
231
|
+
const p2pPropagationTime = config.attestationPropagationTime;
|
|
231
232
|
const proposalValidatorOpts = {
|
|
232
233
|
txsPermitted: !config.disableTransactions,
|
|
233
234
|
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
235
|
+
p2pPropagationTime,
|
|
234
236
|
};
|
|
235
237
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
|
|
236
238
|
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
237
239
|
this.checkpointAttestationValidator = config.fishermanMode
|
|
238
|
-
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry
|
|
239
|
-
|
|
240
|
+
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry, {
|
|
241
|
+
l1PublishingTime: config.l1PublishingTime,
|
|
242
|
+
})
|
|
243
|
+
: new CheckpointAttestationValidator(epochCache, { l1PublishingTime: config.l1PublishingTime });
|
|
240
244
|
|
|
241
245
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
242
246
|
|
|
@@ -248,12 +252,15 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
248
252
|
return true;
|
|
249
253
|
};
|
|
250
254
|
|
|
251
|
-
this.
|
|
252
|
-
|
|
255
|
+
this.allNodesCheckpointReceivedCallback = (
|
|
256
|
+
_checkpoint: CheckpointProposalCore,
|
|
257
|
+
): Promise<CheckpointAttestation[] | undefined> => {
|
|
258
|
+
throw new CheckpointProposalReceivedCallbackNotRegisteredError();
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
this.validatorCheckpointReceivedCallback = (
|
|
262
|
+
_checkpoint: CheckpointProposalCore,
|
|
253
263
|
): Promise<CheckpointAttestation[] | undefined> => {
|
|
254
|
-
this.logger.debug(
|
|
255
|
-
`Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
|
|
256
|
-
);
|
|
257
264
|
return Promise.resolve(undefined);
|
|
258
265
|
};
|
|
259
266
|
}
|
|
@@ -343,9 +350,12 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
343
350
|
const l1Constants = epochCache.getL1Constants();
|
|
344
351
|
const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
|
|
345
352
|
slotDurationMs: l1Constants.slotDuration * 1000,
|
|
353
|
+
ethereumSlotDuration: l1Constants.ethereumSlotDuration,
|
|
346
354
|
heartbeatIntervalMs: config.gossipsubInterval,
|
|
347
355
|
targetCommitteeSize: l1Constants.targetCommitteeSize,
|
|
348
356
|
blockDurationMs: config.blockDurationMs,
|
|
357
|
+
l1PublishingTime: config.l1PublishingTime,
|
|
358
|
+
p2pPropagationTime: config.attestationPropagationTime,
|
|
349
359
|
expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
|
|
350
360
|
});
|
|
351
361
|
|
|
@@ -447,9 +457,8 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
447
457
|
topics: topicScoreParams,
|
|
448
458
|
}),
|
|
449
459
|
}) as (components: GossipSubComponents) => GossipSub,
|
|
450
|
-
components: (components: { connectionManager: ConnectionManager
|
|
460
|
+
components: (components: { connectionManager: ConnectionManager }) => ({
|
|
451
461
|
connectionManager: components.connectionManager,
|
|
452
|
-
addressManager: components.addressManager,
|
|
453
462
|
}),
|
|
454
463
|
},
|
|
455
464
|
logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
|
|
@@ -471,6 +480,9 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
471
480
|
epochCache,
|
|
472
481
|
);
|
|
473
482
|
|
|
483
|
+
// Gate req/resp data protocols for unauthenticated peers when p2pAllowOnlyValidators is enabled
|
|
484
|
+
reqresp.setShouldRejectPeer(peerId => peerManager.shouldDisableP2PGossip(peerId));
|
|
485
|
+
|
|
474
486
|
// Configure application-specific scoring for gossipsub.
|
|
475
487
|
// The weight scales app score to align with gossipsub thresholds:
|
|
476
488
|
// - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
|
|
@@ -508,22 +520,20 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
508
520
|
|
|
509
521
|
// Get listen & announce addresses for logging
|
|
510
522
|
const { p2pIp, p2pPort } = this.config;
|
|
511
|
-
if (!p2pIp
|
|
523
|
+
if (!p2pIp) {
|
|
512
524
|
throw new Error('Announce address not provided.');
|
|
513
525
|
}
|
|
514
|
-
const announceTcpMultiaddr =
|
|
526
|
+
const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
|
|
515
527
|
|
|
516
528
|
// Create request response protocol handlers
|
|
517
529
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
518
530
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
519
|
-
const blockHandler = reqRespBlockHandler(this.archiver);
|
|
520
531
|
const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
|
|
521
532
|
|
|
522
533
|
const requestResponseHandlers: Partial<ReqRespSubProtocolHandlers> = {
|
|
523
534
|
[ReqRespSubProtocol.PING]: pingHandler,
|
|
524
535
|
[ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
|
|
525
536
|
[ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
|
|
526
|
-
[ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
|
|
527
537
|
};
|
|
528
538
|
|
|
529
539
|
if (!this.config.disableTransactions) {
|
|
@@ -544,7 +554,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
544
554
|
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
545
555
|
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
546
556
|
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
547
|
-
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
|
|
548
557
|
};
|
|
549
558
|
|
|
550
559
|
await this.peerManager.initializePeers();
|
|
@@ -565,31 +574,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
565
574
|
if (!this.config.p2pDiscoveryDisabled) {
|
|
566
575
|
await this.peerDiscoveryService.start();
|
|
567
576
|
}
|
|
568
|
-
|
|
569
|
-
// When queryForIp is enabled and no static IP was configured, bridge discv5 IP discovery to libp2p.
|
|
570
|
-
// Discv5 discovers our public IP via peer WHOAREYOU exchanges (enrUpdate=true) and emits 'ip:changed'.
|
|
571
|
-
// We confirm the discovered address in the libp2p AddressManager so it appears in getMultiaddrs()
|
|
572
|
-
// and is pushed to all connected peers via the identify protocol.
|
|
573
|
-
if (this.config.queryForIp && !p2pIp) {
|
|
574
|
-
this.ipChangedHandler = (ip: string) => {
|
|
575
|
-
const addressManager = this.node.services.components.addressManager;
|
|
576
|
-
const newAddr = multiaddr(convertToMultiaddr(ip, this.config.p2pPort, 'tcp'));
|
|
577
|
-
|
|
578
|
-
// Remove old discovered IP if one exists
|
|
579
|
-
if (this.discoveredP2pIp) {
|
|
580
|
-
const oldAddr = multiaddr(convertToMultiaddr(this.discoveredP2pIp, this.config.p2pPort, 'tcp'));
|
|
581
|
-
addressManager.removeObservedAddr(oldAddr);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
addressManager.addObservedAddr(newAddr);
|
|
585
|
-
addressManager.confirmObservedAddr(newAddr);
|
|
586
|
-
// Store discovered IP
|
|
587
|
-
this.discoveredP2pIp = ip;
|
|
588
|
-
this.logger.info('Public IP discovered via discv5', { ip });
|
|
589
|
-
};
|
|
590
|
-
this.peerDiscoveryService.on('ip:changed', this.ipChangedHandler);
|
|
591
|
-
}
|
|
592
|
-
|
|
593
577
|
this.discoveryRunningPromise = new RunningPromise(
|
|
594
578
|
async () => {
|
|
595
579
|
await this.peerManager.heartbeat();
|
|
@@ -602,7 +586,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
602
586
|
this.logger.info(`Started P2P service`, {
|
|
603
587
|
listen: this.config.listenAddress,
|
|
604
588
|
port: this.config.p2pPort,
|
|
605
|
-
announce: announceTcpMultiaddr
|
|
589
|
+
announce: announceTcpMultiaddr,
|
|
606
590
|
peerId: this.node.peerId.toString(),
|
|
607
591
|
});
|
|
608
592
|
}
|
|
@@ -615,12 +599,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
615
599
|
// Remove gossip sub listener
|
|
616
600
|
this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
617
601
|
|
|
618
|
-
// Remove ip:changed listener if registered
|
|
619
|
-
if (this.ipChangedHandler) {
|
|
620
|
-
this.peerDiscoveryService.off('ip:changed', this.ipChangedHandler);
|
|
621
|
-
this.ipChangedHandler = undefined;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
602
|
// Stop peer manager
|
|
625
603
|
this.logger.debug('Stopping peer manager...');
|
|
626
604
|
await this.peerManager.stop();
|
|
@@ -703,8 +681,16 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
703
681
|
this.blockReceivedCallback = callback;
|
|
704
682
|
}
|
|
705
683
|
|
|
706
|
-
public
|
|
707
|
-
this.
|
|
684
|
+
public registerValidatorCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
|
|
685
|
+
this.validatorCheckpointReceivedCallback = callback;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
public registerAllNodesCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
|
|
689
|
+
this.allNodesCheckpointReceivedCallback = callback;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
public async notifyOwnCheckpointProposal(checkpoint: CheckpointProposalCore): Promise<void> {
|
|
693
|
+
await this.allNodesCheckpointReceivedCallback(checkpoint, this.node.peerId);
|
|
708
694
|
}
|
|
709
695
|
|
|
710
696
|
/**
|
|
@@ -1441,9 +1427,11 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1441
1427
|
source: sender.toString(),
|
|
1442
1428
|
});
|
|
1443
1429
|
|
|
1430
|
+
await this.allNodesCheckpointReceivedCallback(checkpoint, sender);
|
|
1431
|
+
|
|
1444
1432
|
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1445
1433
|
// to validate and potentially generate attestations
|
|
1446
|
-
const attestations = await this.
|
|
1434
|
+
const attestations = await this.validatorCheckpointReceivedCallback(checkpoint, sender);
|
|
1447
1435
|
if (attestations && attestations.length > 0) {
|
|
1448
1436
|
// If the callback returned attestations, add them to the pool and propagate them
|
|
1449
1437
|
await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
|
|
@@ -1591,53 +1579,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1591
1579
|
}
|
|
1592
1580
|
}
|
|
1593
1581
|
|
|
1594
|
-
/**
|
|
1595
|
-
* Validates a BLOCK response.
|
|
1596
|
-
*
|
|
1597
|
-
* If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
|
|
1598
|
-
* Penalizes on block number mismatch or hash mismatch.
|
|
1599
|
-
*
|
|
1600
|
-
* @param requestedBlockNumber - The requested block number.
|
|
1601
|
-
* @param responseBlock - The block returned by the peer.
|
|
1602
|
-
* @param peerId - The peer that returned the block.
|
|
1603
|
-
* @returns True if the response is valid, false otherwise.
|
|
1604
|
-
*/
|
|
1605
|
-
@trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
|
|
1606
|
-
[Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
|
|
1607
|
-
}))
|
|
1608
|
-
protected async validateRequestedBlock(
|
|
1609
|
-
requestedBlockNumber: Fr,
|
|
1610
|
-
responseBlock: L2Block,
|
|
1611
|
-
peerId: PeerId,
|
|
1612
|
-
): Promise<boolean> {
|
|
1613
|
-
try {
|
|
1614
|
-
const reqNum = Number(requestedBlockNumber.toString());
|
|
1615
|
-
if (responseBlock.number !== reqNum) {
|
|
1616
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1617
|
-
return false;
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
const local = await this.archiver.getBlock(BlockNumber(reqNum));
|
|
1621
|
-
if (!local) {
|
|
1622
|
-
// We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
|
|
1623
|
-
// TODO: Consider extending this validator to accept an expected hash or
|
|
1624
|
-
// performing quorum-based checks when using P2P syncing prior to L1 sync.
|
|
1625
|
-
this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
|
|
1626
|
-
return false;
|
|
1627
|
-
}
|
|
1628
|
-
const [localHash, respHash] = await Promise.all([local.hash(), responseBlock.hash()]);
|
|
1629
|
-
if (!localHash.equals(respHash)) {
|
|
1630
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1631
|
-
return false;
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
return true;
|
|
1635
|
-
} catch (e) {
|
|
1636
|
-
this.logger.warn(`Error validating requested block`, e);
|
|
1637
|
-
return false;
|
|
1638
|
-
}
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
1582
|
protected async validateRequestedTx(
|
|
1642
1583
|
tx: Tx,
|
|
1643
1584
|
peerId: PeerId,
|
|
@@ -226,20 +226,30 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
/**
|
|
229
|
-
* Cleans up expired timeouts.
|
|
229
|
+
* Cleans up expired timeouts and stale failed-auth-handshake entries.
|
|
230
230
|
*
|
|
231
231
|
* When peers fail to dial after a number of retries, they are temporarily timed out.
|
|
232
232
|
* This function removes any peers that have been in the timed out state for too long.
|
|
233
233
|
* To give them a chance to reconnect.
|
|
234
|
+
*
|
|
235
|
+
* Also evicts entries from the failed-auth-handshake map whose expiry window has passed.
|
|
236
|
+
* Without this, peers that probe once and never reconnect would leave their entries in the
|
|
237
|
+
* map forever, causing an unbounded memory leak.
|
|
234
238
|
*/
|
|
235
239
|
private cleanupExpiredTimeouts() {
|
|
236
|
-
// Clean up expired timeouts
|
|
237
240
|
const now = this.dateProvider.now();
|
|
241
|
+
|
|
238
242
|
for (const [peerId, timedOutPeer] of this.timedOutPeers.entries()) {
|
|
239
243
|
if (now >= timedOutPeer.timeoutUntilMs) {
|
|
240
244
|
this.timedOutPeers.delete(peerId);
|
|
241
245
|
}
|
|
242
246
|
}
|
|
247
|
+
|
|
248
|
+
for (const [id, entry] of this.failedAuthHandshakes.entries()) {
|
|
249
|
+
if (now - entry.lastFailureTimestamp > FAILED_AUTH_HANDSHAKE_EXPIRY_MS) {
|
|
250
|
+
this.failedAuthHandshakes.delete(id);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
243
253
|
}
|
|
244
254
|
|
|
245
255
|
/**
|
|
@@ -303,15 +313,20 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
303
313
|
*/
|
|
304
314
|
private handleDisconnectedPeerEvent(e: CustomEvent<PeerId>) {
|
|
305
315
|
const peerId = e.detail;
|
|
316
|
+
const peerIdStr = peerId.toString();
|
|
306
317
|
this.metrics.peerDisconnected(peerId);
|
|
307
|
-
this.logger.verbose(`Disconnected from peer ${
|
|
308
|
-
const validatorAddress = this.authenticatedPeerIdToValidatorAddress.get(
|
|
318
|
+
this.logger.verbose(`Disconnected from peer ${peerIdStr}`);
|
|
319
|
+
const validatorAddress = this.authenticatedPeerIdToValidatorAddress.get(peerIdStr);
|
|
309
320
|
if (validatorAddress !== undefined) {
|
|
310
321
|
this.logger.info(
|
|
311
|
-
`Removing authentication for validator ${validatorAddress} at peer id ${
|
|
322
|
+
`Removing authentication for validator ${validatorAddress} at peer id ${peerIdStr} due to disconnection`,
|
|
312
323
|
);
|
|
313
324
|
this.authenticatedValidatorAddressToPeerId.delete(validatorAddress.toString());
|
|
314
|
-
this.authenticatedPeerIdToValidatorAddress.delete(
|
|
325
|
+
this.authenticatedPeerIdToValidatorAddress.delete(peerIdStr);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (this.peerScoring.getScoreState(peerIdStr) === PeerScoreState.Healthy) {
|
|
329
|
+
this.peerScoring.removePeer(peerIdStr);
|
|
315
330
|
}
|
|
316
331
|
}
|
|
317
332
|
|
|
@@ -713,6 +728,12 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
713
728
|
return;
|
|
714
729
|
}
|
|
715
730
|
|
|
731
|
+
// Don't dial peers that have exceeded the auth failure threshold
|
|
732
|
+
if (!this.isNodeAllowedToConnect(peerId)) {
|
|
733
|
+
this.logger.trace(`Skipping peer ${peerId} due to failed auth handshake attempts`);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
|
|
716
737
|
const [multiaddrTcp] = await Promise.all([enr.getFullMultiaddr('tcp')]);
|
|
717
738
|
|
|
718
739
|
this.logger.trace(`Handling discovered peer ${peerId} at ${multiaddrTcp?.toString() ?? 'undefined address'}`);
|
|
@@ -970,14 +991,14 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
970
991
|
const peerIdStr = peerId.toString();
|
|
971
992
|
|
|
972
993
|
const existingEntry = this.failedAuthHandshakes.get(peerIdStr);
|
|
994
|
+
const failureCount = (existingEntry?.count || 0) + 1;
|
|
973
995
|
this.failedAuthHandshakes.set(peerIdStr, {
|
|
974
|
-
count:
|
|
996
|
+
count: failureCount,
|
|
975
997
|
lastFailureTimestamp: now,
|
|
976
998
|
});
|
|
977
999
|
|
|
978
1000
|
const connections = this.libP2PNode.getConnections(peerId);
|
|
979
1001
|
connections.forEach(conn => {
|
|
980
|
-
// We mark the IP address
|
|
981
1002
|
const address = conn.remoteAddr.nodeAddress().address;
|
|
982
1003
|
const existingAddressEntry = this.failedAuthHandshakes.get(address);
|
|
983
1004
|
this.failedAuthHandshakes.set(address, {
|
|
@@ -985,6 +1006,15 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
985
1006
|
lastFailureTimestamp: now,
|
|
986
1007
|
});
|
|
987
1008
|
});
|
|
1009
|
+
|
|
1010
|
+
// Ban the peer from being re-dialed for a cooldown period (exponential backoff)
|
|
1011
|
+
const banTimeMs = this.config.peerFailedBanTimeMs ?? DEFAULT_FAILED_PEER_BAN_TIME_MS;
|
|
1012
|
+
const backoffMs = banTimeMs * Math.pow(2, Math.min(failureCount - 1, 5));
|
|
1013
|
+
this.timedOutPeers.set(peerIdStr, {
|
|
1014
|
+
peerId: peerIdStr,
|
|
1015
|
+
timeoutUntilMs: now + backoffMs,
|
|
1016
|
+
});
|
|
1017
|
+
this.cachedPeers.delete(peerIdStr);
|
|
988
1018
|
}
|
|
989
1019
|
|
|
990
1020
|
/*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { median } from '@aztec/foundation/collection';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
3
4
|
import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
4
5
|
import {
|
|
5
6
|
Attributes,
|
|
@@ -54,6 +55,7 @@ export enum PeerScoreState {
|
|
|
54
55
|
// TODO: move into config / constants
|
|
55
56
|
const MIN_SCORE_BEFORE_BAN = -100;
|
|
56
57
|
const MIN_SCORE_BEFORE_DISCONNECT = -50;
|
|
58
|
+
const SCORE_CLEANUP_THRESHOLD = 0.1;
|
|
57
59
|
|
|
58
60
|
export class PeerScoring {
|
|
59
61
|
private logger = createLogger('p2p:peer-scoring');
|
|
@@ -65,7 +67,11 @@ export class PeerScoring {
|
|
|
65
67
|
|
|
66
68
|
private peerStateCounter: UpDownCounter;
|
|
67
69
|
|
|
68
|
-
constructor(
|
|
70
|
+
constructor(
|
|
71
|
+
config: P2PConfig,
|
|
72
|
+
telemetry: TelemetryClient = getTelemetryClient(),
|
|
73
|
+
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
74
|
+
) {
|
|
69
75
|
const orderedValues = config.peerPenaltyValues?.sort((a, b) => a - b);
|
|
70
76
|
this.peerPenalties = {
|
|
71
77
|
[PeerErrorSeverity.HighToleranceError]:
|
|
@@ -92,7 +98,7 @@ export class PeerScoring {
|
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
updateScore(peerId: string, scoreDelta: number): number {
|
|
95
|
-
const currentTime =
|
|
101
|
+
const currentTime = this.dateProvider.now();
|
|
96
102
|
const lastUpdate = this.lastUpdateTime.get(peerId) || currentTime;
|
|
97
103
|
const timePassed = currentTime - lastUpdate;
|
|
98
104
|
const decayPeriods = Math.floor(timePassed / this.decayInterval);
|
|
@@ -111,19 +117,35 @@ export class PeerScoring {
|
|
|
111
117
|
}
|
|
112
118
|
|
|
113
119
|
decayAllScores(): void {
|
|
114
|
-
const currentTime =
|
|
120
|
+
const currentTime = this.dateProvider.now();
|
|
115
121
|
for (const [peerId, lastUpdate] of this.lastUpdateTime.entries()) {
|
|
116
122
|
const timePassed = currentTime - lastUpdate;
|
|
117
123
|
const decayPeriods = Math.floor(timePassed / this.decayInterval);
|
|
118
124
|
if (decayPeriods > 0) {
|
|
119
125
|
let score = this.scores.get(peerId) || 0;
|
|
120
126
|
score *= Math.pow(this.decayFactor, decayPeriods);
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
if (Math.abs(score) < SCORE_CLEANUP_THRESHOLD) {
|
|
128
|
+
this.scores.delete(peerId);
|
|
129
|
+
this.lastUpdateTime.delete(peerId);
|
|
130
|
+
} else {
|
|
131
|
+
this.scores.set(peerId, score);
|
|
132
|
+
this.lastUpdateTime.set(peerId, currentTime);
|
|
133
|
+
}
|
|
123
134
|
}
|
|
124
135
|
}
|
|
125
136
|
}
|
|
126
137
|
|
|
138
|
+
/** Resets all peer scores. Useful for benchmarks to prevent cross-case contamination. */
|
|
139
|
+
resetAllScores(): void {
|
|
140
|
+
this.scores.clear();
|
|
141
|
+
this.lastUpdateTime.clear();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
removePeer(peerId: string): void {
|
|
145
|
+
this.scores.delete(peerId);
|
|
146
|
+
this.lastUpdateTime.delete(peerId);
|
|
147
|
+
}
|
|
148
|
+
|
|
127
149
|
getScore(peerId: string): number {
|
|
128
150
|
return this.scores.get(peerId) || 0;
|
|
129
151
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ConfigMappingsType, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';
|
|
2
2
|
|
|
3
3
|
export const DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS = 10_000;
|
|
4
4
|
export const DEFAULT_OVERALL_REQUEST_TIMEOUT_MS = 10_000; // Not currently used
|
|
@@ -27,7 +27,7 @@ export interface P2PReqRespConfig {
|
|
|
27
27
|
dialTimeoutMs: number;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export const p2pReqRespConfigMappings:
|
|
30
|
+
export const p2pReqRespConfigMappings: ConfigMappingsType<P2PReqRespConfig> = {
|
|
31
31
|
overallRequestTimeoutMs: {
|
|
32
32
|
env: 'P2P_REQRESP_OVERALL_REQUEST_TIMEOUT_MS',
|
|
33
33
|
description: 'The overall timeout for a request response operation.',
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
|
-
import { L2Block } from '@aztec/stdlib/block';
|
|
3
|
-
import { MAX_L2_BLOCK_SIZE_KB } from '@aztec/stdlib/p2p';
|
|
4
1
|
import { TxArray, TxHashArray } from '@aztec/stdlib/tx';
|
|
5
2
|
|
|
6
3
|
import type { PeerId } from '@libp2p/interface';
|
|
@@ -24,7 +21,6 @@ export const PING_PROTOCOL = '/aztec/req/ping/1.0.0';
|
|
|
24
21
|
export const STATUS_PROTOCOL = '/aztec/req/status/1.0.0';
|
|
25
22
|
export const GOODBYE_PROTOCOL = '/aztec/req/goodbye/1.0.0';
|
|
26
23
|
export const TX_REQ_PROTOCOL = '/aztec/req/tx/1.0.0';
|
|
27
|
-
export const BLOCK_REQ_PROTOCOL = '/aztec/req/block/1.0.0';
|
|
28
24
|
export const AUTH_PROTOCOL = '/aztec/req/auth/1.0.0';
|
|
29
25
|
export const BLOCK_TXS_REQ_PROTOCOL = '/aztec/req/block_txs/1.0.0';
|
|
30
26
|
|
|
@@ -33,7 +29,6 @@ export enum ReqRespSubProtocol {
|
|
|
33
29
|
STATUS = STATUS_PROTOCOL,
|
|
34
30
|
GOODBYE = GOODBYE_PROTOCOL,
|
|
35
31
|
TX = TX_REQ_PROTOCOL,
|
|
36
|
-
BLOCK = BLOCK_REQ_PROTOCOL,
|
|
37
32
|
AUTH = AUTH_PROTOCOL,
|
|
38
33
|
BLOCK_TXS = BLOCK_TXS_REQ_PROTOCOL,
|
|
39
34
|
}
|
|
@@ -100,12 +95,29 @@ export type ReqRespSubProtocolValidators = {
|
|
|
100
95
|
[S in ReqRespSubProtocol]: ResponseValidator<any, any>;
|
|
101
96
|
};
|
|
102
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Protocols that are always allowed without authentication, even when p2pAllowOnlyValidators is enabled.
|
|
100
|
+
* These are needed for the handshake and connection management flow.
|
|
101
|
+
* All other protocols require the remote peer to be authenticated.
|
|
102
|
+
*/
|
|
103
|
+
export const UNAUTHENTICATED_ALLOWED_PROTOCOLS: ReadonlySet<ReqRespSubProtocol> = new Set([
|
|
104
|
+
ReqRespSubProtocol.PING,
|
|
105
|
+
ReqRespSubProtocol.STATUS,
|
|
106
|
+
ReqRespSubProtocol.AUTH,
|
|
107
|
+
ReqRespSubProtocol.GOODBYE,
|
|
108
|
+
]);
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Callback that checks whether a peer should be rejected from req/resp data protocols.
|
|
112
|
+
* Returns true if the peer should be rejected (i.e. p2pAllowOnlyValidators is on and peer is unauthenticated).
|
|
113
|
+
*/
|
|
114
|
+
export type ShouldRejectPeer = (peerId: string) => boolean;
|
|
115
|
+
|
|
103
116
|
export const DEFAULT_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
|
|
104
117
|
[ReqRespSubProtocol.PING]: noopValidator,
|
|
105
118
|
[ReqRespSubProtocol.STATUS]: noopValidator,
|
|
106
119
|
[ReqRespSubProtocol.TX]: noopValidator,
|
|
107
120
|
[ReqRespSubProtocol.GOODBYE]: noopValidator,
|
|
108
|
-
[ReqRespSubProtocol.BLOCK]: noopValidator,
|
|
109
121
|
[ReqRespSubProtocol.AUTH]: noopValidator,
|
|
110
122
|
[ReqRespSubProtocol.BLOCK_TXS]: noopValidator,
|
|
111
123
|
};
|
|
@@ -203,10 +215,6 @@ export const subProtocolMap = {
|
|
|
203
215
|
request: RequestableBuffer,
|
|
204
216
|
response: RequestableBuffer,
|
|
205
217
|
},
|
|
206
|
-
[ReqRespSubProtocol.BLOCK]: {
|
|
207
|
-
request: Fr, // block number
|
|
208
|
-
response: L2Block,
|
|
209
|
-
},
|
|
210
218
|
[ReqRespSubProtocol.AUTH]: {
|
|
211
219
|
request: AuthRequest,
|
|
212
220
|
response: AuthResponse,
|
|
@@ -229,7 +237,6 @@ export type ExpectedResponseSizeCalculator = (requestBuffer: Buffer) => number;
|
|
|
229
237
|
export const subProtocolSizeCalculators: Record<ReqRespSubProtocol, ExpectedResponseSizeCalculator> = {
|
|
230
238
|
[ReqRespSubProtocol.TX]: calculateTxResponseSize,
|
|
231
239
|
[ReqRespSubProtocol.BLOCK_TXS]: calculateBlockTxsResponseSize,
|
|
232
|
-
[ReqRespSubProtocol.BLOCK]: () => MAX_L2_BLOCK_SIZE_KB,
|
|
233
240
|
[ReqRespSubProtocol.STATUS]: () => 1,
|
|
234
241
|
[ReqRespSubProtocol.PING]: () => 1,
|
|
235
242
|
[ReqRespSubProtocol.AUTH]: () => 1,
|
|
@@ -264,5 +271,8 @@ export interface ReqRespInterface {
|
|
|
264
271
|
|
|
265
272
|
updateConfig(config: Partial<P2PReqRespConfig>): void;
|
|
266
273
|
|
|
274
|
+
/** Sets the callback used to reject unauthenticated peers on gated req/resp protocols. */
|
|
275
|
+
setShouldRejectPeer(checker: ShouldRejectPeer): void;
|
|
276
|
+
|
|
267
277
|
getConnectionSampler(): Pick<ConnectionSampler, 'getPeerListSortedByConnectionCountAsc'>;
|
|
268
278
|
}
|