@aztec/p2p 0.0.1-commit.cd76b27 → 0.0.1-commit.ce4f8c4f2
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/README.md +129 -3
- package/dest/client/factory.d.ts +5 -6
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +28 -26
- package/dest/client/interface.d.ts +6 -13
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +5 -13
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +25 -92
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +4 -5
- package/dest/config.d.ts +33 -15
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +86 -37
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -4
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +8 -4
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +6 -6
- package/dest/mem_pools/instrumentation.d.ts +4 -2
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +16 -14
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +2 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +4 -4
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +3 -2
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +2 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +7 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.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/eviction/low_priority_eviction_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +10 -6
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +8 -6
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +15 -9
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +3 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +48 -11
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +81 -17
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +26 -44
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +5 -3
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +6 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +3 -2
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +196 -151
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +5 -4
- package/dest/msg_validators/clock_tolerance.d.ts +1 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +4 -3
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +53 -41
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +24 -20
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
- 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/data_validator.js +35 -2
- package/dest/msg_validators/tx_validator/factory.d.ts +133 -6
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +247 -60
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +67 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +104 -37
- package/dest/msg_validators/tx_validator/index.d.ts +3 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +2 -0
- 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/metadata_validator.js +4 -4
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +22 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
- 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 +4 -2
- package/dest/services/dummy_service.d.ts +2 -3
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +1 -4
- package/dest/services/encoding.d.ts +6 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +14 -8
- package/dest/services/libp2p/libp2p_service.d.ts +20 -20
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +221 -143
- 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 +6 -0
- package/dest/services/peer-manager/peer_manager.d.ts +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +6 -3
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +11 -8
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +82 -101
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +3 -2
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +19 -11
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +52 -15
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
- package/dest/services/reqresp/reqresp.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +19 -10
- package/dest/services/service.d.ts +8 -2
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -4
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +57 -73
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +6 -7
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +4 -4
- package/dest/services/tx_collection/request_tracker.d.ts +53 -0
- package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/request_tracker.js +84 -0
- package/dest/services/tx_collection/slow_tx_collection.js +1 -1
- package/dest/services/tx_collection/tx_collection.d.ts +3 -6
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_provider.d.ts +3 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +4 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +1 -2
- package/dest/test-helpers/mock-pubsub.d.ts +7 -3
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +11 -3
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +2 -2
- package/dest/test-helpers/testbench-utils.d.ts +2 -2
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +22 -3
- package/dest/testbench/p2p_client_testbench_worker.js +10 -9
- package/dest/testbench/worker_client_manager.d.ts +3 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +6 -2
- package/dest/util.d.ts +9 -4
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +2 -9
- package/package.json +14 -14
- package/src/client/factory.ts +45 -45
- package/src/client/interface.ts +5 -19
- package/src/client/p2p_client.ts +26 -122
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +5 -8
- package/src/config.ts +125 -43
- package/src/mem_pools/attestation_pool/attestation_pool.ts +8 -7
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +6 -6
- package/src/mem_pools/instrumentation.ts +17 -13
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +2 -1
- package/src/mem_pools/tx_pool/priority.ts +4 -4
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
- package/src/mem_pools/tx_pool_v2/README.md +9 -1
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +3 -2
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +3 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +11 -1
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +2 -2
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +10 -6
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +15 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +2 -1
- package/src/mem_pools/tx_pool_v2/index.ts +1 -1
- package/src/mem_pools/tx_pool_v2/interfaces.ts +16 -8
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +115 -20
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +29 -43
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +17 -2
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +207 -154
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +5 -4
- package/src/msg_validators/clock_tolerance.ts +4 -3
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +14 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +20 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +69 -45
- package/src/msg_validators/tx_validator/README.md +119 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -3
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
- package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
- package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
- package/src/msg_validators/tx_validator/data_validator.ts +42 -1
- package/src/msg_validators/tx_validator/factory.ts +394 -78
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +123 -27
- package/src/msg_validators/tx_validator/index.ts +2 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
- package/src/services/discv5/discV5_service.ts +4 -2
- package/src/services/dummy_service.ts +1 -5
- package/src/services/encoding.ts +14 -7
- package/src/services/libp2p/libp2p_service.ts +235 -166
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +7 -3
- package/src/services/reqresp/README.md +229 -0
- package/src/services/reqresp/batch-tx-requester/README.md +46 -7
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +78 -111
- package/src/services/reqresp/batch-tx-requester/interface.ts +2 -1
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +68 -24
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
- package/src/services/reqresp/reqresp.ts +22 -12
- package/src/services/service.ts +8 -1
- package/src/services/tx_collection/fast_tx_collection.ts +57 -83
- package/src/services/tx_collection/proposal_tx_collector.ts +8 -13
- package/src/services/tx_collection/request_tracker.ts +127 -0
- package/src/services/tx_collection/slow_tx_collection.ts +1 -1
- package/src/services/tx_collection/tx_collection.ts +3 -5
- package/src/services/tx_provider.ts +2 -2
- package/src/test-helpers/make-test-p2p-clients.ts +1 -3
- package/src/test-helpers/mock-pubsub.ts +12 -6
- package/src/test-helpers/reqresp-nodes.ts +3 -6
- package/src/test-helpers/testbench-utils.ts +30 -4
- package/src/testbench/p2p_client_testbench_worker.ts +7 -12
- package/src/testbench/worker_client_manager.ts +13 -5
- package/src/util.ts +9 -13
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
- package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
- package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
- package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
2
|
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { maxBy } from '@aztec/foundation/collection';
|
|
3
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
5
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
5
6
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
@@ -16,13 +17,12 @@ import {
|
|
|
16
17
|
CheckpointProposal,
|
|
17
18
|
type CheckpointProposalCore,
|
|
18
19
|
type Gossipable,
|
|
19
|
-
P2PClientType,
|
|
20
20
|
P2PMessage,
|
|
21
|
-
type ValidationResult as P2PValidationResult,
|
|
22
21
|
PeerErrorSeverity,
|
|
22
|
+
PeerErrorSeverityByHarshness,
|
|
23
23
|
TopicType,
|
|
24
24
|
createTopicString,
|
|
25
|
-
|
|
25
|
+
getTopicsForConfig,
|
|
26
26
|
metricsTopicStrToLabels,
|
|
27
27
|
} from '@aztec/stdlib/p2p';
|
|
28
28
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
@@ -51,9 +51,10 @@ import { yamux } from '@chainsafe/libp2p-yamux';
|
|
|
51
51
|
import { bootstrap } from '@libp2p/bootstrap';
|
|
52
52
|
import { identify } from '@libp2p/identify';
|
|
53
53
|
import { type Message, type MultiaddrConnection, type PeerId, TopicValidatorResult } from '@libp2p/interface';
|
|
54
|
-
import type { ConnectionManager } from '@libp2p/interface-internal';
|
|
54
|
+
import type { AddressManager, ConnectionManager } from '@libp2p/interface-internal';
|
|
55
55
|
import { mplex } from '@libp2p/mplex';
|
|
56
56
|
import { tcp } from '@libp2p/tcp';
|
|
57
|
+
import { multiaddr } from '@multiformats/multiaddr';
|
|
57
58
|
import { ENR } from '@nethermindeth/enr';
|
|
58
59
|
import { createLibp2p } from 'libp2p';
|
|
59
60
|
|
|
@@ -69,9 +70,11 @@ import {
|
|
|
69
70
|
} from '../../msg_validators/index.js';
|
|
70
71
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
71
72
|
import {
|
|
72
|
-
type
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
type TransactionValidator,
|
|
74
|
+
createFirstStageTxValidationsForGossipedTransactions,
|
|
75
|
+
createSecondStageTxValidationsForGossipedTransactions,
|
|
76
|
+
createTxValidatorForBlockProposalReceivedTxs,
|
|
77
|
+
createTxValidatorForReqResponseReceivedTxs,
|
|
75
78
|
} from '../../msg_validators/tx_validator/factory.js';
|
|
76
79
|
import { GossipSubEvent } from '../../types/index.js';
|
|
77
80
|
import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
|
|
@@ -87,6 +90,9 @@ import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
|
87
90
|
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
88
91
|
import type { P2PReqRespConfig } from '../reqresp/config.js';
|
|
89
92
|
import {
|
|
93
|
+
AuthRequest,
|
|
94
|
+
BlockTxsRequest,
|
|
95
|
+
BlockTxsResponse,
|
|
90
96
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
91
97
|
type ReqRespInterface,
|
|
92
98
|
type ReqRespResponse,
|
|
@@ -94,14 +100,9 @@ import {
|
|
|
94
100
|
type ReqRespSubProtocolHandler,
|
|
95
101
|
type ReqRespSubProtocolHandlers,
|
|
96
102
|
type ReqRespSubProtocolValidators,
|
|
103
|
+
StatusMessage,
|
|
97
104
|
type SubProtocolMap,
|
|
98
105
|
ValidationError,
|
|
99
|
-
} from '../reqresp/index.js';
|
|
100
|
-
import {
|
|
101
|
-
AuthRequest,
|
|
102
|
-
BlockTxsRequest,
|
|
103
|
-
BlockTxsResponse,
|
|
104
|
-
StatusMessage,
|
|
105
106
|
pingHandler,
|
|
106
107
|
reqGoodbyeHandler,
|
|
107
108
|
reqRespBlockHandler,
|
|
@@ -130,12 +131,12 @@ type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: Vali
|
|
|
130
131
|
// REFACTOR: Unify with the type above
|
|
131
132
|
type ReceivedMessageValidationResult<T, M = undefined> =
|
|
132
133
|
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
|
|
133
|
-
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
|
|
134
|
+
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M; severity: PeerErrorSeverity };
|
|
134
135
|
|
|
135
136
|
/**
|
|
136
137
|
* Lib P2P implementation of the P2PService interface.
|
|
137
138
|
*/
|
|
138
|
-
export class LibP2PService
|
|
139
|
+
export class LibP2PService extends WithTracer implements P2PService {
|
|
139
140
|
private discoveryRunningPromise?: RunningPromise;
|
|
140
141
|
private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
|
|
141
142
|
|
|
@@ -174,6 +175,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
174
175
|
private checkpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
175
176
|
|
|
176
177
|
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;
|
|
177
182
|
|
|
178
183
|
private instrumentation: P2PInstrumentation;
|
|
179
184
|
|
|
@@ -182,7 +187,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
182
187
|
protected logger: Logger;
|
|
183
188
|
|
|
184
189
|
constructor(
|
|
185
|
-
private clientType: T,
|
|
186
190
|
private config: P2PConfig,
|
|
187
191
|
protected node: PubSubLibp2p,
|
|
188
192
|
private peerDiscoveryService: PeerDiscoveryService,
|
|
@@ -224,10 +228,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
224
228
|
this.protocolVersion,
|
|
225
229
|
);
|
|
226
230
|
|
|
227
|
-
|
|
228
|
-
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
|
|
231
|
+
const proposalValidatorOpts = {
|
|
229
232
|
txsPermitted: !config.disableTransactions,
|
|
230
|
-
|
|
233
|
+
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
234
|
+
};
|
|
235
|
+
this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
|
|
236
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
231
237
|
this.checkpointAttestationValidator = config.fishermanMode
|
|
232
238
|
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
233
239
|
: new CheckpointAttestationValidator(epochCache);
|
|
@@ -235,11 +241,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
235
241
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
236
242
|
|
|
237
243
|
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
238
|
-
this.logger.
|
|
239
|
-
`Handler not yet registered
|
|
244
|
+
this.logger.warn(
|
|
245
|
+
`Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
|
|
240
246
|
{ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
|
|
241
247
|
);
|
|
242
|
-
return
|
|
248
|
+
return true;
|
|
243
249
|
};
|
|
244
250
|
|
|
245
251
|
this.checkpointReceivedCallback = (
|
|
@@ -262,8 +268,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
262
268
|
* @param txPool - The transaction pool to be accessed by the service.
|
|
263
269
|
* @returns The new service.
|
|
264
270
|
*/
|
|
265
|
-
public static async new
|
|
266
|
-
clientType: T,
|
|
271
|
+
public static async new(
|
|
267
272
|
config: P2PConfig,
|
|
268
273
|
peerId: PeerId,
|
|
269
274
|
deps: {
|
|
@@ -442,8 +447,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
442
447
|
topics: topicScoreParams,
|
|
443
448
|
}),
|
|
444
449
|
}) as (components: GossipSubComponents) => GossipSub,
|
|
445
|
-
components: (components: { connectionManager: ConnectionManager }) => ({
|
|
450
|
+
components: (components: { connectionManager: ConnectionManager; addressManager: AddressManager }) => ({
|
|
446
451
|
connectionManager: components.connectionManager,
|
|
452
|
+
addressManager: components.addressManager,
|
|
447
453
|
}),
|
|
448
454
|
},
|
|
449
455
|
logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
|
|
@@ -475,7 +481,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
475
481
|
peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
476
482
|
|
|
477
483
|
return new LibP2PService(
|
|
478
|
-
clientType,
|
|
479
484
|
config,
|
|
480
485
|
node,
|
|
481
486
|
peerDiscoveryService,
|
|
@@ -503,10 +508,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
503
508
|
|
|
504
509
|
// Get listen & announce addresses for logging
|
|
505
510
|
const { p2pIp, p2pPort } = this.config;
|
|
506
|
-
if (!p2pIp) {
|
|
511
|
+
if (!p2pIp && !this.config.queryForIp) {
|
|
507
512
|
throw new Error('Announce address not provided.');
|
|
508
513
|
}
|
|
509
|
-
const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
|
|
514
|
+
const announceTcpMultiaddr = p2pIp ? convertToMultiaddr(p2pIp, p2pPort, 'tcp') : undefined;
|
|
510
515
|
|
|
511
516
|
// Create request response protocol handlers
|
|
512
517
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
@@ -549,7 +554,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
549
554
|
await this.node.start();
|
|
550
555
|
|
|
551
556
|
// Subscribe to standard GossipSub topics by default
|
|
552
|
-
for (const topic of
|
|
557
|
+
for (const topic of getTopicsForConfig(this.config.disableTransactions)) {
|
|
553
558
|
this.subscribeToTopic(this.topicStrings[topic]);
|
|
554
559
|
}
|
|
555
560
|
|
|
@@ -560,6 +565,31 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
560
565
|
if (!this.config.p2pDiscoveryDisabled) {
|
|
561
566
|
await this.peerDiscoveryService.start();
|
|
562
567
|
}
|
|
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
|
+
|
|
563
593
|
this.discoveryRunningPromise = new RunningPromise(
|
|
564
594
|
async () => {
|
|
565
595
|
await this.peerManager.heartbeat();
|
|
@@ -572,7 +602,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
572
602
|
this.logger.info(`Started P2P service`, {
|
|
573
603
|
listen: this.config.listenAddress,
|
|
574
604
|
port: this.config.p2pPort,
|
|
575
|
-
announce: announceTcpMultiaddr,
|
|
605
|
+
announce: announceTcpMultiaddr ?? 'pending (queryForIp=true)',
|
|
576
606
|
peerId: this.node.peerId.toString(),
|
|
577
607
|
});
|
|
578
608
|
}
|
|
@@ -585,6 +615,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
585
615
|
// Remove gossip sub listener
|
|
586
616
|
this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
587
617
|
|
|
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
|
+
|
|
588
624
|
// Stop peer manager
|
|
589
625
|
this.logger.debug('Stopping peer manager...');
|
|
590
626
|
await this.peerManager.stop();
|
|
@@ -754,6 +790,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
754
790
|
if (!validator || !validator.addMessage(msgId)) {
|
|
755
791
|
this.instrumentation.incMessagePrevalidationStatus(false, topicType);
|
|
756
792
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
793
|
+
if (topicType === TopicType.tx) {
|
|
794
|
+
this.logger.verbose(`Ignoring already-seen tx gossip message`, { msgId, source: source.toString() });
|
|
795
|
+
}
|
|
757
796
|
return { result: false, topicType };
|
|
758
797
|
}
|
|
759
798
|
|
|
@@ -818,9 +857,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
818
857
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
819
858
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
820
859
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
821
|
-
|
|
822
|
-
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
823
|
-
}
|
|
860
|
+
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
824
861
|
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
825
862
|
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
826
863
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
@@ -882,47 +919,113 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
882
919
|
source: PeerId,
|
|
883
920
|
topicType: TopicType,
|
|
884
921
|
): Promise<ReceivedMessageValidationResult<T, M>> {
|
|
885
|
-
|
|
922
|
+
// Default to reject result with a penalty if validation function throws an error
|
|
923
|
+
let resultAndObj: ReceivedMessageValidationResult<T, M> = {
|
|
924
|
+
result: TopicValidatorResult.Reject,
|
|
925
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
926
|
+
};
|
|
886
927
|
const timer = new Timer();
|
|
887
928
|
try {
|
|
888
929
|
resultAndObj = await validationFunc();
|
|
889
930
|
} catch (err) {
|
|
890
|
-
this.
|
|
891
|
-
this.logger.error(`Error deserializing and validating gossipsub message`, err, {
|
|
892
|
-
msgId,
|
|
893
|
-
source: source.toString(),
|
|
894
|
-
topicType,
|
|
895
|
-
});
|
|
931
|
+
this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
|
|
896
932
|
}
|
|
897
933
|
|
|
898
934
|
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
935
|
+
this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
|
|
899
936
|
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
937
|
+
} else if (resultAndObj.result === TopicValidatorResult.Reject) {
|
|
938
|
+
this.logger.warn(`Message ${topicType} rejected by validator with severity ${resultAndObj.severity}`, {
|
|
939
|
+
msgId,
|
|
940
|
+
source: source.toString(),
|
|
941
|
+
topicType,
|
|
942
|
+
severity: resultAndObj.severity,
|
|
943
|
+
});
|
|
944
|
+
this.peerManager.penalizePeer(source, resultAndObj.severity);
|
|
945
|
+
} else {
|
|
946
|
+
this.logger.trace(`Message ${topicType} ignored by validator`, { msgId, source: source.toString(), topicType });
|
|
900
947
|
}
|
|
901
948
|
|
|
902
949
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
|
|
903
950
|
return resultAndObj;
|
|
904
951
|
}
|
|
905
952
|
|
|
953
|
+
private tryDeserialize<T>(deserializeFunc: () => T, msgId: string, source: PeerId): T | undefined {
|
|
954
|
+
try {
|
|
955
|
+
return deserializeFunc();
|
|
956
|
+
} catch (err) {
|
|
957
|
+
this.logger.warn(`Failed to deserialize gossipsub message from buffer`, {
|
|
958
|
+
err,
|
|
959
|
+
msgId,
|
|
960
|
+
source: source.toString(),
|
|
961
|
+
});
|
|
962
|
+
return undefined;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
906
966
|
protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
|
|
907
967
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
908
|
-
const tx = Tx.fromBuffer(payloadData);
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
968
|
+
const tx = this.tryDeserialize(() => Tx.fromBuffer(payloadData), msgId, source);
|
|
969
|
+
if (!tx) {
|
|
970
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.LowToleranceError };
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
974
|
+
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
975
|
+
|
|
976
|
+
// Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
|
|
977
|
+
const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
978
|
+
const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
|
|
979
|
+
if (!firstStageOutcome.allPassed) {
|
|
980
|
+
const { name } = firstStageOutcome.failure;
|
|
981
|
+
let { severity } = firstStageOutcome.failure;
|
|
982
|
+
|
|
983
|
+
// Double spend validator has a special case handler. We perform more detailed examination
|
|
984
|
+
// as to how recently the nullifier was entered into the tree and if the transaction should
|
|
985
|
+
// have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
|
|
986
|
+
if (name === 'doubleSpendValidator') {
|
|
987
|
+
const txBlockNumber = BlockNumber(currentBlockNumber + 1);
|
|
988
|
+
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
|
|
992
|
+
validator: name,
|
|
993
|
+
severity,
|
|
994
|
+
source: source.toString(),
|
|
995
|
+
});
|
|
996
|
+
return { result: TopicValidatorResult.Reject, severity };
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
|
|
1000
|
+
const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
|
|
1001
|
+
if (canAdd === 'ignored') {
|
|
1002
|
+
this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
|
|
1003
|
+
source: source.toString(),
|
|
913
1004
|
});
|
|
914
|
-
return { result: TopicValidatorResult.
|
|
1005
|
+
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
915
1006
|
}
|
|
916
1007
|
|
|
917
|
-
//
|
|
1008
|
+
// Stage 2: expensive proof verification
|
|
1009
|
+
const secondStageValidators = this.createSecondStageMessageValidators();
|
|
1010
|
+
const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
|
|
1011
|
+
if (!secondStageOutcome.allPassed) {
|
|
1012
|
+
const { severity, name } = secondStageOutcome.failure;
|
|
1013
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
|
|
1014
|
+
validator: name,
|
|
1015
|
+
severity,
|
|
1016
|
+
source: source.toString(),
|
|
1017
|
+
});
|
|
1018
|
+
return { result: TopicValidatorResult.Reject, severity };
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// Pool add: persist the tx
|
|
918
1022
|
const txHash = tx.getTxHash();
|
|
919
1023
|
const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
|
|
920
1024
|
|
|
921
1025
|
const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
|
|
922
1026
|
const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
|
|
923
1027
|
|
|
924
|
-
this.logger.
|
|
925
|
-
isValid,
|
|
1028
|
+
this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
|
|
926
1029
|
wasAccepted,
|
|
927
1030
|
wasIgnored,
|
|
928
1031
|
[Attributes.P2P_ID]: source.toString(),
|
|
@@ -933,7 +1036,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
933
1036
|
} else if (wasIgnored) {
|
|
934
1037
|
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
935
1038
|
} else {
|
|
936
|
-
|
|
1039
|
+
this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
|
|
1040
|
+
source: source.toString(),
|
|
1041
|
+
txHash: txHash.toString(),
|
|
1042
|
+
});
|
|
1043
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
|
|
937
1044
|
}
|
|
938
1045
|
};
|
|
939
1046
|
|
|
@@ -963,7 +1070,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
963
1070
|
source: PeerId,
|
|
964
1071
|
): Promise<void> {
|
|
965
1072
|
const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
|
|
966
|
-
() =>
|
|
1073
|
+
() => {
|
|
1074
|
+
const attestation = this.tryDeserialize(() => CheckpointAttestation.fromBuffer(payloadData), msgId, source);
|
|
1075
|
+
if (!attestation) {
|
|
1076
|
+
return Promise.resolve({
|
|
1077
|
+
result: TopicValidatorResult.Reject,
|
|
1078
|
+
severity: PeerErrorSeverity.LowToleranceError,
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
return this.validateAndStoreCheckpointAttestation(source, attestation);
|
|
1082
|
+
},
|
|
967
1083
|
msgId,
|
|
968
1084
|
source,
|
|
969
1085
|
TopicType.checkpoint_attestation,
|
|
@@ -996,8 +1112,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
996
1112
|
|
|
997
1113
|
if (validationResult.result === 'reject') {
|
|
998
1114
|
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
999
|
-
|
|
1000
|
-
return { result: TopicValidatorResult.Reject };
|
|
1115
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1001
1116
|
}
|
|
1002
1117
|
|
|
1003
1118
|
if (validationResult.result === 'ignore') {
|
|
@@ -1023,16 +1138,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1023
1138
|
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1024
1139
|
}
|
|
1025
1140
|
|
|
1026
|
-
// Could not add (cap reached for signer),
|
|
1141
|
+
// Could not add (cap reached for signer), penalize and do not re-broadcast
|
|
1027
1142
|
if (!added) {
|
|
1028
|
-
this.logger.warn(`
|
|
1143
|
+
this.logger.warn(`Rejecting checkpoint attestation due to cap`, {
|
|
1029
1144
|
slot: slot.toString(),
|
|
1030
1145
|
archive: attestation.archive.toString(),
|
|
1031
1146
|
source: peerId.toString(),
|
|
1032
1147
|
attester: attestation.getSender()?.toString(),
|
|
1033
1148
|
count,
|
|
1034
1149
|
});
|
|
1035
|
-
return { result: TopicValidatorResult.
|
|
1150
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
|
|
1036
1151
|
}
|
|
1037
1152
|
|
|
1038
1153
|
// Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
|
|
@@ -1087,8 +1202,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1087
1202
|
|
|
1088
1203
|
if (validationResult.result === 'reject') {
|
|
1089
1204
|
this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1090
|
-
|
|
1091
|
-
return { result: TopicValidatorResult.Reject };
|
|
1205
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1092
1206
|
}
|
|
1093
1207
|
|
|
1094
1208
|
if (validationResult.result === 'ignore') {
|
|
@@ -1112,7 +1226,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1112
1226
|
|
|
1113
1227
|
// Too many blocks received for this slot and index, penalize peer and do not re-broadcast
|
|
1114
1228
|
if (!added) {
|
|
1115
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1116
1229
|
this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
|
|
1117
1230
|
...block.toBlockInfo(),
|
|
1118
1231
|
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
@@ -1120,7 +1233,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1120
1233
|
proposer: block.getSender()?.toString(),
|
|
1121
1234
|
source: peerId.toString(),
|
|
1122
1235
|
});
|
|
1123
|
-
return {
|
|
1236
|
+
return {
|
|
1237
|
+
result: TopicValidatorResult.Reject,
|
|
1238
|
+
metadata: { isEquivocated },
|
|
1239
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
1240
|
+
};
|
|
1124
1241
|
}
|
|
1125
1242
|
|
|
1126
1243
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
@@ -1165,7 +1282,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1165
1282
|
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1166
1283
|
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1167
1284
|
if (!isValid) {
|
|
1168
|
-
this.logger.
|
|
1285
|
+
this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1169
1286
|
}
|
|
1170
1287
|
}
|
|
1171
1288
|
|
|
@@ -1213,8 +1330,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1213
1330
|
|
|
1214
1331
|
if (validationResult.result === 'reject') {
|
|
1215
1332
|
this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1216
|
-
|
|
1217
|
-
return { result: TopicValidatorResult.Reject };
|
|
1333
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1218
1334
|
}
|
|
1219
1335
|
|
|
1220
1336
|
if (validationResult.result === 'ignore') {
|
|
@@ -1229,20 +1345,21 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1229
1345
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1230
1346
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
1231
1347
|
});
|
|
1232
|
-
const
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
metadata: { isEquivocated } = {},
|
|
1236
|
-
} = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1237
|
-
if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1348
|
+
const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1349
|
+
const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
|
|
1350
|
+
if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1238
1351
|
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1239
1352
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1240
1353
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
1241
1354
|
isEquivocated,
|
|
1242
|
-
result,
|
|
1355
|
+
result: blockProposalResult.result,
|
|
1243
1356
|
});
|
|
1244
|
-
return {
|
|
1245
|
-
|
|
1357
|
+
return {
|
|
1358
|
+
result: TopicValidatorResult.Reject,
|
|
1359
|
+
severity:
|
|
1360
|
+
'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError,
|
|
1361
|
+
};
|
|
1362
|
+
} else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1246
1363
|
processBlock = true;
|
|
1247
1364
|
}
|
|
1248
1365
|
}
|
|
@@ -1269,13 +1386,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1269
1386
|
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1270
1387
|
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1271
1388
|
if (!added) {
|
|
1272
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1273
1389
|
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1274
1390
|
...checkpoint.toCheckpointInfo(),
|
|
1275
1391
|
count,
|
|
1276
1392
|
source: peerId.toString(),
|
|
1277
1393
|
});
|
|
1278
|
-
return {
|
|
1394
|
+
return {
|
|
1395
|
+
result: TopicValidatorResult.Reject,
|
|
1396
|
+
obj: checkpoint,
|
|
1397
|
+
metadata: { isEquivocated, processBlock },
|
|
1398
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
1399
|
+
};
|
|
1279
1400
|
}
|
|
1280
1401
|
|
|
1281
1402
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
@@ -1537,43 +1658,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1537
1658
|
}
|
|
1538
1659
|
|
|
1539
1660
|
protected createRequestedTxValidator(): TxValidator {
|
|
1540
|
-
return
|
|
1661
|
+
return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
|
|
1541
1662
|
l1ChainId: this.config.l1ChainId,
|
|
1542
1663
|
rollupVersion: this.config.rollupVersion,
|
|
1543
1664
|
});
|
|
1544
1665
|
}
|
|
1545
1666
|
|
|
1546
|
-
@trackSpan('Libp2pService.validatePropagatedTx', tx => ({
|
|
1547
|
-
[Attributes.TX_HASH]: tx.getTxHash().toString(),
|
|
1548
|
-
}))
|
|
1549
|
-
protected async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
|
|
1550
|
-
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
1551
|
-
|
|
1552
|
-
// We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
|
|
1553
|
-
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1554
|
-
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
1555
|
-
|
|
1556
|
-
for (const validator of messageValidators) {
|
|
1557
|
-
const outcome = await this.runValidations(tx, validator);
|
|
1558
|
-
|
|
1559
|
-
if (outcome.allPassed) {
|
|
1560
|
-
continue;
|
|
1561
|
-
}
|
|
1562
|
-
const { name } = outcome.failure;
|
|
1563
|
-
let { severity } = outcome.failure;
|
|
1564
|
-
|
|
1565
|
-
// Double spend validator has a special case handler
|
|
1566
|
-
if (name === 'doubleSpendValidator') {
|
|
1567
|
-
const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
|
|
1568
|
-
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1572
|
-
return false;
|
|
1573
|
-
}
|
|
1574
|
-
return true;
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
1667
|
private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
|
|
1578
1668
|
if (blockNumber === this.feesCache?.blockNumber) {
|
|
1579
1669
|
return this.feesCache.gasFees;
|
|
@@ -1601,60 +1691,62 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1601
1691
|
};
|
|
1602
1692
|
}
|
|
1603
1693
|
|
|
1604
|
-
public async
|
|
1605
|
-
const
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1694
|
+
public async validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void> {
|
|
1695
|
+
const validator = createTxValidatorForBlockProposalReceivedTxs(
|
|
1696
|
+
this.proofVerifier,
|
|
1697
|
+
{ l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
|
|
1698
|
+
this.logger.getBindings(),
|
|
1699
|
+
);
|
|
1610
1700
|
|
|
1611
|
-
await Promise.all(
|
|
1701
|
+
const results = await Promise.all(
|
|
1612
1702
|
txs.map(async tx => {
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
if (!outcome.allPassed) {
|
|
1616
|
-
throw new Error('Invalid tx detected', { cause: { outcome } });
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1703
|
+
const result = await validator.validateTx(tx);
|
|
1704
|
+
return result.result !== 'invalid';
|
|
1619
1705
|
}),
|
|
1620
1706
|
);
|
|
1707
|
+
if (results.some(value => value === false)) {
|
|
1708
|
+
throw new Error('Invalid tx detected');
|
|
1709
|
+
}
|
|
1621
1710
|
}
|
|
1622
1711
|
|
|
1623
|
-
/**
|
|
1624
|
-
|
|
1625
|
-
*
|
|
1626
|
-
* Each validator is a pair of a validator and a severity.
|
|
1627
|
-
* If a validator fails, the peer is penalized with the severity of the validator.
|
|
1628
|
-
*
|
|
1629
|
-
* @param currentBlockNumber - The current synced block number.
|
|
1630
|
-
* @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
|
|
1631
|
-
* @returns The message validators.
|
|
1632
|
-
*/
|
|
1633
|
-
private async createMessageValidators(
|
|
1712
|
+
/** Creates the first stage (fast) validators for gossiped transactions. */
|
|
1713
|
+
protected async createFirstStageMessageValidators(
|
|
1634
1714
|
currentBlockNumber: BlockNumber,
|
|
1635
1715
|
nextSlotTimestamp: UInt64,
|
|
1636
|
-
): Promise<Record<string,
|
|
1716
|
+
): Promise<Record<string, TransactionValidator>> {
|
|
1637
1717
|
const gasFees = await this.getGasFees(currentBlockNumber);
|
|
1638
|
-
const allowedInSetup =
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1718
|
+
const allowedInSetup = [
|
|
1719
|
+
...(await getDefaultAllowedSetupFunctions()),
|
|
1720
|
+
...(this.config.txPublicSetupAllowListExtend ?? []),
|
|
1721
|
+
];
|
|
1722
|
+
const blockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1723
|
+
const l1Constants = await this.archiver.getL1Constants();
|
|
1724
|
+
|
|
1725
|
+
return createFirstStageTxValidationsForGossipedTransactions(
|
|
1643
1726
|
nextSlotTimestamp,
|
|
1644
|
-
|
|
1727
|
+
blockNumber,
|
|
1645
1728
|
this.worldStateSynchronizer,
|
|
1646
1729
|
gasFees,
|
|
1647
1730
|
this.config.l1ChainId,
|
|
1648
1731
|
this.config.rollupVersion,
|
|
1649
1732
|
protocolContractsHash,
|
|
1650
1733
|
this.archiver,
|
|
1651
|
-
this.proofVerifier,
|
|
1652
1734
|
!this.config.disableTransactions,
|
|
1653
1735
|
allowedInSetup,
|
|
1654
1736
|
this.logger.getBindings(),
|
|
1737
|
+
{
|
|
1738
|
+
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
1739
|
+
maxBlockL2Gas: this.config.validateMaxL2BlockGas,
|
|
1740
|
+
maxBlockDAGas: this.config.validateMaxDABlockGas,
|
|
1741
|
+
},
|
|
1655
1742
|
);
|
|
1656
1743
|
}
|
|
1657
1744
|
|
|
1745
|
+
/** Creates the second stage (expensive proof verification) validators for gossiped transactions. */
|
|
1746
|
+
protected createSecondStageMessageValidators(): Record<string, TransactionValidator> {
|
|
1747
|
+
return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1658
1750
|
/**
|
|
1659
1751
|
* Run validations on a tx.
|
|
1660
1752
|
* @param tx - The tx to validate.
|
|
@@ -1663,7 +1755,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1663
1755
|
*/
|
|
1664
1756
|
private async runValidations(
|
|
1665
1757
|
tx: Tx,
|
|
1666
|
-
messageValidators: Record<string,
|
|
1758
|
+
messageValidators: Record<string, TransactionValidator>,
|
|
1667
1759
|
): Promise<ValidationOutcome> {
|
|
1668
1760
|
const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
|
|
1669
1761
|
const { result } = await validator.validateTx(tx);
|
|
@@ -1672,8 +1764,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1672
1764
|
|
|
1673
1765
|
// A promise that resolves when all validations have been run
|
|
1674
1766
|
const allValidations = await Promise.all(validationPromises);
|
|
1675
|
-
const
|
|
1676
|
-
if (
|
|
1767
|
+
const failures = allValidations.filter(x => !x.isValid);
|
|
1768
|
+
if (failures.length > 0) {
|
|
1769
|
+
// Pick the most severe failure (lowest tolerance = harshest penalty)
|
|
1770
|
+
const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
|
|
1677
1771
|
return {
|
|
1678
1772
|
allPassed: false,
|
|
1679
1773
|
failure: {
|
|
@@ -1726,31 +1820,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1726
1820
|
return PeerErrorSeverity.HighToleranceError;
|
|
1727
1821
|
}
|
|
1728
1822
|
|
|
1729
|
-
/**
|
|
1730
|
-
* Validate a checkpoint attestation.
|
|
1731
|
-
*
|
|
1732
|
-
* @param attestation - The checkpoint attestation to validate.
|
|
1733
|
-
* @returns True if the checkpoint attestation is valid, false otherwise.
|
|
1734
|
-
*/
|
|
1735
|
-
@trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
|
|
1736
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
1737
|
-
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1738
|
-
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1739
|
-
}))
|
|
1740
|
-
public async validateCheckpointAttestation(
|
|
1741
|
-
peerId: PeerId,
|
|
1742
|
-
attestation: CheckpointAttestation,
|
|
1743
|
-
): Promise<P2PValidationResult> {
|
|
1744
|
-
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1745
|
-
|
|
1746
|
-
if (result.result === 'reject') {
|
|
1747
|
-
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1748
|
-
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1749
|
-
}
|
|
1750
|
-
|
|
1751
|
-
return result;
|
|
1752
|
-
}
|
|
1753
|
-
|
|
1754
1823
|
public getPeerScore(peerId: PeerId): number {
|
|
1755
1824
|
return this.node.services.pubsub.score.score(peerId.toString());
|
|
1756
1825
|
}
|