@aztec/p2p 0.0.0-test.1 → 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,23 +1,403 @@
|
|
|
1
1
|
// @attribution: lodestar impl for inspiration
|
|
2
|
-
function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
function applyDecs2203RFactory() {
|
|
3
|
+
function createAddInitializerMethod(initializers, decoratorFinishedRef) {
|
|
4
|
+
return function addInitializer(initializer) {
|
|
5
|
+
assertNotFinished(decoratorFinishedRef, "addInitializer");
|
|
6
|
+
assertCallable(initializer, "An initializer");
|
|
7
|
+
initializers.push(initializer);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) {
|
|
11
|
+
var kindStr;
|
|
12
|
+
switch(kind){
|
|
13
|
+
case 1:
|
|
14
|
+
kindStr = "accessor";
|
|
15
|
+
break;
|
|
16
|
+
case 2:
|
|
17
|
+
kindStr = "method";
|
|
18
|
+
break;
|
|
19
|
+
case 3:
|
|
20
|
+
kindStr = "getter";
|
|
21
|
+
break;
|
|
22
|
+
case 4:
|
|
23
|
+
kindStr = "setter";
|
|
24
|
+
break;
|
|
25
|
+
default:
|
|
26
|
+
kindStr = "field";
|
|
27
|
+
}
|
|
28
|
+
var ctx = {
|
|
29
|
+
kind: kindStr,
|
|
30
|
+
name: isPrivate ? "#" + name : name,
|
|
31
|
+
static: isStatic,
|
|
32
|
+
private: isPrivate,
|
|
33
|
+
metadata: metadata
|
|
34
|
+
};
|
|
35
|
+
var decoratorFinishedRef = {
|
|
36
|
+
v: false
|
|
37
|
+
};
|
|
38
|
+
ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef);
|
|
39
|
+
var get, set;
|
|
40
|
+
if (kind === 0) {
|
|
41
|
+
if (isPrivate) {
|
|
42
|
+
get = desc.get;
|
|
43
|
+
set = desc.set;
|
|
44
|
+
} else {
|
|
45
|
+
get = function() {
|
|
46
|
+
return this[name];
|
|
47
|
+
};
|
|
48
|
+
set = function(v) {
|
|
49
|
+
this[name] = v;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
} else if (kind === 2) {
|
|
53
|
+
get = function() {
|
|
54
|
+
return desc.value;
|
|
55
|
+
};
|
|
56
|
+
} else {
|
|
57
|
+
if (kind === 1 || kind === 3) {
|
|
58
|
+
get = function() {
|
|
59
|
+
return desc.get.call(this);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (kind === 1 || kind === 4) {
|
|
63
|
+
set = function(v) {
|
|
64
|
+
desc.set.call(this, v);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
ctx.access = get && set ? {
|
|
69
|
+
get: get,
|
|
70
|
+
set: set
|
|
71
|
+
} : get ? {
|
|
72
|
+
get: get
|
|
73
|
+
} : {
|
|
74
|
+
set: set
|
|
75
|
+
};
|
|
76
|
+
try {
|
|
77
|
+
return dec(value, ctx);
|
|
78
|
+
} finally{
|
|
79
|
+
decoratorFinishedRef.v = true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function assertNotFinished(decoratorFinishedRef, fnName) {
|
|
83
|
+
if (decoratorFinishedRef.v) {
|
|
84
|
+
throw new Error("attempted to call " + fnName + " after decoration was finished");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function assertCallable(fn, hint) {
|
|
88
|
+
if (typeof fn !== "function") {
|
|
89
|
+
throw new TypeError(hint + " must be a function");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function assertValidReturnValue(kind, value) {
|
|
93
|
+
var type = typeof value;
|
|
94
|
+
if (kind === 1) {
|
|
95
|
+
if (type !== "object" || value === null) {
|
|
96
|
+
throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
|
|
97
|
+
}
|
|
98
|
+
if (value.get !== undefined) {
|
|
99
|
+
assertCallable(value.get, "accessor.get");
|
|
100
|
+
}
|
|
101
|
+
if (value.set !== undefined) {
|
|
102
|
+
assertCallable(value.set, "accessor.set");
|
|
103
|
+
}
|
|
104
|
+
if (value.init !== undefined) {
|
|
105
|
+
assertCallable(value.init, "accessor.init");
|
|
106
|
+
}
|
|
107
|
+
} else if (type !== "function") {
|
|
108
|
+
var hint;
|
|
109
|
+
if (kind === 0) {
|
|
110
|
+
hint = "field";
|
|
111
|
+
} else if (kind === 10) {
|
|
112
|
+
hint = "class";
|
|
113
|
+
} else {
|
|
114
|
+
hint = "method";
|
|
115
|
+
}
|
|
116
|
+
throw new TypeError(hint + " decorators must return a function or void 0");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) {
|
|
120
|
+
var decs = decInfo[0];
|
|
121
|
+
var desc, init, value;
|
|
122
|
+
if (isPrivate) {
|
|
123
|
+
if (kind === 0 || kind === 1) {
|
|
124
|
+
desc = {
|
|
125
|
+
get: decInfo[3],
|
|
126
|
+
set: decInfo[4]
|
|
127
|
+
};
|
|
128
|
+
} else if (kind === 3) {
|
|
129
|
+
desc = {
|
|
130
|
+
get: decInfo[3]
|
|
131
|
+
};
|
|
132
|
+
} else if (kind === 4) {
|
|
133
|
+
desc = {
|
|
134
|
+
set: decInfo[3]
|
|
135
|
+
};
|
|
136
|
+
} else {
|
|
137
|
+
desc = {
|
|
138
|
+
value: decInfo[3]
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
} else if (kind !== 0) {
|
|
142
|
+
desc = Object.getOwnPropertyDescriptor(base, name);
|
|
143
|
+
}
|
|
144
|
+
if (kind === 1) {
|
|
145
|
+
value = {
|
|
146
|
+
get: desc.get,
|
|
147
|
+
set: desc.set
|
|
148
|
+
};
|
|
149
|
+
} else if (kind === 2) {
|
|
150
|
+
value = desc.value;
|
|
151
|
+
} else if (kind === 3) {
|
|
152
|
+
value = desc.get;
|
|
153
|
+
} else if (kind === 4) {
|
|
154
|
+
value = desc.set;
|
|
155
|
+
}
|
|
156
|
+
var newValue, get, set;
|
|
157
|
+
if (typeof decs === "function") {
|
|
158
|
+
newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
|
|
159
|
+
if (newValue !== void 0) {
|
|
160
|
+
assertValidReturnValue(kind, newValue);
|
|
161
|
+
if (kind === 0) {
|
|
162
|
+
init = newValue;
|
|
163
|
+
} else if (kind === 1) {
|
|
164
|
+
init = newValue.init;
|
|
165
|
+
get = newValue.get || value.get;
|
|
166
|
+
set = newValue.set || value.set;
|
|
167
|
+
value = {
|
|
168
|
+
get: get,
|
|
169
|
+
set: set
|
|
170
|
+
};
|
|
171
|
+
} else {
|
|
172
|
+
value = newValue;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
for(var i = decs.length - 1; i >= 0; i--){
|
|
177
|
+
var dec = decs[i];
|
|
178
|
+
newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
|
|
179
|
+
if (newValue !== void 0) {
|
|
180
|
+
assertValidReturnValue(kind, newValue);
|
|
181
|
+
var newInit;
|
|
182
|
+
if (kind === 0) {
|
|
183
|
+
newInit = newValue;
|
|
184
|
+
} else if (kind === 1) {
|
|
185
|
+
newInit = newValue.init;
|
|
186
|
+
get = newValue.get || value.get;
|
|
187
|
+
set = newValue.set || value.set;
|
|
188
|
+
value = {
|
|
189
|
+
get: get,
|
|
190
|
+
set: set
|
|
191
|
+
};
|
|
192
|
+
} else {
|
|
193
|
+
value = newValue;
|
|
194
|
+
}
|
|
195
|
+
if (newInit !== void 0) {
|
|
196
|
+
if (init === void 0) {
|
|
197
|
+
init = newInit;
|
|
198
|
+
} else if (typeof init === "function") {
|
|
199
|
+
init = [
|
|
200
|
+
init,
|
|
201
|
+
newInit
|
|
202
|
+
];
|
|
203
|
+
} else {
|
|
204
|
+
init.push(newInit);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (kind === 0 || kind === 1) {
|
|
211
|
+
if (init === void 0) {
|
|
212
|
+
init = function(instance, init) {
|
|
213
|
+
return init;
|
|
214
|
+
};
|
|
215
|
+
} else if (typeof init !== "function") {
|
|
216
|
+
var ownInitializers = init;
|
|
217
|
+
init = function(instance, init) {
|
|
218
|
+
var value = init;
|
|
219
|
+
for(var i = 0; i < ownInitializers.length; i++){
|
|
220
|
+
value = ownInitializers[i].call(instance, value);
|
|
221
|
+
}
|
|
222
|
+
return value;
|
|
223
|
+
};
|
|
224
|
+
} else {
|
|
225
|
+
var originalInitializer = init;
|
|
226
|
+
init = function(instance, init) {
|
|
227
|
+
return originalInitializer.call(instance, init);
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
ret.push(init);
|
|
231
|
+
}
|
|
232
|
+
if (kind !== 0) {
|
|
233
|
+
if (kind === 1) {
|
|
234
|
+
desc.get = value.get;
|
|
235
|
+
desc.set = value.set;
|
|
236
|
+
} else if (kind === 2) {
|
|
237
|
+
desc.value = value;
|
|
238
|
+
} else if (kind === 3) {
|
|
239
|
+
desc.get = value;
|
|
240
|
+
} else if (kind === 4) {
|
|
241
|
+
desc.set = value;
|
|
242
|
+
}
|
|
243
|
+
if (isPrivate) {
|
|
244
|
+
if (kind === 1) {
|
|
245
|
+
ret.push(function(instance, args) {
|
|
246
|
+
return value.get.call(instance, args);
|
|
247
|
+
});
|
|
248
|
+
ret.push(function(instance, args) {
|
|
249
|
+
return value.set.call(instance, args);
|
|
250
|
+
});
|
|
251
|
+
} else if (kind === 2) {
|
|
252
|
+
ret.push(value);
|
|
253
|
+
} else {
|
|
254
|
+
ret.push(function(instance, args) {
|
|
255
|
+
return value.call(instance, args);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
Object.defineProperty(base, name, desc);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function applyMemberDecs(Class, decInfos, metadata) {
|
|
264
|
+
var ret = [];
|
|
265
|
+
var protoInitializers;
|
|
266
|
+
var staticInitializers;
|
|
267
|
+
var existingProtoNonFields = new Map();
|
|
268
|
+
var existingStaticNonFields = new Map();
|
|
269
|
+
for(var i = 0; i < decInfos.length; i++){
|
|
270
|
+
var decInfo = decInfos[i];
|
|
271
|
+
if (!Array.isArray(decInfo)) continue;
|
|
272
|
+
var kind = decInfo[1];
|
|
273
|
+
var name = decInfo[2];
|
|
274
|
+
var isPrivate = decInfo.length > 3;
|
|
275
|
+
var isStatic = kind >= 5;
|
|
276
|
+
var base;
|
|
277
|
+
var initializers;
|
|
278
|
+
if (isStatic) {
|
|
279
|
+
base = Class;
|
|
280
|
+
kind = kind - 5;
|
|
281
|
+
staticInitializers = staticInitializers || [];
|
|
282
|
+
initializers = staticInitializers;
|
|
283
|
+
} else {
|
|
284
|
+
base = Class.prototype;
|
|
285
|
+
protoInitializers = protoInitializers || [];
|
|
286
|
+
initializers = protoInitializers;
|
|
287
|
+
}
|
|
288
|
+
if (kind !== 0 && !isPrivate) {
|
|
289
|
+
var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields;
|
|
290
|
+
var existingKind = existingNonFields.get(name) || 0;
|
|
291
|
+
if (existingKind === true || existingKind === 3 && kind !== 4 || existingKind === 4 && kind !== 3) {
|
|
292
|
+
throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
|
|
293
|
+
} else if (!existingKind && kind > 2) {
|
|
294
|
+
existingNonFields.set(name, kind);
|
|
295
|
+
} else {
|
|
296
|
+
existingNonFields.set(name, true);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata);
|
|
300
|
+
}
|
|
301
|
+
pushInitializers(ret, protoInitializers);
|
|
302
|
+
pushInitializers(ret, staticInitializers);
|
|
303
|
+
return ret;
|
|
304
|
+
}
|
|
305
|
+
function pushInitializers(ret, initializers) {
|
|
306
|
+
if (initializers) {
|
|
307
|
+
ret.push(function(instance) {
|
|
308
|
+
for(var i = 0; i < initializers.length; i++){
|
|
309
|
+
initializers[i].call(instance);
|
|
310
|
+
}
|
|
311
|
+
return instance;
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function applyClassDecs(targetClass, classDecs, metadata) {
|
|
316
|
+
if (classDecs.length > 0) {
|
|
317
|
+
var initializers = [];
|
|
318
|
+
var newClass = targetClass;
|
|
319
|
+
var name = targetClass.name;
|
|
320
|
+
for(var i = classDecs.length - 1; i >= 0; i--){
|
|
321
|
+
var decoratorFinishedRef = {
|
|
322
|
+
v: false
|
|
323
|
+
};
|
|
324
|
+
try {
|
|
325
|
+
var nextNewClass = classDecs[i](newClass, {
|
|
326
|
+
kind: "class",
|
|
327
|
+
name: name,
|
|
328
|
+
addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef),
|
|
329
|
+
metadata
|
|
330
|
+
});
|
|
331
|
+
} finally{
|
|
332
|
+
decoratorFinishedRef.v = true;
|
|
333
|
+
}
|
|
334
|
+
if (nextNewClass !== undefined) {
|
|
335
|
+
assertValidReturnValue(10, nextNewClass);
|
|
336
|
+
newClass = nextNewClass;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return [
|
|
340
|
+
defineMetadata(newClass, metadata),
|
|
341
|
+
function() {
|
|
342
|
+
for(var i = 0; i < initializers.length; i++){
|
|
343
|
+
initializers[i].call(newClass);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
];
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
function defineMetadata(Class, metadata) {
|
|
350
|
+
return Object.defineProperty(Class, Symbol.metadata || Symbol.for("Symbol.metadata"), {
|
|
351
|
+
configurable: true,
|
|
352
|
+
enumerable: true,
|
|
353
|
+
value: metadata
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) {
|
|
357
|
+
if (parentClass !== void 0) {
|
|
358
|
+
var parentMetadata = parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")];
|
|
359
|
+
}
|
|
360
|
+
var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata);
|
|
361
|
+
var e = applyMemberDecs(targetClass, memberDecs, metadata);
|
|
362
|
+
if (!classDecs.length) defineMetadata(targetClass, metadata);
|
|
363
|
+
return {
|
|
364
|
+
e: e,
|
|
365
|
+
get c () {
|
|
366
|
+
return applyClassDecs(targetClass, classDecs, metadata);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
};
|
|
7
370
|
}
|
|
371
|
+
function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
372
|
+
return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
|
|
373
|
+
}
|
|
374
|
+
var _dec, _dec1, _dec2, _initProto;
|
|
375
|
+
import { compactArray } from '@aztec/foundation/collection';
|
|
376
|
+
import { AbortError, TimeoutError } from '@aztec/foundation/error';
|
|
8
377
|
import { createLogger } from '@aztec/foundation/log';
|
|
9
378
|
import { executeTimeout } from '@aztec/foundation/timer';
|
|
10
379
|
import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
11
380
|
import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
12
|
-
import {
|
|
381
|
+
import { pipeline } from 'node:stream/promises';
|
|
13
382
|
import { CollectiveReqRespTimeoutError, IndividualReqRespTimeoutError, InvalidResponseError } from '../../errors/reqresp.error.js';
|
|
14
383
|
import { SnappyTransform } from '../encoding.js';
|
|
384
|
+
import { DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS, DEFAULT_REQRESP_DIAL_TIMEOUT_MS } from './config.js';
|
|
15
385
|
import { BatchConnectionSampler } from './connection-sampler/batch_connection_sampler.js';
|
|
16
|
-
import { ConnectionSampler } from './connection-sampler/connection_sampler.js';
|
|
17
|
-
import {
|
|
386
|
+
import { ConnectionSampler, RandomSampler } from './connection-sampler/connection_sampler.js';
|
|
387
|
+
import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, responseFromBuffer } from './interface.js';
|
|
18
388
|
import { ReqRespMetrics } from './metrics.js';
|
|
19
389
|
import { RateLimitStatus, RequestResponseRateLimiter, prettyPrintRateLimitStatus } from './rate-limiter/rate_limiter.js';
|
|
20
390
|
import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqRespStatus } from './status.js';
|
|
391
|
+
_dec = trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
|
|
392
|
+
[Attributes.P2P_REQ_RESP_PROTOCOL]: subProtocol,
|
|
393
|
+
[Attributes.P2P_REQ_RESP_BATCH_REQUESTS_COUNT]: requests.length
|
|
394
|
+
})), _dec1 = trackSpan('ReqResp.sendRequestToPeer', (peerId, subProtocol, _)=>({
|
|
395
|
+
[Attributes.P2P_ID]: peerId.toString(),
|
|
396
|
+
[Attributes.P2P_REQ_RESP_PROTOCOL]: subProtocol
|
|
397
|
+
})), _dec2 = trackSpan('ReqResp.streamHandler', (protocol, { connection })=>({
|
|
398
|
+
[Attributes.P2P_REQ_RESP_PROTOCOL]: protocol,
|
|
399
|
+
[Attributes.P2P_ID]: connection.remotePeer.toString()
|
|
400
|
+
}));
|
|
21
401
|
/**
|
|
22
402
|
* The Request Response Service
|
|
23
403
|
*
|
|
@@ -35,43 +415,82 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
35
415
|
libp2p;
|
|
36
416
|
peerScoring;
|
|
37
417
|
logger;
|
|
38
|
-
|
|
418
|
+
static{
|
|
419
|
+
({ e: [_initProto] } = _apply_decs_2203_r(this, [
|
|
420
|
+
[
|
|
421
|
+
_dec,
|
|
422
|
+
2,
|
|
423
|
+
"sendBatchRequest"
|
|
424
|
+
],
|
|
425
|
+
[
|
|
426
|
+
_dec1,
|
|
427
|
+
2,
|
|
428
|
+
"sendRequestToPeer"
|
|
429
|
+
],
|
|
430
|
+
[
|
|
431
|
+
_dec2,
|
|
432
|
+
2,
|
|
433
|
+
"streamHandler"
|
|
434
|
+
]
|
|
435
|
+
], []));
|
|
436
|
+
}
|
|
39
437
|
individualRequestTimeoutMs;
|
|
40
|
-
|
|
438
|
+
dialTimeoutMs;
|
|
41
439
|
subProtocolHandlers;
|
|
42
440
|
subProtocolValidators;
|
|
43
441
|
connectionSampler;
|
|
44
442
|
rateLimiter;
|
|
45
443
|
snappyTransform;
|
|
46
444
|
metrics;
|
|
47
|
-
constructor(config, libp2p, peerScoring, telemetryClient = getTelemetryClient()){
|
|
445
|
+
constructor(config, libp2p, peerScoring, logger = createLogger('p2p:reqresp'), rateLimits = {}, telemetryClient = getTelemetryClient()){
|
|
48
446
|
this.libp2p = libp2p;
|
|
49
447
|
this.peerScoring = peerScoring;
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
448
|
+
this.logger = logger;
|
|
449
|
+
this.individualRequestTimeoutMs = (_initProto(this), DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS);
|
|
450
|
+
this.dialTimeoutMs = DEFAULT_REQRESP_DIAL_TIMEOUT_MS;
|
|
451
|
+
this.subProtocolHandlers = {};
|
|
452
|
+
this.subProtocolValidators = {};
|
|
453
|
+
this.updateConfig(config);
|
|
454
|
+
this.rateLimiter = new RequestResponseRateLimiter(peerScoring, rateLimits);
|
|
56
455
|
// Connection sampler is used to sample our connected peers
|
|
57
|
-
this.connectionSampler = new ConnectionSampler(libp2p);
|
|
456
|
+
this.connectionSampler = new ConnectionSampler(libp2p, new RandomSampler(), createLogger(`${logger.module}:connection-sampler`), config);
|
|
58
457
|
this.snappyTransform = new SnappyTransform();
|
|
59
458
|
this.metrics = new ReqRespMetrics(telemetryClient);
|
|
60
459
|
}
|
|
460
|
+
updateConfig(config) {
|
|
461
|
+
if (typeof config.individualRequestTimeoutMs === 'number') {
|
|
462
|
+
this.individualRequestTimeoutMs = config.individualRequestTimeoutMs;
|
|
463
|
+
}
|
|
464
|
+
if (typeof config.dialTimeoutMs === 'number') {
|
|
465
|
+
this.dialTimeoutMs = config.dialTimeoutMs;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
61
468
|
get tracer() {
|
|
62
469
|
return this.metrics.tracer;
|
|
63
470
|
}
|
|
64
471
|
/**
|
|
472
|
+
* Get the connection sampler instance
|
|
473
|
+
*/ getConnectionSampler() {
|
|
474
|
+
return this.connectionSampler;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
65
477
|
* Start the reqresp service
|
|
66
478
|
*/ async start(subProtocolHandlers, subProtocolValidators) {
|
|
67
|
-
this.subProtocolHandlers
|
|
68
|
-
this.subProtocolValidators
|
|
479
|
+
Object.assign(this.subProtocolHandlers, subProtocolHandlers);
|
|
480
|
+
Object.assign(this.subProtocolValidators, subProtocolValidators);
|
|
69
481
|
// Register all protocol handlers
|
|
70
|
-
for (const subProtocol of Object.keys(
|
|
482
|
+
for (const subProtocol of Object.keys(subProtocolHandlers)){
|
|
483
|
+
this.logger.debug(`Registering handler for sub protocol ${subProtocol}`);
|
|
71
484
|
await this.libp2p.handle(subProtocol, (data)=>void this.streamHandler(subProtocol, data).catch((err)=>this.logger.error(`Error on libp2p subprotocol ${subProtocol} handler`, err)));
|
|
72
485
|
}
|
|
73
486
|
this.rateLimiter.start();
|
|
74
487
|
}
|
|
488
|
+
async addSubProtocol(subProtocol, handler, validator = DEFAULT_SUB_PROTOCOL_VALIDATORS[subProtocol]) {
|
|
489
|
+
this.subProtocolHandlers[subProtocol] = handler;
|
|
490
|
+
this.subProtocolValidators[subProtocol] = validator;
|
|
491
|
+
this.logger.debug(`Registering handler for sub protocol ${subProtocol}`);
|
|
492
|
+
await this.libp2p.handle(subProtocol, (data)=>void this.streamHandler(subProtocol, data).catch((err)=>this.logger.error(`Error on libp2p subprotocol ${subProtocol} handler`, err)));
|
|
493
|
+
}
|
|
75
494
|
/**
|
|
76
495
|
* Stop the reqresp service
|
|
77
496
|
*/ async stop() {
|
|
@@ -90,81 +509,6 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
90
509
|
// NOTE: We assume libp2p instance is managed by the caller
|
|
91
510
|
}
|
|
92
511
|
/**
|
|
93
|
-
* Send a request to peers, returns the first response
|
|
94
|
-
*
|
|
95
|
-
* @param subProtocol - The protocol being requested
|
|
96
|
-
* @param request - The request to send
|
|
97
|
-
* @returns - The response from the peer, otherwise undefined
|
|
98
|
-
*
|
|
99
|
-
* @description
|
|
100
|
-
* This method attempts to send a request to all active peers using the specified sub-protocol.
|
|
101
|
-
* It opens a stream with each peer, sends the request, and awaits a response.
|
|
102
|
-
* If a valid response is received, it returns the response; otherwise, it continues to the next peer.
|
|
103
|
-
* If no response is received from any peer, it returns undefined.
|
|
104
|
-
*
|
|
105
|
-
* The method performs the following steps:
|
|
106
|
-
* - Sample a peer to send the request to.
|
|
107
|
-
* - Opens a stream with the peer using the specified sub-protocol.
|
|
108
|
-
*
|
|
109
|
-
* When a response is received, it is validated using the given sub protocols response validator.
|
|
110
|
-
* To see the interface for the response validator - see `interface.ts`
|
|
111
|
-
*
|
|
112
|
-
* Failing a response validation requests in a severe peer penalty, and will
|
|
113
|
-
* prompt the node to continue to search to the next peer.
|
|
114
|
-
* For example, a transaction request validator will check that the payload returned does in fact
|
|
115
|
-
* match the txHash that was requested. A peer that fails this check an only be an extremely naughty peer.
|
|
116
|
-
*
|
|
117
|
-
* This entire operation is wrapped in an overall timeout, that is independent of the
|
|
118
|
-
* peer it is requesting data from.
|
|
119
|
-
*
|
|
120
|
-
*/ async sendRequest(subProtocol, request) {
|
|
121
|
-
const responseValidator = this.subProtocolValidators[subProtocol];
|
|
122
|
-
const requestBuffer = request.toBuffer();
|
|
123
|
-
const requestFunction = async ()=>{
|
|
124
|
-
// Attempt to ask all of our peers, but sampled in a random order
|
|
125
|
-
// This function is wrapped in a timeout, so we will exit the loop if we have not received a response
|
|
126
|
-
const numberOfPeers = this.libp2p.getPeers().length;
|
|
127
|
-
if (numberOfPeers === 0) {
|
|
128
|
-
this.logger.debug('No active peers to send requests to');
|
|
129
|
-
return undefined;
|
|
130
|
-
}
|
|
131
|
-
const attemptedPeers = new Map();
|
|
132
|
-
for(let i = 0; i < numberOfPeers; i++){
|
|
133
|
-
// Sample a peer to make a request to
|
|
134
|
-
const peer = this.connectionSampler.getPeer(attemptedPeers);
|
|
135
|
-
this.logger.trace(`Attempting to send request to peer: ${peer?.toString()}`);
|
|
136
|
-
if (!peer) {
|
|
137
|
-
this.logger.debug('No peers available to send requests to');
|
|
138
|
-
return undefined;
|
|
139
|
-
}
|
|
140
|
-
attemptedPeers.set(peer.toString(), true);
|
|
141
|
-
this.logger.trace(`Sending request to peer: ${peer.toString()}`);
|
|
142
|
-
const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffer);
|
|
143
|
-
if (response && response.status !== ReqRespStatus.SUCCESS) {
|
|
144
|
-
this.logger.debug(`Request to peer ${peer.toString()} failed with status ${prettyPrintReqRespStatus(response.status)}`);
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
// If we get a response, return it, otherwise we iterate onto the next peer
|
|
148
|
-
// We do not consider it a success if we have an empty buffer
|
|
149
|
-
if (response && response.data.length > 0) {
|
|
150
|
-
const object = subProtocolMap[subProtocol].response.fromBuffer(response.data);
|
|
151
|
-
// The response validator handles peer punishment within
|
|
152
|
-
const isValid = await responseValidator(request, object, peer);
|
|
153
|
-
if (!isValid) {
|
|
154
|
-
throw new InvalidResponseError();
|
|
155
|
-
}
|
|
156
|
-
return object;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
try {
|
|
161
|
-
return await executeTimeout(requestFunction, this.overallRequestTimeoutMs, ()=>new CollectiveReqRespTimeoutError());
|
|
162
|
-
} catch (e) {
|
|
163
|
-
this.logger.debug(`${e.message} | subProtocol: ${subProtocol}`);
|
|
164
|
-
return undefined;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
512
|
* Request multiple messages over the same sub protocol, balancing the requests across peers.
|
|
169
513
|
*
|
|
170
514
|
* @devnote
|
|
@@ -185,17 +529,27 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
185
529
|
* @returns
|
|
186
530
|
*
|
|
187
531
|
* @throws {CollectiveReqRespTimeoutError} - If the request batch exceeds the specified timeout (`timeoutMs`).
|
|
188
|
-
*/ async sendBatchRequest(subProtocol, requests, timeoutMs = 10000, maxPeers = Math.
|
|
189
|
-
const responseValidator = this.subProtocolValidators[subProtocol];
|
|
532
|
+
*/ async sendBatchRequest(subProtocol, requests, pinnedPeer, timeoutMs = 10000, maxPeers = Math.max(10, Math.ceil(requests.length / 3)), maxRetryAttempts = 3) {
|
|
533
|
+
const responseValidator = this.subProtocolValidators[subProtocol] ?? DEFAULT_SUB_PROTOCOL_VALIDATORS[subProtocol];
|
|
190
534
|
const responses = new Array(requests.length);
|
|
191
535
|
const requestBuffers = requests.map((req)=>req.toBuffer());
|
|
192
|
-
const
|
|
536
|
+
const isEmptyResponse = (value)=>{
|
|
537
|
+
// Some responses serialize to a non-empty buffer even when they contain no items (e.g., empty TxArray).
|
|
538
|
+
if (!value || typeof value !== 'object') {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
const length = value.length;
|
|
542
|
+
return typeof length === 'number' && length === 0;
|
|
543
|
+
};
|
|
544
|
+
const requestFunction = async (signal)=>{
|
|
193
545
|
// Track which requests still need to be processed
|
|
194
546
|
const pendingRequestIndices = new Set(requestBuffers.map((_, i)=>i));
|
|
195
547
|
// Create batch sampler with the total number of requests and max peers
|
|
196
|
-
const batchSampler = new BatchConnectionSampler(this.connectionSampler, requests.length, maxPeers
|
|
197
|
-
|
|
198
|
-
|
|
548
|
+
const batchSampler = new BatchConnectionSampler(this.connectionSampler, requests.length, maxPeers, compactArray([
|
|
549
|
+
pinnedPeer
|
|
550
|
+
]), createLogger(`${this.logger.module}:batch-connection-sampler`));
|
|
551
|
+
if (batchSampler.activePeerCount === 0 && !pinnedPeer) {
|
|
552
|
+
this.logger.warn('No active peers to send requests to');
|
|
199
553
|
return [];
|
|
200
554
|
}
|
|
201
555
|
// This is where it gets fun
|
|
@@ -206,18 +560,38 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
206
560
|
// We will continue to retry until we have processed all indices, or we have reached the max retry attempts
|
|
207
561
|
let retryAttempts = 0;
|
|
208
562
|
while(pendingRequestIndices.size > 0 && batchSampler.activePeerCount > 0 && retryAttempts < maxRetryAttempts){
|
|
209
|
-
|
|
563
|
+
if (signal.aborted) {
|
|
564
|
+
throw new AbortError('Batch request aborted');
|
|
565
|
+
}
|
|
210
566
|
const requestBatches = new Map();
|
|
211
567
|
// Group requests by peer
|
|
212
568
|
for (const requestIndex of pendingRequestIndices){
|
|
213
569
|
const peer = batchSampler.getPeerForRequest(requestIndex);
|
|
214
570
|
if (!peer) {
|
|
215
|
-
|
|
571
|
+
continue;
|
|
216
572
|
}
|
|
217
|
-
|
|
218
|
-
|
|
573
|
+
const peerAsString = peer.toString();
|
|
574
|
+
if (!requestBatches.has(peerAsString)) {
|
|
575
|
+
requestBatches.set(peerAsString, {
|
|
576
|
+
peerId: peer,
|
|
577
|
+
indices: []
|
|
578
|
+
});
|
|
219
579
|
}
|
|
220
|
-
requestBatches.get(
|
|
580
|
+
requestBatches.get(peerAsString).indices.push(requestIndex);
|
|
581
|
+
}
|
|
582
|
+
// If there is a pinned peer, we will always send every request to that peer
|
|
583
|
+
// We use the default limits for the subprotocol to avoid hitting the rate limiter
|
|
584
|
+
if (pinnedPeer) {
|
|
585
|
+
const limit = this.rateLimiter.getRateLimits(subProtocol).peerLimit.quotaCount;
|
|
586
|
+
requestBatches.set(pinnedPeer.toString(), {
|
|
587
|
+
peerId: pinnedPeer,
|
|
588
|
+
indices: Array.from(pendingRequestIndices.values()).slice(0, limit)
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
// If no requests could be assigned (all peers exhausted for all indices), exit early
|
|
592
|
+
if (requestBatches.size === 0) {
|
|
593
|
+
this.logger.warn('No peers available for any pending request indices, stopping batch request');
|
|
594
|
+
break;
|
|
221
595
|
}
|
|
222
596
|
// Make parallel requests for each peer's batch
|
|
223
597
|
// A batch entry will look something like this:
|
|
@@ -225,40 +599,58 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
225
599
|
// PeerId1: [4, 5, 6, 7]
|
|
226
600
|
// Peer Id 0 will send requests 0, 1, 2, 3 in serial
|
|
227
601
|
// while simultaneously Peer Id 1 will send requests 4, 5, 6, 7 in serial
|
|
228
|
-
const batchResults = await Promise.all(Array.from(requestBatches.entries()).map(async ([peer, indices])=>{
|
|
602
|
+
const batchResults = await Promise.all(Array.from(requestBatches.entries()).map(async ([peerAsString, { peerId: peer, indices }])=>{
|
|
229
603
|
try {
|
|
604
|
+
const markIndexFailed = (index)=>batchSampler.markPeerFailedForIndex(peer, index);
|
|
230
605
|
// Requests all going to the same peer are sent synchronously
|
|
231
606
|
const peerResults = [];
|
|
607
|
+
let shouldReplacePeer = false;
|
|
608
|
+
const handleFailure = (status, index)=>{
|
|
609
|
+
this.logger.warn(`Request to peer ${peerAsString} failed with status ${prettyPrintReqRespStatus(status)}`);
|
|
610
|
+
markIndexFailed(index);
|
|
611
|
+
return status === ReqRespStatus.RATE_LIMIT_EXCEEDED;
|
|
612
|
+
};
|
|
232
613
|
for (const index of indices){
|
|
614
|
+
this.logger.info(`Sending request ${index} to peer ${peerAsString}`);
|
|
233
615
|
const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffers[index]);
|
|
234
616
|
// Check the status of the response buffer
|
|
235
|
-
if (response
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
batchSampler.removePeerAndReplace(peer);
|
|
240
|
-
return {
|
|
241
|
-
peer,
|
|
242
|
-
results: peerResults
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
if (response && response.data.length > 0) {
|
|
246
|
-
const object = subProtocolMap[subProtocol].response.fromBuffer(response.data);
|
|
247
|
-
const isValid = await responseValidator(requests[index], object, peer);
|
|
248
|
-
if (isValid) {
|
|
249
|
-
peerResults.push({
|
|
250
|
-
index,
|
|
251
|
-
response: object
|
|
252
|
-
});
|
|
617
|
+
if (response.status !== ReqRespStatus.SUCCESS) {
|
|
618
|
+
shouldReplacePeer = handleFailure(response.status, index);
|
|
619
|
+
if (shouldReplacePeer) {
|
|
620
|
+
break;
|
|
253
621
|
}
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
if (response.data.length === 0) {
|
|
625
|
+
markIndexFailed(index);
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
const object = responseFromBuffer(subProtocol, response.data);
|
|
629
|
+
if (isEmptyResponse(object)) {
|
|
630
|
+
markIndexFailed(index);
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
const isValid = await responseValidator(requests[index], object, peer);
|
|
634
|
+
if (!isValid) {
|
|
635
|
+
markIndexFailed(index);
|
|
636
|
+
continue;
|
|
254
637
|
}
|
|
638
|
+
peerResults.push({
|
|
639
|
+
index,
|
|
640
|
+
response: object
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
// If peer had a hard failure (rate limit), replace it for future iterations
|
|
644
|
+
if (shouldReplacePeer) {
|
|
645
|
+
this.logger.warn(`Peer ${peerAsString} hit a hard failure, removing from sampler`);
|
|
646
|
+
batchSampler.removePeerAndReplace(peer);
|
|
255
647
|
}
|
|
256
648
|
return {
|
|
257
649
|
peer,
|
|
258
650
|
results: peerResults
|
|
259
651
|
};
|
|
260
652
|
} catch (error) {
|
|
261
|
-
this.logger.
|
|
653
|
+
this.logger.warn(`Failed batch request to peer ${peerAsString}:`, error);
|
|
262
654
|
batchSampler.removePeerAndReplace(peer);
|
|
263
655
|
return {
|
|
264
656
|
peer,
|
|
@@ -278,14 +670,14 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
278
670
|
retryAttempts++;
|
|
279
671
|
}
|
|
280
672
|
if (retryAttempts >= maxRetryAttempts) {
|
|
281
|
-
this.logger.
|
|
673
|
+
this.logger.warn(`Max retry attempts ${maxRetryAttempts} reached for batch request`);
|
|
282
674
|
}
|
|
283
675
|
return responses;
|
|
284
676
|
};
|
|
285
677
|
try {
|
|
286
678
|
return await executeTimeout(requestFunction, timeoutMs, ()=>new CollectiveReqRespTimeoutError());
|
|
287
679
|
} catch (e) {
|
|
288
|
-
this.logger.
|
|
680
|
+
this.logger.warn(`${e.message} | subProtocol: ${subProtocol}`);
|
|
289
681
|
return [];
|
|
290
682
|
}
|
|
291
683
|
}
|
|
@@ -299,6 +691,7 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
299
691
|
* @param peerId - The peer to send the request to
|
|
300
692
|
* @param subProtocol - The protocol to use to request
|
|
301
693
|
* @param payload - The payload to send
|
|
694
|
+
* @param dialTimeout - If establishing a stream takes longer than this an error will be thrown
|
|
302
695
|
* @returns If the request is successful, the response is returned, otherwise undefined
|
|
303
696
|
*
|
|
304
697
|
* @description
|
|
@@ -312,24 +705,47 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
312
705
|
*
|
|
313
706
|
* If the stream is not closed by the dialled peer, and a timeout occurs, then
|
|
314
707
|
* the stream is closed on the requester's end and sender (us) updates its peer score
|
|
315
|
-
*/ async sendRequestToPeer(peerId, subProtocol, payload) {
|
|
708
|
+
*/ async sendRequestToPeer(peerId, subProtocol, payload, dialTimeout = this.dialTimeoutMs) {
|
|
316
709
|
let stream;
|
|
317
710
|
try {
|
|
318
711
|
this.metrics.recordRequestSent(subProtocol);
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
712
|
+
this.logger.trace(`Sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
|
|
713
|
+
stream = await this.connectionSampler.dialProtocol(peerId, subProtocol, dialTimeout);
|
|
714
|
+
this.logger.trace(`Opened stream ${stream.id} for sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
|
|
715
|
+
const timeoutErr = new IndividualReqRespTimeoutError();
|
|
716
|
+
const [_, resp] = await executeTimeout((signal)=>Promise.all([
|
|
717
|
+
pipeline([
|
|
718
|
+
payload
|
|
719
|
+
], stream.sink, {
|
|
720
|
+
signal
|
|
721
|
+
}),
|
|
722
|
+
pipeline(stream.source, this.readMessage.bind(this), {
|
|
723
|
+
signal
|
|
724
|
+
})
|
|
725
|
+
]), this.individualRequestTimeoutMs, ()=>timeoutErr);
|
|
726
|
+
return resp;
|
|
325
727
|
} catch (e) {
|
|
728
|
+
this.logger.warn(`SUBPROTOCOL: ${subProtocol}\n`, e);
|
|
729
|
+
// On error we immediately abort the stream, this is preferred way,
|
|
730
|
+
// because it signals to the sender that error happened, whereas
|
|
731
|
+
// closing the stream only closes our side and is much slower
|
|
732
|
+
if (stream) {
|
|
733
|
+
stream.abort(e);
|
|
734
|
+
}
|
|
326
735
|
this.metrics.recordRequestError(subProtocol);
|
|
327
736
|
this.handleResponseError(e, peerId, subProtocol);
|
|
737
|
+
// If there is an exception, we return an unknown response
|
|
738
|
+
this.logger.debug(`Error sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}: ${e}`);
|
|
739
|
+
return {
|
|
740
|
+
status: ReqRespStatus.FAILURE
|
|
741
|
+
};
|
|
328
742
|
} finally{
|
|
329
743
|
// Only close the stream if we created it
|
|
744
|
+
// Note even if we aborted the stream, calling close on it is ok, it's just a no-op
|
|
330
745
|
if (stream) {
|
|
331
746
|
try {
|
|
332
|
-
|
|
747
|
+
this.logger.trace(`Closing stream ${stream.id} for request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
|
|
748
|
+
await this.connectionSampler.close(stream);
|
|
333
749
|
} catch (closeError) {
|
|
334
750
|
this.logger.error(`Error closing stream: ${closeError instanceof Error ? closeError.message : 'Unknown error'}`);
|
|
335
751
|
}
|
|
@@ -346,75 +762,41 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
346
762
|
* @param subProtocol - The sub protocol
|
|
347
763
|
* @returns If the error is non pubishable, then undefined is returned, otherwise the peer is penalized
|
|
348
764
|
*/ handleResponseError(e, peerId, subProtocol) {
|
|
349
|
-
const severity = this.
|
|
765
|
+
const severity = this.categorizeResponseError(e, peerId, subProtocol);
|
|
350
766
|
if (severity) {
|
|
351
767
|
this.peerScoring.penalizePeer(peerId, severity);
|
|
352
768
|
}
|
|
353
769
|
}
|
|
354
770
|
/**
|
|
355
|
-
* Categorize the error and log it.
|
|
356
|
-
*/ categorizeError(e, peerId, subProtocol) {
|
|
357
|
-
// Non punishable errors - we do not expect a response for goodbye messages
|
|
358
|
-
if (subProtocol === ReqRespSubProtocol.GOODBYE) {
|
|
359
|
-
this.logger.debug('Error encountered on goodbye sub protocol, no penalty', {
|
|
360
|
-
peerId: peerId.toString(),
|
|
361
|
-
subProtocol
|
|
362
|
-
});
|
|
363
|
-
return undefined;
|
|
364
|
-
}
|
|
365
|
-
// We do not punish a collective timeout, as the node triggers this interupt, independent of the peer's behaviour
|
|
366
|
-
const logTags = {
|
|
367
|
-
peerId: peerId.toString(),
|
|
368
|
-
subProtocol
|
|
369
|
-
};
|
|
370
|
-
if (e instanceof CollectiveReqRespTimeoutError || e instanceof InvalidResponseError) {
|
|
371
|
-
this.logger.debug(`Non-punishable error: ${e.message} | peerId: ${peerId.toString()} | subProtocol: ${subProtocol}`, logTags);
|
|
372
|
-
return undefined;
|
|
373
|
-
}
|
|
374
|
-
// Pubishable errors
|
|
375
|
-
// Connection reset errors in the networking stack are punished with high severity
|
|
376
|
-
// it just signals an unreliable peer
|
|
377
|
-
// We assume that the requesting node has a functioning networking stack.
|
|
378
|
-
if (e?.code === 'ECONNRESET' || e?.code === 'EPIPE') {
|
|
379
|
-
this.logger.debug(`Connection reset: ${peerId.toString()}`, logTags);
|
|
380
|
-
return PeerErrorSeverity.HighToleranceError;
|
|
381
|
-
}
|
|
382
|
-
if (e?.code === 'ECONNREFUSED') {
|
|
383
|
-
this.logger.debug(`Connection refused: ${peerId.toString()}`, logTags);
|
|
384
|
-
return PeerErrorSeverity.HighToleranceError;
|
|
385
|
-
}
|
|
386
|
-
// Timeout errors are punished with high tolerance, they can be due to a geogrpahically far away peer or an
|
|
387
|
-
// overloaded peer
|
|
388
|
-
if (e instanceof IndividualReqRespTimeoutError) {
|
|
389
|
-
this.logger.debug(`Timeout error: ${e.message} | peerId: ${peerId.toString()} | subProtocol: ${subProtocol}`, logTags);
|
|
390
|
-
return PeerErrorSeverity.HighToleranceError;
|
|
391
|
-
}
|
|
392
|
-
// Catch all error
|
|
393
|
-
this.logger.error(`Unexpected error sending request to peer`, e, logTags);
|
|
394
|
-
return PeerErrorSeverity.HighToleranceError;
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
771
|
* Read a message returned from a stream into a single buffer
|
|
398
772
|
*
|
|
399
773
|
* The message is split into two components
|
|
400
774
|
* - The first chunk should contain a control byte, indicating the status of the response see `ReqRespStatus`
|
|
401
775
|
* - The second chunk should contain the response data
|
|
402
776
|
*/ async readMessage(source) {
|
|
403
|
-
let
|
|
777
|
+
let status;
|
|
404
778
|
const chunks = [];
|
|
405
779
|
try {
|
|
406
780
|
for await (const chunk of source){
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
statusBuffer = parseStatusChunk(firstChunkBuffer);
|
|
410
|
-
} else {
|
|
781
|
+
const statusParsed = status !== undefined;
|
|
782
|
+
if (statusParsed) {
|
|
411
783
|
chunks.push(chunk.subarray());
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
const firstChunkBuffer = chunk.subarray();
|
|
787
|
+
status = parseStatusChunk(firstChunkBuffer);
|
|
788
|
+
// In case status is not SUCCESS, we do not expect any data in the response
|
|
789
|
+
// we can return early
|
|
790
|
+
if (status !== ReqRespStatus.SUCCESS) {
|
|
791
|
+
return {
|
|
792
|
+
status
|
|
793
|
+
};
|
|
412
794
|
}
|
|
413
795
|
}
|
|
414
796
|
const messageData = Buffer.concat(chunks);
|
|
415
|
-
const message = this.snappyTransform.
|
|
797
|
+
const message = this.snappyTransform.inboundTransformData(messageData);
|
|
416
798
|
return {
|
|
417
|
-
status:
|
|
799
|
+
status: status ?? ReqRespStatus.UNKNOWN,
|
|
418
800
|
data: message
|
|
419
801
|
};
|
|
420
802
|
} catch (e) {
|
|
@@ -424,8 +806,7 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
424
806
|
status = e.status;
|
|
425
807
|
}
|
|
426
808
|
return {
|
|
427
|
-
status
|
|
428
|
-
data: Buffer.from([])
|
|
809
|
+
status
|
|
429
810
|
};
|
|
430
811
|
}
|
|
431
812
|
}
|
|
@@ -433,7 +814,8 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
433
814
|
* Stream Handler
|
|
434
815
|
* Reads the incoming stream, determines the protocol, then triggers the appropriate handler
|
|
435
816
|
*
|
|
436
|
-
* @param
|
|
817
|
+
* @param protocol - The sub protocol to handle
|
|
818
|
+
* @param incomingStream - The incoming stream data containing the stream and connection
|
|
437
819
|
*
|
|
438
820
|
* @description
|
|
439
821
|
* An individual stream handler will be bound to each sub protocol, and handles returning data back
|
|
@@ -444,73 +826,196 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
|
|
|
444
826
|
*
|
|
445
827
|
* We check rate limits for each peer, note the peer will be penalised within the rate limiter implementation
|
|
446
828
|
* if they exceed their peer specific limits.
|
|
447
|
-
*/ async streamHandler(protocol,
|
|
448
|
-
|
|
829
|
+
*/ async streamHandler(protocol, incomingStream) {
|
|
830
|
+
const { stream, connection } = incomingStream;
|
|
449
831
|
try {
|
|
450
|
-
|
|
832
|
+
this.metrics.recordRequestReceived(protocol);
|
|
451
833
|
const rateLimitStatus = this.rateLimiter.allow(protocol, connection.remotePeer);
|
|
452
|
-
if (rateLimitStatus
|
|
453
|
-
this.logger.
|
|
834
|
+
if (rateLimitStatus !== RateLimitStatus.Allowed) {
|
|
835
|
+
this.logger.verbose(`Rate limit exceeded ${prettyPrintRateLimitStatus(rateLimitStatus)} for ${protocol} from ${connection.remotePeer}`);
|
|
454
836
|
throw new ReqRespStatusError(ReqRespStatus.RATE_LIMIT_EXCEEDED);
|
|
455
837
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
await pipe(stream, async function*(source) {
|
|
459
|
-
for await (const chunkList of source){
|
|
460
|
-
const msg = Buffer.from(chunkList.subarray());
|
|
461
|
-
const response = await handler(connection.remotePeer, msg);
|
|
462
|
-
if (protocol === ReqRespSubProtocol.GOODBYE) {
|
|
463
|
-
// Don't respond
|
|
464
|
-
await stream.close();
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
// Send success code first, then the response
|
|
468
|
-
const successChunk = Buffer.from([
|
|
469
|
-
ReqRespStatus.SUCCESS
|
|
470
|
-
]);
|
|
471
|
-
yield new Uint8Array(successChunk);
|
|
472
|
-
yield new Uint8Array(transform.outboundTransformNoTopic(response));
|
|
473
|
-
}
|
|
474
|
-
}, stream);
|
|
475
|
-
} catch (e) {
|
|
476
|
-
this.logger.warn('Reqresp Response error: ', e);
|
|
838
|
+
await this.processStream(protocol, incomingStream);
|
|
839
|
+
} catch (err) {
|
|
477
840
|
this.metrics.recordResponseError(protocol);
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
841
|
+
this.handleRequestError(err, connection.remotePeer, protocol);
|
|
842
|
+
if (err instanceof ReqRespStatusError) {
|
|
843
|
+
const errorSent = await this.trySendError(stream, connection.remotePeer, protocol, err.status);
|
|
844
|
+
const logMessage = errorSent ? 'Protocol error sent successfully.' : 'Stream already closed or poisoned, not sending error response.';
|
|
845
|
+
const isRateLimit = err.status === ReqRespStatus.RATE_LIMIT_EXCEEDED;
|
|
846
|
+
const level = isRateLimit ? 'debug' : 'warn';
|
|
847
|
+
this.logger[level](logMessage + ` Status: ${ReqRespStatus[err.status]}`, {
|
|
848
|
+
protocol,
|
|
849
|
+
err,
|
|
850
|
+
errorStatus: err.status,
|
|
851
|
+
cause: err.cause ?? 'Cause unknown'
|
|
852
|
+
});
|
|
853
|
+
} else {
|
|
854
|
+
// In erroneous case we abort the stream, this will signal the peer that something went wrong
|
|
855
|
+
// and that this stream should be dropped
|
|
856
|
+
const isMessageToNotWarn = err instanceof Error && [
|
|
857
|
+
'stream reset',
|
|
858
|
+
'Cannot push value onto an ended pushable'
|
|
859
|
+
].some((msg)=>err.message.includes(msg));
|
|
860
|
+
const level = isMessageToNotWarn ? 'debug' : 'warn';
|
|
861
|
+
this.logger[level]('Unknown stream error while handling the stream, aborting', {
|
|
862
|
+
protocol,
|
|
863
|
+
err
|
|
864
|
+
});
|
|
865
|
+
stream.abort(err);
|
|
482
866
|
}
|
|
483
|
-
const sendErrorChunk = this.sendErrorChunk(errorStatus);
|
|
484
|
-
// Return and yield the response chunk
|
|
485
|
-
await pipe(stream, async function*(_source) {
|
|
486
|
-
yield* sendErrorChunk;
|
|
487
|
-
}, stream);
|
|
488
867
|
} finally{
|
|
868
|
+
//NOTE: This is idempotent action, so it's ok to call it even if stream was aborted
|
|
489
869
|
await stream.close();
|
|
490
870
|
}
|
|
491
871
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
872
|
+
/**
|
|
873
|
+
* Reads incoming data from the stream, processes it according to the sub protocol,
|
|
874
|
+
* and puts response back into the stream.
|
|
875
|
+
*
|
|
876
|
+
* @param protocol - The sub protocol to use for processing the stream
|
|
877
|
+
* @param incomingStream - The incoming stream data containing the stream and connection
|
|
878
|
+
*
|
|
879
|
+
* */ async processStream(protocol, { stream, connection }) {
|
|
880
|
+
const handler = this.subProtocolHandlers[protocol];
|
|
881
|
+
if (!handler) {
|
|
882
|
+
throw new Error(`No handler defined for reqresp subprotocol ${protocol}`);
|
|
883
|
+
}
|
|
884
|
+
const snappy = this.snappyTransform;
|
|
885
|
+
const SUCCESS = Uint8Array.of(ReqRespStatus.SUCCESS);
|
|
886
|
+
await pipeline(stream.source, async function*(source) {
|
|
887
|
+
for await (const chunk of source){
|
|
888
|
+
const response = await handler(connection.remotePeer, chunk.subarray());
|
|
889
|
+
if (protocol === ReqRespSubProtocol.GOODBYE) {
|
|
890
|
+
// NOTE: The stream was already closed by Goodbye handler
|
|
891
|
+
// peerManager.goodbyeReceived(peerId, reason); will call libp2p.hangUp closing all active streams and connections
|
|
892
|
+
// Don't try to respond
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
stream.metadata.written = true; // Mark the stream as written to;
|
|
896
|
+
yield SUCCESS;
|
|
897
|
+
yield snappy.outboundTransformData(response);
|
|
898
|
+
}
|
|
899
|
+
}, stream.sink);
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Try to send error status to the peer. We say try, because the stream,
|
|
903
|
+
* might already be closed
|
|
904
|
+
* @param stream - The stream opened between us and the peer
|
|
905
|
+
* @param status - The error status to send back to the peer
|
|
906
|
+
* @returns true if error was sent successfully, otherwise false
|
|
907
|
+
*
|
|
908
|
+
*/ async trySendError(stream, peerId, protocol, status) {
|
|
909
|
+
const canWriteToStream = // 'writing' is a bit weird naming, but it actually means that the stream is ready to write
|
|
910
|
+
// 'ready' means that stream ready to be opened for writing
|
|
911
|
+
stream.status === 'open' && (stream.writeStatus === 'writing' || stream.writeStatus === 'ready');
|
|
912
|
+
// Stream was already written to, we consider it poisoned, in a sense,
|
|
913
|
+
// that even if we write an error response, it will not be interpreted correctly by the peer
|
|
914
|
+
const streamPoisoned = stream.metadata.written === true;
|
|
915
|
+
const shouldWriteToStream = canWriteToStream && !streamPoisoned;
|
|
916
|
+
if (!shouldWriteToStream) {
|
|
917
|
+
return false;
|
|
918
|
+
}
|
|
919
|
+
try {
|
|
920
|
+
await pipeline(function*() {
|
|
921
|
+
yield Uint8Array.of(status);
|
|
922
|
+
}, stream.sink);
|
|
923
|
+
return true;
|
|
924
|
+
} catch (e) {
|
|
925
|
+
this.logger.warn('Error while sending error response', e);
|
|
926
|
+
stream.abort(e);
|
|
927
|
+
this.handleRequestError(e, peerId, protocol);
|
|
928
|
+
return false;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
handleRequestError(e, peerId, subProtocol) {
|
|
932
|
+
const severity = this.categorizeRequestError(e, peerId, subProtocol);
|
|
933
|
+
if (severity) {
|
|
934
|
+
this.peerScoring.penalizePeer(peerId, severity);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Categorize the request error and log it.
|
|
939
|
+
*
|
|
940
|
+
* @returns Severity of the error, or undefined if the error is not punishable.
|
|
941
|
+
*/ categorizeRequestError(e, peerId, subProtocol) {
|
|
942
|
+
const logTags = {
|
|
943
|
+
peerId: peerId.toString(),
|
|
944
|
+
subProtocol
|
|
945
|
+
};
|
|
946
|
+
//Punishable error - peer should never send badly formed request
|
|
947
|
+
if (e instanceof ReqRespStatusError && e.status === ReqRespStatus.BADLY_FORMED_REQUEST) {
|
|
948
|
+
this.logger.debug(`Punishable error in ${subProtocol}: ${e.cause}`, logTags);
|
|
949
|
+
return PeerErrorSeverity.LowToleranceError;
|
|
950
|
+
}
|
|
951
|
+
//TODO: (mralj): think if we should penalize peer here based on connection errors
|
|
952
|
+
return undefined;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Categorize the response error and log it.
|
|
956
|
+
*
|
|
957
|
+
* @returns Severity of the error, or undefined if the error is not punishable.
|
|
958
|
+
*/ categorizeResponseError(e, peerId, subProtocol) {
|
|
959
|
+
const logTags = {
|
|
960
|
+
peerId: peerId.toString(),
|
|
961
|
+
subProtocol
|
|
962
|
+
};
|
|
963
|
+
// Non punishable errors - we do not expect a response for goodbye messages
|
|
964
|
+
if (subProtocol === ReqRespSubProtocol.GOODBYE) {
|
|
965
|
+
this.logger.debug('Error encountered on goodbye sub protocol, no penalty', logTags);
|
|
966
|
+
return undefined;
|
|
967
|
+
}
|
|
968
|
+
// We do not punish a collective timeout, as the node triggers this interupt, independent of the peer's behaviour
|
|
969
|
+
if (e instanceof CollectiveReqRespTimeoutError || e instanceof InvalidResponseError) {
|
|
970
|
+
this.logger.debug(`Non-punishable error in ${subProtocol}: ${e.message}`, logTags);
|
|
971
|
+
return undefined;
|
|
972
|
+
}
|
|
973
|
+
return this.categorizeConnectionErrors(e, peerId, subProtocol);
|
|
974
|
+
}
|
|
975
|
+
/*
|
|
976
|
+
* Errors specific to connection handling
|
|
977
|
+
* These can happen both when sending request and response*/ categorizeConnectionErrors(e, peerId, subProtocol) {
|
|
978
|
+
const logTags = {
|
|
979
|
+
peerId: peerId.toString(),
|
|
980
|
+
subProtocol
|
|
981
|
+
};
|
|
982
|
+
// Do not punish if we are stopping the service
|
|
983
|
+
if (e instanceof AbortError || e?.code == 'ABORT_ERR') {
|
|
984
|
+
this.logger.debug(`Request aborted: ${e.message}`, logTags);
|
|
985
|
+
return undefined;
|
|
986
|
+
}
|
|
987
|
+
// Do not punish if we are the ones closing the connection
|
|
988
|
+
if (e?.code === 'ERR_CONNECTION_BEING_CLOSED' || e?.code === 'ERR_CONNECTION_CLOSED' || e?.code === 'ERR_TRANSIENT_CONNECTION' || e?.message?.includes('Muxer already closed') || e?.message?.includes('muxer closed') || e?.message?.includes('ended pushable')) {
|
|
989
|
+
this.logger.debug(`Connection closed to peer from our side: ${peerId.toString()} (${e?.message ?? 'missing error message'})`, logTags);
|
|
990
|
+
return undefined;
|
|
991
|
+
}
|
|
992
|
+
// Pubishable errors
|
|
993
|
+
// Connection reset errors in the networking stack are punished with high severity
|
|
994
|
+
// it just signals an unreliable peer
|
|
995
|
+
// We assume that the requesting node has a functioning networking stack.
|
|
996
|
+
if (e?.code === 'ECONNRESET' || e?.code === 'EPIPE') {
|
|
997
|
+
this.logger.debug(`Connection reset: ${peerId.toString()}`, logTags);
|
|
998
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
999
|
+
}
|
|
1000
|
+
if (e?.code === 'ECONNREFUSED') {
|
|
1001
|
+
this.logger.debug(`Connection refused: ${peerId.toString()}`, logTags);
|
|
1002
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
1003
|
+
}
|
|
1004
|
+
if (e?.code === 'ERR_UNEXPECTED_EOF') {
|
|
1005
|
+
this.logger.debug(`Connection unexpected EOF: ${peerId.toString()}`, logTags);
|
|
1006
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
1007
|
+
}
|
|
1008
|
+
if (e?.code === 'ERR_UNSUPPORTED_PROTOCOL') {
|
|
1009
|
+
this.logger.debug(`Sub protocol not supported by peer: ${peerId.toString()}`, logTags);
|
|
1010
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
1011
|
+
}
|
|
1012
|
+
// Timeout errors are punished with high tolerance, they can be due to a geographically far away or overloaded peer
|
|
1013
|
+
if (e instanceof IndividualReqRespTimeoutError || e instanceof TimeoutError) {
|
|
1014
|
+
this.logger.debug(`Timeout error in ${subProtocol}: ${e.message}`, logTags);
|
|
1015
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
1016
|
+
}
|
|
1017
|
+
// Catch all error
|
|
1018
|
+
this.logger.error(`Unexpected error in ReqResp protocol`, e, logTags);
|
|
1019
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
497
1020
|
}
|
|
498
1021
|
}
|
|
499
|
-
_ts_decorate([
|
|
500
|
-
trackSpan('ReqResp.sendBatchRequest', (subProtocol, requests)=>({
|
|
501
|
-
[Attributes.P2P_REQ_RESP_PROTOCOL]: subProtocol,
|
|
502
|
-
[Attributes.P2P_REQ_RESP_BATCH_REQUESTS_COUNT]: requests.length
|
|
503
|
-
}))
|
|
504
|
-
], ReqResp.prototype, "sendBatchRequest", null);
|
|
505
|
-
_ts_decorate([
|
|
506
|
-
trackSpan('ReqResp.sendRequestToPeer', (peerId, subProtocol, _)=>({
|
|
507
|
-
[Attributes.P2P_ID]: peerId.toString(),
|
|
508
|
-
[Attributes.P2P_REQ_RESP_PROTOCOL]: subProtocol
|
|
509
|
-
}))
|
|
510
|
-
], ReqResp.prototype, "sendRequestToPeer", null);
|
|
511
|
-
_ts_decorate([
|
|
512
|
-
trackSpan('ReqResp.streamHandler', (protocol, { connection })=>({
|
|
513
|
-
[Attributes.P2P_REQ_RESP_PROTOCOL]: protocol,
|
|
514
|
-
[Attributes.P2P_ID]: connection.remotePeer.toString()
|
|
515
|
-
}))
|
|
516
|
-
], ReqResp.prototype, "streamHandler", null);
|