@aztec/p2p 0.0.0-test.0 → 0.0.1-commit.24de95ac
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.map +1 -1
- package/dest/bootstrap/bootstrap.js +22 -9
- package/dest/client/factory.d.ts +13 -3
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +60 -24
- package/dest/client/index.d.ts +1 -0
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +1 -0
- package/dest/client/interface.d.ts +155 -0
- package/dest/client/interface.d.ts.map +1 -0
- package/dest/client/interface.js +9 -0
- package/dest/client/p2p_client.d.ts +72 -169
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +365 -174
- package/dest/config.d.ts +123 -103
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +173 -34
- package/dest/enr/generate-enr.d.ts +10 -2
- package/dest/enr/generate-enr.d.ts.map +1 -1
- package/dest/enr/generate-enr.js +27 -5
- package/dest/index.d.ts +3 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +42 -4
- 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.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +204 -54
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +10 -2
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +93 -15
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +10 -2
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +86 -18
- package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +9 -15
- package/dest/mem_pools/instrumentation.d.ts +7 -11
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +25 -37
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +93 -9
- 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 +469 -97
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +33 -9
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +133 -36
- package/dest/mem_pools/tx_pool/priority.js +1 -1
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +64 -8
- 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.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +264 -39
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +45 -9
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +5 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +61 -12
- 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/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.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +4 -4
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +56 -86
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +0 -2
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +21 -27
- package/dest/msg_validators/tx_validator/factory.d.ts +15 -0
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/factory.js +74 -0
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +11 -0
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/gas_validator.js +115 -0
- package/dest/msg_validators/tx_validator/index.d.ts +7 -0
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +7 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +7 -3
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +39 -20
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +14 -0
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/phases_validator.js +91 -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 +12 -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 +8 -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.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +6 -5
- package/dest/services/discv5/discV5_service.d.ts +9 -8
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +63 -36
- package/dest/services/dummy_service.d.ts +49 -10
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +88 -5
- package/dest/services/encoding.d.ts +25 -6
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +73 -5
- package/dest/services/index.d.ts +4 -0
- package/dest/services/index.d.ts.map +1 -1
- package/dest/services/index.js +4 -0
- package/dest/services/libp2p/instrumentation.d.ts +18 -0
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -0
- package/dest/services/libp2p/instrumentation.js +157 -0
- package/dest/services/libp2p/libp2p_service.d.ts +87 -42
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +500 -218
- 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 +3 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +11 -2
- package/dest/services/peer-manager/peer_manager.d.ts +126 -15
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +547 -72
- package/dest/services/reqresp/config.d.ts +10 -8
- 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 +1 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +10 -6
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +30 -13
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +142 -84
- package/dest/services/reqresp/index.d.ts +2 -1
- 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 +72 -23
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +45 -26
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- 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 +5 -0
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block.js +28 -5
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +30 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +75 -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 +39 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +49 -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 +75 -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 +2 -4
- 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 +2 -0
- 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 +0 -2
- package/dest/services/reqresp/protocols/ping.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.d.ts +38 -6
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +72 -5
- package/dest/services/reqresp/protocols/tx.d.ts +12 -1
- 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/rate_limiter.d.ts +4 -2
- 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.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +21 -1
- package/dest/services/reqresp/reqresp.d.ts +45 -47
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +298 -207
- package/dest/services/reqresp/status.d.ts +9 -3
- package/dest/services/reqresp/status.d.ts.map +1 -1
- package/dest/services/reqresp/status.js +9 -2
- package/dest/services/service.d.ts +22 -18
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +25 -0
- package/dest/services/tx_collection/config.d.ts.map +1 -0
- package/dest/services/tx_collection/config.js +58 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +56 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/fast_tx_collection.js +300 -0
- package/dest/services/tx_collection/index.d.ts +3 -0
- package/dest/services/tx_collection/index.d.ts.map +1 -0
- package/dest/services/tx_collection/index.js +2 -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 +34 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +54 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/slow_tx_collection.js +176 -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 +49 -0
- package/dest/services/tx_provider.d.ts.map +1 -0
- package/dest/services/tx_provider.js +210 -0
- package/dest/services/tx_provider_instrumentation.d.ts +13 -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/get-ports.d.ts.map +1 -1
- package/dest/test-helpers/index.d.ts +1 -0
- package/dest/test-helpers/index.d.ts.map +1 -1
- package/dest/test-helpers/index.js +1 -0
- 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 +32 -4
- 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 +14 -10
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +62 -28
- package/dest/testbench/p2p_client_testbench_worker.js +96 -25
- package/dest/testbench/parse_log_file.js +4 -4
- package/dest/testbench/testbench.js +4 -4
- package/dest/testbench/worker_client_manager.d.ts +0 -5
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +11 -19
- package/dest/types/index.d.ts +3 -1
- package/dest/types/index.d.ts.map +1 -1
- package/dest/types/index.js +2 -0
- package/dest/util.d.ts +22 -15
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +64 -67
- package/dest/versioning.d.ts +3 -3
- package/dest/versioning.d.ts.map +1 -1
- package/dest/versioning.js +8 -3
- package/package.json +28 -24
- package/src/bootstrap/bootstrap.ts +27 -11
- package/src/client/factory.ts +136 -45
- package/src/client/index.ts +1 -0
- package/src/client/interface.ts +195 -0
- package/src/client/p2p_client.ts +460 -327
- package/src/config.ts +288 -134
- package/src/enr/generate-enr.ts +39 -6
- package/src/index.ts +4 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +48 -4
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +241 -55
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +117 -20
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +114 -22
- package/src/mem_pools/attestation_pool/mocks.ts +11 -10
- package/src/mem_pools/instrumentation.ts +32 -46
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +549 -108
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +153 -44
- package/src/mem_pools/tx_pool/priority.ts +1 -1
- package/src/mem_pools/tx_pool/tx_pool.ts +67 -8
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +217 -34
- package/src/msg_validators/attestation_validator/attestation_validator.ts +55 -10
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +66 -14
- package/src/msg_validators/msg_seen_validator/msg_seen_validator.ts +36 -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 +4 -4
- package/src/msg_validators/tx_validator/data_validator.ts +81 -69
- package/src/msg_validators/tx_validator/double_spend_validator.ts +19 -17
- package/src/msg_validators/tx_validator/factory.ts +109 -0
- package/src/msg_validators/tx_validator/gas_validator.ts +134 -0
- package/src/msg_validators/tx_validator/index.ts +7 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +58 -21
- package/src/msg_validators/tx_validator/phases_validator.ts +114 -0
- package/src/msg_validators/tx_validator/test_utils.ts +43 -0
- package/src/msg_validators/tx_validator/timestamp_validator.ts +46 -0
- package/src/msg_validators/tx_validator/tx_permitted_validator.ts +17 -0
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +6 -5
- package/src/services/discv5/discV5_service.ts +84 -38
- package/src/services/dummy_service.ts +147 -9
- package/src/services/encoding.ts +80 -5
- package/src/services/index.ts +4 -0
- package/src/services/libp2p/instrumentation.ts +158 -0
- package/src/services/libp2p/libp2p_service.ts +646 -263
- package/src/services/peer-manager/interface.ts +29 -0
- package/src/services/peer-manager/metrics.ts +16 -1
- package/src/services/peer-manager/peer_manager.ts +652 -78
- package/src/services/reqresp/config.ts +26 -9
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +12 -6
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +148 -95
- package/src/services/reqresp/index.ts +2 -0
- package/src/services/reqresp/interface.ts +91 -36
- package/src/services/reqresp/metrics.ts +4 -1
- package/src/services/reqresp/protocols/auth.ts +83 -0
- package/src/services/reqresp/protocols/block.ts +24 -3
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +90 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +53 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +79 -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 +117 -5
- package/src/services/reqresp/protocols/tx.ts +35 -6
- 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 +387 -256
- package/src/services/reqresp/status.ts +12 -3
- package/src/services/service.ts +45 -21
- package/src/services/tx_collection/config.ts +84 -0
- package/src/services/tx_collection/fast_tx_collection.ts +340 -0
- package/src/services/tx_collection/index.ts +2 -0
- package/src/services/tx_collection/instrumentation.ts +43 -0
- package/src/services/tx_collection/slow_tx_collection.ts +232 -0
- package/src/services/tx_collection/tx_collection.ts +215 -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 +216 -0
- package/src/services/tx_provider_instrumentation.ts +44 -0
- package/src/test-helpers/index.ts +1 -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 +86 -35
- package/src/testbench/p2p_client_testbench_worker.ts +145 -22
- package/src/testbench/parse_log_file.ts +4 -4
- package/src/testbench/testbench.ts +4 -4
- package/src/testbench/worker_client_manager.ts +17 -23
- package/src/types/index.ts +2 -0
- package/src/util.ts +93 -89
- package/src/versioning.ts +11 -4
|
@@ -4,13 +4,19 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
4
4
|
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
}
|
|
7
|
+
import { randomInt } from '@aztec/foundation/crypto';
|
|
7
8
|
import { Fr } from '@aztec/foundation/fields';
|
|
8
9
|
import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
9
10
|
import { SerialQueue } from '@aztec/foundation/queue';
|
|
10
11
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
11
|
-
import {
|
|
12
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
13
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
14
|
+
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
15
|
+
import { GasFees } from '@aztec/stdlib/gas';
|
|
16
|
+
import { BlockAttestation, BlockProposal, P2PClientType, P2PMessage, PeerErrorSeverity, TopicType, createTopicString, getTopicsForClientAndConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
|
|
12
17
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
13
18
|
import { Tx } from '@aztec/stdlib/tx';
|
|
19
|
+
import { compressComponentVersions } from '@aztec/stdlib/versioning';
|
|
14
20
|
import { Attributes, OtelMetricsAdapter, WithTracer, trackSpan } from '@aztec/telemetry-client';
|
|
15
21
|
import { gossipsub } from '@chainsafe/libp2p-gossipsub';
|
|
16
22
|
import { createPeerScoreParams, createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
@@ -20,23 +26,30 @@ import { yamux } from '@chainsafe/libp2p-yamux';
|
|
|
20
26
|
import { bootstrap } from '@libp2p/bootstrap';
|
|
21
27
|
import { identify } from '@libp2p/identify';
|
|
22
28
|
import { TopicValidatorResult } from '@libp2p/interface';
|
|
23
|
-
import '@libp2p/kad-dht';
|
|
24
29
|
import { mplex } from '@libp2p/mplex';
|
|
25
30
|
import { tcp } from '@libp2p/tcp';
|
|
31
|
+
import { ENR } from '@nethermindeth/enr';
|
|
26
32
|
import { createLibp2p } from 'libp2p';
|
|
27
33
|
import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
|
|
28
|
-
import {
|
|
34
|
+
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
35
|
+
import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
|
|
36
|
+
import { createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
|
|
37
|
+
import { AggregateTxValidator, DataTxValidator, DoubleSpendTxValidator, MetadataTxValidator, TxProofValidator } from '../../msg_validators/tx_validator/index.js';
|
|
29
38
|
import { GossipSubEvent } from '../../types/index.js';
|
|
30
39
|
import { convertToMultiaddr } from '../../util.js';
|
|
40
|
+
import { getVersions } from '../../versioning.js';
|
|
31
41
|
import { AztecDatastore } from '../data_store.js';
|
|
42
|
+
import { DiscV5Service } from '../discv5/discV5_service.js';
|
|
32
43
|
import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
|
|
33
44
|
import { gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
34
45
|
import { PeerManager } from '../peer-manager/peer_manager.js';
|
|
35
46
|
import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
36
|
-
import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol } from '../reqresp/interface.js';
|
|
47
|
+
import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError } from '../reqresp/interface.js';
|
|
48
|
+
import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
|
|
37
49
|
import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
|
|
38
|
-
import { pingHandler, reqRespBlockHandler,
|
|
50
|
+
import { pingHandler, reqRespBlockHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/protocols/index.js';
|
|
39
51
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
52
|
+
import { P2PInstrumentation } from './instrumentation.js';
|
|
40
53
|
/**
|
|
41
54
|
* Lib P2P implementation of the P2PService interface.
|
|
42
55
|
*/ export class LibP2PService extends WithTracer {
|
|
@@ -44,36 +57,47 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
44
57
|
config;
|
|
45
58
|
node;
|
|
46
59
|
peerDiscoveryService;
|
|
60
|
+
reqresp;
|
|
61
|
+
peerManager;
|
|
47
62
|
mempools;
|
|
48
|
-
|
|
63
|
+
archiver;
|
|
64
|
+
epochCache;
|
|
49
65
|
proofVerifier;
|
|
50
66
|
worldStateSynchronizer;
|
|
51
67
|
logger;
|
|
52
68
|
jobQueue;
|
|
53
|
-
peerManager;
|
|
54
69
|
discoveryRunningPromise;
|
|
70
|
+
msgIdSeenValidators;
|
|
55
71
|
// Message validators
|
|
56
72
|
attestationValidator;
|
|
57
73
|
blockProposalValidator;
|
|
58
|
-
|
|
59
|
-
|
|
74
|
+
protocolVersion;
|
|
75
|
+
topicStrings;
|
|
76
|
+
feesCache;
|
|
60
77
|
/**
|
|
61
78
|
* Callback for when a block is received from a peer.
|
|
62
79
|
* @param block - The block received from the peer.
|
|
63
80
|
* @returns The attestation for the block, if any.
|
|
64
81
|
*/ blockReceivedCallback;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.reqresp = new
|
|
69
|
-
this.
|
|
70
|
-
|
|
71
|
-
this.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.
|
|
82
|
+
gossipSubEventHandler;
|
|
83
|
+
instrumentation;
|
|
84
|
+
constructor(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
|
|
85
|
+
super(telemetry, 'LibP2PService'), this.clientType = clientType, this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.logger = logger, this.jobQueue = new SerialQueue(), this.msgIdSeenValidators = {}, this.protocolVersion = '', this.topicStrings = {};
|
|
86
|
+
this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
|
|
87
|
+
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
88
|
+
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
89
|
+
this.msgIdSeenValidators[TopicType.block_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
90
|
+
const versions = getVersions(config);
|
|
91
|
+
this.protocolVersion = compressComponentVersions(versions);
|
|
92
|
+
logger.info(`Started libp2p service with protocol version ${this.protocolVersion}`);
|
|
93
|
+
this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
|
|
94
|
+
this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
|
|
95
|
+
this.topicStrings[TopicType.block_attestation] = createTopicString(TopicType.block_attestation, this.protocolVersion);
|
|
75
96
|
this.attestationValidator = new AttestationValidator(epochCache);
|
|
76
|
-
this.blockProposalValidator = new BlockProposalValidator(epochCache
|
|
97
|
+
this.blockProposalValidator = new BlockProposalValidator(epochCache, {
|
|
98
|
+
txsPermitted: !config.disableTransactions
|
|
99
|
+
});
|
|
100
|
+
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
77
101
|
this.blockReceivedCallback = async (block)=>{
|
|
78
102
|
this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber.toNumber()} from peer.`, {
|
|
79
103
|
p2pMessageIdentifier: await block.p2pMessageIdentifier()
|
|
@@ -81,25 +105,54 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
81
105
|
return undefined;
|
|
82
106
|
};
|
|
83
107
|
}
|
|
108
|
+
updateConfig(config) {
|
|
109
|
+
this.reqresp.updateConfig(config);
|
|
110
|
+
}
|
|
84
111
|
/**
|
|
85
112
|
* Creates an instance of the LibP2P service.
|
|
86
113
|
* @param config - The configuration to use when creating the service.
|
|
87
114
|
* @param txPool - The transaction pool to be accessed by the service.
|
|
88
115
|
* @returns The new service.
|
|
89
|
-
*/ static async new(clientType, config,
|
|
90
|
-
const {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
const datastore = new AztecDatastore(store);
|
|
116
|
+
*/ static async new(clientType, config, peerId, deps) {
|
|
117
|
+
const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, telemetry, logger, packageVersion } = deps;
|
|
118
|
+
const { p2pPort, maxPeerCount, listenAddress } = config;
|
|
119
|
+
const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
|
|
120
|
+
const datastore = new AztecDatastore(peerStore);
|
|
95
121
|
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
|
|
96
|
-
|
|
122
|
+
const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`));
|
|
123
|
+
// Seed libp2p's bootstrap discovery with private and trusted peers
|
|
124
|
+
const bootstrapNodes = [
|
|
125
|
+
...config.privatePeers,
|
|
126
|
+
...config.trustedPeers
|
|
127
|
+
];
|
|
97
128
|
const peerDiscovery = [];
|
|
98
|
-
if (
|
|
129
|
+
if (bootstrapNodes.length > 0) {
|
|
99
130
|
peerDiscovery.push(bootstrap({
|
|
100
|
-
list:
|
|
131
|
+
list: bootstrapNodes
|
|
101
132
|
}));
|
|
102
133
|
}
|
|
134
|
+
const versions = getVersions(config);
|
|
135
|
+
const protocolVersion = compressComponentVersions(versions);
|
|
136
|
+
const txTopic = createTopicString(TopicType.tx, protocolVersion);
|
|
137
|
+
const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
|
|
138
|
+
const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
|
|
139
|
+
const preferredPeersEnrs = config.preferredPeers.map((enr)=>ENR.decodeTxt(enr));
|
|
140
|
+
const directPeers = (await Promise.all(preferredPeersEnrs.map(async (enr)=>{
|
|
141
|
+
const peerId = await enr.peerId();
|
|
142
|
+
const address = enr.getLocationMultiaddr('tcp');
|
|
143
|
+
if (address === undefined) {
|
|
144
|
+
throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
id: peerId,
|
|
148
|
+
addrs: [
|
|
149
|
+
address
|
|
150
|
+
]
|
|
151
|
+
};
|
|
152
|
+
}))).filter((peer)=>peer !== undefined);
|
|
153
|
+
const announceTcpMultiaddr = config.p2pIp ? [
|
|
154
|
+
convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')
|
|
155
|
+
] : [];
|
|
103
156
|
const node = await createLibp2p({
|
|
104
157
|
start: false,
|
|
105
158
|
peerId,
|
|
@@ -107,44 +160,76 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
107
160
|
listen: [
|
|
108
161
|
bindAddrTcp
|
|
109
162
|
],
|
|
110
|
-
announce:
|
|
111
|
-
announceAddrTcp
|
|
112
|
-
]
|
|
163
|
+
announce: announceTcpMultiaddr
|
|
113
164
|
},
|
|
114
165
|
transports: [
|
|
115
166
|
tcp({
|
|
116
|
-
|
|
167
|
+
// It's better to have this number a bit higher than our maxPeerCount because it's sets the limit on transport (TCP) layer
|
|
168
|
+
// The connection attempts to the node on TCP layer are not necessarily valid Aztec peers so we want to have a bit of leeway here
|
|
169
|
+
// If we hit the limit, the connection will be temporarily accepted and immediately dropped.
|
|
170
|
+
// Docs: https://nodejs.org/api/net.html#servermaxconnections
|
|
171
|
+
maxConnections: maxPeerCount * 2,
|
|
117
172
|
// socket option: the maximum length of the queue of pending connections
|
|
118
|
-
// https://nodejs.org/dist/latest-
|
|
173
|
+
// https://nodejs.org/dist/latest-v22.x/docs/api/net.html#serverlisten
|
|
119
174
|
// it's not safe if we increase this number
|
|
120
175
|
backlog: 5,
|
|
121
176
|
closeServerOnMaxConnections: {
|
|
122
|
-
|
|
123
|
-
|
|
177
|
+
// The property `maxConnections` will protect us against the most DDOS attack
|
|
178
|
+
// This property protects us in case of burst of new connections where server is not able to close them quickly enough
|
|
179
|
+
// In case closeAbove is reached, the server stops listening altogether
|
|
180
|
+
// It's important that there is enough difference between closeAbove and listenAbove,
|
|
181
|
+
// otherwise the server.listener will flap between being closed and open potentially degrading perf even more
|
|
182
|
+
closeAbove: maxPeerCount * 3,
|
|
183
|
+
listenBelow: Math.floor(maxPeerCount * 0.9)
|
|
124
184
|
}
|
|
125
185
|
})
|
|
126
186
|
],
|
|
127
187
|
datastore,
|
|
128
188
|
peerDiscovery,
|
|
129
189
|
streamMuxers: [
|
|
130
|
-
|
|
131
|
-
|
|
190
|
+
yamux(),
|
|
191
|
+
mplex()
|
|
132
192
|
],
|
|
133
193
|
connectionEncryption: [
|
|
134
194
|
noise()
|
|
135
195
|
],
|
|
136
196
|
connectionManager: {
|
|
137
197
|
minConnections: 0,
|
|
198
|
+
// We set maxConnections above maxPeerCount because if we hit limit of maxPeerCount
|
|
199
|
+
// libp2p will start aggressively rejecting all new connections, preventing network discovery and crawling.
|
|
200
|
+
maxConnections: maxPeerCount * 2,
|
|
138
201
|
maxParallelDials: 100,
|
|
139
202
|
dialTimeout: 30_000,
|
|
140
203
|
maxPeerAddrsToDial: 5,
|
|
141
204
|
maxIncomingPendingConnections: 5
|
|
142
205
|
},
|
|
206
|
+
connectionGater: {
|
|
207
|
+
denyInboundConnection: (maConn)=>{
|
|
208
|
+
const allowed = peerManager.isNodeAllowedToConnect(maConn.remoteAddr.nodeAddress().address);
|
|
209
|
+
if (allowed) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
logger.debug(`Connection gater: Denying inbound connection from ${maConn.remoteAddr.toString()}`);
|
|
213
|
+
return true;
|
|
214
|
+
},
|
|
215
|
+
denyInboundEncryptedConnection: (peerId, _maConn)=>{
|
|
216
|
+
//NOTE: it is not necessary to check address here because this was already done by
|
|
217
|
+
// denyInboundConnection
|
|
218
|
+
const allowed = peerManager.isNodeAllowedToConnect(peerId);
|
|
219
|
+
if (allowed) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
logger.debug(`Connection gater: Denying inbound encrypted connection from ${peerId.toString()}`);
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
},
|
|
143
226
|
services: {
|
|
144
227
|
identify: identify({
|
|
145
|
-
protocolPrefix: 'aztec'
|
|
228
|
+
protocolPrefix: 'aztec',
|
|
229
|
+
runOnConnectionOpen: true
|
|
146
230
|
}),
|
|
147
231
|
pubsub: gossipsub({
|
|
232
|
+
directPeers,
|
|
148
233
|
debugName: 'gossipsub',
|
|
149
234
|
globalSignaturePolicy: SignaturePolicy.StrictNoSign,
|
|
150
235
|
allowPublishToZeroTopicPeers: true,
|
|
@@ -156,29 +241,30 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
156
241
|
heartbeatInterval: config.gossipsubInterval,
|
|
157
242
|
mcacheLength: config.gossipsubMcacheLength,
|
|
158
243
|
mcacheGossip: config.gossipsubMcacheGossip,
|
|
244
|
+
seenTTL: config.gossipsubSeenTTL,
|
|
159
245
|
msgIdFn: getMsgIdFn,
|
|
160
246
|
msgIdToStrFn: msgIdToStrFn,
|
|
161
247
|
fastMsgIdFn: fastMsgIdFn,
|
|
162
248
|
dataTransform: new SnappyTransform(),
|
|
163
249
|
metricsRegister: otelMetricsAdapter,
|
|
164
|
-
metricsTopicStrToLabel: metricsTopicStrToLabels(),
|
|
250
|
+
metricsTopicStrToLabel: metricsTopicStrToLabels(protocolVersion),
|
|
165
251
|
asyncValidation: true,
|
|
166
252
|
scoreThresholds: gossipScoreThresholds,
|
|
167
253
|
scoreParams: createPeerScoreParams({
|
|
168
254
|
// IPColocation factor can be disabled for local testing - default to -5
|
|
169
255
|
IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
|
|
170
256
|
topics: {
|
|
171
|
-
[
|
|
257
|
+
[txTopic]: createTopicScoreParams({
|
|
172
258
|
topicWeight: 1,
|
|
173
259
|
invalidMessageDeliveriesWeight: -20,
|
|
174
260
|
invalidMessageDeliveriesDecay: 0.5
|
|
175
261
|
}),
|
|
176
|
-
[
|
|
262
|
+
[blockAttestationTopic]: createTopicScoreParams({
|
|
177
263
|
topicWeight: 1,
|
|
178
264
|
invalidMessageDeliveriesWeight: -20,
|
|
179
265
|
invalidMessageDeliveriesDecay: 0.5
|
|
180
266
|
}),
|
|
181
|
-
[
|
|
267
|
+
[blockProposalTopic]: createTopicScoreParams({
|
|
182
268
|
topicWeight: 1,
|
|
183
269
|
invalidMessageDeliveriesWeight: -20,
|
|
184
270
|
invalidMessageDeliveriesDecay: 0.5
|
|
@@ -192,7 +278,13 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
192
278
|
},
|
|
193
279
|
logger: createLibp2pComponentLogger(logger.module)
|
|
194
280
|
});
|
|
195
|
-
|
|
281
|
+
const peerScoring = new PeerScoring(config);
|
|
282
|
+
const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
|
|
283
|
+
const peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, createLogger(`${logger.module}:peer_manager`), peerScoring, reqresp, worldStateSynchronizer, protocolVersion, epochCache);
|
|
284
|
+
// Update gossipsub score params
|
|
285
|
+
node.services.pubsub.score.params.appSpecificWeight = 10;
|
|
286
|
+
node.services.pubsub.score.params.appSpecificScore = (peerId)=>peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
287
|
+
return new LibP2PService(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
|
|
196
288
|
}
|
|
197
289
|
/**
|
|
198
290
|
* Starts the LibP2P service.
|
|
@@ -203,32 +295,43 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
203
295
|
throw new Error('P2P service already started');
|
|
204
296
|
}
|
|
205
297
|
// Get listen & announce addresses for logging
|
|
206
|
-
const {
|
|
207
|
-
if (!
|
|
298
|
+
const { p2pIp, p2pPort } = this.config;
|
|
299
|
+
if (!p2pIp) {
|
|
208
300
|
throw new Error('Announce address not provided.');
|
|
209
301
|
}
|
|
210
|
-
const announceTcpMultiaddr = convertToMultiaddr(
|
|
302
|
+
const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
|
|
211
303
|
// Start job queue, peer discovery service and libp2p node
|
|
212
304
|
this.jobQueue.start();
|
|
213
|
-
await this.
|
|
305
|
+
await this.peerManager.initializePeers();
|
|
306
|
+
if (!this.config.p2pDiscoveryDisabled) {
|
|
307
|
+
await this.peerDiscoveryService.start();
|
|
308
|
+
}
|
|
214
309
|
await this.node.start();
|
|
215
310
|
// Subscribe to standard GossipSub topics by default
|
|
216
|
-
for (const topic of
|
|
217
|
-
this.subscribeToTopic(
|
|
311
|
+
for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)){
|
|
312
|
+
this.subscribeToTopic(this.topicStrings[topic]);
|
|
218
313
|
}
|
|
219
314
|
// Create request response protocol handlers
|
|
220
315
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
221
316
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
222
|
-
const blockHandler = reqRespBlockHandler(this.
|
|
317
|
+
const blockHandler = reqRespBlockHandler(this.archiver);
|
|
318
|
+
const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
|
|
223
319
|
const requestResponseHandlers = {
|
|
224
320
|
[ReqRespSubProtocol.PING]: pingHandler,
|
|
225
|
-
[ReqRespSubProtocol.STATUS]: statusHandler,
|
|
226
|
-
[ReqRespSubProtocol.TX]: txHandler.bind(this),
|
|
321
|
+
[ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
|
|
227
322
|
[ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
|
|
228
323
|
[ReqRespSubProtocol.BLOCK]: blockHandler.bind(this)
|
|
229
324
|
};
|
|
325
|
+
// Only handle block transactions request if attestation pool is available to the client
|
|
326
|
+
if (this.mempools.attestationPool && !this.config.disableTransactions) {
|
|
327
|
+
const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
|
|
328
|
+
requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
|
|
329
|
+
}
|
|
330
|
+
if (!this.config.disableTransactions) {
|
|
331
|
+
requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
|
|
332
|
+
}
|
|
230
333
|
// add GossipSub listener
|
|
231
|
-
this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.
|
|
334
|
+
this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
232
335
|
// Start running promise for peer discovery
|
|
233
336
|
this.discoveryRunningPromise = new RunningPromise(()=>this.peerManager.heartbeat(), this.logger, this.config.peerCheckIntervalMS);
|
|
234
337
|
this.discoveryRunningPromise.start();
|
|
@@ -236,11 +339,13 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
236
339
|
const reqrespSubProtocolValidators = {
|
|
237
340
|
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
238
341
|
// TODO(#11336): A request validator for blocks
|
|
239
|
-
[ReqRespSubProtocol.TX]: this.
|
|
342
|
+
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
343
|
+
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this)
|
|
240
344
|
};
|
|
241
345
|
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
242
346
|
this.logger.info(`Started P2P service`, {
|
|
243
|
-
listen:
|
|
347
|
+
listen: this.config.listenAddress,
|
|
348
|
+
port: this.config.p2pPort,
|
|
244
349
|
announce: announceTcpMultiaddr,
|
|
245
350
|
peerId: this.node.peerId.toString()
|
|
246
351
|
});
|
|
@@ -250,7 +355,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
250
355
|
* @returns An empty promise.
|
|
251
356
|
*/ async stop() {
|
|
252
357
|
// Remove gossip sub listener
|
|
253
|
-
this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.
|
|
358
|
+
this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
254
359
|
// Stop peer manager
|
|
255
360
|
this.logger.debug('Stopping peer manager...');
|
|
256
361
|
await this.peerManager.stop();
|
|
@@ -266,6 +371,12 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
266
371
|
await this.stopLibP2P();
|
|
267
372
|
this.logger.info('LibP2P service stopped');
|
|
268
373
|
}
|
|
374
|
+
addReqRespSubProtocol(subProtocol, handler, validator) {
|
|
375
|
+
return this.reqresp.addSubProtocol(subProtocol, handler, validator);
|
|
376
|
+
}
|
|
377
|
+
registerThisValidatorAddresses(address) {
|
|
378
|
+
this.peerManager.registerThisValidatorAddresses(address);
|
|
379
|
+
}
|
|
269
380
|
getPeers(includePending) {
|
|
270
381
|
return this.peerManager.getPeers(includePending);
|
|
271
382
|
}
|
|
@@ -281,24 +392,12 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
281
392
|
setImmediate(()=>void safeJob());
|
|
282
393
|
}
|
|
283
394
|
/**
|
|
284
|
-
* Send Request via the ReqResp service
|
|
285
|
-
* The subprotocol defined will determine the request and response types
|
|
286
|
-
*
|
|
287
|
-
* See the subProtocolMap for the mapping of subprotocols to request/response types in `interface.ts`
|
|
288
|
-
*
|
|
289
|
-
* @param protocol The request response protocol to use
|
|
290
|
-
* @param request The request type to send
|
|
291
|
-
* @returns
|
|
292
|
-
*/ sendRequest(protocol, request) {
|
|
293
|
-
return this.reqresp.sendRequest(protocol, request);
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
395
|
* Send a batch of requests to peers, and return the responses
|
|
297
396
|
* @param protocol - The request response protocol to use
|
|
298
397
|
* @param requests - The requests to send to the peers
|
|
299
398
|
* @returns The responses to the requests
|
|
300
|
-
*/ sendBatchRequest(protocol, requests) {
|
|
301
|
-
return this.reqresp.sendBatchRequest(protocol, requests);
|
|
399
|
+
*/ sendBatchRequest(protocol, requests, pinnedPeerId) {
|
|
400
|
+
return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
|
|
302
401
|
}
|
|
303
402
|
/**
|
|
304
403
|
* Get the ENR of the node
|
|
@@ -308,7 +407,6 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
308
407
|
}
|
|
309
408
|
registerBlockReceivedCallback(callback) {
|
|
310
409
|
this.blockReceivedCallback = callback;
|
|
311
|
-
this.logger.verbose('Block received callback registered');
|
|
312
410
|
}
|
|
313
411
|
/**
|
|
314
412
|
* Subscribes to a topic.
|
|
@@ -322,133 +420,246 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
322
420
|
/**
|
|
323
421
|
* Publishes data to a topic.
|
|
324
422
|
* @param topic - The topic to publish to.
|
|
325
|
-
* @param data - The
|
|
423
|
+
* @param data - The message to publish.
|
|
326
424
|
* @returns The number of recipients the data was sent to.
|
|
327
|
-
*/ async publishToTopic(topic,
|
|
425
|
+
*/ async publishToTopic(topic, message) {
|
|
328
426
|
if (!this.node.services.pubsub) {
|
|
329
427
|
throw new Error('Pubsub service not available.');
|
|
330
428
|
}
|
|
331
|
-
const
|
|
429
|
+
const p2pMessage = P2PMessage.fromGossipable(message);
|
|
430
|
+
const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
|
|
332
431
|
return result.recipients.length;
|
|
333
432
|
}
|
|
334
433
|
/**
|
|
434
|
+
* Checks if this message has already been seen, based on its msgId computed from hashing the message data.
|
|
435
|
+
* Note that we do not rely on the seenCache from gossipsub since we want to keep a longer history of seen
|
|
436
|
+
* messages to avoid tx echoes across the network.
|
|
437
|
+
*/ preValidateReceivedMessage(msg, msgId, source) {
|
|
438
|
+
let topicType;
|
|
439
|
+
switch(msg.topic){
|
|
440
|
+
case this.topicStrings[TopicType.tx]:
|
|
441
|
+
topicType = TopicType.tx;
|
|
442
|
+
break;
|
|
443
|
+
case this.topicStrings[TopicType.block_attestation]:
|
|
444
|
+
topicType = TopicType.block_attestation;
|
|
445
|
+
break;
|
|
446
|
+
case this.topicStrings[TopicType.block_proposal]:
|
|
447
|
+
topicType = TopicType.block_proposal;
|
|
448
|
+
break;
|
|
449
|
+
default:
|
|
450
|
+
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
const validator = topicType ? this.msgIdSeenValidators[topicType] : undefined;
|
|
454
|
+
if (!validator || !validator.addMessage(msgId)) {
|
|
455
|
+
this.instrumentation.incMessagePrevalidationStatus(false, topicType);
|
|
456
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
457
|
+
return {
|
|
458
|
+
result: false,
|
|
459
|
+
topicType
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
this.instrumentation.incMessagePrevalidationStatus(true, topicType);
|
|
463
|
+
return {
|
|
464
|
+
result: true,
|
|
465
|
+
topicType
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
335
469
|
* Handles a new gossip message that was received by the client.
|
|
336
470
|
* @param topic - The message's topic.
|
|
337
471
|
* @param data - The message data
|
|
338
472
|
*/ async handleNewGossipMessage(msg, msgId, source) {
|
|
339
|
-
|
|
340
|
-
|
|
473
|
+
const p2pMessage = P2PMessage.fromMessageData(Buffer.from(msg.data));
|
|
474
|
+
const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
|
|
475
|
+
if (!preValidationResult.result) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
479
|
+
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
341
480
|
}
|
|
342
|
-
if (msg.topic ===
|
|
343
|
-
await this.processAttestationFromPeer(
|
|
481
|
+
if (msg.topic === this.topicStrings[TopicType.block_attestation] && this.clientType === P2PClientType.Full) {
|
|
482
|
+
await this.processAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
344
483
|
}
|
|
345
|
-
if (msg.topic
|
|
346
|
-
await this.processBlockFromPeer(
|
|
484
|
+
if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
485
|
+
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
347
486
|
}
|
|
348
487
|
return;
|
|
349
488
|
}
|
|
350
|
-
async validateReceivedMessage(validationFunc, msgId, source) {
|
|
489
|
+
async validateReceivedMessage(validationFunc, msgId, source, topicType) {
|
|
351
490
|
let resultAndObj = {
|
|
352
|
-
result:
|
|
353
|
-
obj: undefined
|
|
491
|
+
result: TopicValidatorResult.Reject
|
|
354
492
|
};
|
|
493
|
+
const timer = new Timer();
|
|
355
494
|
try {
|
|
356
495
|
resultAndObj = await validationFunc();
|
|
357
496
|
} catch (err) {
|
|
358
|
-
this.logger.error(`Error
|
|
497
|
+
this.logger.error(`Error deserializing and validating gossipsub message`, err, {
|
|
498
|
+
msgId,
|
|
499
|
+
source: source.toString(),
|
|
500
|
+
topicType
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
504
|
+
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
359
505
|
}
|
|
360
|
-
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result
|
|
506
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
|
|
361
507
|
return resultAndObj;
|
|
362
508
|
}
|
|
363
|
-
async handleGossipedTx(
|
|
509
|
+
async handleGossipedTx(payloadData, msgId, source) {
|
|
364
510
|
const validationFunc = async ()=>{
|
|
365
|
-
const tx = Tx.fromBuffer(
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
511
|
+
const tx = Tx.fromBuffer(payloadData);
|
|
512
|
+
const isValid = await this.validatePropagatedTx(tx, source);
|
|
513
|
+
const exists = isValid && await this.mempools.txPool.hasTx(tx.getTxHash());
|
|
514
|
+
this.logger.trace(`Validate propagated tx`, {
|
|
515
|
+
isValid,
|
|
516
|
+
exists,
|
|
517
|
+
[Attributes.P2P_ID]: source.toString()
|
|
518
|
+
});
|
|
519
|
+
if (!isValid) {
|
|
520
|
+
return {
|
|
521
|
+
result: TopicValidatorResult.Reject
|
|
522
|
+
};
|
|
523
|
+
} else if (exists) {
|
|
524
|
+
return {
|
|
525
|
+
result: TopicValidatorResult.Ignore,
|
|
526
|
+
obj: tx
|
|
527
|
+
};
|
|
528
|
+
} else {
|
|
529
|
+
return {
|
|
530
|
+
result: TopicValidatorResult.Accept,
|
|
531
|
+
obj: tx
|
|
532
|
+
};
|
|
533
|
+
}
|
|
371
534
|
};
|
|
372
|
-
const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source);
|
|
373
|
-
if (
|
|
535
|
+
const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.tx);
|
|
536
|
+
if (result !== TopicValidatorResult.Accept || !tx) {
|
|
374
537
|
return;
|
|
375
538
|
}
|
|
376
|
-
const txHash =
|
|
539
|
+
const txHash = tx.getTxHash();
|
|
377
540
|
const txHashString = txHash.toString();
|
|
378
|
-
this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()}
|
|
541
|
+
this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
|
|
542
|
+
source: source.toString(),
|
|
543
|
+
txHash: txHashString
|
|
544
|
+
});
|
|
545
|
+
if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
|
|
546
|
+
this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
379
549
|
await this.mempools.txPool.addTxs([
|
|
380
550
|
tx
|
|
381
551
|
]);
|
|
382
552
|
}
|
|
383
|
-
/**
|
|
553
|
+
/**
|
|
554
|
+
* Process Attestation From Peer
|
|
384
555
|
* When a proposal is received from a peer, we add it to the attestation pool, so it can be accessed by other services.
|
|
385
556
|
*
|
|
386
557
|
* @param attestation - The attestation to process.
|
|
387
|
-
*/ async processAttestationFromPeer(
|
|
558
|
+
*/ async processAttestationFromPeer(payloadData, msgId, source) {
|
|
388
559
|
const validationFunc = async ()=>{
|
|
389
|
-
const attestation = BlockAttestation.fromBuffer(
|
|
390
|
-
const
|
|
391
|
-
this.
|
|
392
|
-
|
|
560
|
+
const attestation = BlockAttestation.fromBuffer(payloadData);
|
|
561
|
+
const isValid = await this.validateAttestation(source, attestation);
|
|
562
|
+
const exists = isValid && await this.mempools.attestationPool.hasAttestation(attestation);
|
|
563
|
+
this.logger.trace(`Validate propagated block attestation`, {
|
|
564
|
+
isValid,
|
|
565
|
+
exists,
|
|
566
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
393
567
|
[Attributes.P2P_ID]: source.toString()
|
|
394
568
|
});
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
569
|
+
if (!isValid) {
|
|
570
|
+
return {
|
|
571
|
+
result: TopicValidatorResult.Reject
|
|
572
|
+
};
|
|
573
|
+
} else if (exists) {
|
|
574
|
+
return {
|
|
575
|
+
result: TopicValidatorResult.Ignore,
|
|
576
|
+
obj: attestation
|
|
577
|
+
};
|
|
578
|
+
} else {
|
|
579
|
+
return {
|
|
580
|
+
result: TopicValidatorResult.Accept,
|
|
581
|
+
obj: attestation
|
|
582
|
+
};
|
|
583
|
+
}
|
|
399
584
|
};
|
|
400
|
-
const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source);
|
|
401
|
-
if (
|
|
585
|
+
const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_attestation);
|
|
586
|
+
if (result !== TopicValidatorResult.Accept || !attestation) {
|
|
402
587
|
return;
|
|
403
588
|
}
|
|
404
|
-
this.logger.debug(`Received attestation for
|
|
589
|
+
this.logger.debug(`Received attestation for slot ${attestation.slotNumber.toNumber()} from external peer ${source.toString()}`, {
|
|
405
590
|
p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
|
|
406
591
|
slot: attestation.slotNumber.toNumber(),
|
|
407
592
|
archive: attestation.archive.toString(),
|
|
408
|
-
|
|
593
|
+
source: source.toString()
|
|
409
594
|
});
|
|
410
595
|
await this.mempools.attestationPool.addAttestations([
|
|
411
596
|
attestation
|
|
412
597
|
]);
|
|
413
598
|
}
|
|
414
|
-
async processBlockFromPeer(
|
|
599
|
+
async processBlockFromPeer(payloadData, msgId, source) {
|
|
415
600
|
const validationFunc = async ()=>{
|
|
416
|
-
const block = BlockProposal.fromBuffer(
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
|
|
601
|
+
const block = BlockProposal.fromBuffer(payloadData);
|
|
602
|
+
const isValid = await this.validateBlockProposal(source, block);
|
|
603
|
+
// Note that we dont have an attestation pool if we're a prover node, but we still
|
|
604
|
+
// subscribe to block proposal topics in order to prevent their txs from being cleared.
|
|
605
|
+
const exists = isValid && await this.mempools.attestationPool?.hasBlockProposal(block);
|
|
606
|
+
this.logger.trace(`Validate propagated block proposal`, {
|
|
607
|
+
isValid,
|
|
608
|
+
exists,
|
|
609
|
+
[Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
|
|
420
610
|
[Attributes.P2P_ID]: source.toString()
|
|
421
611
|
});
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
612
|
+
if (!isValid) {
|
|
613
|
+
return {
|
|
614
|
+
result: TopicValidatorResult.Reject
|
|
615
|
+
};
|
|
616
|
+
} else if (exists) {
|
|
617
|
+
return {
|
|
618
|
+
result: TopicValidatorResult.Ignore,
|
|
619
|
+
obj: block
|
|
620
|
+
};
|
|
621
|
+
} else {
|
|
622
|
+
return {
|
|
623
|
+
result: TopicValidatorResult.Accept,
|
|
624
|
+
obj: block
|
|
625
|
+
};
|
|
626
|
+
}
|
|
426
627
|
};
|
|
427
|
-
const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source);
|
|
628
|
+
const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_proposal);
|
|
428
629
|
if (!result || !block) {
|
|
429
630
|
return;
|
|
430
631
|
}
|
|
431
|
-
await this.processValidBlockProposal(block);
|
|
632
|
+
await this.processValidBlockProposal(block, source);
|
|
432
633
|
}
|
|
433
634
|
// REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
434
|
-
async processValidBlockProposal(block) {
|
|
435
|
-
|
|
635
|
+
async processValidBlockProposal(block, sender) {
|
|
636
|
+
const slot = block.slotNumber.toBigInt();
|
|
637
|
+
const previousSlot = slot - 1n;
|
|
638
|
+
this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
436
639
|
p2pMessageIdentifier: await block.p2pMessageIdentifier(),
|
|
437
640
|
slot: block.slotNumber.toNumber(),
|
|
438
641
|
archive: block.archive.toString(),
|
|
439
|
-
|
|
642
|
+
source: sender.toString()
|
|
440
643
|
});
|
|
441
|
-
const
|
|
644
|
+
const attestationsForPreviousSlot = await this.mempools.attestationPool?.getAttestationsForSlot(previousSlot);
|
|
645
|
+
if (attestationsForPreviousSlot !== undefined) {
|
|
646
|
+
this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
|
|
647
|
+
}
|
|
648
|
+
// Mark the txs in this proposal as non-evictable
|
|
649
|
+
await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
|
|
650
|
+
await this.mempools.attestationPool?.addBlockProposal(block);
|
|
651
|
+
const attestations = await this.blockReceivedCallback(block, sender);
|
|
442
652
|
// TODO: fix up this pattern - the abstraction is not nice
|
|
443
653
|
// The attestation can be undefined if no handler is registered / the validator deems the block invalid
|
|
444
|
-
if (
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
654
|
+
if (attestations?.length) {
|
|
655
|
+
for (const attestation of attestations){
|
|
656
|
+
this.logger.verbose(`Broadcasting attestation for slot ${attestation.slotNumber.toNumber()}`, {
|
|
657
|
+
p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
|
|
658
|
+
slot: attestation.slotNumber.toNumber(),
|
|
659
|
+
archive: attestation.archive.toString()
|
|
660
|
+
});
|
|
661
|
+
await this.broadcastAttestation(attestation);
|
|
662
|
+
}
|
|
452
663
|
}
|
|
453
664
|
}
|
|
454
665
|
/**
|
|
@@ -474,83 +685,145 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
474
685
|
});
|
|
475
686
|
}
|
|
476
687
|
/**
|
|
477
|
-
* Validate
|
|
688
|
+
* Validate the requested block transactions.
|
|
689
|
+
* @param request - The block transactions request.
|
|
690
|
+
* @param response - The block transactions response.
|
|
691
|
+
* @param peerId - The ID of the peer that made the request.
|
|
692
|
+
* @returns True if the requested block transactions are valid, false otherwise.
|
|
693
|
+
*/ async validateRequestedBlockTxs(_request, response, peerId) {
|
|
694
|
+
const requestedTxValidator = this.createRequestedTxValidator();
|
|
695
|
+
try {
|
|
696
|
+
// TODO(palla/txs): Validate that this tx belongs to the block hash being requested
|
|
697
|
+
await Promise.all(response.txs.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator)));
|
|
698
|
+
return true;
|
|
699
|
+
} catch (e) {
|
|
700
|
+
if (e instanceof ValidationError) {
|
|
701
|
+
this.logger.warn(`Failed validation for requested block txs from peer ${peerId.toString()}`);
|
|
702
|
+
} else {
|
|
703
|
+
this.logger.error(`Error during validation of requested block txs`, e);
|
|
704
|
+
}
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Validate a collection of txs that has been requested from a peer.
|
|
478
710
|
*
|
|
479
|
-
* The core component of this validator is that
|
|
711
|
+
* The core component of this validator is that each tx hash MUST match the requested tx hash,
|
|
480
712
|
* In order to perform this check, the tx proof must be verified.
|
|
481
713
|
*
|
|
482
714
|
* Note: This function is called from within `ReqResp.sendRequest` as part of the
|
|
483
715
|
* ReqRespSubProtocol.TX subprotocol validation.
|
|
484
716
|
*
|
|
485
|
-
* @param requestedTxHash - The
|
|
486
|
-
* @param responseTx - The
|
|
717
|
+
* @param requestedTxHash - The collection of the txs that was requested.
|
|
718
|
+
* @param responseTx - The collectin of txs that was received as a response to the request.
|
|
487
719
|
* @param peerId - The peer ID of the peer that sent the tx.
|
|
488
|
-
* @returns True if the
|
|
489
|
-
*/ async
|
|
490
|
-
const
|
|
491
|
-
const
|
|
492
|
-
//
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
720
|
+
* @returns True if the whole collection of txs is valid, false otherwise.
|
|
721
|
+
*/ async validateRequestedTxs(requestedTxHash, responseTx, peerId) {
|
|
722
|
+
const requested = new Set(requestedTxHash.map((h)=>h.toString()));
|
|
723
|
+
const requestedTxValidator = this.createRequestedTxValidator();
|
|
724
|
+
//TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
|
|
725
|
+
// I think we should still extract the valid txs and return them, so that we can still use the response.
|
|
726
|
+
try {
|
|
727
|
+
await Promise.all(responseTx.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
|
|
728
|
+
return true;
|
|
729
|
+
} catch (e) {
|
|
730
|
+
if (e instanceof ValidationError) {
|
|
731
|
+
this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
|
|
732
|
+
} else {
|
|
733
|
+
this.logger.error(`Error during validation of requested txs`, e);
|
|
734
|
+
}
|
|
496
735
|
return false;
|
|
497
736
|
}
|
|
498
|
-
|
|
499
|
-
|
|
737
|
+
}
|
|
738
|
+
createRequestedTxValidator() {
|
|
739
|
+
return new AggregateTxValidator(new DataTxValidator(), new MetadataTxValidator({
|
|
740
|
+
l1ChainId: new Fr(this.config.l1ChainId),
|
|
741
|
+
rollupVersion: new Fr(this.config.rollupVersion),
|
|
742
|
+
protocolContractsHash,
|
|
743
|
+
vkTreeRoot: getVKTreeRoot()
|
|
744
|
+
}), new TxProofValidator(this.proofVerifier));
|
|
745
|
+
}
|
|
746
|
+
async validateRequestedTx(tx, peerId, txValidator, requested) {
|
|
747
|
+
if (!await tx.validateTxHash()) {
|
|
748
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
749
|
+
throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
|
|
750
|
+
}
|
|
751
|
+
if (requested && !requested.has(tx.getTxHash().toString())) {
|
|
752
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
753
|
+
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
|
|
754
|
+
}
|
|
755
|
+
const { result } = await txValidator.validateTx(tx);
|
|
756
|
+
if (result === 'invalid') {
|
|
500
757
|
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
501
|
-
|
|
758
|
+
throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
|
|
502
759
|
}
|
|
503
|
-
return true;
|
|
504
760
|
}
|
|
505
761
|
async validatePropagatedTx(tx, peerId) {
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
|
|
762
|
+
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
763
|
+
// We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
|
|
764
|
+
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
765
|
+
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
766
|
+
for (const validator of messageValidators){
|
|
767
|
+
const outcome = await this.runValidations(tx, validator);
|
|
768
|
+
if (outcome.allPassed) {
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
771
|
+
const { name } = outcome.failure;
|
|
772
|
+
let { severity } = outcome.failure;
|
|
773
|
+
// Double spend validator has a special case handler
|
|
774
|
+
if (name === 'doubleSpendValidator') {
|
|
775
|
+
const txBlockNumber = currentBlockNumber + 1; // tx is expected to be in the next block
|
|
776
|
+
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
777
|
+
}
|
|
778
|
+
this.peerManager.penalizePeer(peerId, severity);
|
|
779
|
+
return false;
|
|
511
780
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
if (
|
|
516
|
-
|
|
781
|
+
return true;
|
|
782
|
+
}
|
|
783
|
+
async getGasFees(blockNumber) {
|
|
784
|
+
if (blockNumber === this.feesCache?.blockNumber) {
|
|
785
|
+
return this.feesCache.gasFees;
|
|
517
786
|
}
|
|
518
|
-
this.
|
|
519
|
-
|
|
787
|
+
const header = await this.archiver.getBlockHeader(blockNumber);
|
|
788
|
+
const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
|
|
789
|
+
this.feesCache = {
|
|
790
|
+
blockNumber,
|
|
791
|
+
gasFees
|
|
792
|
+
};
|
|
793
|
+
return gasFees;
|
|
794
|
+
}
|
|
795
|
+
async validate(txs) {
|
|
796
|
+
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
797
|
+
// We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
|
|
798
|
+
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
799
|
+
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
800
|
+
await Promise.all(txs.map(async (tx)=>{
|
|
801
|
+
for (const validator of messageValidators){
|
|
802
|
+
const outcome = await this.runValidations(tx, validator);
|
|
803
|
+
if (!outcome.allPassed) {
|
|
804
|
+
throw new Error('Invalid tx detected', {
|
|
805
|
+
cause: {
|
|
806
|
+
outcome
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}));
|
|
520
812
|
}
|
|
521
813
|
/**
|
|
522
|
-
* Create message validators for the given block number.
|
|
814
|
+
* Create message validators for the given block number and timestamp.
|
|
523
815
|
*
|
|
524
816
|
* Each validator is a pair of a validator and a severity.
|
|
525
817
|
* If a validator fails, the peer is penalized with the severity of the validator.
|
|
526
818
|
*
|
|
527
|
-
* @param
|
|
819
|
+
* @param currentBlockNumber - The current synced block number.
|
|
820
|
+
* @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
|
|
528
821
|
* @returns The message validators.
|
|
529
|
-
*/ createMessageValidators(
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
},
|
|
535
|
-
metadataValidator: {
|
|
536
|
-
validator: new MetadataTxValidator(new Fr(this.config.l1ChainId), new Fr(blockNumber)),
|
|
537
|
-
severity: PeerErrorSeverity.HighToleranceError
|
|
538
|
-
},
|
|
539
|
-
proofValidator: {
|
|
540
|
-
validator: new TxProofValidator(this.proofVerifier),
|
|
541
|
-
severity: PeerErrorSeverity.MidToleranceError
|
|
542
|
-
},
|
|
543
|
-
doubleSpendValidator: {
|
|
544
|
-
validator: new DoubleSpendTxValidator({
|
|
545
|
-
nullifiersExist: async (nullifiers)=>{
|
|
546
|
-
const merkleTree = this.worldStateSynchronizer.getCommitted();
|
|
547
|
-
const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
|
|
548
|
-
return indices.map((index)=>index !== undefined);
|
|
549
|
-
}
|
|
550
|
-
}),
|
|
551
|
-
severity: PeerErrorSeverity.HighToleranceError
|
|
552
|
-
}
|
|
553
|
-
};
|
|
822
|
+
*/ async createMessageValidators(currentBlockNumber, nextSlotTimestamp) {
|
|
823
|
+
const gasFees = await this.getGasFees(currentBlockNumber);
|
|
824
|
+
const allowedInSetup = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
|
|
825
|
+
const blockNumberInWhichTheTxIsConsideredToBeIncluded = currentBlockNumber + 1;
|
|
826
|
+
return createTxMessageValidators(nextSlotTimestamp, blockNumberInWhichTheTxIsConsideredToBeIncluded, this.worldStateSynchronizer, gasFees, this.config.l1ChainId, this.config.rollupVersion, protocolContractsHash, this.archiver, this.proofVerifier, !this.config.disableTransactions, allowedInSetup);
|
|
554
827
|
}
|
|
555
828
|
/**
|
|
556
829
|
* Run validations on a tx.
|
|
@@ -562,29 +835,32 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
562
835
|
const { result } = await validator.validateTx(tx);
|
|
563
836
|
return {
|
|
564
837
|
name,
|
|
565
|
-
isValid: result
|
|
838
|
+
isValid: result !== 'invalid',
|
|
566
839
|
severity
|
|
567
840
|
};
|
|
568
841
|
});
|
|
569
842
|
// A promise that resolves when all validations have been run
|
|
570
|
-
const allValidations = Promise.all(validationPromises);
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
843
|
+
const allValidations = await Promise.all(validationPromises);
|
|
844
|
+
const failed = allValidations.find((x)=>!x.isValid);
|
|
845
|
+
if (failed) {
|
|
846
|
+
return {
|
|
847
|
+
allPassed: false,
|
|
848
|
+
failure: {
|
|
849
|
+
isValid: {
|
|
850
|
+
result: 'invalid',
|
|
851
|
+
reason: [
|
|
852
|
+
'Failed validation'
|
|
853
|
+
]
|
|
854
|
+
},
|
|
855
|
+
name: failed.name,
|
|
856
|
+
severity: failed.severity
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
} else {
|
|
860
|
+
return {
|
|
861
|
+
allPassed: true
|
|
862
|
+
};
|
|
863
|
+
}
|
|
588
864
|
}
|
|
589
865
|
/**
|
|
590
866
|
* Handle a double spend failure.
|
|
@@ -634,6 +910,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
634
910
|
*/ async validateBlockProposal(peerId, block) {
|
|
635
911
|
const severity = await this.blockProposalValidator.validate(block);
|
|
636
912
|
if (severity) {
|
|
913
|
+
this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
637
914
|
this.peerManager.penalizePeer(peerId, severity);
|
|
638
915
|
return false;
|
|
639
916
|
}
|
|
@@ -642,13 +919,16 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
642
919
|
getPeerScore(peerId) {
|
|
643
920
|
return this.node.services.pubsub.score.score(peerId.toString());
|
|
644
921
|
}
|
|
922
|
+
handleAuthRequestFromPeer(authRequest, peerId) {
|
|
923
|
+
return this.peerManager.handleAuthRequestFromPeer(authRequest, peerId);
|
|
924
|
+
}
|
|
645
925
|
async sendToPeers(message) {
|
|
646
926
|
const parent = message.constructor;
|
|
647
927
|
const identifier = await message.p2pMessageIdentifier().then((i)=>i.toString());
|
|
648
928
|
this.logger.trace(`Sending message ${identifier}`, {
|
|
649
929
|
p2pMessageIdentifier: identifier
|
|
650
930
|
});
|
|
651
|
-
const recipientsNum = await this.publishToTopic(parent.p2pTopic, message
|
|
931
|
+
const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);
|
|
652
932
|
this.logger.debug(`Sent message ${identifier} to ${recipientsNum} peers`, {
|
|
653
933
|
p2pMessageIdentifier: identifier,
|
|
654
934
|
sourcePeer: this.node.peerId.toString()
|
|
@@ -673,7 +953,6 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
673
953
|
}
|
|
674
954
|
_ts_decorate([
|
|
675
955
|
trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
|
|
676
|
-
[Attributes.BLOCK_NUMBER]: block.blockNumber.toNumber(),
|
|
677
956
|
[Attributes.SLOT_NUMBER]: block.slotNumber.toNumber(),
|
|
678
957
|
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
679
958
|
[Attributes.P2P_ID]: await block.p2pMessageIdentifier().then((i)=>i.toString())
|
|
@@ -681,32 +960,35 @@ _ts_decorate([
|
|
|
681
960
|
], LibP2PService.prototype, "processValidBlockProposal", null);
|
|
682
961
|
_ts_decorate([
|
|
683
962
|
trackSpan('Libp2pService.broadcastAttestation', async (attestation)=>({
|
|
684
|
-
[Attributes.
|
|
685
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.globalVariables.slotNumber.toNumber(),
|
|
963
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
|
|
686
964
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
687
965
|
[Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
|
|
688
966
|
}))
|
|
689
967
|
], LibP2PService.prototype, "broadcastAttestation", null);
|
|
968
|
+
_ts_decorate([
|
|
969
|
+
trackSpan('Libp2pService.validateRequestedBlockTxs', (request)=>({
|
|
970
|
+
[Attributes.BLOCK_HASH]: request.blockHash.toString()
|
|
971
|
+
}))
|
|
972
|
+
], LibP2PService.prototype, "validateRequestedBlockTxs", null);
|
|
690
973
|
_ts_decorate([
|
|
691
974
|
trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
|
|
692
975
|
[Attributes.TX_HASH]: requestedTxHash.toString()
|
|
693
976
|
}))
|
|
694
|
-
], LibP2PService.prototype, "
|
|
977
|
+
], LibP2PService.prototype, "validateRequestedTxs", null);
|
|
695
978
|
_ts_decorate([
|
|
696
|
-
trackSpan('Libp2pService.validatePropagatedTx',
|
|
697
|
-
[Attributes.TX_HASH]:
|
|
979
|
+
trackSpan('Libp2pService.validatePropagatedTx', (tx)=>({
|
|
980
|
+
[Attributes.TX_HASH]: tx.getTxHash().toString()
|
|
698
981
|
}))
|
|
699
982
|
], LibP2PService.prototype, "validatePropagatedTx", null);
|
|
700
983
|
_ts_decorate([
|
|
701
984
|
trackSpan('Libp2pService.validateAttestation', async (_, attestation)=>({
|
|
702
|
-
[Attributes.
|
|
703
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.globalVariables.slotNumber.toNumber(),
|
|
985
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
|
|
704
986
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
705
987
|
[Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
|
|
706
988
|
}))
|
|
707
989
|
], LibP2PService.prototype, "validateAttestation", null);
|
|
708
990
|
_ts_decorate([
|
|
709
991
|
trackSpan('Libp2pService.validateBlockProposal', (_peerId, block)=>({
|
|
710
|
-
[Attributes.SLOT_NUMBER]: block.payload.header.
|
|
992
|
+
[Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString()
|
|
711
993
|
}))
|
|
712
994
|
], LibP2PService.prototype, "validateBlockProposal", null);
|