@aztec/p2p 0.0.1-commit.b655e406 → 0.0.1-commit.fce3e4f
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/bootstrap/bootstrap.d.ts +1 -1
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/client/factory.d.ts +1 -1
- package/dest/client/index.d.ts +1 -1
- package/dest/client/interface.d.ts +4 -2
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +4 -22
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +10 -5
- package/dest/config.d.ts +60 -54
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +11 -1
- package/dest/enr/generate-enr.d.ts +1 -1
- package/dest/enr/index.d.ts +1 -1
- package/dest/errors/attestation-pool.error.d.ts +7 -0
- package/dest/errors/attestation-pool.error.d.ts.map +1 -0
- package/dest/errors/attestation-pool.error.js +12 -0
- package/dest/errors/reqresp.error.d.ts +1 -1
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/index.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +28 -6
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +33 -32
- package/dest/mem_pools/attestation_pool/index.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +13 -6
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +40 -17
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +11 -6
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +30 -8
- package/dest/mem_pools/attestation_pool/mocks.d.ts +224 -3
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +1 -1
- package/dest/mem_pools/index.d.ts +1 -1
- package/dest/mem_pools/instrumentation.d.ts +3 -1
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +11 -2
- package/dest/mem_pools/interface.d.ts +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +1 -36
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/index.d.ts +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +11 -11
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +67 -0
- package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
- package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/index.js +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +1 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +21 -9
- package/dest/msg_validators/block_proposal_validator/index.d.ts +1 -1
- package/dest/msg_validators/index.d.ts +1 -1
- package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +1 -1
- package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
- package/dest/msg_validators/tx_validator/archive_cache.d.ts +1 -1
- package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.d.ts +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/index.d.ts +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +3 -1
- package/dest/msg_validators/tx_validator/test_utils.d.ts +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
- package/dest/services/data_store.d.ts +1 -1
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.d.ts +1 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/dummy_service.d.ts +1 -1
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/encoding.d.ts +1 -1
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/gossipsub/scoring.d.ts +1 -1
- package/dest/services/index.d.ts +1 -1
- 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 +9 -2
- package/dest/services/libp2p/libp2p_service.d.ts +11 -67
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +224 -54
- package/dest/services/peer-manager/interface.d.ts +1 -1
- package/dest/services/peer-manager/metrics.d.ts +3 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +11 -0
- package/dest/services/peer-manager/peer_manager.d.ts +1 -32
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +2 -0
- 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 +40 -2
- package/dest/services/reqresp/config.d.ts +1 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +1 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +1 -4
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/index.d.ts +1 -1
- package/dest/services/reqresp/interface.d.ts +1 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.d.ts +1 -1
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/auth.d.ts +1 -1
- package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +3 -5
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/index.d.ts +1 -1
- package/dest/services/reqresp/protocols/goodbye.d.ts +1 -1
- package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.d.ts +1 -1
- package/dest/services/reqresp/protocols/ping.d.ts +1 -1
- package/dest/services/reqresp/protocols/status.d.ts +2 -2
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +2 -2
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts +1 -41
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/status.d.ts +2 -2
- package/dest/services/reqresp/status.d.ts.map +1 -1
- package/dest/services/service.d.ts +1 -1
- package/dest/services/tx_collection/config.d.ts +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -7
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/index.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.d.ts +1 -3
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +2 -1
- package/dest/services/tx_collection/tx_collection.d.ts +1 -2
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.d.ts +3 -3
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.d.ts +1 -1
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_provider.d.ts +1 -1
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.d.ts +1 -1
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
- package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
- package/dest/test-helpers/get-ports.d.ts +1 -1
- package/dest/test-helpers/get-ports.d.ts.map +1 -1
- package/dest/test-helpers/index.d.ts +1 -1
- package/dest/test-helpers/make-enrs.d.ts +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts +2 -2
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.d.ts +4 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-tx-helpers.d.ts +2 -2
- package/dest/test-helpers/mock-tx-helpers.d.ts.map +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/testbench/p2p_client_testbench_worker.d.ts +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +11 -8
- package/dest/testbench/parse_log_file.d.ts +1 -1
- package/dest/testbench/testbench.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/types/index.d.ts +1 -1
- package/dest/util.d.ts +2 -1
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +11 -2
- package/dest/versioning.d.ts +1 -1
- package/package.json +19 -18
- package/src/client/interface.ts +4 -1
- package/src/client/p2p_client.ts +12 -6
- package/src/config.ts +18 -1
- package/src/errors/attestation-pool.error.ts +13 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +29 -5
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +45 -32
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +65 -23
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +50 -16
- package/src/mem_pools/attestation_pool/mocks.ts +1 -1
- package/src/mem_pools/instrumentation.ts +13 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +13 -15
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +91 -0
- package/src/msg_validators/attestation_validator/index.ts +1 -0
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +25 -9
- package/src/msg_validators/tx_validator/phases_validator.ts +3 -1
- package/src/services/libp2p/instrumentation.ts +10 -1
- package/src/services/libp2p/libp2p_service.ts +248 -59
- package/src/services/peer-manager/metrics.ts +10 -0
- package/src/services/peer-manager/peer_manager.ts +2 -0
- package/src/services/peer-manager/peer_scoring.ts +46 -3
- package/src/services/tx_collection/slow_tx_collection.ts +3 -2
- package/src/testbench/p2p_client_testbench_worker.ts +8 -5
- package/src/util.ts +12 -2
|
@@ -4,10 +4,10 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
4
4
|
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
}
|
|
7
|
+
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
7
8
|
import { randomInt } from '@aztec/foundation/crypto';
|
|
8
9
|
import { Fr } from '@aztec/foundation/fields';
|
|
9
10
|
import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
10
|
-
import { SerialQueue } from '@aztec/foundation/queue';
|
|
11
11
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
12
12
|
import { Timer } from '@aztec/foundation/timer';
|
|
13
13
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
@@ -30,7 +30,8 @@ import { mplex } from '@libp2p/mplex';
|
|
|
30
30
|
import { tcp } from '@libp2p/tcp';
|
|
31
31
|
import { ENR } from '@nethermindeth/enr';
|
|
32
32
|
import { createLibp2p } from 'libp2p';
|
|
33
|
-
import {
|
|
33
|
+
import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
|
|
34
|
+
import { AttestationValidator, BlockProposalValidator, FishermanAttestationValidator } from '../../msg_validators/index.js';
|
|
34
35
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
35
36
|
import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
|
|
36
37
|
import { createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
|
|
@@ -64,8 +65,6 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
64
65
|
epochCache;
|
|
65
66
|
proofVerifier;
|
|
66
67
|
worldStateSynchronizer;
|
|
67
|
-
logger;
|
|
68
|
-
jobQueue;
|
|
69
68
|
discoveryRunningPromise;
|
|
70
69
|
msgIdSeenValidators;
|
|
71
70
|
// Message validators
|
|
@@ -81,8 +80,11 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
81
80
|
*/ blockReceivedCallback;
|
|
82
81
|
gossipSubEventHandler;
|
|
83
82
|
instrumentation;
|
|
83
|
+
logger;
|
|
84
84
|
constructor(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
|
|
85
|
-
super(telemetry, 'LibP2PService'), this.clientType = clientType, this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.
|
|
85
|
+
super(telemetry, 'LibP2PService'), this.clientType = clientType, this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.msgIdSeenValidators = {}, this.protocolVersion = '', this.topicStrings = {};
|
|
86
|
+
// Create child logger with fisherman prefix if in fisherman mode
|
|
87
|
+
this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
|
|
86
88
|
this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
|
|
87
89
|
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
88
90
|
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
@@ -93,14 +95,15 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
93
95
|
this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
|
|
94
96
|
this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
|
|
95
97
|
this.topicStrings[TopicType.block_attestation] = createTopicString(TopicType.block_attestation, this.protocolVersion);
|
|
96
|
-
|
|
98
|
+
// Use FishermanAttestationValidator in fisherman mode to validate attestation payloads against proposals
|
|
99
|
+
this.attestationValidator = config.fishermanMode ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry) : new AttestationValidator(epochCache);
|
|
97
100
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, {
|
|
98
101
|
txsPermitted: !config.disableTransactions
|
|
99
102
|
});
|
|
100
103
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
101
104
|
this.blockReceivedCallback = async (block)=>{
|
|
102
|
-
this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber
|
|
103
|
-
p2pMessageIdentifier: await block.
|
|
105
|
+
this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`, {
|
|
106
|
+
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier()
|
|
104
107
|
});
|
|
105
108
|
return undefined;
|
|
106
109
|
};
|
|
@@ -278,7 +281,7 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
278
281
|
},
|
|
279
282
|
logger: createLibp2pComponentLogger(logger.module)
|
|
280
283
|
});
|
|
281
|
-
const peerScoring = new PeerScoring(config);
|
|
284
|
+
const peerScoring = new PeerScoring(config, telemetry);
|
|
282
285
|
const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
|
|
283
286
|
const peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, createLogger(`${logger.module}:peer_manager`), peerScoring, reqresp, worldStateSynchronizer, protocolVersion, epochCache);
|
|
284
287
|
// Update gossipsub score params
|
|
@@ -300,8 +303,6 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
300
303
|
throw new Error('Announce address not provided.');
|
|
301
304
|
}
|
|
302
305
|
const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
|
|
303
|
-
// Start job queue, peer discovery service and libp2p node
|
|
304
|
-
this.jobQueue.start();
|
|
305
306
|
await this.peerManager.initializePeers();
|
|
306
307
|
if (!this.config.p2pDiscoveryDisabled) {
|
|
307
308
|
await this.peerDiscoveryService.start();
|
|
@@ -332,15 +333,17 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
332
333
|
}
|
|
333
334
|
// add GossipSub listener
|
|
334
335
|
this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
335
|
-
// Start running promise for peer discovery
|
|
336
|
-
this.discoveryRunningPromise = new RunningPromise(()=>
|
|
336
|
+
// Start running promise for peer discovery and metrics collection
|
|
337
|
+
this.discoveryRunningPromise = new RunningPromise(async ()=>{
|
|
338
|
+
await this.peerManager.heartbeat();
|
|
339
|
+
}, this.logger, this.config.peerCheckIntervalMS);
|
|
337
340
|
this.discoveryRunningPromise.start();
|
|
338
341
|
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
339
342
|
const reqrespSubProtocolValidators = {
|
|
340
343
|
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
341
|
-
// TODO(#11336): A request validator for blocks
|
|
342
344
|
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
343
|
-
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this)
|
|
345
|
+
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
346
|
+
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this)
|
|
344
347
|
};
|
|
345
348
|
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
346
349
|
this.logger.info(`Started P2P service`, {
|
|
@@ -359,8 +362,6 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
359
362
|
// Stop peer manager
|
|
360
363
|
this.logger.debug('Stopping peer manager...');
|
|
361
364
|
await this.peerManager.stop();
|
|
362
|
-
this.logger.debug('Stopping job queue...');
|
|
363
|
-
await this.jobQueue.end();
|
|
364
365
|
this.logger.debug('Stopping running promise...');
|
|
365
366
|
await this.discoveryRunningPromise?.stop();
|
|
366
367
|
this.logger.debug('Stopping peer discovery service...');
|
|
@@ -426,7 +427,7 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
426
427
|
if (!this.node.services.pubsub) {
|
|
427
428
|
throw new Error('Pubsub service not available.');
|
|
428
429
|
}
|
|
429
|
-
const p2pMessage = P2PMessage.fromGossipable(message);
|
|
430
|
+
const p2pMessage = P2PMessage.fromGossipable(message, this.config.debugP2PInstrumentMessages);
|
|
430
431
|
const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
|
|
431
432
|
return result.recipients.length;
|
|
432
433
|
}
|
|
@@ -466,24 +467,57 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
466
467
|
};
|
|
467
468
|
}
|
|
468
469
|
/**
|
|
470
|
+
* Safely deserializes a P2PMessage from raw message data.
|
|
471
|
+
* @param msgId - The message ID.
|
|
472
|
+
* @param source - The peer ID of the message source.
|
|
473
|
+
* @param data - The raw message data.
|
|
474
|
+
* @returns The deserialized P2PMessage or undefined if deserialization fails.
|
|
475
|
+
*/ safelyDeserializeP2PMessage(msgId, source, data) {
|
|
476
|
+
try {
|
|
477
|
+
return P2PMessage.fromMessageData(Buffer.from(data), this.config.debugP2PInstrumentMessages);
|
|
478
|
+
} catch (err) {
|
|
479
|
+
this.logger.error(`Error deserializing P2PMessage`, err, {
|
|
480
|
+
msgId,
|
|
481
|
+
source: source.toString()
|
|
482
|
+
});
|
|
483
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Reject);
|
|
484
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
|
|
485
|
+
return undefined;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
469
489
|
* Handles a new gossip message that was received by the client.
|
|
470
490
|
* @param topic - The message's topic.
|
|
471
491
|
* @param data - The message data
|
|
472
492
|
*/ async handleNewGossipMessage(msg, msgId, source) {
|
|
473
|
-
const
|
|
493
|
+
const msgReceivedTime = Date.now();
|
|
494
|
+
let topicType;
|
|
495
|
+
const p2pMessage = this.safelyDeserializeP2PMessage(msgId, source, msg.data);
|
|
496
|
+
if (!p2pMessage) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
474
499
|
const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
|
|
475
500
|
if (!preValidationResult.result) {
|
|
476
501
|
return;
|
|
477
502
|
}
|
|
478
503
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
504
|
+
topicType = TopicType.tx;
|
|
479
505
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
480
506
|
}
|
|
481
|
-
if (msg.topic === this.topicStrings[TopicType.block_attestation]
|
|
482
|
-
|
|
507
|
+
if (msg.topic === this.topicStrings[TopicType.block_attestation]) {
|
|
508
|
+
topicType = TopicType.block_attestation;
|
|
509
|
+
if (this.clientType === P2PClientType.Full) {
|
|
510
|
+
await this.processAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
511
|
+
}
|
|
483
512
|
}
|
|
484
513
|
if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
514
|
+
topicType = TopicType.block_proposal;
|
|
485
515
|
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
486
516
|
}
|
|
517
|
+
if (p2pMessage.timestamp !== undefined && topicType !== undefined) {
|
|
518
|
+
const latency = msgReceivedTime - p2pMessage.timestamp.getTime();
|
|
519
|
+
this.instrumentation.recordMessageLatency(topicType, latency);
|
|
520
|
+
}
|
|
487
521
|
return;
|
|
488
522
|
}
|
|
489
523
|
async validateReceivedMessage(validationFunc, msgId, source, topicType) {
|
|
@@ -494,6 +528,7 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
494
528
|
try {
|
|
495
529
|
resultAndObj = await validationFunc();
|
|
496
530
|
} catch (err) {
|
|
531
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
|
|
497
532
|
this.logger.error(`Error deserializing and validating gossipsub message`, err, {
|
|
498
533
|
msgId,
|
|
499
534
|
source: source.toString(),
|
|
@@ -546,6 +581,7 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
546
581
|
this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
|
|
547
582
|
return;
|
|
548
583
|
}
|
|
584
|
+
this.instrumentation.incrementTxReceived(1);
|
|
549
585
|
await this.mempools.txPool.addTxs([
|
|
550
586
|
tx
|
|
551
587
|
]);
|
|
@@ -558,11 +594,20 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
558
594
|
*/ async processAttestationFromPeer(payloadData, msgId, source) {
|
|
559
595
|
const validationFunc = async ()=>{
|
|
560
596
|
const attestation = BlockAttestation.fromBuffer(payloadData);
|
|
597
|
+
const pool = this.mempools.attestationPool;
|
|
561
598
|
const isValid = await this.validateAttestation(source, attestation);
|
|
562
|
-
const exists = isValid && await
|
|
599
|
+
const exists = isValid && await pool.hasAttestation(attestation);
|
|
600
|
+
let canAdd = true;
|
|
601
|
+
if (isValid && !exists) {
|
|
602
|
+
const slot = attestation.payload.header.slotNumber;
|
|
603
|
+
const { committee } = await this.epochCache.getCommittee(slot);
|
|
604
|
+
const committeeSize = committee?.length ?? 0;
|
|
605
|
+
canAdd = await pool.canAddAttestation(attestation, committeeSize);
|
|
606
|
+
}
|
|
563
607
|
this.logger.trace(`Validate propagated block attestation`, {
|
|
564
608
|
isValid,
|
|
565
609
|
exists,
|
|
610
|
+
canAdd,
|
|
566
611
|
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
567
612
|
[Attributes.P2P_ID]: source.toString()
|
|
568
613
|
});
|
|
@@ -575,6 +620,16 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
575
620
|
result: TopicValidatorResult.Ignore,
|
|
576
621
|
obj: attestation
|
|
577
622
|
};
|
|
623
|
+
} else if (!canAdd) {
|
|
624
|
+
this.logger.warn(`Dropping block attestation due to per-(slot, proposalId) attestation cap`, {
|
|
625
|
+
slot: attestation.payload.header.slotNumber.toString(),
|
|
626
|
+
archive: attestation.archive.toString(),
|
|
627
|
+
source: source.toString()
|
|
628
|
+
});
|
|
629
|
+
return {
|
|
630
|
+
result: TopicValidatorResult.Ignore,
|
|
631
|
+
obj: attestation
|
|
632
|
+
};
|
|
578
633
|
} else {
|
|
579
634
|
return {
|
|
580
635
|
result: TopicValidatorResult.Accept,
|
|
@@ -586,9 +641,9 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
586
641
|
if (result !== TopicValidatorResult.Accept || !attestation) {
|
|
587
642
|
return;
|
|
588
643
|
}
|
|
589
|
-
this.logger.debug(`Received attestation for slot ${attestation.slotNumber
|
|
590
|
-
p2pMessageIdentifier: await attestation.
|
|
591
|
-
slot: attestation.slotNumber
|
|
644
|
+
this.logger.debug(`Received attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`, {
|
|
645
|
+
p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
|
|
646
|
+
slot: attestation.slotNumber,
|
|
592
647
|
archive: attestation.archive.toString(),
|
|
593
648
|
source: source.toString()
|
|
594
649
|
});
|
|
@@ -600,12 +655,15 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
600
655
|
const validationFunc = async ()=>{
|
|
601
656
|
const block = BlockProposal.fromBuffer(payloadData);
|
|
602
657
|
const isValid = await this.validateBlockProposal(source, block);
|
|
658
|
+
const pool = this.mempools.attestationPool;
|
|
603
659
|
// Note that we dont have an attestation pool if we're a prover node, but we still
|
|
604
660
|
// subscribe to block proposal topics in order to prevent their txs from being cleared.
|
|
605
|
-
const exists = isValid && await
|
|
661
|
+
const exists = isValid && await pool?.hasBlockProposal(block);
|
|
662
|
+
const canAdd = isValid && await pool?.canAddProposal(block);
|
|
606
663
|
this.logger.trace(`Validate propagated block proposal`, {
|
|
607
664
|
isValid,
|
|
608
665
|
exists,
|
|
666
|
+
canAdd,
|
|
609
667
|
[Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
|
|
610
668
|
[Attributes.P2P_ID]: source.toString()
|
|
611
669
|
});
|
|
@@ -618,6 +676,16 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
618
676
|
result: TopicValidatorResult.Ignore,
|
|
619
677
|
obj: block
|
|
620
678
|
};
|
|
679
|
+
} else if (!canAdd) {
|
|
680
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
|
|
681
|
+
this.logger.warn(`Penalizing peer for block proposal exceeding per-slot cap`, {
|
|
682
|
+
slot: block.slotNumber.toString(),
|
|
683
|
+
archive: block.archive.toString(),
|
|
684
|
+
source: source.toString()
|
|
685
|
+
});
|
|
686
|
+
return {
|
|
687
|
+
result: TopicValidatorResult.Reject
|
|
688
|
+
};
|
|
621
689
|
} else {
|
|
622
690
|
return {
|
|
623
691
|
result: TopicValidatorResult.Accept,
|
|
@@ -633,11 +701,11 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
633
701
|
}
|
|
634
702
|
// REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
635
703
|
async processValidBlockProposal(block, sender) {
|
|
636
|
-
const slot = block.slotNumber
|
|
637
|
-
const previousSlot = slot -
|
|
704
|
+
const slot = block.slotNumber;
|
|
705
|
+
const previousSlot = SlotNumber(slot - 1);
|
|
638
706
|
this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
639
|
-
p2pMessageIdentifier: await block.
|
|
640
|
-
slot: block.slotNumber
|
|
707
|
+
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
|
|
708
|
+
slot: block.slotNumber,
|
|
641
709
|
archive: block.archive.toString(),
|
|
642
710
|
source: sender.toString()
|
|
643
711
|
});
|
|
@@ -645,17 +713,30 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
645
713
|
if (attestationsForPreviousSlot !== undefined) {
|
|
646
714
|
this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
|
|
647
715
|
}
|
|
648
|
-
//
|
|
716
|
+
// Attempt to add proposal, then mark the txs in this proposal as non-evictable
|
|
717
|
+
try {
|
|
718
|
+
await this.mempools.attestationPool?.addBlockProposal(block);
|
|
719
|
+
} catch (err) {
|
|
720
|
+
// Drop proposals if we hit per-slot cap in the attestation pool; rethrow unknown errors
|
|
721
|
+
if (err instanceof ProposalSlotCapExceededError) {
|
|
722
|
+
this.logger.warn(`Dropping block proposal due to per-slot proposal cap`, {
|
|
723
|
+
slot: String(slot),
|
|
724
|
+
archive: block.archive.toString(),
|
|
725
|
+
error: err.message
|
|
726
|
+
});
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
throw err;
|
|
730
|
+
}
|
|
649
731
|
await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
|
|
650
|
-
await this.mempools.attestationPool?.addBlockProposal(block);
|
|
651
732
|
const attestations = await this.blockReceivedCallback(block, sender);
|
|
652
733
|
// TODO: fix up this pattern - the abstraction is not nice
|
|
653
|
-
// The attestation can be undefined if no handler is registered / the validator deems the block invalid
|
|
734
|
+
// The attestation can be undefined if no handler is registered / the validator deems the block invalid / in fisherman mode
|
|
654
735
|
if (attestations?.length) {
|
|
655
736
|
for (const attestation of attestations){
|
|
656
|
-
this.logger.verbose(`Broadcasting attestation for slot ${attestation.slotNumber
|
|
657
|
-
p2pMessageIdentifier: await attestation.
|
|
658
|
-
slot: attestation.slotNumber
|
|
737
|
+
this.logger.verbose(`Broadcasting attestation for slot ${attestation.slotNumber}`, {
|
|
738
|
+
p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
|
|
739
|
+
slot: attestation.slotNumber,
|
|
659
740
|
archive: attestation.archive.toString()
|
|
660
741
|
});
|
|
661
742
|
await this.broadcastAttestation(attestation);
|
|
@@ -672,28 +753,72 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
672
753
|
* Propagates provided message to peers.
|
|
673
754
|
* @param message - The message to propagate.
|
|
674
755
|
*/ async propagate(message) {
|
|
675
|
-
const p2pMessageIdentifier = await message.
|
|
756
|
+
const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
|
|
676
757
|
this.logger.trace(`Message ${p2pMessageIdentifier} queued`, {
|
|
677
758
|
p2pMessageIdentifier
|
|
678
759
|
});
|
|
679
|
-
void this.
|
|
680
|
-
await this.sendToPeers(message);
|
|
681
|
-
}).catch((error)=>{
|
|
760
|
+
void this.sendToPeers(message).catch((error)=>{
|
|
682
761
|
this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, {
|
|
683
762
|
error
|
|
684
763
|
});
|
|
685
764
|
});
|
|
686
765
|
}
|
|
687
766
|
/**
|
|
688
|
-
* Validate the requested block transactions.
|
|
767
|
+
* Validate the requested block transactions. Allow partial returns.
|
|
689
768
|
* @param request - The block transactions request.
|
|
690
769
|
* @param response - The block transactions response.
|
|
691
770
|
* @param peerId - The ID of the peer that made the request.
|
|
692
771
|
* @returns True if the requested block transactions are valid, false otherwise.
|
|
693
|
-
*/ async validateRequestedBlockTxs(
|
|
772
|
+
*/ async validateRequestedBlockTxs(request, response, peerId) {
|
|
694
773
|
const requestedTxValidator = this.createRequestedTxValidator();
|
|
695
774
|
try {
|
|
696
|
-
|
|
775
|
+
if (!response.blockHash.equals(request.blockHash)) {
|
|
776
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
777
|
+
throw new ValidationError(`Received block txs for unexpected block: expected ${request.blockHash.toString()}, got ${response.blockHash.toString()}`);
|
|
778
|
+
}
|
|
779
|
+
if (response.txIndices.getLength() !== request.txIndices.getLength()) {
|
|
780
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
781
|
+
throw new ValidationError(`Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`);
|
|
782
|
+
}
|
|
783
|
+
// Check no duplicates and not exceeding returnable count
|
|
784
|
+
const requestedIndices = new Set(request.txIndices.getTrueIndices());
|
|
785
|
+
const availableIndices = new Set(response.txIndices.getTrueIndices());
|
|
786
|
+
const maxReturnable = [
|
|
787
|
+
...requestedIndices
|
|
788
|
+
].filter((i)=>availableIndices.has(i)).length;
|
|
789
|
+
const returnedHashes = await Promise.all(response.txs.map((tx)=>tx.getTxHash().toString()));
|
|
790
|
+
const uniqueReturned = new Set(returnedHashes.map((h)=>h.toString()));
|
|
791
|
+
if (uniqueReturned.size !== returnedHashes.length) {
|
|
792
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
793
|
+
throw new ValidationError(`Received duplicate txs in block txs response`);
|
|
794
|
+
}
|
|
795
|
+
if (response.txs.length > maxReturnable) {
|
|
796
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
797
|
+
throw new ValidationError(`Received more txs (${response.txs.length}) than requested-and-available (${maxReturnable})`);
|
|
798
|
+
}
|
|
799
|
+
// Given proposal (should have locally), ensure returned txs are valid subset and match request indices
|
|
800
|
+
const proposal = await this.mempools.attestationPool?.getBlockProposal(request.blockHash.toString());
|
|
801
|
+
if (proposal) {
|
|
802
|
+
// Build intersected indices
|
|
803
|
+
const intersectIdx = request.txIndices.getTrueIndices().filter((i)=>response.txIndices.isSet(i));
|
|
804
|
+
// Enforce subset membership and preserve increasing order by index.
|
|
805
|
+
const hashToIndexInProposal = new Map(proposal.txHashes.map((h, i)=>[
|
|
806
|
+
h.toString(),
|
|
807
|
+
i
|
|
808
|
+
]));
|
|
809
|
+
const allowedIndexSet = new Set(intersectIdx);
|
|
810
|
+
const indices = returnedHashes.map((h)=>hashToIndexInProposal.get(h));
|
|
811
|
+
const allAllowed = indices.every((idx)=>idx !== undefined && allowedIndexSet.has(idx));
|
|
812
|
+
const strictlyIncreasing = indices.every((idx, i)=>i === 0 ? idx !== undefined : idx > indices[i - 1]);
|
|
813
|
+
if (!allAllowed || !strictlyIncreasing) {
|
|
814
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
815
|
+
throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
|
|
816
|
+
}
|
|
817
|
+
} else {
|
|
818
|
+
// No local proposal, cannot check the membership/order of the returned txs
|
|
819
|
+
this.logger.warn(`Block proposal not found for block hash ${request.blockHash.toString()}; cannot validate membership/order of returned txs`);
|
|
820
|
+
return false;
|
|
821
|
+
}
|
|
697
822
|
await Promise.all(response.txs.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator)));
|
|
698
823
|
return true;
|
|
699
824
|
} catch (e) {
|
|
@@ -715,7 +840,7 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
715
840
|
* ReqRespSubProtocol.TX subprotocol validation.
|
|
716
841
|
*
|
|
717
842
|
* @param requestedTxHash - The collection of the txs that was requested.
|
|
718
|
-
* @param responseTx - The
|
|
843
|
+
* @param responseTx - The collection of txs that was received as a response to the request.
|
|
719
844
|
* @param peerId - The peer ID of the peer that sent the tx.
|
|
720
845
|
* @returns True if the whole collection of txs is valid, false otherwise.
|
|
721
846
|
*/ async validateRequestedTxs(requestedTxHash, responseTx, peerId) {
|
|
@@ -735,6 +860,45 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
735
860
|
return false;
|
|
736
861
|
}
|
|
737
862
|
}
|
|
863
|
+
/**
|
|
864
|
+
* Validates a BLOCK response.
|
|
865
|
+
*
|
|
866
|
+
* If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
|
|
867
|
+
* Penalizes on block number mismatch or hash mismatch.
|
|
868
|
+
*
|
|
869
|
+
* @param requestedBlockNumber - The requested block number.
|
|
870
|
+
* @param responseBlock - The block returned by the peer.
|
|
871
|
+
* @param peerId - The peer that returned the block.
|
|
872
|
+
* @returns True if the response is valid, false otherwise.
|
|
873
|
+
*/ async validateRequestedBlock(requestedBlockNumber, responseBlock, peerId) {
|
|
874
|
+
try {
|
|
875
|
+
const reqNum = Number(requestedBlockNumber.toString());
|
|
876
|
+
if (responseBlock.number !== reqNum) {
|
|
877
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
878
|
+
return false;
|
|
879
|
+
}
|
|
880
|
+
const local = await this.archiver.getBlock(reqNum);
|
|
881
|
+
if (!local) {
|
|
882
|
+
// We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
|
|
883
|
+
// TODO: Consider extending this validator to accept an expected hash or
|
|
884
|
+
// performing quorum-based checks when using P2P syncing prior to L1 sync.
|
|
885
|
+
this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
|
|
886
|
+
return false;
|
|
887
|
+
}
|
|
888
|
+
const [localHash, respHash] = await Promise.all([
|
|
889
|
+
local.hash(),
|
|
890
|
+
responseBlock.hash()
|
|
891
|
+
]);
|
|
892
|
+
if (!localHash.equals(respHash)) {
|
|
893
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
894
|
+
return false;
|
|
895
|
+
}
|
|
896
|
+
return true;
|
|
897
|
+
} catch (e) {
|
|
898
|
+
this.logger.warn(`Error validating requested block`, e);
|
|
899
|
+
return false;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
738
902
|
createRequestedTxValidator() {
|
|
739
903
|
return new AggregateTxValidator(new DataTxValidator(), new MetadataTxValidator({
|
|
740
904
|
l1ChainId: new Fr(this.config.l1ChainId),
|
|
@@ -744,17 +908,18 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
744
908
|
}), new TxProofValidator(this.proofVerifier));
|
|
745
909
|
}
|
|
746
910
|
async validateRequestedTx(tx, peerId, txValidator, requested) {
|
|
911
|
+
const penalize = (severity)=>this.peerManager.penalizePeer(peerId, severity);
|
|
747
912
|
if (!await tx.validateTxHash()) {
|
|
748
|
-
|
|
913
|
+
penalize(PeerErrorSeverity.MidToleranceError);
|
|
749
914
|
throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
|
|
750
915
|
}
|
|
751
916
|
if (requested && !requested.has(tx.getTxHash().toString())) {
|
|
752
|
-
|
|
917
|
+
penalize(PeerErrorSeverity.MidToleranceError);
|
|
753
918
|
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
|
|
754
919
|
}
|
|
755
920
|
const { result } = await txValidator.validateTx(tx);
|
|
756
921
|
if (result === 'invalid') {
|
|
757
|
-
|
|
922
|
+
penalize(PeerErrorSeverity.LowToleranceError);
|
|
758
923
|
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
|
|
759
924
|
}
|
|
760
925
|
}
|
|
@@ -924,7 +1089,7 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
924
1089
|
}
|
|
925
1090
|
async sendToPeers(message) {
|
|
926
1091
|
const parent = message.constructor;
|
|
927
|
-
const identifier = await message.
|
|
1092
|
+
const identifier = await message.p2pMessageLoggingIdentifier().then((i)=>i.toString());
|
|
928
1093
|
this.logger.trace(`Sending message ${identifier}`, {
|
|
929
1094
|
p2pMessageIdentifier: identifier
|
|
930
1095
|
});
|
|
@@ -953,16 +1118,16 @@ import { P2PInstrumentation } from './instrumentation.js';
|
|
|
953
1118
|
}
|
|
954
1119
|
_ts_decorate([
|
|
955
1120
|
trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
|
|
956
|
-
[Attributes.SLOT_NUMBER]: block.slotNumber
|
|
1121
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber,
|
|
957
1122
|
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
958
|
-
[Attributes.P2P_ID]: await block.
|
|
1123
|
+
[Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then((i)=>i.toString())
|
|
959
1124
|
}))
|
|
960
1125
|
], LibP2PService.prototype, "processValidBlockProposal", null);
|
|
961
1126
|
_ts_decorate([
|
|
962
1127
|
trackSpan('Libp2pService.broadcastAttestation', async (attestation)=>({
|
|
963
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber
|
|
1128
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
964
1129
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
965
|
-
[Attributes.P2P_ID]: await attestation.
|
|
1130
|
+
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then((i)=>i.toString())
|
|
966
1131
|
}))
|
|
967
1132
|
], LibP2PService.prototype, "broadcastAttestation", null);
|
|
968
1133
|
_ts_decorate([
|
|
@@ -975,6 +1140,11 @@ _ts_decorate([
|
|
|
975
1140
|
[Attributes.TX_HASH]: requestedTxHash.toString()
|
|
976
1141
|
}))
|
|
977
1142
|
], LibP2PService.prototype, "validateRequestedTxs", null);
|
|
1143
|
+
_ts_decorate([
|
|
1144
|
+
trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock)=>({
|
|
1145
|
+
[Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString()
|
|
1146
|
+
}))
|
|
1147
|
+
], LibP2PService.prototype, "validateRequestedBlock", null);
|
|
978
1148
|
_ts_decorate([
|
|
979
1149
|
trackSpan('Libp2pService.validatePropagatedTx', (tx)=>({
|
|
980
1150
|
[Attributes.TX_HASH]: tx.getTxHash().toString()
|
|
@@ -982,9 +1152,9 @@ _ts_decorate([
|
|
|
982
1152
|
], LibP2PService.prototype, "validatePropagatedTx", null);
|
|
983
1153
|
_ts_decorate([
|
|
984
1154
|
trackSpan('Libp2pService.validateAttestation', async (_, attestation)=>({
|
|
985
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber
|
|
1155
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
986
1156
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
987
|
-
[Attributes.P2P_ID]: await attestation.
|
|
1157
|
+
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then((i)=>i.toString())
|
|
988
1158
|
}))
|
|
989
1159
|
], LibP2PService.prototype, "validateAttestation", null);
|
|
990
1160
|
_ts_decorate([
|
|
@@ -20,4 +20,4 @@ export interface PeerManagerInterface {
|
|
|
20
20
|
/** If node running this P2P stack is validator, passes in validator address to P2P layer */
|
|
21
21
|
registerThisValidatorAddresses(address: EthAddress[]): void;
|
|
22
22
|
}
|
|
23
|
-
//# sourceMappingURL=
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvcGVlci1tYW5hZ2VyL2ludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxRQUFRLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRTNELE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRWhELE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RSxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUVyRSxNQUFNLFdBQVcsb0JBQW9CO0lBQ25DLFFBQVEsQ0FBQyxlQUFlLENBQUMsRUFBRSxPQUFPLEdBQUcsUUFBUSxFQUFFLENBQUM7SUFFaEQsZUFBZSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqQyxTQUFTLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNCLGNBQWMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLElBQUksQ0FBQztJQUNyQyxjQUFjLENBQUMsTUFBTSxFQUFFLE1BQU0sR0FBRyxJQUFJLENBQUM7SUFDckMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLE1BQU0sR0FBRyxJQUFJLENBQUM7SUFDdkMsZUFBZSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLGFBQWEsR0FBRyxJQUFJLENBQUM7SUFDN0QsWUFBWSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLGlCQUFpQixHQUFHLElBQUksQ0FBQztJQUMvRCx5QkFBeUIsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBRTVGLFlBQVksQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUNyQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQztJQUVoRCxJQUFJLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRXRCLDRGQUE0RjtJQUM1Riw4QkFBOEIsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsSUFBSSxDQUFDO0NBQzdEIn0=
|
|
@@ -5,10 +5,12 @@ export declare class PeerManagerMetrics {
|
|
|
5
5
|
private sentGoodbyes;
|
|
6
6
|
private receivedGoodbyes;
|
|
7
7
|
private peerCount;
|
|
8
|
+
private lowScoreDisconnects;
|
|
8
9
|
readonly tracer: Tracer;
|
|
9
10
|
constructor(telemetryClient?: TelemetryClient, name?: string);
|
|
10
11
|
recordGoodbyeSent(reason: GoodByeReason): void;
|
|
11
12
|
recordGoodbyeReceived(reason: GoodByeReason): void;
|
|
12
13
|
recordPeerCount(count: number): void;
|
|
14
|
+
recordLowScoreDisconnect(scoreState: 'Banned' | 'Disconnect'): void;
|
|
13
15
|
}
|
|
14
|
-
//# sourceMappingURL=
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3BlZXItbWFuYWdlci9tZXRyaWNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFJTCxLQUFLLGVBQWUsRUFDcEIsS0FBSyxNQUFNLEVBSVosTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxPQUFPLEVBQUUsS0FBSyxhQUFhLEVBQXVCLE1BQU0sK0JBQStCLENBQUM7QUFFeEYscUJBQWEsa0JBQWtCO2FBU1gsZUFBZSxFQUFFLGVBQWU7SUFSbEQsT0FBTyxDQUFDLFlBQVksQ0FBZ0I7SUFDcEMsT0FBTyxDQUFDLGdCQUFnQixDQUFnQjtJQUN4QyxPQUFPLENBQUMsU0FBUyxDQUFRO0lBQ3pCLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBZ0I7SUFFM0MsU0FBZ0IsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUUvQixZQUNrQixlQUFlLEdBQUUsZUFBc0MsRUFDdkUsSUFBSSxTQUFnQixFQXlCckI7SUFFTSxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsYUFBYSxRQUU3QztJQUVNLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxhQUFhLFFBRWpEO0lBRU0sZUFBZSxDQUFDLEtBQUssRUFBRSxNQUFNLFFBRW5DO0lBRU0sd0JBQXdCLENBQUMsVUFBVSxFQUFFLFFBQVEsR0FBRyxZQUFZLFFBRWxFO0NBQ0YifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/services/peer-manager/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,MAAM,EAIZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,+BAA+B,CAAC;AAExF,qBAAa,kBAAkB;
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/services/peer-manager/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,MAAM,EAIZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,+BAA+B,CAAC;AAExF,qBAAa,kBAAkB;aASX,eAAe,EAAE,eAAe;IARlD,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,mBAAmB,CAAgB;IAE3C,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,YACkB,eAAe,GAAE,eAAsC,EACvE,IAAI,SAAgB,EAyBrB;IAEM,iBAAiB,CAAC,MAAM,EAAE,aAAa,QAE7C;IAEM,qBAAqB,CAAC,MAAM,EAAE,aAAa,QAEjD;IAEM,eAAe,CAAC,KAAK,EAAE,MAAM,QAEnC;IAEM,wBAAwB,CAAC,UAAU,EAAE,QAAQ,GAAG,YAAY,QAElE;CACF"}
|
|
@@ -5,6 +5,7 @@ export class PeerManagerMetrics {
|
|
|
5
5
|
sentGoodbyes;
|
|
6
6
|
receivedGoodbyes;
|
|
7
7
|
peerCount;
|
|
8
|
+
lowScoreDisconnects;
|
|
8
9
|
tracer;
|
|
9
10
|
constructor(telemetryClient = getTelemetryClient(), name = 'PeerManager'){
|
|
10
11
|
this.telemetryClient = telemetryClient;
|
|
@@ -25,6 +26,11 @@ export class PeerManagerMetrics {
|
|
|
25
26
|
unit: 'peers',
|
|
26
27
|
valueType: ValueType.INT
|
|
27
28
|
});
|
|
29
|
+
this.lowScoreDisconnects = meter.createUpDownCounter(Metrics.PEER_MANAGER_LOW_SCORE_DISCONNECTS, {
|
|
30
|
+
description: 'Number of peers disconnected due to low score',
|
|
31
|
+
unit: 'peers',
|
|
32
|
+
valueType: ValueType.INT
|
|
33
|
+
});
|
|
28
34
|
}
|
|
29
35
|
recordGoodbyeSent(reason) {
|
|
30
36
|
this.sentGoodbyes.add(1, {
|
|
@@ -39,4 +45,9 @@ export class PeerManagerMetrics {
|
|
|
39
45
|
recordPeerCount(count) {
|
|
40
46
|
this.peerCount.record(count);
|
|
41
47
|
}
|
|
48
|
+
recordLowScoreDisconnect(scoreState) {
|
|
49
|
+
this.lowScoreDisconnects.add(1, {
|
|
50
|
+
[Attributes.P2P_PEER_SCORE_STATE]: scoreState
|
|
51
|
+
});
|
|
52
|
+
}
|
|
42
53
|
}
|