@aztec/p2p 0.0.0-test.0 → 0.0.1-commit.023c3e5
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 +4 -3
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +26 -13
- package/dest/client/factory.d.ts +15 -5
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +61 -25
- package/dest/client/index.d.ts +2 -1
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +1 -0
- package/dest/client/interface.d.ts +170 -0
- package/dest/client/interface.d.ts.map +1 -0
- package/dest/client/interface.js +9 -0
- package/dest/client/p2p_client.d.ts +75 -193
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +765 -229
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +2 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +1 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +305 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +73 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +1 -0
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +8 -0
- package/dest/config.d.ts +154 -125
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +182 -34
- package/dest/enr/generate-enr.d.ts +11 -3
- package/dest/enr/generate-enr.d.ts.map +1 -1
- package/dest/enr/generate-enr.js +27 -5
- 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 +4 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +104 -25
- 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 +299 -174
- package/dest/mem_pools/attestation_pool/index.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +29 -11
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +168 -62
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +24 -10
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +133 -82
- package/dest/mem_pools/attestation_pool/mocks.d.ts +234 -11
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +19 -21
- package/dest/mem_pools/index.d.ts +1 -1
- package/dest/mem_pools/instrumentation.d.ts +16 -12
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +56 -41
- package/dest/mem_pools/interface.d.ts +3 -4
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +75 -16
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +493 -142
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +32 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +112 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +157 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +52 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +78 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
- package/dest/mem_pools/tx_pool/index.d.ts +1 -2
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/index.js +0 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +7 -2
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +72 -11
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- 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 +276 -45
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +7 -5
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +79 -10
- 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 +76 -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/clock_tolerance.d.ts +21 -0
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
- package/dest/msg_validators/clock_tolerance.js +37 -0
- package/dest/msg_validators/index.d.ts +2 -2
- package/dest/msg_validators/index.d.ts.map +1 -1
- package/dest/msg_validators/index.js +1 -1
- package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +10 -0
- package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -0
- package/dest/msg_validators/msg_seen_validator/msg_seen_validator.js +36 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
- package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/index.js +3 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.js +104 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +212 -0
- 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 +3 -0
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +27 -0
- package/dest/msg_validators/tx_validator/archive_cache.d.ts +14 -0
- package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/archive_cache.js +22 -0
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +5 -4
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +7 -6
- package/dest/msg_validators/tx_validator/data_validator.d.ts +3 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +60 -87
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +3 -4
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +24 -29
- package/dest/msg_validators/tx_validator/factory.d.ts +21 -0
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/factory.js +84 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +20 -0
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +12 -0
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/gas_validator.js +110 -0
- package/dest/msg_validators/tx_validator/index.d.ts +9 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +8 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +10 -5
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +40 -21
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +15 -0
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/phases_validator.js +93 -0
- package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
- package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/size_validator.js +23 -0
- package/dest/msg_validators/tx_validator/test_utils.d.ts +17 -0
- package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/test_utils.js +22 -0
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +14 -0
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/timestamp_validator.js +32 -0
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_permitted_validator.js +24 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +8 -7
- package/dest/services/data_store.d.ts +1 -1
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/data_store.js +10 -6
- package/dest/services/discv5/discV5_service.d.ts +10 -9
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +64 -37
- package/dest/services/dummy_service.d.ts +66 -11
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +130 -5
- package/dest/services/encoding.d.ts +26 -7
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +75 -6
- package/dest/services/gossipsub/scoring.d.ts +1 -1
- package/dest/services/index.d.ts +5 -1
- package/dest/services/index.d.ts.map +1 -1
- package/dest/services/index.js +4 -0
- package/dest/services/libp2p/instrumentation.d.ts +20 -0
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -0
- package/dest/services/libp2p/instrumentation.js +122 -0
- package/dest/services/libp2p/libp2p_service.d.ts +107 -95
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +1328 -313
- package/dest/services/peer-manager/interface.d.ts +23 -0
- package/dest/services/peer-manager/interface.d.ts.map +1 -0
- package/dest/services/peer-manager/interface.js +1 -0
- package/dest/services/peer-manager/metrics.d.ts +12 -3
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +44 -12
- package/dest/services/peer-manager/peer_manager.d.ts +103 -23
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +551 -82
- 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 +43 -2
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +47 -0
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +566 -0
- package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
- package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +50 -0
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +37 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +151 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +54 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +139 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +20 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +21 -0
- package/dest/services/reqresp/config.d.ts +11 -9
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/config.js +18 -4
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +23 -4
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +73 -10
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +32 -17
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +154 -84
- package/dest/services/reqresp/constants.d.ts +12 -0
- package/dest/services/reqresp/constants.d.ts.map +1 -0
- package/dest/services/reqresp/constants.js +7 -0
- package/dest/services/reqresp/index.d.ts +3 -2
- package/dest/services/reqresp/index.d.ts.map +1 -1
- package/dest/services/reqresp/index.js +2 -1
- package/dest/services/reqresp/interface.d.ts +75 -24
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +46 -27
- package/dest/services/reqresp/metrics.d.ts +6 -5
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.js +17 -21
- package/dest/services/reqresp/protocols/auth.d.ts +43 -0
- package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/auth.js +71 -0
- package/dest/services/reqresp/protocols/block.d.ts +6 -1
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block.js +30 -6
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +34 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +87 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +11 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +52 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +59 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +105 -0
- package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
- package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
- package/dest/services/reqresp/protocols/goodbye.d.ts +3 -5
- package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/goodbye.js +7 -7
- package/dest/services/reqresp/protocols/index.d.ts +3 -1
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.js +2 -0
- package/dest/services/reqresp/protocols/ping.d.ts +1 -3
- package/dest/services/reqresp/protocols/ping.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.d.ts +40 -7
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +76 -5
- package/dest/services/reqresp/protocols/tx.d.ts +14 -4
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +34 -6
- package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +6 -4
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -2
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +21 -1
- package/dest/services/reqresp/reqresp.d.ts +29 -66
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +753 -248
- package/dest/services/reqresp/status.d.ts +10 -4
- package/dest/services/reqresp/status.d.ts.map +1 -1
- package/dest/services/reqresp/status.js +9 -2
- package/dest/services/service.d.ts +40 -20
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +28 -0
- package/dest/services/tx_collection/config.d.ts.map +1 -0
- package/dest/services/tx_collection/config.js +66 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +53 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/fast_tx_collection.js +311 -0
- package/dest/services/tx_collection/index.d.ts +4 -0
- package/dest/services/tx_collection/index.d.ts.map +1 -0
- package/dest/services/tx_collection/index.js +3 -0
- package/dest/services/tx_collection/instrumentation.d.ts +10 -0
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
- package/dest/services/tx_collection/instrumentation.js +31 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +48 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -0
- package/dest/services/tx_collection/proposal_tx_collector.js +50 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +53 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/slow_tx_collection.js +177 -0
- package/dest/services/tx_collection/tx_collection.d.ts +110 -0
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/tx_collection.js +128 -0
- package/dest/services/tx_collection/tx_collection_sink.d.ts +30 -0
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
- package/dest/services/tx_collection/tx_collection_sink.js +111 -0
- package/dest/services/tx_collection/tx_source.d.ts +18 -0
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
- package/dest/services/tx_collection/tx_source.js +31 -0
- package/dest/services/tx_provider.d.ts +51 -0
- package/dest/services/tx_provider.d.ts.map +1 -0
- package/dest/services/tx_provider.js +219 -0
- package/dest/services/tx_provider_instrumentation.d.ts +16 -0
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
- package/dest/services/tx_provider_instrumentation.js +34 -0
- 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 +4 -1
- package/dest/test-helpers/index.d.ts.map +1 -1
- package/dest/test-helpers/index.js +3 -0
- package/dest/test-helpers/make-enrs.d.ts +1 -1
- package/dest/test-helpers/make-enrs.d.ts.map +1 -1
- package/dest/test-helpers/make-enrs.js +4 -5
- package/dest/test-helpers/make-test-p2p-clients.d.ts +33 -5
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +86 -16
- package/dest/test-helpers/mock-pubsub.d.ts +59 -0
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -0
- package/dest/test-helpers/mock-pubsub.js +130 -0
- package/dest/test-helpers/mock-tx-helpers.d.ts +12 -0
- package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -0
- package/dest/test-helpers/mock-tx-helpers.js +19 -0
- package/dest/test-helpers/reqresp-nodes.d.ts +15 -11
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +62 -28
- package/dest/test-helpers/test_tx_provider.d.ts +40 -0
- package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
- package/dest/test-helpers/test_tx_provider.js +41 -0
- package/dest/test-helpers/testbench-utils.d.ts +158 -0
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
- package/dest/test-helpers/testbench-utils.js +297 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts +28 -2
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +259 -90
- package/dest/testbench/parse_log_file.d.ts +1 -1
- package/dest/testbench/parse_log_file.js +4 -4
- package/dest/testbench/testbench.d.ts +1 -1
- package/dest/testbench/testbench.js +4 -4
- package/dest/testbench/worker_client_manager.d.ts +51 -11
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +232 -53
- package/dest/types/index.d.ts +4 -2
- package/dest/types/index.d.ts.map +1 -1
- package/dest/types/index.js +2 -0
- package/dest/util.d.ts +24 -16
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +75 -69
- package/dest/versioning.d.ts +4 -4
- package/dest/versioning.d.ts.map +1 -1
- package/dest/versioning.js +8 -3
- package/package.json +32 -27
- package/src/bootstrap/bootstrap.ts +34 -15
- package/src/client/factory.ts +135 -53
- package/src/client/index.ts +1 -0
- package/src/client/interface.ts +213 -0
- package/src/client/p2p_client.ts +476 -383
- package/src/client/test/tx_proposal_collector/README.md +227 -0
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +336 -0
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
- package/src/config.ts +304 -134
- package/src/enr/generate-enr.ts +39 -6
- package/src/errors/attestation-pool.error.ts +13 -0
- package/src/index.ts +4 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +119 -24
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +352 -201
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +233 -72
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +199 -96
- package/src/mem_pools/attestation_pool/mocks.ts +24 -17
- package/src/mem_pools/instrumentation.ts +72 -48
- package/src/mem_pools/interface.ts +2 -4
- package/src/mem_pools/tx_pool/README.md +270 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +580 -143
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +132 -0
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +208 -0
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +93 -0
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
- package/src/mem_pools/tx_pool/index.ts +0 -1
- package/src/mem_pools/tx_pool/priority.ts +9 -2
- package/src/mem_pools/tx_pool/tx_pool.ts +75 -10
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +225 -36
- package/src/msg_validators/attestation_validator/attestation_validator.ts +72 -14
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +94 -0
- package/src/msg_validators/attestation_validator/index.ts +1 -0
- package/src/msg_validators/clock_tolerance.ts +51 -0
- package/src/msg_validators/index.ts +1 -1
- package/src/msg_validators/msg_seen_validator/msg_seen_validator.ts +36 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
- package/src/msg_validators/proposal_validator/index.ts +3 -0
- package/src/msg_validators/proposal_validator/proposal_validator.ts +92 -0
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +230 -0
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +35 -0
- package/src/msg_validators/tx_validator/archive_cache.ts +28 -0
- package/src/msg_validators/tx_validator/block_header_validator.ts +10 -9
- package/src/msg_validators/tx_validator/data_validator.ts +95 -71
- package/src/msg_validators/tx_validator/double_spend_validator.ts +23 -20
- package/src/msg_validators/tx_validator/factory.ts +151 -0
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
- package/src/msg_validators/tx_validator/gas_validator.ts +123 -0
- package/src/msg_validators/tx_validator/index.ts +8 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +72 -24
- package/src/msg_validators/tx_validator/phases_validator.ts +118 -0
- package/src/msg_validators/tx_validator/size_validator.ts +22 -0
- package/src/msg_validators/tx_validator/test_utils.ts +43 -0
- package/src/msg_validators/tx_validator/timestamp_validator.ts +52 -0
- package/src/msg_validators/tx_validator/tx_permitted_validator.ts +22 -0
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +14 -8
- package/src/services/data_store.ts +10 -7
- package/src/services/discv5/discV5_service.ts +85 -39
- package/src/services/dummy_service.ts +198 -9
- package/src/services/encoding.ts +82 -6
- package/src/services/index.ts +4 -0
- package/src/services/libp2p/instrumentation.ts +126 -0
- package/src/services/libp2p/libp2p_service.ts +1170 -353
- package/src/services/peer-manager/interface.ts +29 -0
- package/src/services/peer-manager/metrics.ts +55 -12
- package/src/services/peer-manager/peer_manager.ts +657 -80
- package/src/services/peer-manager/peer_scoring.ts +45 -3
- package/src/services/reqresp/batch-tx-requester/README.md +305 -0
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +706 -0
- package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
- package/src/services/reqresp/batch-tx-requester/interface.ts +57 -0
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +209 -0
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +205 -0
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
- package/src/services/reqresp/config.ts +26 -9
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +77 -10
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +166 -95
- package/src/services/reqresp/constants.ts +14 -0
- package/src/services/reqresp/index.ts +2 -0
- package/src/services/reqresp/interface.ts +95 -37
- package/src/services/reqresp/metrics.ts +40 -28
- package/src/services/reqresp/protocols/auth.ts +83 -0
- package/src/services/reqresp/protocols/block.ts +26 -4
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +106 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +67 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +121 -0
- package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
- package/src/services/reqresp/protocols/goodbye.ts +9 -7
- package/src/services/reqresp/protocols/index.ts +2 -0
- package/src/services/reqresp/protocols/status.ts +121 -5
- package/src/services/reqresp/protocols/tx.ts +36 -8
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +12 -3
- package/src/services/reqresp/rate-limiter/rate_limits.ts +21 -1
- package/src/services/reqresp/reqresp.ts +449 -271
- package/src/services/reqresp/status.ts +12 -3
- package/src/services/service.ts +65 -22
- package/src/services/tx_collection/config.ts +98 -0
- package/src/services/tx_collection/fast_tx_collection.ts +364 -0
- package/src/services/tx_collection/index.ts +7 -0
- package/src/services/tx_collection/instrumentation.ts +35 -0
- package/src/services/tx_collection/proposal_tx_collector.ts +114 -0
- package/src/services/tx_collection/slow_tx_collection.ts +233 -0
- package/src/services/tx_collection/tx_collection.ts +216 -0
- package/src/services/tx_collection/tx_collection_sink.ts +129 -0
- package/src/services/tx_collection/tx_source.ts +37 -0
- package/src/services/tx_provider.ts +232 -0
- package/src/services/tx_provider_instrumentation.ts +54 -0
- package/src/test-helpers/index.ts +3 -0
- package/src/test-helpers/make-enrs.ts +4 -5
- package/src/test-helpers/make-test-p2p-clients.ts +111 -21
- package/src/test-helpers/mock-pubsub.ts +188 -0
- package/src/test-helpers/mock-tx-helpers.ts +24 -0
- package/src/test-helpers/reqresp-nodes.ts +87 -36
- package/src/test-helpers/test_tx_provider.ts +64 -0
- package/src/test-helpers/testbench-utils.ts +374 -0
- package/src/testbench/p2p_client_testbench_worker.ts +434 -89
- package/src/testbench/parse_log_file.ts +4 -4
- package/src/testbench/testbench.ts +4 -4
- package/src/testbench/worker_client_manager.ts +315 -59
- package/src/types/index.ts +2 -0
- package/src/util.ts +105 -91
- package/src/versioning.ts +11 -4
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -56
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -141
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -8
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -21
- package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.js +0 -1
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -174
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -29
- package/src/msg_validators/block_proposal_validator/index.ts +0 -1
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
// @attribution: lodestar impl for inspiration
|
|
2
|
-
import {
|
|
2
|
+
import { compactArray } from '@aztec/foundation/collection';
|
|
3
|
+
import { AbortError, TimeoutError } from '@aztec/foundation/error';
|
|
4
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
5
|
import { executeTimeout } from '@aztec/foundation/timer';
|
|
4
6
|
import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
5
7
|
import { Attributes, type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
6
8
|
|
|
7
9
|
import type { IncomingStreamData, PeerId, Stream } from '@libp2p/interface';
|
|
8
|
-
import { pipe } from 'it-pipe';
|
|
9
10
|
import type { Libp2p } from 'libp2p';
|
|
11
|
+
import { pipeline } from 'node:stream/promises';
|
|
10
12
|
import type { Uint8ArrayList } from 'uint8arraylist';
|
|
11
13
|
|
|
12
14
|
import {
|
|
@@ -16,18 +18,24 @@ import {
|
|
|
16
18
|
} from '../../errors/reqresp.error.js';
|
|
17
19
|
import { SnappyTransform } from '../encoding.js';
|
|
18
20
|
import type { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
19
|
-
import
|
|
21
|
+
import {
|
|
22
|
+
DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS,
|
|
23
|
+
DEFAULT_REQRESP_DIAL_TIMEOUT_MS,
|
|
24
|
+
type P2PReqRespConfig,
|
|
25
|
+
} from './config.js';
|
|
20
26
|
import { BatchConnectionSampler } from './connection-sampler/batch_connection_sampler.js';
|
|
21
|
-
import { ConnectionSampler } from './connection-sampler/connection_sampler.js';
|
|
27
|
+
import { ConnectionSampler, RandomSampler } from './connection-sampler/connection_sampler.js';
|
|
22
28
|
import {
|
|
23
|
-
DEFAULT_SUB_PROTOCOL_HANDLERS,
|
|
24
29
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
30
|
+
type ReqRespInterface,
|
|
25
31
|
type ReqRespResponse,
|
|
26
32
|
ReqRespSubProtocol,
|
|
33
|
+
type ReqRespSubProtocolHandler,
|
|
27
34
|
type ReqRespSubProtocolHandlers,
|
|
35
|
+
type ReqRespSubProtocolRateLimits,
|
|
28
36
|
type ReqRespSubProtocolValidators,
|
|
29
37
|
type SubProtocolMap,
|
|
30
|
-
|
|
38
|
+
responseFromBuffer,
|
|
31
39
|
} from './interface.js';
|
|
32
40
|
import { ReqRespMetrics } from './metrics.js';
|
|
33
41
|
import {
|
|
@@ -51,15 +59,12 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
51
59
|
*
|
|
52
60
|
* see: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#the-reqresp-domain
|
|
53
61
|
*/
|
|
54
|
-
export class ReqResp {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
private overallRequestTimeoutMs: number;
|
|
58
|
-
private individualRequestTimeoutMs: number;
|
|
62
|
+
export class ReqResp implements ReqRespInterface {
|
|
63
|
+
private individualRequestTimeoutMs: number = DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS;
|
|
64
|
+
private dialTimeoutMs: number = DEFAULT_REQRESP_DIAL_TIMEOUT_MS;
|
|
59
65
|
|
|
60
|
-
|
|
61
|
-
private
|
|
62
|
-
private subProtocolValidators: ReqRespSubProtocolValidators = DEFAULT_SUB_PROTOCOL_VALIDATORS;
|
|
66
|
+
private subProtocolHandlers: Partial<ReqRespSubProtocolHandlers> = {};
|
|
67
|
+
private subProtocolValidators: Partial<ReqRespSubProtocolValidators> = {};
|
|
63
68
|
|
|
64
69
|
private connectionSampler: ConnectionSampler;
|
|
65
70
|
private rateLimiter: RequestResponseRateLimiter;
|
|
@@ -72,35 +77,57 @@ export class ReqResp {
|
|
|
72
77
|
config: P2PReqRespConfig,
|
|
73
78
|
private libp2p: Libp2p,
|
|
74
79
|
private peerScoring: PeerScoring,
|
|
80
|
+
private logger = createLogger('p2p:reqresp'),
|
|
81
|
+
rateLimits: Partial<ReqRespSubProtocolRateLimits> = {},
|
|
75
82
|
telemetryClient: TelemetryClient = getTelemetryClient(),
|
|
76
83
|
) {
|
|
77
|
-
this.
|
|
84
|
+
this.updateConfig(config);
|
|
78
85
|
|
|
79
|
-
this.
|
|
80
|
-
this.individualRequestTimeoutMs = config.individualRequestTimeoutMs;
|
|
81
|
-
|
|
82
|
-
this.rateLimiter = new RequestResponseRateLimiter(peerScoring);
|
|
86
|
+
this.rateLimiter = new RequestResponseRateLimiter(peerScoring, rateLimits);
|
|
83
87
|
|
|
84
88
|
// Connection sampler is used to sample our connected peers
|
|
85
|
-
this.connectionSampler = new ConnectionSampler(
|
|
89
|
+
this.connectionSampler = new ConnectionSampler(
|
|
90
|
+
libp2p,
|
|
91
|
+
new RandomSampler(),
|
|
92
|
+
createLogger(`${logger.module}:connection-sampler`),
|
|
93
|
+
config,
|
|
94
|
+
);
|
|
86
95
|
|
|
87
96
|
this.snappyTransform = new SnappyTransform();
|
|
88
97
|
this.metrics = new ReqRespMetrics(telemetryClient);
|
|
89
98
|
}
|
|
90
99
|
|
|
100
|
+
public updateConfig(config: Partial<P2PReqRespConfig>): void {
|
|
101
|
+
if (typeof config.individualRequestTimeoutMs === 'number') {
|
|
102
|
+
this.individualRequestTimeoutMs = config.individualRequestTimeoutMs;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (typeof config.dialTimeoutMs === 'number') {
|
|
106
|
+
this.dialTimeoutMs = config.dialTimeoutMs;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
91
110
|
get tracer() {
|
|
92
111
|
return this.metrics.tracer;
|
|
93
112
|
}
|
|
94
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Get the connection sampler instance
|
|
116
|
+
*/
|
|
117
|
+
getConnectionSampler(): Pick<ConnectionSampler, 'getPeerListSortedByConnectionCountAsc'> {
|
|
118
|
+
return this.connectionSampler;
|
|
119
|
+
}
|
|
120
|
+
|
|
95
121
|
/**
|
|
96
122
|
* Start the reqresp service
|
|
97
123
|
*/
|
|
98
124
|
async start(subProtocolHandlers: ReqRespSubProtocolHandlers, subProtocolValidators: ReqRespSubProtocolValidators) {
|
|
99
|
-
this.subProtocolHandlers
|
|
100
|
-
this.subProtocolValidators
|
|
125
|
+
Object.assign(this.subProtocolHandlers, subProtocolHandlers);
|
|
126
|
+
Object.assign(this.subProtocolValidators, subProtocolValidators);
|
|
101
127
|
|
|
102
128
|
// Register all protocol handlers
|
|
103
|
-
for (const subProtocol of Object.keys(
|
|
129
|
+
for (const subProtocol of Object.keys(subProtocolHandlers)) {
|
|
130
|
+
this.logger.debug(`Registering handler for sub protocol ${subProtocol}`);
|
|
104
131
|
await this.libp2p.handle(
|
|
105
132
|
subProtocol,
|
|
106
133
|
(data: IncomingStreamData) =>
|
|
@@ -112,6 +139,23 @@ export class ReqResp {
|
|
|
112
139
|
this.rateLimiter.start();
|
|
113
140
|
}
|
|
114
141
|
|
|
142
|
+
async addSubProtocol(
|
|
143
|
+
subProtocol: ReqRespSubProtocol,
|
|
144
|
+
handler: ReqRespSubProtocolHandler,
|
|
145
|
+
validator: ReqRespSubProtocolValidators[ReqRespSubProtocol] = DEFAULT_SUB_PROTOCOL_VALIDATORS[subProtocol],
|
|
146
|
+
): Promise<void> {
|
|
147
|
+
this.subProtocolHandlers[subProtocol] = handler;
|
|
148
|
+
this.subProtocolValidators[subProtocol] = validator;
|
|
149
|
+
this.logger.debug(`Registering handler for sub protocol ${subProtocol}`);
|
|
150
|
+
await this.libp2p.handle(
|
|
151
|
+
subProtocol,
|
|
152
|
+
(data: IncomingStreamData) =>
|
|
153
|
+
void this.streamHandler(subProtocol as ReqRespSubProtocol, data).catch(err =>
|
|
154
|
+
this.logger.error(`Error on libp2p subprotocol ${subProtocol} handler`, err),
|
|
155
|
+
),
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
115
159
|
/**
|
|
116
160
|
* Stop the reqresp service
|
|
117
161
|
*/
|
|
@@ -135,100 +179,6 @@ export class ReqResp {
|
|
|
135
179
|
// NOTE: We assume libp2p instance is managed by the caller
|
|
136
180
|
}
|
|
137
181
|
|
|
138
|
-
/**
|
|
139
|
-
* Send a request to peers, returns the first response
|
|
140
|
-
*
|
|
141
|
-
* @param subProtocol - The protocol being requested
|
|
142
|
-
* @param request - The request to send
|
|
143
|
-
* @returns - The response from the peer, otherwise undefined
|
|
144
|
-
*
|
|
145
|
-
* @description
|
|
146
|
-
* This method attempts to send a request to all active peers using the specified sub-protocol.
|
|
147
|
-
* It opens a stream with each peer, sends the request, and awaits a response.
|
|
148
|
-
* If a valid response is received, it returns the response; otherwise, it continues to the next peer.
|
|
149
|
-
* If no response is received from any peer, it returns undefined.
|
|
150
|
-
*
|
|
151
|
-
* The method performs the following steps:
|
|
152
|
-
* - Sample a peer to send the request to.
|
|
153
|
-
* - Opens a stream with the peer using the specified sub-protocol.
|
|
154
|
-
*
|
|
155
|
-
* When a response is received, it is validated using the given sub protocols response validator.
|
|
156
|
-
* To see the interface for the response validator - see `interface.ts`
|
|
157
|
-
*
|
|
158
|
-
* Failing a response validation requests in a severe peer penalty, and will
|
|
159
|
-
* prompt the node to continue to search to the next peer.
|
|
160
|
-
* For example, a transaction request validator will check that the payload returned does in fact
|
|
161
|
-
* match the txHash that was requested. A peer that fails this check an only be an extremely naughty peer.
|
|
162
|
-
*
|
|
163
|
-
* This entire operation is wrapped in an overall timeout, that is independent of the
|
|
164
|
-
* peer it is requesting data from.
|
|
165
|
-
*
|
|
166
|
-
*/
|
|
167
|
-
async sendRequest<SubProtocol extends ReqRespSubProtocol>(
|
|
168
|
-
subProtocol: SubProtocol,
|
|
169
|
-
request: InstanceType<SubProtocolMap[SubProtocol]['request']>,
|
|
170
|
-
): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']> | undefined> {
|
|
171
|
-
const responseValidator = this.subProtocolValidators[subProtocol];
|
|
172
|
-
const requestBuffer = request.toBuffer();
|
|
173
|
-
|
|
174
|
-
const requestFunction = async () => {
|
|
175
|
-
// Attempt to ask all of our peers, but sampled in a random order
|
|
176
|
-
// This function is wrapped in a timeout, so we will exit the loop if we have not received a response
|
|
177
|
-
const numberOfPeers = this.libp2p.getPeers().length;
|
|
178
|
-
|
|
179
|
-
if (numberOfPeers === 0) {
|
|
180
|
-
this.logger.debug('No active peers to send requests to');
|
|
181
|
-
return undefined;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const attemptedPeers: Map<string, boolean> = new Map();
|
|
185
|
-
for (let i = 0; i < numberOfPeers; i++) {
|
|
186
|
-
// Sample a peer to make a request to
|
|
187
|
-
const peer = this.connectionSampler.getPeer(attemptedPeers);
|
|
188
|
-
this.logger.trace(`Attempting to send request to peer: ${peer?.toString()}`);
|
|
189
|
-
if (!peer) {
|
|
190
|
-
this.logger.debug('No peers available to send requests to');
|
|
191
|
-
return undefined;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
attemptedPeers.set(peer.toString(), true);
|
|
195
|
-
|
|
196
|
-
this.logger.trace(`Sending request to peer: ${peer.toString()}`);
|
|
197
|
-
const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffer);
|
|
198
|
-
|
|
199
|
-
if (response && response.status !== ReqRespStatus.SUCCESS) {
|
|
200
|
-
this.logger.debug(
|
|
201
|
-
`Request to peer ${peer.toString()} failed with status ${prettyPrintReqRespStatus(response.status)}`,
|
|
202
|
-
);
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// If we get a response, return it, otherwise we iterate onto the next peer
|
|
207
|
-
// We do not consider it a success if we have an empty buffer
|
|
208
|
-
if (response && response.data.length > 0) {
|
|
209
|
-
const object = subProtocolMap[subProtocol].response.fromBuffer(response.data);
|
|
210
|
-
// The response validator handles peer punishment within
|
|
211
|
-
const isValid = await responseValidator(request, object, peer);
|
|
212
|
-
if (!isValid) {
|
|
213
|
-
throw new InvalidResponseError();
|
|
214
|
-
}
|
|
215
|
-
return object;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
return await executeTimeout<InstanceType<SubProtocolMap[SubProtocol]['response']> | undefined>(
|
|
222
|
-
requestFunction,
|
|
223
|
-
this.overallRequestTimeoutMs,
|
|
224
|
-
() => new CollectiveReqRespTimeoutError(),
|
|
225
|
-
);
|
|
226
|
-
} catch (e: any) {
|
|
227
|
-
this.logger.debug(`${e.message} | subProtocol: ${subProtocol}`);
|
|
228
|
-
return undefined;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
182
|
/**
|
|
233
183
|
* Request multiple messages over the same sub protocol, balancing the requests across peers.
|
|
234
184
|
*
|
|
@@ -261,23 +211,38 @@ export class ReqResp {
|
|
|
261
211
|
async sendBatchRequest<SubProtocol extends ReqRespSubProtocol>(
|
|
262
212
|
subProtocol: SubProtocol,
|
|
263
213
|
requests: InstanceType<SubProtocolMap[SubProtocol]['request']>[],
|
|
214
|
+
pinnedPeer: PeerId | undefined,
|
|
264
215
|
timeoutMs = 10000,
|
|
265
|
-
maxPeers = Math.
|
|
216
|
+
maxPeers = Math.max(10, Math.ceil(requests.length / 3)),
|
|
266
217
|
maxRetryAttempts = 3,
|
|
267
218
|
): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']>[]> {
|
|
268
|
-
const responseValidator = this.subProtocolValidators[subProtocol];
|
|
219
|
+
const responseValidator = this.subProtocolValidators[subProtocol] ?? DEFAULT_SUB_PROTOCOL_VALIDATORS[subProtocol];
|
|
269
220
|
const responses: InstanceType<SubProtocolMap[SubProtocol]['response']>[] = new Array(requests.length);
|
|
270
221
|
const requestBuffers = requests.map(req => req.toBuffer());
|
|
222
|
+
const isEmptyResponse = (value: unknown): boolean => {
|
|
223
|
+
// Some responses serialize to a non-empty buffer even when they contain no items (e.g., empty TxArray).
|
|
224
|
+
if (!value || typeof value !== 'object') {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
const length = (value as { length?: number }).length;
|
|
228
|
+
return typeof length === 'number' && length === 0;
|
|
229
|
+
};
|
|
271
230
|
|
|
272
|
-
const requestFunction = async () => {
|
|
231
|
+
const requestFunction = async (signal: AbortSignal) => {
|
|
273
232
|
// Track which requests still need to be processed
|
|
274
233
|
const pendingRequestIndices = new Set(requestBuffers.map((_, i) => i));
|
|
275
234
|
|
|
276
235
|
// Create batch sampler with the total number of requests and max peers
|
|
277
|
-
const batchSampler = new BatchConnectionSampler(
|
|
236
|
+
const batchSampler = new BatchConnectionSampler(
|
|
237
|
+
this.connectionSampler,
|
|
238
|
+
requests.length,
|
|
239
|
+
maxPeers,
|
|
240
|
+
compactArray([pinnedPeer]), // Exclude pinned peer from sampling, we will forcefully send all requests to it
|
|
241
|
+
createLogger(`${this.logger.module}:batch-connection-sampler`),
|
|
242
|
+
);
|
|
278
243
|
|
|
279
|
-
if (batchSampler.activePeerCount === 0) {
|
|
280
|
-
this.logger.
|
|
244
|
+
if (batchSampler.activePeerCount === 0 && !pinnedPeer) {
|
|
245
|
+
this.logger.warn('No active peers to send requests to');
|
|
281
246
|
return [];
|
|
282
247
|
}
|
|
283
248
|
|
|
@@ -291,20 +256,42 @@ export class ReqResp {
|
|
|
291
256
|
|
|
292
257
|
let retryAttempts = 0;
|
|
293
258
|
while (pendingRequestIndices.size > 0 && batchSampler.activePeerCount > 0 && retryAttempts < maxRetryAttempts) {
|
|
259
|
+
if (signal.aborted) {
|
|
260
|
+
throw new AbortError('Batch request aborted');
|
|
261
|
+
}
|
|
294
262
|
// Process requests in parallel for each available peer
|
|
295
|
-
|
|
263
|
+
type BatchEntry = { peerId: PeerId; indices: number[] };
|
|
264
|
+
const requestBatches = new Map<string, BatchEntry>();
|
|
296
265
|
|
|
297
266
|
// Group requests by peer
|
|
298
267
|
for (const requestIndex of pendingRequestIndices) {
|
|
299
268
|
const peer = batchSampler.getPeerForRequest(requestIndex);
|
|
300
269
|
if (!peer) {
|
|
301
|
-
|
|
270
|
+
// No peer available for this specific index (all peers exhausted for it)
|
|
271
|
+
// Skip this index for now - it stays in pendingRequestIndices for retry
|
|
272
|
+
continue;
|
|
302
273
|
}
|
|
303
|
-
|
|
304
|
-
if (!requestBatches.has(
|
|
305
|
-
requestBatches.set(peer, []);
|
|
274
|
+
const peerAsString = peer.toString();
|
|
275
|
+
if (!requestBatches.has(peerAsString)) {
|
|
276
|
+
requestBatches.set(peerAsString, { peerId: peer, indices: [] });
|
|
306
277
|
}
|
|
307
|
-
requestBatches.get(
|
|
278
|
+
requestBatches.get(peerAsString)!.indices.push(requestIndex);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// If there is a pinned peer, we will always send every request to that peer
|
|
282
|
+
// We use the default limits for the subprotocol to avoid hitting the rate limiter
|
|
283
|
+
if (pinnedPeer) {
|
|
284
|
+
const limit = this.rateLimiter.getRateLimits(subProtocol).peerLimit.quotaCount;
|
|
285
|
+
requestBatches.set(pinnedPeer.toString(), {
|
|
286
|
+
peerId: pinnedPeer,
|
|
287
|
+
indices: Array.from(pendingRequestIndices.values()).slice(0, limit),
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// If no requests could be assigned (all peers exhausted for all indices), exit early
|
|
292
|
+
if (requestBatches.size === 0) {
|
|
293
|
+
this.logger.warn('No peers available for any pending request indices, stopping batch request');
|
|
294
|
+
break;
|
|
308
295
|
}
|
|
309
296
|
|
|
310
297
|
// Make parallel requests for each peer's batch
|
|
@@ -316,41 +303,63 @@ export class ReqResp {
|
|
|
316
303
|
// while simultaneously Peer Id 1 will send requests 4, 5, 6, 7 in serial
|
|
317
304
|
|
|
318
305
|
const batchResults = await Promise.all(
|
|
319
|
-
Array.from(requestBatches.entries()).map(async ([peer, indices]) => {
|
|
306
|
+
Array.from(requestBatches.entries()).map(async ([peerAsString, { peerId: peer, indices }]) => {
|
|
320
307
|
try {
|
|
308
|
+
const markIndexFailed = (index: number) => batchSampler.markPeerFailedForIndex(peer, index);
|
|
321
309
|
// Requests all going to the same peer are sent synchronously
|
|
322
310
|
const peerResults: { index: number; response: InstanceType<SubProtocolMap[SubProtocol]['response']> }[] =
|
|
323
311
|
[];
|
|
312
|
+
let shouldReplacePeer = false;
|
|
313
|
+
const handleFailure = (status: ReqRespStatus, index: number) => {
|
|
314
|
+
this.logger.warn(
|
|
315
|
+
`Request to peer ${peerAsString} failed with status ${prettyPrintReqRespStatus(status)}`,
|
|
316
|
+
);
|
|
317
|
+
markIndexFailed(index);
|
|
318
|
+
return status === ReqRespStatus.RATE_LIMIT_EXCEEDED;
|
|
319
|
+
};
|
|
320
|
+
|
|
324
321
|
for (const index of indices) {
|
|
322
|
+
this.logger.info(`Sending request ${index} to peer ${peerAsString}`);
|
|
325
323
|
const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffers[index]);
|
|
326
324
|
|
|
327
325
|
// Check the status of the response buffer
|
|
328
|
-
if (response
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
// If we hit a rate limit or some failure, we remove the peer and return the results,
|
|
336
|
-
// they will be split among remaining peers and the new sampled peer
|
|
337
|
-
batchSampler.removePeerAndReplace(peer);
|
|
338
|
-
return { peer, results: peerResults };
|
|
326
|
+
if (response.status !== ReqRespStatus.SUCCESS) {
|
|
327
|
+
shouldReplacePeer = handleFailure(response.status, index);
|
|
328
|
+
if (shouldReplacePeer) {
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
continue;
|
|
339
332
|
}
|
|
340
333
|
|
|
341
|
-
if (response
|
|
342
|
-
|
|
343
|
-
|
|
334
|
+
if (response.data.length === 0) {
|
|
335
|
+
markIndexFailed(index);
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
344
338
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
339
|
+
const object = responseFromBuffer(subProtocol, response.data);
|
|
340
|
+
if (isEmptyResponse(object)) {
|
|
341
|
+
markIndexFailed(index);
|
|
342
|
+
continue;
|
|
348
343
|
}
|
|
344
|
+
|
|
345
|
+
const isValid = await responseValidator(requests[index], object, peer);
|
|
346
|
+
if (!isValid) {
|
|
347
|
+
markIndexFailed(index);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
peerResults.push({ index, response: object });
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// If peer had a hard failure (rate limit), replace it for future iterations
|
|
355
|
+
if (shouldReplacePeer) {
|
|
356
|
+
this.logger.warn(`Peer ${peerAsString} hit a hard failure, removing from sampler`);
|
|
357
|
+
batchSampler.removePeerAndReplace(peer);
|
|
349
358
|
}
|
|
350
359
|
|
|
351
360
|
return { peer, results: peerResults };
|
|
352
361
|
} catch (error) {
|
|
353
|
-
this.logger.
|
|
362
|
+
this.logger.warn(`Failed batch request to peer ${peerAsString}:`, error);
|
|
354
363
|
batchSampler.removePeerAndReplace(peer);
|
|
355
364
|
return { peer, results: [] };
|
|
356
365
|
}
|
|
@@ -371,7 +380,7 @@ export class ReqResp {
|
|
|
371
380
|
}
|
|
372
381
|
|
|
373
382
|
if (retryAttempts >= maxRetryAttempts) {
|
|
374
|
-
this.logger.
|
|
383
|
+
this.logger.warn(`Max retry attempts ${maxRetryAttempts} reached for batch request`);
|
|
375
384
|
}
|
|
376
385
|
|
|
377
386
|
return responses;
|
|
@@ -384,7 +393,7 @@ export class ReqResp {
|
|
|
384
393
|
() => new CollectiveReqRespTimeoutError(),
|
|
385
394
|
);
|
|
386
395
|
} catch (e: any) {
|
|
387
|
-
this.logger.
|
|
396
|
+
this.logger.warn(`${e.message} | subProtocol: ${subProtocol}`);
|
|
388
397
|
return [];
|
|
389
398
|
}
|
|
390
399
|
}
|
|
@@ -399,6 +408,7 @@ export class ReqResp {
|
|
|
399
408
|
* @param peerId - The peer to send the request to
|
|
400
409
|
* @param subProtocol - The protocol to use to request
|
|
401
410
|
* @param payload - The payload to send
|
|
411
|
+
* @param dialTimeout - If establishing a stream takes longer than this an error will be thrown
|
|
402
412
|
* @returns If the request is successful, the response is returned, otherwise undefined
|
|
403
413
|
*
|
|
404
414
|
* @description
|
|
@@ -421,29 +431,53 @@ export class ReqResp {
|
|
|
421
431
|
peerId: PeerId,
|
|
422
432
|
subProtocol: ReqRespSubProtocol,
|
|
423
433
|
payload: Buffer,
|
|
424
|
-
|
|
434
|
+
dialTimeout: number = this.dialTimeoutMs,
|
|
435
|
+
): Promise<ReqRespResponse> {
|
|
425
436
|
let stream: Stream | undefined;
|
|
426
437
|
try {
|
|
427
438
|
this.metrics.recordRequestSent(subProtocol);
|
|
428
439
|
|
|
429
|
-
|
|
440
|
+
this.logger.trace(`Sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
|
|
441
|
+
stream = await this.connectionSampler.dialProtocol(peerId, subProtocol, dialTimeout);
|
|
442
|
+
this.logger.trace(
|
|
443
|
+
`Opened stream ${stream.id} for sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}`,
|
|
444
|
+
);
|
|
430
445
|
|
|
431
|
-
|
|
432
|
-
const
|
|
433
|
-
|
|
446
|
+
const timeoutErr = new IndividualReqRespTimeoutError();
|
|
447
|
+
const [_, resp] = await executeTimeout(
|
|
448
|
+
signal =>
|
|
449
|
+
Promise.all([
|
|
450
|
+
pipeline([payload], stream!.sink, { signal }),
|
|
451
|
+
pipeline(stream!.source, this.readMessage.bind(this), { signal }),
|
|
452
|
+
]),
|
|
434
453
|
this.individualRequestTimeoutMs,
|
|
435
|
-
() =>
|
|
454
|
+
() => timeoutErr,
|
|
436
455
|
);
|
|
437
|
-
|
|
438
|
-
return result;
|
|
456
|
+
return resp;
|
|
439
457
|
} catch (e: any) {
|
|
458
|
+
this.logger.warn(`SUBPROTOCOL: ${subProtocol}\n`, e);
|
|
459
|
+
// On error we immediately abort the stream, this is preferred way,
|
|
460
|
+
// because it signals to the sender that error happened, whereas
|
|
461
|
+
// closing the stream only closes our side and is much slower
|
|
462
|
+
if (stream) {
|
|
463
|
+
stream!.abort(e);
|
|
464
|
+
}
|
|
465
|
+
|
|
440
466
|
this.metrics.recordRequestError(subProtocol);
|
|
441
467
|
this.handleResponseError(e, peerId, subProtocol);
|
|
468
|
+
|
|
469
|
+
// If there is an exception, we return an unknown response
|
|
470
|
+
this.logger.debug(`Error sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}: ${e}`);
|
|
471
|
+
return { status: ReqRespStatus.FAILURE };
|
|
442
472
|
} finally {
|
|
443
473
|
// Only close the stream if we created it
|
|
474
|
+
// Note even if we aborted the stream, calling close on it is ok, it's just a no-op
|
|
444
475
|
if (stream) {
|
|
445
476
|
try {
|
|
446
|
-
|
|
477
|
+
this.logger.trace(
|
|
478
|
+
`Closing stream ${stream.id} for request to peer ${peerId.toString()} on sub protocol ${subProtocol}`,
|
|
479
|
+
);
|
|
480
|
+
await this.connectionSampler.close(stream);
|
|
447
481
|
} catch (closeError) {
|
|
448
482
|
this.logger.error(
|
|
449
483
|
`Error closing stream: ${closeError instanceof Error ? closeError.message : 'Unknown error'}`,
|
|
@@ -464,67 +498,12 @@ export class ReqResp {
|
|
|
464
498
|
* @returns If the error is non pubishable, then undefined is returned, otherwise the peer is penalized
|
|
465
499
|
*/
|
|
466
500
|
private handleResponseError(e: any, peerId: PeerId, subProtocol: ReqRespSubProtocol): void {
|
|
467
|
-
const severity = this.
|
|
501
|
+
const severity = this.categorizeResponseError(e, peerId, subProtocol);
|
|
468
502
|
if (severity) {
|
|
469
503
|
this.peerScoring.penalizePeer(peerId, severity);
|
|
470
504
|
}
|
|
471
505
|
}
|
|
472
506
|
|
|
473
|
-
/**
|
|
474
|
-
* Categorize the error and log it.
|
|
475
|
-
*/
|
|
476
|
-
private categorizeError(e: any, peerId: PeerId, subProtocol: ReqRespSubProtocol): PeerErrorSeverity | undefined {
|
|
477
|
-
// Non punishable errors - we do not expect a response for goodbye messages
|
|
478
|
-
if (subProtocol === ReqRespSubProtocol.GOODBYE) {
|
|
479
|
-
this.logger.debug('Error encountered on goodbye sub protocol, no penalty', {
|
|
480
|
-
peerId: peerId.toString(),
|
|
481
|
-
subProtocol,
|
|
482
|
-
});
|
|
483
|
-
return undefined;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
// We do not punish a collective timeout, as the node triggers this interupt, independent of the peer's behaviour
|
|
487
|
-
const logTags = {
|
|
488
|
-
peerId: peerId.toString(),
|
|
489
|
-
subProtocol,
|
|
490
|
-
};
|
|
491
|
-
if (e instanceof CollectiveReqRespTimeoutError || e instanceof InvalidResponseError) {
|
|
492
|
-
this.logger.debug(
|
|
493
|
-
`Non-punishable error: ${e.message} | peerId: ${peerId.toString()} | subProtocol: ${subProtocol}`,
|
|
494
|
-
logTags,
|
|
495
|
-
);
|
|
496
|
-
return undefined;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// Pubishable errors
|
|
500
|
-
// Connection reset errors in the networking stack are punished with high severity
|
|
501
|
-
// it just signals an unreliable peer
|
|
502
|
-
// We assume that the requesting node has a functioning networking stack.
|
|
503
|
-
if (e?.code === 'ECONNRESET' || e?.code === 'EPIPE') {
|
|
504
|
-
this.logger.debug(`Connection reset: ${peerId.toString()}`, logTags);
|
|
505
|
-
return PeerErrorSeverity.HighToleranceError;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
if (e?.code === 'ECONNREFUSED') {
|
|
509
|
-
this.logger.debug(`Connection refused: ${peerId.toString()}`, logTags);
|
|
510
|
-
return PeerErrorSeverity.HighToleranceError;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// Timeout errors are punished with high tolerance, they can be due to a geogrpahically far away peer or an
|
|
514
|
-
// overloaded peer
|
|
515
|
-
if (e instanceof IndividualReqRespTimeoutError) {
|
|
516
|
-
this.logger.debug(
|
|
517
|
-
`Timeout error: ${e.message} | peerId: ${peerId.toString()} | subProtocol: ${subProtocol}`,
|
|
518
|
-
logTags,
|
|
519
|
-
);
|
|
520
|
-
return PeerErrorSeverity.HighToleranceError;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// Catch all error
|
|
524
|
-
this.logger.error(`Unexpected error sending request to peer`, e, logTags);
|
|
525
|
-
return PeerErrorSeverity.HighToleranceError;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
507
|
/**
|
|
529
508
|
* Read a message returned from a stream into a single buffer
|
|
530
509
|
*
|
|
@@ -533,24 +512,34 @@ export class ReqResp {
|
|
|
533
512
|
* - The second chunk should contain the response data
|
|
534
513
|
*/
|
|
535
514
|
private async readMessage(source: AsyncIterable<Uint8ArrayList>): Promise<ReqRespResponse> {
|
|
536
|
-
let
|
|
515
|
+
let status: ReqRespStatus | undefined;
|
|
537
516
|
const chunks: Uint8Array[] = [];
|
|
538
517
|
|
|
539
518
|
try {
|
|
540
519
|
for await (const chunk of source) {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
statusBuffer = parseStatusChunk(firstChunkBuffer);
|
|
544
|
-
} else {
|
|
520
|
+
const statusParsed = status !== undefined;
|
|
521
|
+
if (statusParsed) {
|
|
545
522
|
chunks.push(chunk.subarray());
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const firstChunkBuffer = chunk.subarray();
|
|
527
|
+
status = parseStatusChunk(firstChunkBuffer);
|
|
528
|
+
|
|
529
|
+
// In case status is not SUCCESS, we do not expect any data in the response
|
|
530
|
+
// we can return early
|
|
531
|
+
if (status !== ReqRespStatus.SUCCESS) {
|
|
532
|
+
return {
|
|
533
|
+
status,
|
|
534
|
+
};
|
|
546
535
|
}
|
|
547
536
|
}
|
|
548
537
|
|
|
549
538
|
const messageData = Buffer.concat(chunks);
|
|
550
|
-
const message: Buffer = this.snappyTransform.
|
|
539
|
+
const message: Buffer = this.snappyTransform.inboundTransformData(messageData);
|
|
551
540
|
|
|
552
541
|
return {
|
|
553
|
-
status:
|
|
542
|
+
status: status ?? ReqRespStatus.UNKNOWN,
|
|
554
543
|
data: message,
|
|
555
544
|
};
|
|
556
545
|
} catch (e: any) {
|
|
@@ -563,7 +552,6 @@ export class ReqResp {
|
|
|
563
552
|
|
|
564
553
|
return {
|
|
565
554
|
status,
|
|
566
|
-
data: Buffer.from([]),
|
|
567
555
|
};
|
|
568
556
|
}
|
|
569
557
|
}
|
|
@@ -572,7 +560,8 @@ export class ReqResp {
|
|
|
572
560
|
* Stream Handler
|
|
573
561
|
* Reads the incoming stream, determines the protocol, then triggers the appropriate handler
|
|
574
562
|
*
|
|
575
|
-
* @param
|
|
563
|
+
* @param protocol - The sub protocol to handle
|
|
564
|
+
* @param incomingStream - The incoming stream data containing the stream and connection
|
|
576
565
|
*
|
|
577
566
|
* @description
|
|
578
567
|
* An individual stream handler will be bound to each sub protocol, and handles returning data back
|
|
@@ -588,14 +577,13 @@ export class ReqResp {
|
|
|
588
577
|
[Attributes.P2P_REQ_RESP_PROTOCOL]: protocol,
|
|
589
578
|
[Attributes.P2P_ID]: connection.remotePeer.toString(),
|
|
590
579
|
}))
|
|
591
|
-
private async streamHandler(protocol: ReqRespSubProtocol,
|
|
592
|
-
|
|
593
|
-
|
|
580
|
+
private async streamHandler(protocol: ReqRespSubProtocol, incomingStream: IncomingStreamData) {
|
|
581
|
+
const { stream, connection } = incomingStream;
|
|
594
582
|
try {
|
|
595
|
-
|
|
583
|
+
this.metrics.recordRequestReceived(protocol);
|
|
596
584
|
const rateLimitStatus = this.rateLimiter.allow(protocol, connection.remotePeer);
|
|
597
|
-
if (rateLimitStatus
|
|
598
|
-
this.logger.
|
|
585
|
+
if (rateLimitStatus !== RateLimitStatus.Allowed) {
|
|
586
|
+
this.logger.verbose(
|
|
599
587
|
`Rate limit exceeded ${prettyPrintRateLimitStatus(rateLimitStatus)} for ${protocol} from ${
|
|
600
588
|
connection.remotePeer
|
|
601
589
|
}`,
|
|
@@ -604,58 +592,248 @@ export class ReqResp {
|
|
|
604
592
|
throw new ReqRespStatusError(ReqRespStatus.RATE_LIMIT_EXCEEDED);
|
|
605
593
|
}
|
|
606
594
|
|
|
607
|
-
|
|
608
|
-
|
|
595
|
+
await this.processStream(protocol, incomingStream);
|
|
596
|
+
} catch (err: any) {
|
|
597
|
+
this.metrics.recordResponseError(protocol);
|
|
598
|
+
this.handleRequestError(err, connection.remotePeer, protocol);
|
|
599
|
+
|
|
600
|
+
if (err instanceof ReqRespStatusError) {
|
|
601
|
+
const errorSent = await this.trySendError(stream, connection.remotePeer, protocol, err.status);
|
|
602
|
+
const logMessage = errorSent
|
|
603
|
+
? 'Protocol error sent successfully.'
|
|
604
|
+
: 'Stream already closed or poisoned, not sending error response.';
|
|
605
|
+
|
|
606
|
+
const isRateLimit = err.status === ReqRespStatus.RATE_LIMIT_EXCEEDED;
|
|
607
|
+
|
|
608
|
+
const level = isRateLimit ? 'debug' : 'warn';
|
|
609
|
+
this.logger[level](logMessage + ` Status: ${ReqRespStatus[err.status]}`, {
|
|
610
|
+
protocol,
|
|
611
|
+
err,
|
|
612
|
+
errorStatus: err.status,
|
|
613
|
+
cause: err.cause ?? 'Cause unknown',
|
|
614
|
+
});
|
|
615
|
+
} else {
|
|
616
|
+
// In erroneous case we abort the stream, this will signal the peer that something went wrong
|
|
617
|
+
// and that this stream should be dropped
|
|
618
|
+
const isMessageToNotWarn =
|
|
619
|
+
err instanceof Error &&
|
|
620
|
+
['stream reset', 'Cannot push value onto an ended pushable'].some(msg => err.message.includes(msg));
|
|
621
|
+
const level = isMessageToNotWarn ? 'debug' : 'warn';
|
|
622
|
+
this.logger[level]('Unknown stream error while handling the stream, aborting', {
|
|
623
|
+
protocol,
|
|
624
|
+
err,
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
stream.abort(err);
|
|
628
|
+
}
|
|
629
|
+
} finally {
|
|
630
|
+
//NOTE: This is idempotent action, so it's ok to call it even if stream was aborted
|
|
631
|
+
await stream.close();
|
|
632
|
+
}
|
|
633
|
+
}
|
|
609
634
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
635
|
+
/**
|
|
636
|
+
* Reads incoming data from the stream, processes it according to the sub protocol,
|
|
637
|
+
* and puts response back into the stream.
|
|
638
|
+
*
|
|
639
|
+
* @param protocol - The sub protocol to use for processing the stream
|
|
640
|
+
* @param incomingStream - The incoming stream data containing the stream and connection
|
|
641
|
+
*
|
|
642
|
+
* */
|
|
643
|
+
private async processStream(protocol: ReqRespSubProtocol, { stream, connection }: IncomingStreamData): Promise<void> {
|
|
644
|
+
const handler = this.subProtocolHandlers[protocol];
|
|
645
|
+
if (!handler) {
|
|
646
|
+
throw new Error(`No handler defined for reqresp subprotocol ${protocol}`);
|
|
647
|
+
}
|
|
616
648
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
await stream.close();
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
649
|
+
const snappy = this.snappyTransform;
|
|
650
|
+
const SUCCESS = Uint8Array.of(ReqRespStatus.SUCCESS);
|
|
622
651
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
652
|
+
await pipeline(
|
|
653
|
+
stream.source,
|
|
654
|
+
async function* (source: any) {
|
|
655
|
+
for await (const chunk of source) {
|
|
656
|
+
const response = await handler(connection.remotePeer, chunk.subarray());
|
|
626
657
|
|
|
627
|
-
|
|
658
|
+
if (protocol === ReqRespSubProtocol.GOODBYE) {
|
|
659
|
+
// NOTE: The stream was already closed by Goodbye handler
|
|
660
|
+
// peerManager.goodbyeReceived(peerId, reason); will call libp2p.hangUp closing all active streams and connections
|
|
661
|
+
// Don't try to respond
|
|
662
|
+
return;
|
|
628
663
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
664
|
+
|
|
665
|
+
stream.metadata.written = true; // Mark the stream as written to;
|
|
666
|
+
|
|
667
|
+
yield SUCCESS;
|
|
668
|
+
yield snappy.outboundTransformData(response);
|
|
669
|
+
}
|
|
670
|
+
},
|
|
671
|
+
stream.sink,
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Try to send error status to the peer. We say try, because the stream,
|
|
677
|
+
* might already be closed
|
|
678
|
+
* @param stream - The stream opened between us and the peer
|
|
679
|
+
* @param status - The error status to send back to the peer
|
|
680
|
+
* @returns true if error was sent successfully, otherwise false
|
|
681
|
+
*
|
|
682
|
+
*/
|
|
683
|
+
private async trySendError(
|
|
684
|
+
stream: Stream,
|
|
685
|
+
peerId: PeerId,
|
|
686
|
+
protocol: ReqRespSubProtocol,
|
|
687
|
+
status: ReqRespStatus,
|
|
688
|
+
): Promise<boolean> {
|
|
689
|
+
const canWriteToStream =
|
|
690
|
+
// 'writing' is a bit weird naming, but it actually means that the stream is ready to write
|
|
691
|
+
// 'ready' means that stream ready to be opened for writing
|
|
692
|
+
stream.status === 'open' && (stream.writeStatus === 'writing' || stream.writeStatus === 'ready');
|
|
693
|
+
|
|
694
|
+
// Stream was already written to, we consider it poisoned, in a sense,
|
|
695
|
+
// that even if we write an error response, it will not be interpreted correctly by the peer
|
|
696
|
+
const streamPoisoned = stream.metadata.written === true;
|
|
697
|
+
const shouldWriteToStream = canWriteToStream && !streamPoisoned;
|
|
698
|
+
|
|
699
|
+
if (!shouldWriteToStream) {
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
try {
|
|
704
|
+
await pipeline(function* () {
|
|
705
|
+
yield Uint8Array.of(status);
|
|
706
|
+
}, stream.sink);
|
|
707
|
+
|
|
708
|
+
return true;
|
|
632
709
|
} catch (e: any) {
|
|
633
|
-
this.logger.warn('
|
|
634
|
-
|
|
710
|
+
this.logger.warn('Error while sending error response', e);
|
|
711
|
+
stream.abort(e);
|
|
635
712
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
}
|
|
713
|
+
this.handleRequestError(e, peerId, protocol);
|
|
714
|
+
return false;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
641
717
|
|
|
642
|
-
|
|
718
|
+
private handleRequestError(e: any, peerId: PeerId, subProtocol: ReqRespSubProtocol): void {
|
|
719
|
+
const severity = this.categorizeRequestError(e, peerId, subProtocol);
|
|
720
|
+
if (severity) {
|
|
721
|
+
this.peerScoring.penalizePeer(peerId, severity);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
643
724
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
725
|
+
/**
|
|
726
|
+
* Categorize the request error and log it.
|
|
727
|
+
*
|
|
728
|
+
* @returns Severity of the error, or undefined if the error is not punishable.
|
|
729
|
+
*/
|
|
730
|
+
private categorizeRequestError(
|
|
731
|
+
e: any,
|
|
732
|
+
peerId: PeerId,
|
|
733
|
+
subProtocol: ReqRespSubProtocol,
|
|
734
|
+
): PeerErrorSeverity | undefined {
|
|
735
|
+
const logTags = { peerId: peerId.toString(), subProtocol };
|
|
736
|
+
|
|
737
|
+
//Punishable error - peer should never send badly formed request
|
|
738
|
+
if (e instanceof ReqRespStatusError && e.status === ReqRespStatus.BADLY_FORMED_REQUEST) {
|
|
739
|
+
this.logger.debug(`Punishable error in ${subProtocol}: ${e.cause}`, logTags);
|
|
740
|
+
return PeerErrorSeverity.LowToleranceError;
|
|
654
741
|
}
|
|
742
|
+
|
|
743
|
+
//TODO: (mralj): think if we should penalize peer here based on connection errors
|
|
744
|
+
return undefined;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Categorize the response error and log it.
|
|
749
|
+
*
|
|
750
|
+
* @returns Severity of the error, or undefined if the error is not punishable.
|
|
751
|
+
*/
|
|
752
|
+
private categorizeResponseError(
|
|
753
|
+
e: any,
|
|
754
|
+
peerId: PeerId,
|
|
755
|
+
subProtocol: ReqRespSubProtocol,
|
|
756
|
+
): PeerErrorSeverity | undefined {
|
|
757
|
+
const logTags = { peerId: peerId.toString(), subProtocol };
|
|
758
|
+
|
|
759
|
+
// Non punishable errors - we do not expect a response for goodbye messages
|
|
760
|
+
if (subProtocol === ReqRespSubProtocol.GOODBYE) {
|
|
761
|
+
this.logger.debug('Error encountered on goodbye sub protocol, no penalty', logTags);
|
|
762
|
+
return undefined;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// We do not punish a collective timeout, as the node triggers this interupt, independent of the peer's behaviour
|
|
766
|
+
if (e instanceof CollectiveReqRespTimeoutError || e instanceof InvalidResponseError) {
|
|
767
|
+
this.logger.debug(`Non-punishable error in ${subProtocol}: ${e.message}`, logTags);
|
|
768
|
+
return undefined;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
return this.categorizeConnectionErrors(e, peerId, subProtocol);
|
|
655
772
|
}
|
|
656
773
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
774
|
+
/*
|
|
775
|
+
* Errors specific to connection handling
|
|
776
|
+
* These can happen both when sending request and response*/
|
|
777
|
+
private categorizeConnectionErrors(
|
|
778
|
+
e: any,
|
|
779
|
+
peerId: PeerId,
|
|
780
|
+
subProtocol: ReqRespSubProtocol,
|
|
781
|
+
): PeerErrorSeverity | undefined {
|
|
782
|
+
const logTags = { peerId: peerId.toString(), subProtocol };
|
|
783
|
+
// Do not punish if we are stopping the service
|
|
784
|
+
if (e instanceof AbortError || e?.code == 'ABORT_ERR') {
|
|
785
|
+
this.logger.debug(`Request aborted: ${e.message}`, logTags);
|
|
786
|
+
return undefined;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// Do not punish if we are the ones closing the connection
|
|
790
|
+
if (
|
|
791
|
+
e?.code === 'ERR_CONNECTION_BEING_CLOSED' ||
|
|
792
|
+
e?.code === 'ERR_CONNECTION_CLOSED' ||
|
|
793
|
+
e?.code === 'ERR_TRANSIENT_CONNECTION' ||
|
|
794
|
+
e?.message?.includes('Muxer already closed') ||
|
|
795
|
+
e?.message?.includes('muxer closed') ||
|
|
796
|
+
e?.message?.includes('ended pushable')
|
|
797
|
+
) {
|
|
798
|
+
this.logger.debug(
|
|
799
|
+
`Connection closed to peer from our side: ${peerId.toString()} (${e?.message ?? 'missing error message'})`,
|
|
800
|
+
logTags,
|
|
801
|
+
);
|
|
802
|
+
return undefined;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// Pubishable errors
|
|
806
|
+
// Connection reset errors in the networking stack are punished with high severity
|
|
807
|
+
// it just signals an unreliable peer
|
|
808
|
+
// We assume that the requesting node has a functioning networking stack.
|
|
809
|
+
if (e?.code === 'ECONNRESET' || e?.code === 'EPIPE') {
|
|
810
|
+
this.logger.debug(`Connection reset: ${peerId.toString()}`, logTags);
|
|
811
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
if (e?.code === 'ECONNREFUSED') {
|
|
815
|
+
this.logger.debug(`Connection refused: ${peerId.toString()}`, logTags);
|
|
816
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
if (e?.code === 'ERR_UNEXPECTED_EOF') {
|
|
820
|
+
this.logger.debug(`Connection unexpected EOF: ${peerId.toString()}`, logTags);
|
|
821
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if (e?.code === 'ERR_UNSUPPORTED_PROTOCOL') {
|
|
825
|
+
this.logger.debug(`Sub protocol not supported by peer: ${peerId.toString()}`, logTags);
|
|
826
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// Timeout errors are punished with high tolerance, they can be due to a geographically far away or overloaded peer
|
|
830
|
+
if (e instanceof IndividualReqRespTimeoutError || e instanceof TimeoutError) {
|
|
831
|
+
this.logger.debug(`Timeout error in ${subProtocol}: ${e.message}`, logTags);
|
|
832
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Catch all error
|
|
836
|
+
this.logger.error(`Unexpected error in ReqResp protocol`, e, logTags);
|
|
837
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
660
838
|
}
|
|
661
839
|
}
|