From 2b65777570f3ee5df9914fd6020e5b94240bd210 Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Tue, 9 Jun 2026 20:05:42 +0400 Subject: [PATCH 01/13] Migrate Polkadot SDK to stable2603 --- .config/hakari.toml | 83 +- Cargo.lock | 5885 ++++++++--------- Cargo.toml | 280 +- THIRD_PARTY_NOTICES.md | 5 + TODOS.md | 14 + docs/polkadot-sdk-stable2603-3-migration.md | 98 + ethexe/cli/Cargo.toml | 1 - ethexe/common/src/gear.rs | 14 +- ethexe/db/Cargo.toml | 4 +- ethexe/ethereum/src/abi/mod.rs | 3 +- ethexe/network/Cargo.toml | 8 +- ethexe/network/src/db_sync/mod.rs | 4 - ethexe/network/src/gossipsub.rs | 27 +- ethexe/network/src/injected.rs | 17 +- ethexe/network/src/peer_score.rs | 10 +- ethexe/network/src/slots.rs | 4 +- ethexe/rpc/src/apis/mod.rs | 3 +- ethexe/service/Cargo.toml | 1 - protocol/core/src/limited/vec.rs | 4 +- protocol/core/src/message/common.rs | 37 +- protocol/core/src/message/context.rs | 19 +- protocol/core/src/message/mod.rs | 3 +- protocol/core/src/message/stored.rs | 38 +- protocol/core/src/message/user.rs | 26 +- protocol/core/src/reservation.rs | 3 +- protocol/errors/src/simple.rs | 56 +- protocol/gprimitives/src/lib.rs | 12 +- protocol/sandbox/src/host_executor.rs | 3 +- protocol/sandbox/src/lib.rs | 5 +- substrate/README.md | 5 +- substrate/runtime-executor/Cargo.toml | 2 +- substrate/runtime-executor/common/Cargo.toml | 2 +- substrate/runtime-executor/polkavm/Cargo.toml | 2 +- .../runtime-executor/wasmtime/Cargo.toml | 8 +- substrate/sc-mixnet/Cargo.toml | 49 - substrate/sc-mixnet/README.md | 8 - substrate/sc-mixnet/src/api.rs | 61 - substrate/sc-mixnet/src/config.rs | 75 - substrate/sc-mixnet/src/error.rs | 43 - substrate/sc-mixnet/src/extrinsic_queue.rs | 91 - substrate/sc-mixnet/src/lib.rs | 36 - substrate/sc-mixnet/src/maybe_inf_delay.rs | 108 - substrate/sc-mixnet/src/packet_dispatcher.rs | 194 - substrate/sc-mixnet/src/peer_id.rs | 23 - substrate/sc-mixnet/src/protocol.rs | 67 - substrate/sc-mixnet/src/request.rs | 112 - substrate/sc-mixnet/src/run.rs | 380 -- substrate/sc-mixnet/src/sync_with_runtime.rs | 219 - .../Cargo.toml | 2 +- .../src/lib.rs | 39 +- .../src/pass_by/codec.rs | 59 - .../src/pass_by/enum_.rs | 108 - .../src/pass_by/inner.rs | 110 - .../src/pass_by/mod.rs | 26 - .../bare_function_interface.rs | 61 +- .../host_function_interface.rs | 178 +- .../src/runtime_interface/trait_decl_impl.rs | 28 +- .../src/utils.rs | 74 +- substrate/sp-wasm-interface-common/src/lib.rs | 10 +- substrate/sp-wasm-interface/Cargo.toml | 4 +- substrate/sp-wasm-interface/src/lib.rs | 3 +- substrate/substrate-wasm-builder/Cargo.toml | 2 +- utils/gear-workspace-hack/Cargo.toml | 713 +- vara/common/src/event.rs | 36 +- vara/common/src/gas_provider/auxiliary.rs | 2 +- vara/common/src/gas_provider/mod.rs | 2 +- .../src/gas_provider/negative_imbalance.rs | 2 +- vara/common/src/gas_provider/node.rs | 35 +- .../src/gas_provider/positive_imbalance.rs | 2 +- vara/common/src/lib.rs | 4 +- vara/node/authorship/src/authorship.rs | 103 +- vara/node/authorship/src/block_builder.rs | 9 +- vara/node/service/Cargo.toml | 3 +- vara/node/service/src/client.rs | 2 + vara/node/service/src/lib.rs | 89 +- vara/node/testing/Cargo.toml | 2 +- vara/pallets/gear-builtin/src/bls12_381.rs | 96 +- vara/pallets/gear-builtin/src/lib.rs | 2 +- .../gear-eth-bridge/primitives/src/lib.rs | 123 +- vara/pallets/gear-eth-bridge/src/builtin.rs | 7 +- vara/pallets/gear-eth-bridge/src/internal.rs | 13 +- vara/pallets/gear-eth-bridge/src/lib.rs | 9 +- .../gear-eth-bridge/src/migrations/reset.rs | 2 +- .../src/migrations/set_hash.rs | 2 +- vara/pallets/gear-voucher/src/internal.rs | 5 +- vara/pallets/gear/src/schedule.rs | 7 +- vara/pallets/grandpa-signer/src/lib.rs | 23 +- vara/pallets/payment/src/lib.rs | 134 +- vara/pallets/staking-rewards/src/extension.rs | 62 +- vara/pallets/staking-rewards/src/lib.rs | 69 +- vara/runtime/common/src/apis.rs | 8 +- vara/runtime/interface/sandbox/src/lib.rs | 26 +- vara/runtime/interface/src/lib.rs | 62 +- vara/runtime/vara/Cargo.toml | 5 + .../vara/src/genesis_config_presets.rs | 11 +- .../runtime/vara/src/governance/fellowship.rs | 47 +- vara/runtime/vara/src/governance/mod.rs | 3 + vara/runtime/vara/src/governance/origins.rs | 4 +- vara/runtime/vara/src/governance/tracks.rs | 56 +- vara/runtime/vara/src/lib.rs | 243 +- vara/runtime/vara/src/migrations.rs | 13 +- .../vara/src/weights/pallet_utility.rs | 14 + vara/sdk/builtins/common/src/eth_bridge.rs | 3 +- 103 files changed, 4802 insertions(+), 6107 deletions(-) create mode 100644 TODOS.md create mode 100644 docs/polkadot-sdk-stable2603-3-migration.md delete mode 100644 substrate/sc-mixnet/Cargo.toml delete mode 100644 substrate/sc-mixnet/README.md delete mode 100644 substrate/sc-mixnet/src/api.rs delete mode 100644 substrate/sc-mixnet/src/config.rs delete mode 100644 substrate/sc-mixnet/src/error.rs delete mode 100644 substrate/sc-mixnet/src/extrinsic_queue.rs delete mode 100644 substrate/sc-mixnet/src/lib.rs delete mode 100644 substrate/sc-mixnet/src/maybe_inf_delay.rs delete mode 100644 substrate/sc-mixnet/src/packet_dispatcher.rs delete mode 100644 substrate/sc-mixnet/src/peer_id.rs delete mode 100644 substrate/sc-mixnet/src/protocol.rs delete mode 100644 substrate/sc-mixnet/src/request.rs delete mode 100644 substrate/sc-mixnet/src/run.rs delete mode 100644 substrate/sc-mixnet/src/sync_with_runtime.rs delete mode 100644 substrate/sp-runtime-interface-proc-macro/src/pass_by/codec.rs delete mode 100644 substrate/sp-runtime-interface-proc-macro/src/pass_by/enum_.rs delete mode 100644 substrate/sp-runtime-interface-proc-macro/src/pass_by/inner.rs delete mode 100644 substrate/sp-runtime-interface-proc-macro/src/pass_by/mod.rs diff --git a/.config/hakari.toml b/.config/hakari.toml index 559599a5007..262b65033f2 100644 --- a/.config/hakari.toml +++ b/.config/hakari.toml @@ -33,7 +33,6 @@ workspace-members = [ "sc-executor-common", "sc-executor-polkavm", "sc-executor-wasmtime", - "sc-mixnet", "sp-allocator", "sp-runtime-interface-proc-macro", "sp-wasm-interface", @@ -44,45 +43,45 @@ workspace-members = [ third-party = [ # we have to exclude these deps because of their `try-runtime` and `runtime-benchmarks` features, # because we cannot, for example, run `cargo build --package gear-cli` without `--all-features` flag - { name = "frame-benchmarking", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "frame-benchmarking-cli", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "frame-election-provider-support", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "frame-executive", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "frame-support", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "frame-system", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "frame-try-runtime", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-authority-discovery", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-authorship", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-babe", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-bags-list", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-balances", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-bounties", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-child-bounties", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-conviction-voting", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-election-provider-multi-phase", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-grandpa", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-identity", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-im-online", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-multisig", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-nomination-pools", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-offences", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-preimage", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-proxy", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-ranked-collective", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-referenda", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-scheduler", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-session", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-staking", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-sudo", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-timestamp", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-transaction-payment", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-treasury", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-utility", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-vesting", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "pallet-whitelist", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "sc-cli", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "sc-client-db", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "sc-service", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "sp-runtime", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, - { name = "sp-staking", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" }, + { name = "frame-benchmarking", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "frame-benchmarking-cli", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "frame-election-provider-support", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "frame-executive", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "frame-support", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "frame-system", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "frame-try-runtime", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-authority-discovery", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-authorship", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-babe", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-bags-list", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-balances", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-bounties", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-child-bounties", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-conviction-voting", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-election-provider-multi-phase", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-grandpa", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-identity", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-im-online", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-multisig", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-nomination-pools", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-offences", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-preimage", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-proxy", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-ranked-collective", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-referenda", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-scheduler", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-session", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-staking", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-sudo", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-timestamp", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-transaction-payment", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-treasury", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-utility", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-vesting", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-whitelist", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "sc-cli", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "sc-client-db", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "sc-service", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "sp-runtime", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "sp-staking", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, ] diff --git a/Cargo.lock b/Cargo.lock index ef2fac30c1a..54a327ce122 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,16 +44,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "advisory-lock" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6caee7d48f930f9ad3fc9546f8cbf843365da0c5b0ca4eee1d1ac3dd12d8f93" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "aead" version = "0.5.2" @@ -89,6 +79,17 @@ dependencies = [ "subtle 2.6.1", ] +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "version_check", +] + [[package]] name = "ahash" version = "0.8.12" @@ -675,7 +676,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "alloy-sol-types", - "itertools 0.13.0", + "itertools 0.14.0", "serde", "serde_json", "serde_with", @@ -831,7 +832,7 @@ checksum = "a29980e69119444ed26b75e7ee5bed2043870f904a64318297e55800db686564" dependencies = [ "alloy-json-rpc", "alloy-transport", - "itertools 0.13.0", + "itertools 0.14.0", "reqwest 0.13.2", "serde_json", "tower 0.5.2", @@ -849,7 +850,7 @@ dependencies = [ "alloy-transport", "futures", "http 1.4.0", - "rustls 0.23.36", + "rustls", "serde_json", "tokio", "tokio-tungstenite 0.28.0", @@ -999,561 +1000,258 @@ dependencies = [ ] [[package]] -name = "arc-malachitebft-app" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-bls12-377" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" dependencies = [ - "arc-malachitebft-codec", - "arc-malachitebft-config", - "arc-malachitebft-core-consensus", - "arc-malachitebft-core-types", - "arc-malachitebft-engine", - "arc-malachitebft-metrics", - "arc-malachitebft-network", - "arc-malachitebft-peer", - "arc-malachitebft-signing", - "arc-malachitebft-sync", - "arc-malachitebft-wal", - "async-trait", - "derive-where", - "eyre", - "libp2p 0.56.0", - "libp2p-identity", - "ractor", - "rand 0.8.5", - "serde", - "tokio", - "tracing", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-std 0.4.0", ] [[package]] -name = "arc-malachitebft-app-channel" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-bls12-377" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfedac3173d12820a5e0d6cd4de31b49719a74f4a41dc09b6652d0276a3b2cd4" dependencies = [ - "arc-malachitebft-app", - "arc-malachitebft-config", - "arc-malachitebft-engine", - "arc-malachitebft-signing", - "bytes", - "derive-where", - "eyre", - "ractor", - "thiserror 2.0.17", - "tokio", - "tracing", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-codec" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-bls12-377-ext" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07208c7ea9e7abfe8fb01e190eba611f6e7c3cdbdef4a5473c9297d396495d1b" dependencies = [ - "bytes", + "ark-bls12-377 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-models-ext", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-config" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" dependencies = [ - "arc-malachitebft-core-types", - "bytesize", - "config", - "humantime-serde", - "multiaddr 0.18.2", - "serde", - "tracing", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", ] [[package]] -name = "arc-malachitebft-core-consensus" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-bls12-381" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df4dcc01ff89867cd86b0da835f23c3f02738353aaee7dde7495af71363b8d5" dependencies = [ - "arc-malachitebft-core-driver", - "arc-malachitebft-core-types", - "arc-malachitebft-core-votekeeper", - "arc-malachitebft-metrics", - "arc-malachitebft-peer", - "async-recursion", - "derive-where", - "futures", - "genawaiter", - "multiaddr 0.18.2", - "thiserror 2.0.17", - "tokio", - "tracing", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-core-driver" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-bls12-381-ext" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a83d59f25570c846b9cfc430539a150e9634c9db6949f87b12f3cbc53149b17" dependencies = [ - "arc-malachitebft-core-state-machine", - "arc-malachitebft-core-types", - "arc-malachitebft-core-votekeeper", - "derive-where", - "thiserror 2.0.17", - "tracing", + "ark-bls12-381 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-models-ext", + "ark-serialize 0.5.0", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-core-state-machine" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-bw6-761" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cc9cae367e0c3c0b52e3ef13371122752654f45d0212ec7306fb0c1c012cd98" dependencies = [ - "arc-malachitebft-core-types", - "derive-where", - "displaydoc", + "ark-bls12-377 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-core-types" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-bw6-761-ext" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60f7fc87dfb5699c1c5a12e8d4f13564c174a5224b5702002587ca67205a9ca7" dependencies = [ - "arc-malachitebft-peer", - "async-trait", - "bytes", - "derive-where", - "serde", - "thiserror 2.0.17", + "ark-bw6-761", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-models-ext", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-core-votekeeper" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" dependencies = [ - "arc-malachitebft-core-types", - "derive-where", - "thiserror 2.0.17", - "tracing", + "ark-ff 0.4.2", + "ark-poly 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", ] [[package]] -name = "arc-malachitebft-discovery" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" dependencies = [ - "arc-malachitebft-metrics", - "either", - "eyre", - "libp2p 0.56.0", - "rand 0.8.5", - "serde", - "tokio", - "tracing", + "ahash 0.8.12", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.5", + "itertools 0.13.0", + "num-bigint", + "num-integer", + "num-traits", + "rayon", + "zeroize", ] [[package]] -name = "arc-malachitebft-engine" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ed-on-bls12-377" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebbf817b2db27d2787009b2ff76304a5b90b4b01bb16aa8351701fd40f5f37b2" dependencies = [ - "arc-malachitebft-codec", - "arc-malachitebft-config", - "arc-malachitebft-core-consensus", - "arc-malachitebft-core-driver", - "arc-malachitebft-core-state-machine", - "arc-malachitebft-core-types", - "arc-malachitebft-core-votekeeper", - "arc-malachitebft-metrics", - "arc-malachitebft-network", - "arc-malachitebft-signing", - "arc-malachitebft-sync", - "arc-malachitebft-wal", - "async-recursion", - "async-trait", - "byteorder", - "bytes", - "bytesize", - "derive-where", - "eyre", - "hex", - "libp2p 0.56.0", - "ractor", - "rand 0.8.5", - "tokio", - "tracing", + "ark-bls12-377 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-metrics" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ed-on-bls12-377-ext" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93170025f4679342661d00f27c9a1586ccf053d29ad78b072d5be11649cae02c" dependencies = [ - "arc-malachitebft-core-state-machine", - "prometheus-client 0.23.1", + "ark-ec 0.5.0", + "ark-ed-on-bls12-377", + "ark-ff 0.5.0", + "ark-models-ext", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-network" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ed-on-bls12-381-bandersnatch" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1786b2e3832f6f0f7c8d62d5d5a282f6952a1ab99981c54cd52b6ac1d8f02df5" dependencies = [ - "arc-malachitebft-discovery", - "arc-malachitebft-metrics", - "arc-malachitebft-peer", - "arc-malachitebft-sync", - "async-trait", - "asynchronous-codec 0.7.0", - "bytes", - "either", - "eyre", - "futures", - "hex", - "itertools 0.14.0", - "libp2p 0.56.0", - "libp2p-gossipsub", - "libp2p-scatter", - "libp2p-stream", - "seahash", - "serde", - "thiserror 2.0.17", - "tokio", - "tracing", - "unsigned-varint 0.8.0", + "ark-bls12-381 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-peer" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ed-on-bls12-381-bandersnatch-ext" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee7e1fb880811e22d4fc8ffe83eaa260e39a4deb0f345dcc8ffb663d3e034e7a" dependencies = [ - "bs58 0.5.1", - "multihash 0.19.3", - "rand 0.8.5", - "serde", - "thiserror 2.0.17", + "ark-ec 0.5.0", + "ark-ed-on-bls12-381-bandersnatch", + "ark-ff 0.5.0", + "ark-models-ext", + "ark-std 0.5.0", ] [[package]] -name = "arc-malachitebft-proto" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" dependencies = [ - "prost 0.13.5", - "prost-types 0.13.5", - "thiserror 2.0.17", + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", ] [[package]] -name = "arc-malachitebft-signing" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" dependencies = [ - "arc-malachitebft-core-types", - "async-trait", - "signature", + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", ] [[package]] -name = "arc-malachitebft-signing-ecdsa" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" dependencies = [ - "arc-malachitebft-core-types", - "base64 0.22.1", - "k256", - "rand 0.8.5", - "serde", - "signature", + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec 0.7.6", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "zeroize", ] [[package]] -name = "arc-malachitebft-signing-ed25519" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "arc-malachitebft-core-types", - "base64 0.22.1", - "ed25519-consensus", - "rand 0.8.5", - "serde", - "signature", -] - -[[package]] -name = "arc-malachitebft-sync" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" -dependencies = [ - "arc-malachitebft-core-types", - "arc-malachitebft-metrics", - "arc-malachitebft-peer", - "async-trait", - "bytes", - "dashmap 6.1.0", - "derive-where", - "displaydoc", - "eyre", - "genawaiter", - "libp2p 0.56.0", - "rand 0.8.5", - "serde", - "thiserror 2.0.17", - "tracing", -] - -[[package]] -name = "arc-malachitebft-test" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" -dependencies = [ - "arc-malachitebft-app", - "arc-malachitebft-codec", - "arc-malachitebft-config", - "arc-malachitebft-core-consensus", - "arc-malachitebft-core-types", - "arc-malachitebft-engine", - "arc-malachitebft-peer", - "arc-malachitebft-proto", - "arc-malachitebft-signing", - "arc-malachitebft-signing-ed25519", - "arc-malachitebft-sync", - "async-trait", - "base64 0.22.1", - "bytes", - "ed25519-consensus", - "eyre", - "futures", - "hex", - "libp2p-identity", - "prost 0.13.5", - "prost-build 0.13.5", - "prost-types 0.13.5", - "protox", - "rand 0.8.5", - "serde", - "serde_json", - "sha3", - "signature", - "tokio", - "tracing", -] - -[[package]] -name = "arc-malachitebft-wal" -version = "0.7.0-pre" -source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" -dependencies = [ - "advisory-lock", - "bytes", - "cfg-if", - "crc32fast", -] - -[[package]] -name = "ark-bls12-377" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" -dependencies = [ - "ark-ec", - "ark-ff 0.4.2", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-bls12-377-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c7021f180a0cbea0380eba97c2af3c57074cdaffe0eef7e840e1c9f2841e55" -dependencies = [ - "ark-bls12-377", - "ark-ec", - "ark-models-ext", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-bls12-381" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" -dependencies = [ - "ark-ec", - "ark-ff 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-bls12-381-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1dc4b3d08f19e8ec06e949712f95b8361e43f1391d94f65e4234df03480631c" -dependencies = [ - "ark-bls12-381", - "ark-ec", - "ark-ff 0.4.2", - "ark-models-ext", - "ark-serialize 0.4.2", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-bw6-761" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e0605daf0cc5aa2034b78d008aaf159f56901d92a52ee4f6ecdfdac4f426700" -dependencies = [ - "ark-bls12-377", - "ark-ec", - "ark-ff 0.4.2", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-bw6-761-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccee5fba47266f460067588ee1bf070a9c760bf2050c1c509982c5719aadb4f2" -dependencies = [ - "ark-bw6-761", - "ark-ec", - "ark-ff 0.4.2", - "ark-models-ext", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-ec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" -dependencies = [ - "ark-ff 0.4.2", - "ark-poly", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "hashbrown 0.13.2", - "itertools 0.10.5", - "num-traits", - "rayon", - "zeroize", -] - -[[package]] -name = "ark-ed-on-bls12-377" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b10d901b9ac4b38f9c32beacedfadcdd64e46f8d7f8e88c1ae1060022cf6f6c6" -dependencies = [ - "ark-bls12-377", - "ark-ec", - "ark-ff 0.4.2", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-ed-on-bls12-377-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524a4fb7540df2e1a8c2e67a83ba1d1e6c3947f4f9342cc2359fc2e789ad731d" -dependencies = [ - "ark-ec", - "ark-ed-on-bls12-377", - "ark-ff 0.4.2", - "ark-models-ext", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-ed-on-bls12-381-bandersnatch" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cde0f2aa063a2a5c28d39b47761aa102bda7c13c84fc118a61b87c7b2f785c" -dependencies = [ - "ark-bls12-381", - "ark-ec", - "ark-ff 0.4.2", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-ed-on-bls12-381-bandersnatch-ext" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15185f1acb49a07ff8cbe5f11a1adc5a93b19e211e325d826ae98e98e124346" -dependencies = [ - "ark-ec", - "ark-ed-on-bls12-381-bandersnatch", - "ark-ff 0.4.2", - "ark-models-ext", - "ark-std 0.4.0", -] - -[[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.1", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" -dependencies = [ - "ark-ff-asm 0.5.0", - "ark-ff-macros 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", - "arrayvec 0.7.6", - "digest 0.10.7", - "educe", - "itertools 0.13.0", - "num-bigint", - "num-traits", - "paste", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", + "quote", + "syn 1.0.109", ] [[package]] @@ -1616,17 +1314,42 @@ dependencies = [ [[package]] name = "ark-models-ext" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9eab5d4b5ff2f228b763d38442adc9b084b0a465409b059fac5c2308835ec2" +checksum = "6294fd6ddc4996910adf2a9d3b56e3aa6a1f605ea315952169d2ddebc304dc4c" dependencies = [ - "ark-ec", - "ark-ff 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", "derivative", ] +[[package]] +name = "ark-pallas" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c676d42c65f0b2d334fc0ae72a422de2e62ed75beb3022050c0e8a81f6ccc0f" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-pallas-ext" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6906648fb42b7c83fc40ea43b12fbf75b704532057d71a467a25ec4afc239b6" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-models-ext", + "ark-pallas", + "ark-serialize 0.5.0", + "ark-std 0.5.0", +] + [[package]] name = "ark-poly" version = "0.4.2" @@ -1640,13 +1363,28 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash 0.8.12", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.5", +] + [[package]] name = "ark-scale" version = "0.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f69c00b3b529be29528a6f2fd5fa7b1790f8bed81b9cdca17e326538545a179" dependencies = [ - "ark-ec", + "ark-ec 0.4.2", "ark-ff 0.4.2", "ark-serialize 0.4.2", "ark-std 0.4.0", @@ -1654,6 +1392,20 @@ dependencies = [ "scale-info", ] +[[package]] +name = "ark-scale" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985c81a9c7b23a72f62b7b20686d5326d2a9956806f37de9ee35cb1238faf0c0" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "ark-serialize" version = "0.3.0" @@ -1670,7 +1422,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ - "ark-serialize-derive", + "ark-serialize-derive 0.4.2", "ark-std 0.4.0", "digest 0.10.7", "num-bigint", @@ -1682,10 +1434,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ + "ark-serialize-derive 0.5.0", "ark-std 0.5.0", "arrayvec 0.7.6", "digest 0.10.7", "num-bigint", + "rayon", ] [[package]] @@ -1699,6 +1453,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "ark-std" version = "0.3.0" @@ -1717,7 +1482,6 @@ checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", "rand 0.8.5", - "rayon", ] [[package]] @@ -1728,6 +1492,66 @@ checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" dependencies = [ "num-traits", "rand 0.8.5", + "rayon", +] + +[[package]] +name = "ark-transcript" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c1c928edb9d8ff24cb5dcb7651d3a98494fff3099eee95c2404cd813a9139f" +dependencies = [ + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "digest 0.10.7", + "rand_core 0.6.4", + "sha3", +] + +[[package]] +name = "ark-vesta" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a6d658e5e7380af710828550b2dc2c7b033c9f3103d2690711cb07d5a62df6" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-pallas", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-vesta-ext" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27dfabb2b731180273184366ebf57b1793600889e9c7b548916433dd19fb8932" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-models-ext", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "ark-vesta", +] + +[[package]] +name = "ark-vrf" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d63e9780640021b74d02b32895d8cec1b4abe8e5547b560a6bda6b14b78c6da" +dependencies = [ + "ark-bls12-381 0.5.0", + "ark-ec 0.5.0", + "ark-ed-on-bls12-381-bandersnatch", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "digest 0.10.7", + "rand_chacha 0.3.1", + "sha2 0.10.9", + "w3f-ring-proof", + "zeroize", ] [[package]] @@ -1760,22 +1584,6 @@ dependencies = [ "serde", ] -[[package]] -name = "asn1-rs" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" -dependencies = [ - "asn1-rs-derive 0.4.0", - "asn1-rs-impl 0.1.0", - "displaydoc", - "nom 7.1.3", - "num-traits", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - [[package]] name = "asn1-rs" version = "0.6.2" @@ -1783,7 +1591,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" dependencies = [ "asn1-rs-derive 0.5.1", - "asn1-rs-impl 0.2.0", + "asn1-rs-impl", "displaydoc", "nom 7.1.3", "num-traits", @@ -1799,7 +1607,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" dependencies = [ "asn1-rs-derive 0.6.0", - "asn1-rs-impl 0.2.0", + "asn1-rs-impl", "displaydoc", "nom 7.1.3", "num-traits", @@ -1808,18 +1616,6 @@ dependencies = [ "time", ] -[[package]] -name = "asn1-rs-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure 0.12.6", -] - [[package]] name = "asn1-rs-derive" version = "0.5.1" @@ -1844,17 +1640,6 @@ dependencies = [ "synstructure 0.13.2", ] -[[package]] -name = "asn1-rs-impl" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "asn1-rs-impl" version = "0.2.0" @@ -1881,7 +1666,7 @@ dependencies = [ "anstyle", "bstr", "libc", - "predicates 3.1.3", + "predicates", "predicates-core", "predicates-tree", "wait-timeout", @@ -1953,6 +1738,21 @@ dependencies = [ "futures-lite", ] +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + [[package]] name = "async-io" version = "2.6.0" @@ -2040,6 +1840,32 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "async-std" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers 0.3.0", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -2150,18 +1976,6 @@ dependencies = [ "url", ] -[[package]] -name = "attohttpc" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e2cdb6d5ed835199484bb92bb8b3edd526effe995c61732580439c1a67e2e9" -dependencies = [ - "base64 0.22.1", - "http 1.4.0", - "log", - "url", -] - [[package]] name = "atty" version = "0.2.14" @@ -2255,12 +2069,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -2285,12 +2093,6 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" - [[package]] name = "bimap" version = "0.6.3" @@ -2300,8 +2102,18 @@ checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" [[package]] name = "binary-merkle-tree" version = "16.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6d867f1ffee8b07e7bee466f4f33a043b91f868f5c7b1d22d8a02f86e92bee8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6d867f1ffee8b07e7bee466f4f33a043b91f868f5c7b1d22d8a02f86e92bee8" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", +] + +[[package]] +name = "binary-merkle-tree" +version = "16.1.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "hash-db", "log", @@ -2319,32 +2131,50 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.65.1" +version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.13.0", "cexpr", "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "prettyplease 0.2.37", + "itertools 0.13.0", "proc-macro2", "quote", "regex", - "rustc-hash 1.1.0", + "rustc-hash 2.1.1", "shlex", "syn 2.0.114", ] +[[package]] +name = "bip32" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db40d3dfbeab4e031d78c844642fa0caa0b0db11ce1607ac9d2986dff1405c69" +dependencies = [ + "bs58", + "hmac 0.12.1", + "k256", + "rand_core 0.6.4", + "ripemd", + "secp256k1 0.27.0", + "sha2 0.10.9", + "subtle 2.6.1", + "zeroize", +] + [[package]] name = "bip39" version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc" dependencies = [ - "bitcoin_hashes 0.14.1", + "bitcoin_hashes", + "rand 0.8.5", + "rand_core 0.6.4", + "serde", + "unicode-normalization", ] [[package]] @@ -2362,28 +2192,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" -[[package]] -name = "bitcoin-internals" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" - [[package]] name = "bitcoin-io" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" -[[package]] -name = "bitcoin_hashes" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" -dependencies = [ - "bitcoin-internals", - "hex-conservative 0.1.2", -] - [[package]] name = "bitcoin_hashes" version = "0.14.1" @@ -2391,7 +2205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" dependencies = [ "bitcoin-io", - "hex-conservative 0.2.2", + "hex-conservative", ] [[package]] @@ -2402,9 +2216,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "bitvec" @@ -2414,6 +2228,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -2460,17 +2275,6 @@ dependencies = [ "constant_time_eq 0.3.1", ] -[[package]] -name = "blake2s_simd" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90f7deecfac93095eb874a40febd69427776e24e1bd7f87f33ac62d6f0174df" -dependencies = [ - "arrayref", - "arrayvec 0.7.6", - "constant_time_eq 0.3.1", -] - [[package]] name = "blake3" version = "1.8.3" @@ -2528,29 +2332,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "bon" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97493a391b4b18ee918675fb8663e53646fd09321c58b46afa04e8ce2499c869" -dependencies = [ - "bon-macros", - "rustversion", -] - -[[package]] -name = "bon-macros" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2af3eac944c12cdf4423eab70d310da0a8e5851a18ffb192c0a5e3f7ae1663" -dependencies = [ - "darling 0.20.11", - "ident_case", - "proc-macro2", - "quote", - "syn 2.0.114", -] - [[package]] name = "borsh" version = "1.6.0" @@ -2576,20 +2357,30 @@ dependencies = [ [[package]] name = "bounded-collections" -version = "0.2.4" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ad8a0bed7827f0b07a5d23cec2e58cc02038a99e4ca81616cb2bb2025f804d" +checksum = "dee8eddd066a8825ec5570528e6880471210fd5d88cb6abbe1cfdd51ca249c33" dependencies = [ + "jam-codec", "log", "parity-scale-codec", "scale-info", "serde", ] +[[package]] +name = "bounded-vec" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68534a48cbf63a4b1323c433cf21238c9ec23711e0df13b08c33e5c2082663ce" +dependencies = [ + "thiserror 1.0.69", +] + [[package]] name = "bp-header-chain" -version = "0.18.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.26.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "bp-runtime", "finality-grandpa", @@ -2605,14 +2396,13 @@ dependencies = [ [[package]] name = "bp-runtime" -version = "0.18.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.26.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support", "frame-system", "hash-db", "impl-trait-for-tuples", - "log", "num-traits", "parity-scale-codec", "scale-info", @@ -2623,15 +2413,10 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-trie", + "tracing", "trie-db", ] -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - [[package]] name = "bs58" version = "0.5.1" @@ -2649,7 +2434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", - "regex-automata", + "regex-automata 0.4.13", "serde", ] @@ -2734,18 +2519,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" -dependencies = [ - "serde", -] - -[[package]] -name = "bytesize" -version = "1.3.3" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -2901,15 +2677,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" -[[package]] -name = "cbor4ii" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "472931dd4dfcc785075b09be910147f9c6258883fc4591d0dac6116392b2daa6" -dependencies = [ - "serde", -] - [[package]] name = "cc" version = "1.2.52" @@ -3041,28 +2808,13 @@ dependencies = [ [[package]] name = "cid" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9b68e3193982cd54187d71afdb2a271ad4cf8af157858e9cb911b91321de143" -dependencies = [ - "core2", - "multibase", - "multihash 0.17.0", - "serde", - "unsigned-varint 0.7.2", -] - -[[package]] -name = "cid" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3" +checksum = "21a304f95f84d169a6f31c4d0a30d784643aaa0bbc9c1e449a2c23e963ec4971" dependencies = [ - "core2", "multibase", - "multihash 0.18.1", - "serde", - "unsigned-varint 0.7.2", + "multihash 0.19.5", + "unsigned-varint 0.8.0", ] [[package]] @@ -3093,7 +2845,6 @@ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading", ] [[package]] @@ -3200,6 +2951,17 @@ dependencies = [ "cc", ] +[[package]] +name = "coarsetime" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e58eb270476aa4fc7843849f8a35063e8743b4dbcdf6dd0f8ea0886980c204c2" +dependencies = [ + "libc", + "wasix", + "wasm-bindgen", +] + [[package]] name = "cobs" version = "0.3.0" @@ -3217,7 +2979,7 @@ checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ "serde", "termcolor", - "unicode-width 0.2.2", + "unicode-width 0.1.14", ] [[package]] @@ -3226,7 +2988,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2073678591747aed4000dd468b97b14d7007f7936851d3f2f01846899f5ebf08" dependencies = [ - "bs58 0.5.1", + "bs58", "coins-core", "digest 0.10.7", "hmac 0.12.1", @@ -3260,7 +3022,7 @@ checksum = "62b962ad8545e43a28e14e87377812ba9ae748dd4fd963f4c10e9fcc6d13475b" dependencies = [ "base64 0.21.7", "bech32", - "bs58 0.5.1", + "bs58", "const-hex", "digest 0.10.7", "generic-array 0.14.7", @@ -3322,18 +3084,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "config" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" -dependencies = [ - "nom 7.1.3", - "pathdiff", - "serde", - "toml 0.8.23", -] - [[package]] name = "console" version = "0.15.11" @@ -3454,6 +3204,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "convert_case" version = "0.10.0" @@ -3791,76 +3550,246 @@ dependencies = [ ] [[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle 2.6.1", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +dependencies = [ + "generic-array 0.12.4", + "subtle 1.0.0", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.7", + "subtle 2.6.1", +] + +[[package]] +name = "crypto_secretbox" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" +dependencies = [ + "aead", + "cipher 0.4.4", + "generic-array 0.14.7", + "poly1305", + "salsa20", + "subtle 2.6.1", + "zeroize", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher 0.4.4", +] + +[[package]] +name = "cumulus-client-parachain-inherent" +version = "0.23.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-relay-chain-interface", + "cumulus-test-relay-sproof-builder", + "parity-scale-codec", + "sc-client-api", + "sc-consensus-babe", + "sc-network-types", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", + "sp-inherents", + "sp-runtime", + "sp-state-machine", + "sp-storage", + "tracing", +] + +[[package]] +name = "cumulus-pallet-parachain-system" +version = "0.26.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "array-bytes", + "bytes", + "cumulus-pallet-parachain-system-proc-macro", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-primitives-proof-size-hostfunction", + "derive-where", + "docify", + "environmental", + "frame-benchmarking", + "frame-support", + "frame-system", + "hashbrown 0.15.5", + "impl-trait-for-tuples", + "log", + "pallet-message-queue", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-runtime-parachains", + "scale-info", + "sp-api", + "sp-consensus-babe", + "sp-core", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", + "sp-externalities", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", + "sp-version", + "staging-xcm", + "staging-xcm-builder", + "trie-db", +] + +[[package]] +name = "cumulus-pallet-parachain-system-proc-macro" +version = "0.8.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "crossbeam-utils", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.114", ] [[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +name = "cumulus-primitives-core" +version = "0.24.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "generic-array 0.14.7", - "rand_core 0.6.4", - "subtle 2.6.1", - "zeroize", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-primitives", + "scale-info", + "sp-api", + "sp-runtime", + "sp-trie", + "staging-xcm", + "tracing", ] [[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +name = "cumulus-primitives-parachain-inherent" +version = "0.24.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "generic-array 0.14.7", - "rand_core 0.6.4", - "typenum", + "async-trait", + "cumulus-primitives-core", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-inherents", + "sp-trie", ] [[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +name = "cumulus-primitives-proof-size-hostfunction" +version = "0.17.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "generic-array 0.12.4", - "subtle 1.0.0", + "sp-externalities", + "sp-runtime-interface", + "sp-trie", ] [[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +name = "cumulus-relay-chain-interface" +version = "0.29.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "generic-array 0.14.7", - "subtle 2.6.1", + "async-trait", + "cumulus-primitives-core", + "futures", + "jsonrpsee-core", + "parity-scale-codec", + "polkadot-overseer", + "sc-client-api", + "sc-network", + "sp-api", + "sp-blockchain", + "sp-state-machine", + "sp-storage", + "sp-version", + "thiserror 1.0.69", ] [[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +name = "cumulus-test-relay-sproof-builder" +version = "0.25.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "cipher 0.4.4", + "cumulus-primitives-core", + "parity-scale-codec", + "polkadot-primitives", + "sp-consensus-babe", + "sp-core", + "sp-io", + "sp-keyring", + "sp-runtime", + "sp-state-machine", + "sp-trie", ] [[package]] @@ -3890,19 +3819,6 @@ dependencies = [ "syn 2.0.114", ] -[[package]] -name = "curve25519-dalek-ng" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.6.4", - "subtle-ng", - "zeroize", -] - [[package]] name = "cxx" version = "1.0.192" @@ -4123,6 +4039,15 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + [[package]] name = "defer" version = "0.2.1" @@ -4842,20 +4767,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "der-parser" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" -dependencies = [ - "asn1-rs 0.5.2", - "displaydoc", - "nom 7.1.3", - "num-bigint", - "num-traits", - "rusticata-macros", -] - [[package]] name = "der-parser" version = "9.0.0" @@ -5227,21 +5138,6 @@ dependencies = [ "signature", ] -[[package]] -name = "ed25519-consensus" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" -dependencies = [ - "curve25519-dalek-ng", - "hex", - "rand_core 0.6.4", - "serde", - "sha2 0.9.9", - "thiserror 1.0.69", - "zeroize", -] - [[package]] name = "ed25519-dalek" version = "2.2.0" @@ -5306,7 +5202,6 @@ dependencies = [ "ff", "generic-array 0.14.7", "group", - "pem-rfc7468", "pkcs8", "rand_core 0.6.4", "sec1", @@ -5335,26 +5230,34 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "enum-as-inner" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.114", ] [[package]] -name = "enum-as-inner" -version = "0.6.1" +name = "enum-display" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +checksum = "02058bb25d8d0605829af88230427dd5cd50661590bd2b09d1baf7c64c417f24" dependencies = [ - "heck 0.5.0", - "proc-macro2", + "enum-display-macro", +] + +[[package]] +name = "enum-display-macro" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4be2cf2fe7b971b1865febbacd4d8df544aa6bd377cca011a6d69dcf4c60d94" +dependencies = [ + "convert_case 0.6.0", "quote", - "syn 2.0.114", + "syn 1.0.109", ] [[package]] @@ -5510,7 +5413,6 @@ dependencies = [ "ethexe-compute", "ethexe-db", "ethexe-ethereum", - "ethexe-malachite", "ethexe-network", "ethexe-processor", "ethexe-prometheus", @@ -5670,66 +5572,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "ethexe-malachite" -version = "2.0.0" -dependencies = [ - "alloy", - "anyhow", - "async-trait", - "derive_more 2.1.1", - "ethexe-common", - "ethexe-db", - "ethexe-malachite-core", - "ethexe-runtime-common", - "futures", - "gear-workspace-hack", - "gprimitives", - "gsigner", - "parity-scale-codec", - "proptest", - "tempfile", - "tokio", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "ethexe-malachite-core" -version = "2.0.0" -dependencies = [ - "advisory-lock", - "anyhow", - "arc-malachitebft-app", - "arc-malachitebft-app-channel", - "arc-malachitebft-codec", - "arc-malachitebft-core-consensus", - "arc-malachitebft-core-types", - "arc-malachitebft-engine", - "arc-malachitebft-signing", - "arc-malachitebft-signing-ecdsa", - "arc-malachitebft-sync", - "arc-malachitebft-test", - "async-trait", - "bytes", - "futures", - "gear-core", - "gear-workspace-hack", - "gprimitives", - "gsigner", - "hex", - "libp2p-identity", - "parity-scale-codec", - "proptest", - "rocksdb", - "serde", - "sha3", - "tempfile", - "tokio", - "tracing", - "tracing-subscriber", -] - [[package]] name = "ethexe-network" version = "2.0.0" @@ -5749,7 +5591,7 @@ dependencies = [ "indexmap 2.14.0", "ip_network", "itertools 0.13.0", - "libp2p 0.56.0", + "libp2p", "libp2p-gossipsub", "libp2p-swarm-test", "log", @@ -5758,7 +5600,7 @@ dependencies = [ "metrics-derive", "nonempty 0.12.0", "parity-scale-codec", - "prometheus-client 0.23.1", + "prometheus-client", "proptest", "rand 0.8.5", "tokio", @@ -5997,7 +5839,6 @@ dependencies = [ "ethexe-consensus", "ethexe-db", "ethexe-ethereum", - "ethexe-malachite", "ethexe-network", "ethexe-observer", "ethexe-processor", @@ -6077,22 +5918,12 @@ dependencies = [ "blake2 0.10.6", "file-guard", "fs-err", - "prettyplease 0.2.37", + "prettyplease", "proc-macro2", "quote", "syn 2.0.114", ] -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - [[package]] name = "fail" version = "0.5.1" @@ -6138,6 +5969,30 @@ dependencies = [ "bytes", ] +[[package]] +name = "fatality" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec6f82451ff7f0568c6181287189126d492b5654e30a788add08027b6363d019" +dependencies = [ + "fatality-proc-macro", + "thiserror 1.0.69", +] + +[[package]] +name = "fatality-proc-macro" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb42427514b063d97ce21d5199f36c0c307d981434a6be32582bc79fe5bd2303" +dependencies = [ + "expander", + "indexmap 2.14.0", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "fdlimit" version = "0.3.0" @@ -6226,6 +6081,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flagset" version = "0.4.7" @@ -6242,15 +6103,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "float-cmp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" -dependencies = [ - "num-traits", -] - [[package]] name = "float-cmp" version = "0.10.0" @@ -6295,8 +6147,8 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fork-tree" -version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "13.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", ] @@ -6328,8 +6180,8 @@ checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" [[package]] name = "frame-benchmarking" -version = "38.1.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support", "frame-support-procedural", @@ -6352,24 +6204,30 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" -version = "43.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "54.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "Inflector", "array-bytes", "chrono", "clap 4.5.54", "comfy-table", + "cumulus-client-parachain-inherent", + "cumulus-primitives-core", + "cumulus-primitives-proof-size-hostfunction", + "env_filter", "frame-benchmarking", + "frame-storage-access-test-runtime", "frame-support", "frame-system", "gethostname", "handlebars", "itertools 0.11.0", - "lazy_static", "linked-hash-map", "log", "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-primitives", "rand 0.8.5", "rand_pcg", "sc-block-builder", @@ -6378,11 +6236,15 @@ dependencies = [ "sc-client-api", "sc-client-db", "sc-executor", + "sc-executor-common", + "sc-executor-wasmtime", + "sc-runtime-utilities", "sc-service", "sc-sysinfo", "serde", "serde_json", "sp-api", + "sp-block-builder", "sp-blockchain", "sp-core", "sp-database", @@ -6392,10 +6254,16 @@ dependencies = [ "sp-io", "sp-keystore", "sp-runtime", + "sp-runtime-interface", "sp-state-machine", "sp-storage", + "sp-timestamp", + "sp-transaction-pool", "sp-trie", + "sp-version", "sp-wasm-interface", + "subxt", + "subxt-signer", "thiserror 1.0.69", "thousands", ] @@ -6418,8 +6286,8 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" -version = "14.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "16.1.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -6429,8 +6297,8 @@ dependencies = [ [[package]] name = "frame-election-provider-support" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -6441,12 +6309,13 @@ dependencies = [ "sp-core", "sp-npos-elections", "sp-runtime", + "sp-std", ] [[package]] name = "frame-executive" -version = "38.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "aquamarine", "frame-support", @@ -6487,10 +6356,11 @@ dependencies = [ [[package]] name = "frame-metadata-hash-extension" -version = "0.6.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.14.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", + "const-hex", "docify", "frame-support", "frame-system", @@ -6502,37 +6372,52 @@ dependencies = [ [[package]] name = "frame-remote-externalities" -version = "0.46.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.57.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "futures", "indicatif 0.17.11", "jsonrpsee", "log", "parity-scale-codec", + "rand 0.8.5", "serde", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "sp-io", "sp-runtime", "sp-state-machine", "spinners", "substrate-rpc-client", "tokio", - "tokio-retry", +] + +[[package]] +name = "frame-storage-access-test-runtime" +version = "0.7.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "cumulus-pallet-parachain-system", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-state-machine", + "sp-trie", + "substrate-wasm-builder", ] [[package]] name = "frame-support" -version = "38.2.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "aquamarine", "array-bytes", + "binary-merkle-tree 16.1.1 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "bitflags 1.3.2", "docify", "environmental", - "frame-metadata 16.0.0", + "frame-metadata 23.0.1", "frame-support-procedural", "impl-trait-for-tuples", "k256", @@ -6543,7 +6428,6 @@ dependencies = [ "scale-info", "serde", "serde_json", - "smallvec", "sp-api", "sp-arithmetic", "sp-core", @@ -6558,15 +6442,15 @@ dependencies = [ "sp-state-machine", "sp-std", "sp-tracing", + "sp-trie", "sp-weights", - "static_assertions", "tt-call", ] [[package]] name = "frame-support-procedural" -version = "30.0.6" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "37.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "Inflector", "cfg-expr", @@ -6576,17 +6460,17 @@ dependencies = [ "frame-support-procedural-tools", "itertools 0.11.0", "macro_magic", - "proc-macro-warning 1.84.1", + "proc-macro-warning", "proc-macro2", "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "syn 2.0.114", ] [[package]] name = "frame-support-procedural-tools" -version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "13.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate 3.4.0", @@ -6598,7 +6482,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "12.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "proc-macro2", "quote", @@ -6608,11 +6492,11 @@ dependencies = [ [[package]] name = "frame-support-test" version = "3.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-executive", - "frame-metadata 16.0.0", + "frame-metadata 23.0.1", "frame-support", "frame-support-test-pallet", "frame-system", @@ -6636,7 +6520,7 @@ dependencies = [ [[package]] name = "frame-support-test-pallet" version = "4.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support", "frame-system", @@ -6648,8 +6532,8 @@ dependencies = [ [[package]] name = "frame-system" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "cfg-if", "docify", @@ -6661,15 +6545,14 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std", "sp-version", "sp-weights", ] [[package]] name = "frame-system-benchmarking" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -6682,8 +6565,8 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "docify", "parity-scale-codec", @@ -6692,8 +6575,8 @@ dependencies = [ [[package]] name = "frame-try-runtime" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.52.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support", "parity-scale-codec", @@ -6756,16 +6639,6 @@ dependencies = [ "futures-util", ] -[[package]] -name = "futures-bounded" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b07bbbe7d7e78809544c6f718d875627addc73a7c3582447abc052cd3dc67e0" -dependencies = [ - "futures-timer", - "futures-util", -] - [[package]] name = "futures-bounded" version = "0.2.4" @@ -6834,16 +6707,6 @@ dependencies = [ "syn 2.0.114", ] -[[package]] -name = "futures-rustls" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd3cf68c183738046838e300353e4716c674dc5e56890de4826801a6622a28" -dependencies = [ - "futures-io", - "rustls 0.21.12", -] - [[package]] name = "futures-rustls" version = "0.26.0" @@ -6851,7 +6714,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.36", + "rustls", "rustls-pki-types", ] @@ -6867,13 +6730,24 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-ticker" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9763058047f713632a52e916cc7f6a4b3fc6e9fc1ff8c5b1dc49e5a89041682e" +dependencies = [ + "futures", + "futures-timer", + "instant", +] + [[package]] name = "futures-timer" version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" dependencies = [ - "gloo-timers", + "gloo-timers 0.2.6", "send_wrapper 0.4.0", ] @@ -6902,12 +6776,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" [[package]] -name = "fxhash" -version = "0.2.1" +name = "fxprof-processed-profile" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +checksum = "25234f20a3ec0a962a61770cfe39ecf03cb529a6e474ad8cff025ed497eda557" dependencies = [ - "byteorder", + "bitflags 2.13.0", + "debugid", + "rustc-hash 2.1.1", + "serde", + "serde_derive", + "serde_json", ] [[package]] @@ -6922,10 +6801,10 @@ dependencies = [ name = "gbuiltin-bls381" version = "2.0.0" dependencies = [ - "ark-bls12-381", - "ark-ec", + "ark-bls12-381 0.4.0", + "ark-ec 0.4.2", "ark-ff 0.4.2", - "ark-scale", + "ark-scale 0.0.12", "ark-serialize 0.4.2", "gear-workspace-hack", "parity-scale-codec", @@ -7137,7 +7016,7 @@ dependencies = [ "gear-workspace-hack", "gsys", "log", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "proptest", "scale-decode 0.16.2", "scale-encode", @@ -7597,7 +7476,7 @@ name = "gear-ss58" version = "2.0.0" dependencies = [ "blake2 0.10.6", - "bs58 0.5.1", + "bs58", "gear-workspace-hack", "hex", ] @@ -7764,7 +7643,7 @@ dependencies = [ name = "gear-workspace-hack" version = "0.1.0" dependencies = [ - "ahash", + "ahash 0.8.12", "alloy", "alloy-chains", "alloy-consensus", @@ -7783,25 +7662,33 @@ dependencies = [ "alloy-sol-types", "anyhow", "arbitrary", - "ark-bls12-381", + "ark-bls12-381 0.4.0", + "ark-bls12-381 0.5.0", "ark-bls12-381-ext", - "ark-ec", + "ark-ec 0.4.2", + "ark-ec 0.5.0", "ark-ff 0.4.2", + "ark-ff 0.5.0", "ark-models-ext", - "ark-scale", + "ark-scale 0.0.12", + "ark-scale 0.0.13", "ark-serialize 0.4.2", + "ark-serialize 0.5.0", "ark-std 0.4.0", + "ark-std 0.5.0", "arrayvec 0.7.6", "base64 0.22.1", - "binary-merkle-tree", - "bitflags 2.10.0", + "binary-merkle-tree 16.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "binary-merkle-tree 16.1.1 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", + "bip39", + "bitflags 2.13.0", "bitvec", "blake2 0.10.6", "blake2b_simd", "bounded-collections", "bp-header-chain", "bp-runtime", - "bs58 0.5.1", + "bs58", "bumpalo", "byte-slice-cast", "bytemuck", @@ -7813,14 +7700,15 @@ dependencies = [ "concurrent-queue", "const-hex", "cranelift-bitset", - "cranelift-codegen", - "cranelift-codegen-meta", "crc32fast", "crossbeam-channel", "crossbeam-epoch", + "crossbeam-queue", "crossbeam-utils", "crunchy", "crypto-common", + "cumulus-pallet-parachain-system", + "cumulus-primitives-core", "curve25519-dalek", "data-encoding", "der", @@ -7836,6 +7724,7 @@ dependencies = [ "either", "elliptic-curve", "enumflags2", + "env_filter", "environmental", "errno", "event-listener 5.4.1", @@ -7843,12 +7732,13 @@ dependencies = [ "finality-grandpa", "fixed-hash", "fnv", + "foldhash 0.1.5", "foldhash 0.2.0", "form_urlencoded", "frame-executive", - "frame-metadata 16.0.0", "frame-metadata 23.0.1", "frame-metadata-hash-extension", + "frame-storage-access-test-runtime", "frame-support", "frame-support-procedural", "frame-system-rpc-runtime-api", @@ -7857,6 +7747,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", + "futures-rustls", "futures-sink", "futures-task", "futures-timer", @@ -7868,26 +7759,29 @@ dependencies = [ "getrandom_or_panic", "hash-db", "hash256-std-hasher", + "hashbrown 0.12.3", "hashbrown 0.13.2", "hashbrown 0.14.5", + "hashbrown 0.15.5", "hashbrown 0.16.1", "hashbrown 0.17.1", "hex", - "hickory-proto", "hkdf", "hmac 0.12.1", "http-body-util", "hyper 0.14.32", "hyper 1.8.1", - "hyper-rustls 0.27.7", + "hyper-rustls", "hyper-util", - "idna 1.1.0", - "impl-codec 0.6.0", - "impl-serde 0.4.0", + "idna", + "if-watch", + "impl-codec 0.7.1", + "impl-serde 0.5.0", "indexmap 2.14.0", "ipnet", "itertools 0.10.5", "itertools 0.13.0", + "itertools 0.14.0", "js-sys", "jsonrpsee", "jsonrpsee-client-transport", @@ -7895,13 +7789,10 @@ dependencies = [ "k256", "keccak", "libc", - "libp2p 0.52.4", - "libp2p 0.56.0", - "libp2p-core 0.43.2", - "libp2p-gossipsub", + "libp2p", "libp2p-identity", - "libp2p-kad 0.48.0", - "libp2p-request-response 0.29.0", + "libp2p-swarm", + "libp2p-tcp", "librocksdb-sys", "libsecp256k1", "libsecp256k1-core", @@ -7913,8 +7804,9 @@ dependencies = [ "merlin", "miniz_oxide", "mio", - "multihash 0.19.3", "names", + "netlink-proto", + "netlink-sys", "nix", "nom 7.1.3", "num-bigint", @@ -7923,20 +7815,22 @@ dependencies = [ "num-traits", "numerated", "once_cell", - "openssl", - "openssl-sys", + "pallet-asset-conversion", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-bounties", + "pallet-broker", "pallet-child-bounties", "pallet-conviction-voting", "pallet-election-provider-multi-phase", "pallet-grandpa", "pallet-identity", "pallet-im-online", + "pallet-message-queue", + "pallet-migrations", "pallet-multisig", "pallet-nomination-pools", "pallet-nomination-pools-runtime-api", @@ -7957,22 +7851,25 @@ dependencies = [ "pallet-utility", "pallet-vesting", "pallet-whitelist", - "parity-bip39", "parity-scale-codec", "parity-scale-codec-derive", "parity-wasm", "pbkdf2", "percent-encoding", + "petgraph 0.6.5", "pkcs8", - "polkavm-common", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-runtime-parachains", + "polkadot-sdk-frame", + "polkavm-common 0.9.0", "portable-atomic", "ppv-lite86", - "predicates 3.1.3", - "primitive-types 0.12.2", + "predicates", "primitive-types 0.13.1", "proc-macro2", "proptest", - "prost 0.12.6", + "prost 0.13.5", "pulley-interpreter", "quanta", "quote", @@ -7983,17 +7880,20 @@ dependencies = [ "rand_core 0.6.4", "rand_core 0.9.3", "regex", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.13", + "regex-syntax 0.8.8", "reqwest 0.12.28", "ring 0.17.14", + "ripemd", "rocksdb", + "rtnetlink", "ruint", + "rustc-demangle", "rustc-hash 1.1.0", "rustc-hash 2.1.1", "rustc-hex", "rustix 1.1.3", - "rustls 0.23.36", + "rustls", "rustls-webpki 0.103.8", "sc-client-db", "scale-bits 0.7.0", @@ -8005,7 +7905,8 @@ dependencies = [ "schnorrkel", "sec1", "secp256k1 0.28.2", - "secrecy", + "secp256k1-sys 0.9.2", + "secrecy 0.8.0", "security-framework 3.5.1", "security-framework-sys", "semver 1.0.27", @@ -8013,7 +7914,7 @@ dependencies = [ "serde-json-wasm", "serde_core", "serde_json", - "sha-1", + "serde_with", "sha1", "sha2 0.10.9", "sha3", @@ -8026,13 +7927,15 @@ dependencies = [ "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", + "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-grandpa", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", + "sp-database", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", @@ -8057,19 +7960,25 @@ dependencies = [ "spki", "ss58-registry", "stable_deref_trait", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", "strum 0.24.1", "strum 0.26.3", "strum 0.27.2", "substrate-bip39", "subtle 2.6.1", + "subxt", "subxt-metadata", + "subxt-rpcs", "syn 1.0.109", "syn 2.0.114", "thiserror 2.0.17", + "tikv-jemalloc-sys", "time", "tiny-keccak", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tokio-stream", "tokio-util", "toml_datetime 0.7.5+spec-1.1.0", @@ -8082,45 +7991,29 @@ dependencies = [ "trie-db", "trie-root", "trybuild", + "tuplex", "twox-hash 1.6.3", "uint 0.10.0", - "uint 0.9.5", "unicode-normalization", "unsigned-varint 0.7.2", "unsigned-varint 0.8.0", "url", + "uuid", "wasm-bindgen", "wasm-encoder 0.230.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.38.0", "wasmparser 0.230.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmtime", "wasmtime-internal-core", - "wasmtime-internal-cranelift", "winnow", - "x25519-dalek", + "yasna", "zerocopy", "zeroize", ] -[[package]] -name = "genawaiter" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" -dependencies = [ - "genawaiter-macro", -] - -[[package]] -name = "genawaiter-macro" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" - [[package]] name = "generate-bags" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "chrono", "frame-election-provider-support", @@ -8257,7 +8150,7 @@ version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "libc", "libgit2-sys", "log", @@ -8305,6 +8198,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "gloo-utils" version = "0.2.0" @@ -8349,7 +8254,7 @@ dependencies = [ "gear-ss58", "gear-workspace-hack", "hex", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "scale-decode 0.16.2", "scale-encode", "scale-info", @@ -8372,9 +8277,9 @@ dependencies = [ name = "gsdk" version = "2.0.0" dependencies = [ - "ark-bls12-381", - "ark-ec", - "ark-scale", + "ark-bls12-381 0.4.0", + "ark-ec 0.4.2", + "ark-scale 0.0.12", "ark-serialize 0.4.2", "ark-std 0.4.0", "colored", @@ -8444,12 +8349,12 @@ dependencies = [ "libp2p-identity", "nacl", "parity-scale-codec", - "predicates 3.1.3", + "predicates", "proptest", "rand 0.8.5", "scale-info", "schnorrkel", - "secrecy", + "secrecy 0.8.0", "serde", "serde_json", "sha3", @@ -8627,6 +8532,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] [[package]] name = "hashbrown" @@ -8634,7 +8542,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash", + "ahash 0.8.12", ] [[package]] @@ -8643,7 +8551,7 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash", + "ahash 0.8.12", "allocator-api2", ] @@ -8690,15 +8598,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "hashlink" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" -dependencies = [ - "hashbrown 0.14.5", -] - [[package]] name = "headers" version = "0.3.9" @@ -8764,15 +8663,6 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-conservative" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" [[package]] name = "hex-conservative" @@ -8795,6 +8685,31 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" +[[package]] +name = "hickory-proto" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.8.5", + "socket2 0.5.10", + "thiserror 1.0.69", + "tinyvec", + "tokio", + "tracing", + "url", +] + [[package]] name = "hickory-proto" version = "0.25.2" @@ -8804,16 +8719,15 @@ dependencies = [ "async-trait", "cfg-if", "data-encoding", - "enum-as-inner 0.6.1", + "enum-as-inner", "futures-channel", "futures-io", "futures-util", - "idna 1.1.0", + "idna", "ipnet", "once_cell", "rand 0.9.2", "ring 0.17.14", - "socket2 0.5.10", "thiserror 2.0.17", "tinyvec", "tokio", @@ -8821,6 +8735,27 @@ dependencies = [ "url", ] +[[package]] +name = "hickory-resolver" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto 0.24.4", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot 0.12.5", + "rand 0.8.5", + "resolv-conf", + "smallvec", + "thiserror 1.0.69", + "tokio", + "tracing", +] + [[package]] name = "hickory-resolver" version = "0.25.2" @@ -8829,7 +8764,7 @@ checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" dependencies = [ "cfg-if", "futures-util", - "hickory-proto", + "hickory-proto 0.25.2", "ipconfig", "moka", "once_cell", @@ -8957,22 +8892,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" - -[[package]] -name = "humantime-serde" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c" -dependencies = [ - "humantime", - "serde", -] - [[package]] name = "hyper" version = "0.14.32" @@ -9020,22 +8939,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "log", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", - "tokio", - "tokio-rustls 0.24.1", -] - [[package]] name = "hyper-rustls" version = "0.27.7" @@ -9046,10 +8949,11 @@ dependencies = [ "hyper 1.8.1", "hyper-util", "log", - "rustls 0.23.36", + "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tower-service", "webpki-roots 1.0.5", ] @@ -9205,27 +9109,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "1.1.0" @@ -9275,46 +9158,26 @@ dependencies = [ "netlink-proto", "netlink-sys", "rtnetlink", - "system-configuration", - "tokio", - "windows 0.53.0", -] - -[[package]] -name = "igd-next" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "064d90fec10d541084e7b39ead8875a5a80d9114a2b18791565253bae25f49e4" -dependencies = [ - "async-trait", - "attohttpc 0.24.1", - "bytes", - "futures", - "http 0.2.12", - "hyper 0.14.32", - "log", - "rand 0.8.5", + "smol", + "system-configuration", "tokio", - "url", - "xmltree", + "windows 0.53.0", ] [[package]] name = "igd-next" -version = "0.16.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516893339c97f6011282d5825ac94fc1c7aad5cad26bdc2d0cee068c0bf97f97" +checksum = "064d90fec10d541084e7b39ead8875a5a80d9114a2b18791565253bae25f49e4" dependencies = [ "async-trait", - "attohttpc 0.30.1", + "attohttpc", "bytes", "futures", - "http 1.4.0", - "http-body-util", - "hyper 1.8.1", - "hyper-util", + "http 0.2.12", + "hyper 0.14.32", "log", - "rand 0.9.2", + "rand 0.8.5", "tokio", "url", "xmltree", @@ -9338,6 +9201,17 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-num-traits" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d15461ab0dcc56706adf266158acbc44ccf719bf7d0af30705f58b90a4b8c" +dependencies = [ + "integer-sqrt", + "num-traits", + "uint 0.10.0", +] + [[package]] name = "impl-serde" version = "0.4.0" @@ -9386,12 +9260,6 @@ dependencies = [ "quote", ] -[[package]] -name = "indenter" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" - [[package]] name = "indexmap" version = "1.9.3" @@ -9604,6 +9472,54 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +[[package]] +name = "ittapi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" +dependencies = [ + "cc", +] + +[[package]] +name = "jam-codec" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb948eace373d99de60501a02fb17125d30ac632570de20dccc74370cdd611b9" +dependencies = [ + "arrayvec 0.7.6", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "jam-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "jam-codec-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "319af585c4c8a6b5552a52b7787a1ab3e4d59df7614190b1f85b9b842488789d" +dependencies = [ + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "jiff" version = "0.2.18" @@ -9701,13 +9617,13 @@ dependencies = [ "http 1.4.0", "jsonrpsee-core", "pin-project", - "rustls 0.23.36", + "rustls", "rustls-pki-types", "rustls-platform-verifier 0.5.3", "soketto", "thiserror 1.0.69", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tokio-util", "tracing", "url", @@ -9750,11 +9666,11 @@ dependencies = [ "base64 0.22.1", "http-body 1.0.1", "hyper 1.8.1", - "hyper-rustls 0.27.7", + "hyper-rustls", "hyper-util", "jsonrpsee-core", "jsonrpsee-types", - "rustls 0.23.36", + "rustls", "rustls-platform-verifier 0.5.3", "serde", "serde_json", @@ -9899,6 +9815,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28" +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "kvdb" version = "0.13.0" @@ -9920,16 +9845,15 @@ dependencies = [ [[package]] name = "kvdb-rocksdb" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b644c70b92285f66bfc2032922a79000ea30af7bc2ab31902992a5dcb9b434f6" +checksum = "739ac938a308a9a8b6772fd1d840fd9c0078f9c74fe294feaf32faae727102cc" dependencies = [ "kvdb", "num_cpus", "parking_lot 0.12.5", "regex", "rocksdb", - "smallvec", ] [[package]] @@ -9975,12 +9899,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "leb128fmt" version = "0.1.0" @@ -10026,16 +9944,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - [[package]] name = "libm" version = "0.2.16" @@ -10054,139 +9962,79 @@ dependencies = [ [[package]] name = "libp2p" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94495eb319a85b70a68b85e2389a95bb3555c71c49025b78c691a854a7e6464" -dependencies = [ - "bytes", - "either", - "futures", - "futures-timer", - "getrandom 0.2.16", - "instant", - "libp2p-allow-block-list 0.2.0", - "libp2p-connection-limits 0.2.1", - "libp2p-core 0.40.1", - "libp2p-dns 0.40.1", - "libp2p-identify 0.43.1", - "libp2p-identity", - "libp2p-kad 0.44.6", - "libp2p-mdns 0.44.0", - "libp2p-metrics 0.13.1", - "libp2p-noise 0.43.2", - "libp2p-ping 0.43.1", - "libp2p-quic 0.9.3", - "libp2p-request-response 0.25.3", - "libp2p-swarm 0.43.7", - "libp2p-tcp 0.40.1", - "libp2p-upnp 0.1.1", - "libp2p-wasm-ext", - "libp2p-websocket", - "libp2p-yamux 0.44.1", - "multiaddr 0.18.2", - "pin-project", - "rw-stream-sink", - "thiserror 1.0.69", -] - -[[package]] -name = "libp2p" -version = "0.56.0" +version = "0.54.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce71348bf5838e46449ae240631117b487073d5f347c06d434caddcb91dceb5a" +checksum = "bbbe80f9c7e00526cd6b838075b9c171919404a4732cb2fa8ece0a093223bfc4" dependencies = [ "bytes", "either", "futures", "futures-timer", "getrandom 0.2.16", - "libp2p-allow-block-list 0.6.0", - "libp2p-connection-limits 0.6.0", - "libp2p-core 0.43.2", - "libp2p-dns 0.44.0", + "libp2p-allow-block-list", + "libp2p-connection-limits", + "libp2p-core", + "libp2p-dns", "libp2p-gossipsub", - "libp2p-identify 0.47.0", + "libp2p-identify", "libp2p-identity", - "libp2p-kad 0.48.0", - "libp2p-mdns 0.48.0", - "libp2p-metrics 0.17.0", - "libp2p-noise 0.46.1", - "libp2p-ping 0.47.0", + "libp2p-kad", + "libp2p-mdns", + "libp2p-metrics", + "libp2p-noise", + "libp2p-ping", "libp2p-plaintext", - "libp2p-quic 0.13.0", - "libp2p-request-response 0.29.0", - "libp2p-swarm 0.47.0", - "libp2p-tcp 0.44.0", - "libp2p-tls 0.6.2", - "libp2p-upnp 0.5.0", - "libp2p-yamux 0.47.0", + "libp2p-quic", + "libp2p-request-response", + "libp2p-swarm", + "libp2p-tcp", + "libp2p-tls", + "libp2p-upnp", + "libp2p-websocket", + "libp2p-yamux", "multiaddr 0.18.2", "pin-project", "rw-stream-sink", - "thiserror 2.0.17", + "thiserror 1.0.69", ] [[package]] name = "libp2p-allow-block-list" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55b46558c5c0bf99d3e2a1a38fd54ff5476ca66dd1737b12466a1824dd219311" +checksum = "d1027ccf8d70320ed77e984f273bc8ce952f623762cb9bf2d126df73caef8041" dependencies = [ - "libp2p-core 0.40.1", + "libp2p-core", "libp2p-identity", - "libp2p-swarm 0.43.7", + "libp2p-swarm", "void", ] -[[package]] -name = "libp2p-allow-block-list" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16ccf824ee859ca83df301e1c0205270206223fd4b1f2e512a693e1912a8f4a" -dependencies = [ - "libp2p-core 0.43.2", - "libp2p-identity", - "libp2p-swarm 0.47.0", -] - [[package]] name = "libp2p-connection-limits" -version = "0.2.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5107ad45cb20b2f6c3628c7b6014b996fcb13a88053f4569c872c6e30abf58" +checksum = "8d003540ee8baef0d254f7b6bfd79bac3ddf774662ca0abf69186d517ef82ad8" dependencies = [ - "libp2p-core 0.40.1", + "libp2p-core", "libp2p-identity", - "libp2p-swarm 0.43.7", + "libp2p-swarm", "void", ] -[[package]] -name = "libp2p-connection-limits" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18b8b607cf3bfa2f8c57db9c7d8569a315d5cc0a282e6bfd5ebfc0a9840b2a0" -dependencies = [ - "libp2p-core 0.43.2", - "libp2p-identity", - "libp2p-swarm 0.47.0", -] - [[package]] name = "libp2p-core" -version = "0.40.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd44289ab25e4c9230d9246c475a22241e301b23e8f4061d3bdef304a1a99713" +checksum = "a61f26c83ed111104cd820fe9bc3aaabbac5f1652a1d213ed6e900b7918a1298" dependencies = [ "either", "fnv", "futures", "futures-timer", - "instant", "libp2p-identity", - "log", "multiaddr 0.18.2", - "multihash 0.19.3", + "multihash 0.19.5", "multistream-select", "once_cell", "parking_lot 0.12.5", @@ -10196,61 +10044,22 @@ dependencies = [ "rw-stream-sink", "smallvec", "thiserror 1.0.69", - "unsigned-varint 0.7.2", - "void", -] - -[[package]] -name = "libp2p-core" -version = "0.43.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "249128cd37a2199aff30a7675dffa51caf073b51aa612d2f544b19932b9aebca" -dependencies = [ - "either", - "fnv", - "futures", - "futures-timer", - "libp2p-identity", - "multiaddr 0.18.2", - "multihash 0.19.3", - "multistream-select", - "parking_lot 0.12.5", - "pin-project", - "quick-protobuf", - "rand 0.8.5", - "rw-stream-sink", - "thiserror 2.0.17", "tracing", "unsigned-varint 0.8.0", + "void", "web-time", ] [[package]] name = "libp2p-dns" -version = "0.40.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a18db73084b4da2871438f6239fef35190b05023de7656e877c18a00541a3b" -dependencies = [ - "async-trait", - "futures", - "libp2p-core 0.40.1", - "libp2p-identity", - "log", - "parking_lot 0.12.5", - "smallvec", - "trust-dns-resolver", -] - -[[package]] -name = "libp2p-dns" -version = "0.44.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b770c1c8476736ca98c578cba4b505104ff8e842c2876b528925f9766379f9a" +checksum = "97f37f30d5c7275db282ecd86e54f29dd2176bd3ac656f06abf43bedb21eb8bd" dependencies = [ "async-trait", "futures", - "hickory-resolver", - "libp2p-core 0.43.2", + "hickory-resolver 0.24.4", + "libp2p-core", "libp2p-identity", "parking_lot 0.12.5", "smallvec", @@ -10259,11 +10068,10 @@ dependencies = [ [[package]] name = "libp2p-gossipsub" -version = "0.49.4" +version = "0.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a538e571cd38f504f761c61b8f79127489ea7a7d6f05c41ca15d31ffb5726326" +checksum = "b4e830fdf24ac8c444c12415903174d506e1e077fbe3875c404a78c5935a8543" dependencies = [ - "async-channel 2.5.0", "asynchronous-codec 0.7.0", "base64 0.22.1", "byteorder", @@ -10271,66 +10079,45 @@ dependencies = [ "either", "fnv", "futures", - "futures-timer", + "futures-ticker", "getrandom 0.2.16", - "hashlink 0.9.1", "hex_fmt", - "libp2p-core 0.43.2", + "libp2p-core", "libp2p-identity", - "libp2p-swarm 0.47.0", - "prometheus-client 0.23.1", + "libp2p-swarm", + "prometheus-client", "quick-protobuf", - "quick-protobuf-codec 0.3.1", + "quick-protobuf-codec", "rand 0.8.5", "regex", - "serde", "sha2 0.10.9", + "smallvec", "tracing", + "void", "web-time", ] [[package]] name = "libp2p-identify" -version = "0.43.1" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a96638a0a176bec0a4bcaebc1afa8cf909b114477209d7456ade52c61cd9cd" +checksum = "1711b004a273be4f30202778856368683bd9a83c4c7dcc8f848847606831a4e3" dependencies = [ - "asynchronous-codec 0.6.2", + "asynchronous-codec 0.7.0", "either", "futures", - "futures-bounded 0.1.0", + "futures-bounded", "futures-timer", - "libp2p-core 0.40.1", + "libp2p-core", "libp2p-identity", - "libp2p-swarm 0.43.7", - "log", + "libp2p-swarm", "lru 0.12.5", "quick-protobuf", - "quick-protobuf-codec 0.2.0", + "quick-protobuf-codec", "smallvec", "thiserror 1.0.69", - "void", -] - -[[package]] -name = "libp2p-identify" -version = "0.47.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab792a8b68fdef443a62155b01970c81c3aadab5e659621b063ef252a8e65e8" -dependencies = [ - "asynchronous-codec 0.7.0", - "either", - "futures", - "futures-bounded 0.2.4", - "futures-timer", - "libp2p-core 0.43.2", - "libp2p-identity", - "libp2p-swarm 0.47.0", - "quick-protobuf", - "quick-protobuf-codec 0.3.1", - "smallvec", - "thiserror 2.0.17", "tracing", + "void", ] [[package]] @@ -10340,15 +10127,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0c7892c221730ba55f7196e98b0b8ba5e04b4155651736036628e9f73ed6fc3" dependencies = [ "asn1_der", - "bs58 0.5.1", + "bs58", "ed25519-dalek", "hkdf", "k256", - "multihash 0.19.3", - "p256", + "multihash 0.19.5", "quick-protobuf", "rand 0.8.5", - "sec1", "serde", "sha2 0.10.9", "thiserror 2.0.17", @@ -10358,151 +10143,87 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.44.6" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ea178dabba6dde6ffc260a8e0452ccdc8f79becf544946692fff9d412fc29d" +checksum = "ced237d0bd84bbebb7c2cad4c073160dacb4fe40534963c32ed6d4c6bb7702a3" dependencies = [ "arrayvec 0.7.6", - "asynchronous-codec 0.6.2", + "asynchronous-codec 0.7.0", "bytes", "either", "fnv", "futures", + "futures-bounded", "futures-timer", - "instant", - "libp2p-core 0.40.1", + "libp2p-core", "libp2p-identity", - "libp2p-swarm 0.43.7", - "log", + "libp2p-swarm", "quick-protobuf", - "quick-protobuf-codec 0.2.0", + "quick-protobuf-codec", "rand 0.8.5", "sha2 0.10.9", "smallvec", "thiserror 1.0.69", + "tracing", "uint 0.9.5", - "unsigned-varint 0.7.2", "void", -] - -[[package]] -name = "libp2p-kad" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d3fd632a5872ec804d37e7413ceea20588f69d027a0fa3c46f82574f4dee60" -dependencies = [ - "asynchronous-codec 0.7.0", - "bytes", - "either", - "fnv", - "futures", - "futures-bounded 0.2.4", - "futures-timer", - "libp2p-core 0.43.2", - "libp2p-identity", - "libp2p-swarm 0.47.0", - "quick-protobuf", - "quick-protobuf-codec 0.3.1", - "rand 0.8.5", - "serde", - "sha2 0.10.9", - "smallvec", - "thiserror 2.0.17", - "tracing", - "uint 0.10.0", "web-time", ] [[package]] name = "libp2p-mdns" -version = "0.44.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a2567c305232f5ef54185e9604579a894fd0674819402bb0ac0246da82f52a" +checksum = "14b8546b6644032565eb29046b42744aee1e9f261ed99671b2c93fb140dba417" dependencies = [ "data-encoding", "futures", + "hickory-proto 0.24.4", "if-watch", - "libp2p-core 0.40.1", - "libp2p-identity", - "libp2p-swarm 0.43.7", - "log", - "rand 0.8.5", - "smallvec", - "socket2 0.5.10", - "tokio", - "trust-dns-proto 0.22.0", - "void", -] - -[[package]] -name = "libp2p-mdns" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66872d0f1ffcded2788683f76931be1c52e27f343edb93bc6d0bcd8887be443" -dependencies = [ - "futures", - "hickory-proto", - "if-watch", - "libp2p-core 0.43.2", + "libp2p-core", "libp2p-identity", - "libp2p-swarm 0.47.0", + "libp2p-swarm", "rand 0.8.5", "smallvec", "socket2 0.5.10", "tokio", "tracing", + "void", ] [[package]] name = "libp2p-metrics" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239ba7d28f8d0b5d77760dc6619c05c7e88e74ec8fbbe97f856f20a56745e620" -dependencies = [ - "instant", - "libp2p-core 0.40.1", - "libp2p-identify 0.43.1", - "libp2p-identity", - "libp2p-kad 0.44.6", - "libp2p-ping 0.43.1", - "libp2p-swarm 0.43.7", - "once_cell", - "prometheus-client 0.21.2", -] - -[[package]] -name = "libp2p-metrics" -version = "0.17.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "805a555148522cb3414493a5153451910cb1a146c53ffbf4385708349baf62b7" +checksum = "77ebafa94a717c8442d8db8d3ae5d1c6a15e30f2d347e0cd31d057ca72e42566" dependencies = [ "futures", - "libp2p-core 0.43.2", + "libp2p-core", "libp2p-gossipsub", - "libp2p-identify 0.47.0", + "libp2p-identify", "libp2p-identity", - "libp2p-kad 0.48.0", - "libp2p-ping 0.47.0", - "libp2p-swarm 0.47.0", + "libp2p-kad", + "libp2p-ping", + "libp2p-swarm", "pin-project", - "prometheus-client 0.23.1", + "prometheus-client", "web-time", ] [[package]] name = "libp2p-noise" -version = "0.43.2" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2eeec39ad3ad0677551907dd304b2f13f17208ccebe333bef194076cd2e8921" +checksum = "36b137cb1ae86ee39f8e5d6245a296518912014eaa87427d24e6ff58cfc1b28c" dependencies = [ + "asynchronous-codec 0.7.0", "bytes", "curve25519-dalek", "futures", - "libp2p-core 0.40.1", + "libp2p-core", "libp2p-identity", - "log", "multiaddr 0.18.2", - "multihash 0.19.3", + "multihash 0.19.5", "once_cell", "quick-protobuf", "rand 0.8.5", @@ -10510,28 +10231,6 @@ dependencies = [ "snow", "static_assertions", "thiserror 1.0.69", - "x25519-dalek", - "zeroize", -] - -[[package]] -name = "libp2p-noise" -version = "0.46.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc73eacbe6462a0eb92a6527cac6e63f02026e5407f8831bde8293f19217bfbf" -dependencies = [ - "asynchronous-codec 0.7.0", - "bytes", - "futures", - "libp2p-core 0.43.2", - "libp2p-identity", - "multiaddr 0.18.2", - "multihash 0.19.3", - "quick-protobuf", - "rand 0.8.5", - "snow", - "static_assertions", - "thiserror 2.0.17", "tracing", "x25519-dalek", "zeroize", @@ -10539,281 +10238,151 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.43.1" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e702d75cd0827dfa15f8fd92d15b9932abe38d10d21f47c50438c71dd1b5dae3" +checksum = "005a34420359223b974ee344457095f027e51346e992d1e0dcd35173f4cdd422" dependencies = [ "either", "futures", "futures-timer", - "instant", - "libp2p-core 0.40.1", - "libp2p-identity", - "libp2p-swarm 0.43.7", - "log", - "rand 0.8.5", - "void", -] - -[[package]] -name = "libp2p-ping" -version = "0.47.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74bb7fcdfd9fead4144a3859da0b49576f171a8c8c7c0bfc7c541921d25e60d3" -dependencies = [ - "futures", - "futures-timer", - "libp2p-core 0.43.2", + "libp2p-core", "libp2p-identity", - "libp2p-swarm 0.47.0", + "libp2p-swarm", "rand 0.8.5", "tracing", + "void", "web-time", ] [[package]] name = "libp2p-plaintext" -version = "0.43.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e659439578fc6d305da8303834beb9d62f155f40e7f5b9d81c9f2b2c69d1926" +checksum = "5b63d926c6be56a2489e0e7316b17fe95a70bc5c4f3e85740bb3e67c0f3c6a44" dependencies = [ "asynchronous-codec 0.7.0", "bytes", "futures", - "libp2p-core 0.43.2", + "libp2p-core", "libp2p-identity", "quick-protobuf", - "quick-protobuf-codec 0.3.1", + "quick-protobuf-codec", "tracing", ] [[package]] name = "libp2p-quic" -version = "0.9.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "130d451d83f21b81eb7b35b360bc7972aeafb15177784adc56528db082e6b927" +checksum = "46352ac5cd040c70e88e7ff8257a2ae2f891a4076abad2c439584a31c15fd24e" dependencies = [ "bytes", "futures", "futures-timer", "if-watch", - "libp2p-core 0.40.1", + "libp2p-core", "libp2p-identity", - "libp2p-tls 0.2.1", - "log", + "libp2p-tls", "parking_lot 0.12.5", - "quinn 0.10.2", - "rand 0.8.5", - "ring 0.16.20", - "rustls 0.21.12", - "socket2 0.5.10", - "thiserror 1.0.69", - "tokio", -] - -[[package]] -name = "libp2p-quic" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc448b2de9f4745784e3751fe8bc6c473d01b8317edd5ababcb0dec803d843f" -dependencies = [ - "futures", - "futures-timer", - "if-watch", - "libp2p-core 0.43.2", - "libp2p-identity", - "libp2p-tls 0.6.2", - "quinn 0.11.9", + "quinn", "rand 0.8.5", "ring 0.17.14", - "rustls 0.23.36", + "rustls", "socket2 0.5.10", - "thiserror 2.0.17", + "thiserror 1.0.69", "tokio", "tracing", ] [[package]] name = "libp2p-request-response" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e3b4d67870478db72bac87bfc260ee6641d0734e0e3e275798f089c3fecfd4" -dependencies = [ - "async-trait", - "futures", - "instant", - "libp2p-core 0.40.1", - "libp2p-identity", - "libp2p-swarm 0.43.7", - "log", - "rand 0.8.5", - "smallvec", - "void", -] - -[[package]] -name = "libp2p-request-response" -version = "0.29.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9f1cca83488b90102abac7b67d5c36fc65bc02ed47620228af7ed002e6a1478" +checksum = "1356c9e376a94a75ae830c42cdaea3d4fe1290ba409a22c809033d1b7dcab0a6" dependencies = [ "async-trait", - "cbor4ii", - "futures", - "futures-bounded 0.2.4", - "libp2p-core 0.43.2", - "libp2p-identity", - "libp2p-swarm 0.47.0", - "rand 0.8.5", - "serde", - "smallvec", - "tracing", -] - -[[package]] -name = "libp2p-scatter" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea402c419f99e6013d5b12f97c5a1a1abe4aca285844b01b0ed96deab11f0b6e" -dependencies = [ - "bytes", - "fnv", - "futures", - "libp2p 0.56.0", - "prometheus-client 0.23.1", - "tracing", - "unsigned-varint 0.8.0", -] - -[[package]] -name = "libp2p-stream" -version = "0.4.0-alpha" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6bd8025c80205ec2810cfb28b02f362ab48a01bee32c50ab5f12761e033464" -dependencies = [ - "futures", - "libp2p-core 0.43.2", - "libp2p-identity", - "libp2p-swarm 0.47.0", - "rand 0.8.5", - "tracing", -] - -[[package]] -name = "libp2p-swarm" -version = "0.43.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "580189e0074af847df90e75ef54f3f30059aedda37ea5a1659e8b9fca05c0141" -dependencies = [ - "either", - "fnv", "futures", + "futures-bounded", "futures-timer", - "instant", - "libp2p-core 0.40.1", + "libp2p-core", "libp2p-identity", - "libp2p-swarm-derive 0.33.0", - "log", - "multistream-select", - "once_cell", + "libp2p-swarm", "rand 0.8.5", "smallvec", - "tokio", + "tracing", "void", + "web-time", ] [[package]] name = "libp2p-swarm" -version = "0.47.0" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aa762e5215919a34e31c35d4b18bf2e18566ecab7f8a3d39535f4a3068f8b62" +checksum = "d7dd6741793d2c1fb2088f67f82cf07261f25272ebe3c0b0c311e0c6b50e851a" dependencies = [ + "async-std", "either", "fnv", "futures", "futures-timer", - "libp2p-core 0.43.2", + "libp2p-core", "libp2p-identity", - "libp2p-swarm-derive 0.35.1", + "libp2p-swarm-derive", "lru 0.12.5", "multistream-select", + "once_cell", "rand 0.8.5", "smallvec", "tokio", "tracing", + "void", "web-time", ] [[package]] name = "libp2p-swarm-derive" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4d5ec2a3df00c7836d7696c136274c9c59705bac69133253696a6c932cd1d74" -dependencies = [ - "heck 0.4.1", - "proc-macro-warning 0.4.2", - "proc-macro2", - "quote", - "syn 2.0.114", -] - -[[package]] -name = "libp2p-swarm-derive" -version = "0.35.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd297cf53f0cb3dee4d2620bb319ae47ef27c702684309f682bdb7e55a18ae9c" +checksum = "206e0aa0ebe004d778d79fb0966aa0de996c19894e2c0605ba2f8524dd4443d8" dependencies = [ "heck 0.5.0", + "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "libp2p-swarm-test" -version = "0.6.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b149112570d507efe305838c7130835955a0b1147aa8051c1c3867a83175cf6" +checksum = "ea4e1d1d92421dc4c90cad42e3cd24f50fd210191c9f126d41bd483a09567f67" dependencies = [ "async-trait", "futures", "futures-timer", - "libp2p-core 0.43.2", + "libp2p-core", "libp2p-identity", "libp2p-plaintext", - "libp2p-swarm 0.47.0", - "libp2p-tcp 0.44.0", - "libp2p-yamux 0.47.0", + "libp2p-swarm", + "libp2p-tcp", + "libp2p-yamux", + "rand 0.8.5", "tracing", ] [[package]] name = "libp2p-tcp" -version = "0.40.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b558dd40d1bcd1aaaed9de898e9ec6a436019ecc2420dd0016e712fbb61c5508" +checksum = "ad964f312c59dcfcac840acd8c555de8403e295d39edf96f5240048b5fcaa314" dependencies = [ + "async-io", "futures", "futures-timer", "if-watch", "libc", - "libp2p-core 0.40.1", + "libp2p-core", "libp2p-identity", - "log", - "socket2 0.5.10", - "tokio", -] - -[[package]] -name = "libp2p-tcp" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65b4e030c52c46c8d01559b2b8ca9b7c4185f10576016853129ca1fe5cd1a644" -dependencies = [ - "futures", - "futures-timer", - "if-watch", - "libc", - "libp2p-core 0.43.2", "socket2 0.5.10", "tokio", "tracing", @@ -10821,134 +10390,73 @@ dependencies = [ [[package]] name = "libp2p-tls" -version = "0.2.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8218d1d5482b122ccae396bbf38abdcb283ecc96fa54760e1dfd251f0546ac61" +checksum = "47b23dddc2b9c355f73c1e36eb0c3ae86f7dc964a3715f0731cfad352db4d847" dependencies = [ "futures", - "futures-rustls 0.24.0", - "libp2p-core 0.40.1", + "futures-rustls", + "libp2p-core", "libp2p-identity", - "rcgen 0.10.0", - "ring 0.16.20", - "rustls 0.21.12", + "rcgen", + "ring 0.17.14", + "rustls", "rustls-webpki 0.101.7", "thiserror 1.0.69", - "x509-parser 0.15.1", - "yasna", -] - -[[package]] -name = "libp2p-tls" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ff65a82e35375cbc31ebb99cacbbf28cb6c4fefe26bf13756ddcf708d40080" -dependencies = [ - "futures", - "futures-rustls 0.26.0", - "libp2p-core 0.43.2", - "libp2p-identity", - "rcgen 0.13.2", - "ring 0.17.14", - "rustls 0.23.36", - "rustls-webpki 0.103.8", - "thiserror 2.0.17", - "x509-parser 0.17.0", + "x509-parser 0.16.0", "yasna", ] [[package]] name = "libp2p-upnp" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82775a47b34f10f787ad3e2a22e2c1541e6ebef4fe9f28f3ac553921554c94c1" -dependencies = [ - "futures", - "futures-timer", - "igd-next 0.14.3", - "libp2p-core 0.40.1", - "libp2p-swarm 0.43.7", - "log", - "tokio", - "void", -] - -[[package]] -name = "libp2p-upnp" -version = "0.5.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4757e65fe69399c1a243bbb90ec1ae5a2114b907467bf09f3575e899815bb8d3" +checksum = "01bf2d1b772bd3abca049214a3304615e6a36fa6ffc742bdd1ba774486200b8f" dependencies = [ "futures", "futures-timer", - "igd-next 0.16.2", - "libp2p-core 0.43.2", - "libp2p-swarm 0.47.0", + "igd-next", + "libp2p-core", + "libp2p-swarm", "tokio", "tracing", -] - -[[package]] -name = "libp2p-wasm-ext" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e5d8e3a9e07da0ef5b55a9f26c009c8fb3c725d492d8bb4b431715786eea79c" -dependencies = [ - "futures", - "js-sys", - "libp2p-core 0.40.1", - "send_wrapper 0.6.0", - "wasm-bindgen", - "wasm-bindgen-futures", + "void", ] [[package]] name = "libp2p-websocket" -version = "0.42.2" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004ee9c4a4631435169aee6aad2f62e3984dc031c43b6d29731e8e82a016c538" +checksum = "888b2ff2e5d8dcef97283daab35ad1043d18952b65e05279eecbe02af4c6e347" dependencies = [ "either", "futures", - "futures-rustls 0.24.0", - "libp2p-core 0.40.1", + "futures-rustls", + "libp2p-core", "libp2p-identity", - "log", "parking_lot 0.12.5", "pin-project-lite", "rw-stream-sink", "soketto", "thiserror 1.0.69", + "tracing", "url", "webpki-roots 0.25.4", ] [[package]] name = "libp2p-yamux" -version = "0.44.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eedcb62824c4300efb9cfd4e2a6edaf3ca097b9e68b36dabe45a44469fd6a85" -dependencies = [ - "futures", - "libp2p-core 0.40.1", - "log", - "thiserror 1.0.69", - "yamux 0.12.1", -] - -[[package]] -name = "libp2p-yamux" -version = "0.47.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f15df094914eb4af272acf9adaa9e287baa269943f32ea348ba29cfb9bfc60d8" +checksum = "788b61c80789dba9760d8c669a5bedb642c8267555c803fabd8396e4ca5c5882" dependencies = [ "either", "futures", - "libp2p-core 0.43.2", - "thiserror 2.0.17", + "libp2p-core", + "thiserror 1.0.69", "tracing", "yamux 0.12.1", - "yamux 0.13.8", + "yamux 0.13.10", ] [[package]] @@ -10957,21 +10465,20 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "libc", "redox_syscall 0.7.0", ] [[package]] name = "librocksdb-sys" -version = "0.11.0+8.1.1" +version = "0.17.3+10.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" +checksum = "cef2a00ee60fe526157c9023edab23943fae1ce2ab6f4abb2a807c1746835de9" dependencies = [ "bindgen", "bzip2-sys", "cc", - "glob", "libc", "libz-sys", "tikv-jemalloc-sys", @@ -11116,55 +10623,50 @@ checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "litep2p" -version = "0.6.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f46c51c205264b834ceed95c8b195026e700494bc3991aaba3b4ea9e20626d9" +checksum = "cbf3924cf539a761465543592b34c4198d60db2cda16594769edd43451e5ab41" dependencies = [ "async-trait", - "bs58 0.4.0", + "bs58", "bytes", - "cid 0.10.1", + "cid", "ed25519-dalek", + "enum-display", "futures", "futures-timer", - "hex-literal", + "hickory-resolver 0.25.2", "indexmap 2.14.0", + "ip_network", "libc", - "mockall 0.12.1", + "mockall", "multiaddr 0.17.1", "multihash 0.17.0", "network-interface", - "nohash-hasher", "parking_lot 0.12.5", "pin-project", - "prost 0.12.6", - "prost-build 0.11.9", - "quinn 0.9.4", + "prost 0.13.5", + "prost-build 0.14.4", "rand 0.8.5", - "rcgen 0.10.0", - "ring 0.16.20", - "rustls 0.20.9", + "ring 0.17.14", "serde", "sha2 0.10.9", "simple-dns", "smallvec", "snow", "socket2 0.5.10", - "static_assertions", - "str0m", - "thiserror 1.0.69", + "thiserror 2.0.17", "tokio", "tokio-stream", - "tokio-tungstenite 0.20.1", + "tokio-tungstenite 0.27.0", "tokio-util", "tracing", - "trust-dns-resolver", - "uint 0.9.5", + "uint 0.10.0", "unsigned-varint 0.8.0", "url", - "webpki", "x25519-dalek", - "x509-parser 0.16.0", + "x509-parser 0.17.0", + "yamux 0.13.10", "yasna", "zeroize", ] @@ -11181,47 +10683,16 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "logos" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154" -dependencies = [ - "logos-derive", -] - -[[package]] -name = "logos-codegen" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "192a3a2b90b0c05b27a0b2c43eecdb7c415e29243acc3f89cc8247a5b693045c" -dependencies = [ - "beef", - "fnv", - "lazy_static", - "proc-macro2", - "quote", - "regex-syntax", - "rustc_version 0.4.1", - "syn 2.0.114", + "scopeguard", ] [[package]] -name = "logos-derive" -version = "0.15.1" +name = "log" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" dependencies = [ - "logos-codegen", + "value-bag", ] [[package]] @@ -11237,6 +10708,15 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lru" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +dependencies = [ + "hashbrown 0.12.3", +] + [[package]] name = "lru" version = "0.12.5" @@ -11382,19 +10862,13 @@ dependencies = [ [[package]] name = "matchers" -version = "0.2.0" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "matrixmultiply" version = "0.3.10" @@ -11449,11 +10923,13 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.32.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +checksum = "7e300c54e3239a86f9c61cc63ab0f03862eb40b1c6e065dc6fd6ceaeff6da93d" dependencies = [ + "foldhash 0.1.5", "hash-db", + "hashbrown 0.15.5", ] [[package]] @@ -11494,7 +10970,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5312e9ba3771cfa961b585728215e3d972c950a3eed9252aa093d6301277e8" dependencies = [ - "ahash", + "ahash 0.8.12", "portable-atomic", ] @@ -11545,28 +11021,6 @@ dependencies = [ "sketches-ddsketch", ] -[[package]] -name = "miette" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" -dependencies = [ - "cfg-if", - "miette-derive", - "unicode-width 0.1.14", -] - -[[package]] -name = "miette-derive" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", -] - [[package]] name = "mimalloc" version = "0.1.48" @@ -11633,7 +11087,7 @@ dependencies = [ "c2-chacha", "curve25519-dalek", "either", - "hashlink 0.8.4", + "hashlink", "lioness", "log", "parking_lot 0.12.5", @@ -11647,51 +11101,23 @@ dependencies = [ [[package]] name = "mockall" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96" -dependencies = [ - "cfg-if", - "downcast", - "fragile", - "lazy_static", - "mockall_derive 0.11.4", - "predicates 2.1.5", - "predicates-tree", -] - -[[package]] -name = "mockall" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" dependencies = [ "cfg-if", "downcast", "fragile", - "lazy_static", - "mockall_derive 0.12.1", - "predicates 3.1.3", + "mockall_derive", + "predicates", "predicates-tree", ] [[package]] name = "mockall_derive" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" -dependencies = [ - "cfg-if", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "mockall_derive" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" dependencies = [ "cfg-if", "proc-macro2", @@ -11752,7 +11178,7 @@ dependencies = [ "data-encoding", "libp2p-identity", "multibase", - "multihash 0.19.3", + "multihash 0.19.5", "percent-encoding", "serde", "static_assertions", @@ -11779,25 +11205,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" dependencies = [ "blake2b_simd", - "blake2s_simd", - "blake3", - "core2", - "digest 0.10.7", - "multihash-derive", - "sha2 0.10.9", - "sha3", - "unsigned-varint 0.7.2", -] - -[[package]] -name = "multihash" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" -dependencies = [ - "blake2b_simd", - "blake2s_simd", - "blake3", "core2", "digest 0.10.7", "multihash-derive", @@ -11808,12 +11215,10 @@ dependencies = [ [[package]] name = "multihash" -version = "0.19.3" +version = "0.19.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b430e7953c29dd6a09afc29ff0bb69c6e306329ee6794700aee27b76a1aea8d" +checksum = "577c63b00ad74d57e8c9aa870b5fccebf2fd64a308a5aee9f1bb88e4aea19447" dependencies = [ - "core2", - "serde", "unsigned-varint 0.8.0", ] @@ -11831,12 +11236,6 @@ dependencies = [ "synstructure 0.12.6", ] -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - [[package]] name = "multimap" version = "0.10.1" @@ -11888,6 +11287,12 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" + [[package]] name = "native-tls" version = "0.2.14" @@ -11962,6 +11367,7 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23" dependencies = [ + "async-io", "bytes", "futures", "libc", @@ -11971,13 +11377,13 @@ dependencies = [ [[package]] name = "network-interface" -version = "1.1.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a43439bf756eed340bdf8feba761e2d50c7d47175d87545cd5cbe4a137c4d1" +checksum = "4ddcb8865ad3d9950f22f42ffa0ef0aecbfbf191867b3122413602b0a360b2a6" dependencies = [ "cc", "libc", - "thiserror 1.0.69", + "thiserror 2.0.17", "winapi", ] @@ -12055,6 +11461,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + [[package]] name = "ntest" version = "0.9.5" @@ -12090,11 +11505,12 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.50.3" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "windows-sys 0.61.2", + "overload", + "winapi", ] [[package]] @@ -12276,15 +11692,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "oid-registry" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" -dependencies = [ - "asn1-rs 0.5.2", -] - [[package]] name = "oid-registry" version = "0.7.1" @@ -12343,7 +11750,7 @@ version = "0.10.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "cfg-if", "foreign-types", "libc", @@ -12375,15 +11782,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" -[[package]] -name = "openssl-src" -version = "300.5.4+3.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72" -dependencies = [ - "cc", -] - [[package]] name = "openssl-sys" version = "0.9.114" @@ -12392,7 +11790,6 @@ checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", - "openssl-src", "pkg-config", "vcpkg", ] @@ -12403,6 +11800,39 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "orchestra" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19051f0b0512402f5d52d6776999f55996f01887396278aeeccbbdfbc83eef2d" +dependencies = [ + "async-trait", + "dyn-clonable", + "futures", + "futures-timer", + "orchestra-proc-macro", + "pin-project", + "prioritized-metered-channel", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "orchestra-proc-macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43dfaf083aef571385fccfdc3a2f8ede8d0a1863160455d4f2b014d8f7d04a3f" +dependencies = [ + "expander", + "indexmap 2.14.0", + "itertools 0.11.0", + "petgraph 0.6.5", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ordered-float" version = "2.10.1" @@ -12419,16 +11849,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] -name = "p256" -version = "0.13.2" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2 0.10.9", -] +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "page_size" @@ -12440,10 +11864,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "pallet-asset-conversion" +version = "28.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", +] + [[package]] name = "pallet-authority-discovery" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support", "frame-system", @@ -12457,8 +11899,8 @@ dependencies = [ [[package]] name = "pallet-authorship" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support", "frame-system", @@ -12470,8 +11912,8 @@ dependencies = [ [[package]] name = "pallet-babe" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -12493,8 +11935,8 @@ dependencies = [ [[package]] name = "pallet-bags-list" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "aquamarine", "docify", @@ -12514,8 +11956,8 @@ dependencies = [ [[package]] name = "pallet-balances" -version = "39.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "47.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "docify", "frame-benchmarking", @@ -12524,13 +11966,14 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", + "sp-core", "sp-runtime", ] [[package]] name = "pallet-bounties" -version = "37.0.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -12544,10 +11987,28 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "pallet-broker" +version = "0.25.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "bitvec", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-runtime", +] + [[package]] name = "pallet-child-bounties" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -12564,8 +12025,8 @@ dependencies = [ [[package]] name = "pallet-conviction-voting" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "assert_matches", "frame-benchmarking", @@ -12580,15 +12041,14 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-election-provider-support", "frame-support", "frame-system", "log", - "pallet-election-provider-support-benchmarking", "parity-scale-codec", "rand 0.8.5", "scale-info", @@ -12600,19 +12060,6 @@ dependencies = [ "strum 0.26.3", ] -[[package]] -name = "pallet-election-provider-support-benchmarking" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" -dependencies = [ - "frame-benchmarking", - "frame-election-provider-support", - "frame-system", - "parity-scale-codec", - "sp-npos-elections", - "sp-runtime", -] - [[package]] name = "pallet-gear" version = "2.0.0" @@ -12695,7 +12142,7 @@ dependencies = [ "pallet-gear-voucher", "pallet-timestamp", "parity-scale-codec", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "rand 0.8.5", "rand_pcg", "scale-info", @@ -12725,7 +12172,7 @@ dependencies = [ "pallet-authorship", "pallet-balances", "parity-scale-codec", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "scale-info", "sp-io", "sp-runtime", @@ -12770,7 +12217,7 @@ dependencies = [ "pallet-staking", "pallet-timestamp", "parity-scale-codec", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "scale-info", "sha2 0.10.9", "sp-core", @@ -12809,7 +12256,7 @@ dependencies = [ name = "pallet-gear-eth-bridge" version = "2.0.0" dependencies = [ - "binary-merkle-tree", + "binary-merkle-tree 16.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "bp-header-chain", "builtins-common", "frame-benchmarking", @@ -12851,7 +12298,7 @@ dependencies = [ name = "pallet-gear-eth-bridge-primitives" version = "2.0.0" dependencies = [ - "binary-merkle-tree", + "binary-merkle-tree 16.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gear-workspace-hack", "gprimitives", "parity-scale-codec", @@ -12866,7 +12313,7 @@ dependencies = [ "gear-workspace-hack", "jsonrpsee", "pallet-gear-eth-bridge-rpc-runtime-api", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "sp-api", "sp-blockchain", "sp-runtime", @@ -12895,7 +12342,7 @@ dependencies = [ "pallet-balances", "pallet-gear-messenger", "parity-scale-codec", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "scale-info", "sp-io", "sp-runtime", @@ -12917,7 +12364,7 @@ dependencies = [ "pallet-balances", "pallet-gear-gas", "parity-scale-codec", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "scale-info", "sp-io", "sp-runtime", @@ -12948,7 +12395,7 @@ dependencies = [ "pallet-timestamp", "pallet-transaction-payment", "parity-scale-codec", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "scale-info", "sp-io", "sp-runtime", @@ -13120,7 +12567,7 @@ dependencies = [ "gear-workspace-hack", "pallet-balances", "parity-scale-codec", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "scale-info", "sp-core", "sp-io", @@ -13130,8 +12577,8 @@ dependencies = [ [[package]] name = "pallet-grandpa" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -13170,8 +12617,8 @@ dependencies = [ [[package]] name = "pallet-identity" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "enumflags2", "frame-benchmarking", @@ -13186,8 +12633,8 @@ dependencies = [ [[package]] name = "pallet-im-online" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -13203,25 +12650,71 @@ dependencies = [ "sp-staking", ] +[[package]] +name = "pallet-message-queue" +version = "49.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "environmental", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-weights", +] + +[[package]] +name = "pallet-migrations" +version = "16.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "polkadot-sdk-frame", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", +] + +[[package]] +name = "pallet-mmr" +version = "46.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "log", + "parity-scale-codec", + "polkadot-sdk-frame", + "scale-info", + "sp-mmr-primitives", +] + [[package]] name = "pallet-multisig" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", "log", "parity-scale-codec", + "polkadot-sdk-frame", "scale-info", - "sp-io", - "sp-runtime", ] [[package]] name = "pallet-nomination-pools" -version = "35.0.3" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "44.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support", "frame-system", @@ -13238,8 +12731,8 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" -version = "33.0.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "42.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "pallet-nomination-pools", "parity-scale-codec", @@ -13248,13 +12741,12 @@ dependencies = [ [[package]] name = "pallet-offences" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support", "frame-system", "log", - "pallet-balances", "parity-scale-codec", "scale-info", "serde", @@ -13264,8 +12756,8 @@ dependencies = [ [[package]] name = "pallet-preimage" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -13280,22 +12772,18 @@ dependencies = [ [[package]] name = "pallet-proxy" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", "parity-scale-codec", + "polkadot-sdk-frame", "scale-info", - "sp-io", - "sp-runtime", ] [[package]] name = "pallet-ranked-collective" -version = "38.2.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -13312,8 +12800,8 @@ dependencies = [ [[package]] name = "pallet-referenda" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "assert_matches", "frame-benchmarking", @@ -13330,8 +12818,8 @@ dependencies = [ [[package]] name = "pallet-scheduler" -version = "39.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "47.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "docify", "frame-benchmarking", @@ -13347,13 +12835,14 @@ dependencies = [ [[package]] name = "pallet-session" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-support", "frame-system", "impl-trait-for-tuples", "log", + "pallet-balances", "pallet-timestamp", "parity-scale-codec", "scale-info", @@ -13366,10 +12855,26 @@ dependencies = [ "sp-trie", ] +[[package]] +name = "pallet-session-benchmarking" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-session", + "pallet-staking", + "parity-scale-codec", + "rand 0.8.5", + "sp-runtime", + "sp-session", +] + [[package]] name = "pallet-staking" -version = "38.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -13390,8 +12895,8 @@ dependencies = [ [[package]] name = "pallet-staking-reward-fn" -version = "22.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "24.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "log", "sp-arithmetic", @@ -13399,8 +12904,8 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" -version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "31.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "sp-api", @@ -13409,8 +12914,8 @@ dependencies = [ [[package]] name = "pallet-sudo" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "docify", "frame-benchmarking", @@ -13424,8 +12929,8 @@ dependencies = [ [[package]] name = "pallet-timestamp" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "docify", "frame-benchmarking", @@ -13435,7 +12940,6 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-inherents", - "sp-io", "sp-runtime", "sp-storage", "sp-timestamp", @@ -13443,23 +12947,24 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" -version = "38.0.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", + "log", "parity-scale-codec", "scale-info", "serde", - "sp-core", "sp-io", "sp-runtime", ] [[package]] name = "pallet-transaction-payment-rpc" -version = "41.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "49.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -13474,8 +12979,8 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -13486,14 +12991,15 @@ dependencies = [ [[package]] name = "pallet-treasury" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "docify", "frame-benchmarking", "frame-support", "frame-system", "impl-trait-for-tuples", + "log", "pallet-balances", "parity-scale-codec", "scale-info", @@ -13504,8 +13010,8 @@ dependencies = [ [[package]] name = "pallet-utility" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -13519,8 +13025,8 @@ dependencies = [ [[package]] name = "pallet-vesting" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "frame-benchmarking", "frame-support", @@ -13533,16 +13039,12 @@ dependencies = [ [[package]] name = "pallet-whitelist" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", "parity-scale-codec", + "polkadot-sdk-frame", "scale-info", - "sp-api", - "sp-runtime", ] [[package]] @@ -13556,19 +13058,6 @@ dependencies = [ "unicode-width 0.1.14", ] -[[package]] -name = "parity-bip39" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" -dependencies = [ - "bitcoin_hashes 0.13.0", - "rand 0.8.5", - "rand_core 0.6.4", - "serde", - "unicode-normalization", -] - [[package]] name = "parity-db" version = "0.4.13" @@ -13724,21 +13213,6 @@ dependencies = [ "password-hash", ] -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "pem" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" -dependencies = [ - "base64 0.13.1", -] - [[package]] name = "pem" version = "3.0.6" @@ -13808,110 +13282,414 @@ dependencies = [ ] [[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset 0.4.2", + "indexmap 2.14.0", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset 0.5.7", + "hashbrown 0.15.5", + "indexmap 2.14.0", +] + +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version 0.4.1", +] + +[[package]] +name = "picosimd" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7823ffd00d2b55ebe51750a19f47f2a33cb1f1d135f5cba893379b81c4d44856" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "polkadot-ckb-merkle-mountain-range" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f70a16374b7a26b74bfb4788254f8fd64c3406034e81694142cf93f1dd59368f" +dependencies = [ + "cfg-if", + "itertools 0.10.5", +] + +[[package]] +name = "polkadot-core-primitives" +version = "22.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "polkadot-node-metrics" +version = "29.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "bs58", + "futures", + "futures-timer", + "parity-scale-codec", + "polkadot-primitives", + "prioritized-metered-channel", + "sc-cli", + "sc-service", + "sc-tracing", + "substrate-prometheus-endpoint", +] + +[[package]] +name = "polkadot-node-network-protocol" +version = "29.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "async-channel 1.9.0", + "async-trait", + "bitvec", + "derive_more 0.99.20", + "fatality", + "futures", + "hex", + "parity-scale-codec", + "polkadot-node-primitives", + "polkadot-primitives", + "rand 0.8.5", + "sc-authority-discovery", + "sc-network", + "sc-network-types", + "sp-runtime", + "strum 0.26.3", + "thiserror 1.0.69", + "tracing-gum", +] + +[[package]] +name = "polkadot-node-primitives" +version = "24.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "bitvec", + "bounded-vec", + "futures", + "futures-timer", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-primitives", + "sc-keystore", + "schnorrkel", + "serde", + "sp-application-crypto", + "sp-consensus-babe", + "sp-consensus-slots", + "sp-keystore", + "sp-maybe-compressed-blob", + "thiserror 1.0.69", + "zstd 0.12.4", +] + +[[package]] +name = "polkadot-node-subsystem-types" +version = "29.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "fixedbitset", - "indexmap 2.14.0", + "async-trait", + "derive_more 0.99.20", + "fatality", + "futures", + "orchestra", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-primitives", + "polkadot-statement-table", + "sc-client-api", + "sc-network", + "sc-network-types", + "sc-transaction-pool-api", + "smallvec", + "sp-api", + "sp-authority-discovery", + "sp-blockchain", + "sp-consensus-babe", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror 1.0.69", ] [[package]] -name = "pharos" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +name = "polkadot-overseer" +version = "29.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ + "async-trait", "futures", - "rustc_version 0.4.1", + "futures-timer", + "orchestra", + "polkadot-node-metrics", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-node-subsystem-types", + "polkadot-primitives", + "sc-client-api", + "sp-core", + "tikv-jemalloc-ctl", + "tracing-gum", ] [[package]] -name = "pin-project" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +name = "polkadot-parachain-primitives" +version = "21.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "pin-project-internal", + "array-bytes", + "bounded-collections", + "derive_more 0.99.20", + "parity-scale-codec", + "polkadot-core-primitives", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-weights", ] [[package]] -name = "pin-project-internal" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +name = "polkadot-primitives" +version = "23.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", + "bitvec", + "bounded-collections", + "hex-literal", + "log", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-authority-discovery", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-staking", + "sp-std", + "thiserror 1.0.69", ] [[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +name = "polkadot-runtime-metrics" +version = "26.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", + "bs58", + "frame-benchmarking", + "parity-scale-codec", + "polkadot-primitives", + "sp-tracing", ] [[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +name = "polkadot-runtime-parachains" +version = "25.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "der", - "spki", + "bitflags 1.3.2", + "bitvec", + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-authority-discovery", + "pallet-authorship", + "pallet-babe", + "pallet-balances", + "pallet-broker", + "pallet-message-queue", + "pallet-mmr", + "pallet-session", + "pallet-session-benchmarking", + "pallet-staking", + "pallet-timestamp", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-runtime-metrics", + "rand 0.8.5", + "rand_chacha 0.3.1", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-inherents", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", + "staging-xcm", + "staging-xcm-executor", + "static_assertions", ] [[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +name = "polkadot-sdk-frame" +version = "0.15.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", + "docify", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-api", + "sp-arithmetic", + "sp-block-builder", + "sp-consensus-aura", + "sp-consensus-grandpa", + "sp-core", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-keyring", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-storage", + "sp-transaction-pool", + "sp-version", ] [[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +name = "polkadot-statement-table" +version = "24.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "plotters-backend", + "parity-scale-codec", + "polkadot-primitives", + "tracing-gum", ] [[package]] @@ -13923,7 +13701,7 @@ dependencies = [ "libc", "log", "polkavm-assembler", - "polkavm-common", + "polkavm-common 0.9.0", "polkavm-linux-raw", ] @@ -13945,22 +13723,31 @@ dependencies = [ "log", ] +[[package]] +name = "polkavm-common" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0a3e43fa1a54b955a2f9422b1690c3cc29252ac8828c02a99d2370b9f2a188e" +dependencies = [ + "picosimd", +] + [[package]] name = "polkavm-derive" -version = "0.9.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +checksum = "c3d944b6b4e792c2a120232b52bd6f2c9dd3071d3f48462afb2b5d00cb9f7ac9" dependencies = [ "polkavm-derive-impl-macro", ] [[package]] name = "polkavm-derive-impl" -version = "0.9.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +checksum = "57c14b030150f81dfde110997b6fafc19741998130908fdab85f1a66bb735025" dependencies = [ - "polkavm-common", + "polkavm-common 0.31.0", "proc-macro2", "quote", "syn 2.0.114", @@ -13968,9 +13755,9 @@ dependencies = [ [[package]] name = "polkavm-derive-impl-macro" -version = "0.9.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +checksum = "f3fcadb13edfcc3b4046fcd2d292597782f5b7a2af140e6363fbf71fe196b425" dependencies = [ "polkavm-derive-impl", "syn 2.0.114", @@ -13986,7 +13773,7 @@ dependencies = [ "hashbrown 0.14.5", "log", "object 0.32.2", - "polkavm-common", + "polkavm-common 0.9.0", "regalloc2 0.9.3", "rustc-demangle", ] @@ -14085,20 +13872,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "predicates" -version = "2.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" -dependencies = [ - "difflib", - "float-cmp 0.9.0", - "itertools 0.10.5", - "normalize-line-endings", - "predicates-core", - "regex", -] - [[package]] name = "predicates" version = "3.1.3" @@ -14107,7 +13880,7 @@ checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" dependencies = [ "anstyle", "difflib", - "float-cmp 0.10.0", + "float-cmp", "normalize-line-endings", "predicates-core", "regex", @@ -14139,16 +13912,6 @@ dependencies = [ "yansi", ] -[[package]] -name = "prettyplease" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "prettyplease" version = "0.2.37" @@ -14159,15 +13922,6 @@ dependencies = [ "syn 2.0.114", ] -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - [[package]] name = "primitive-types" version = "0.12.2" @@ -14176,8 +13930,6 @@ checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec 0.6.0", - "impl-serde 0.4.0", - "scale-info", "uint 0.9.5", ] @@ -14189,11 +13941,28 @@ checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" dependencies = [ "fixed-hash", "impl-codec 0.7.1", + "impl-num-traits", "impl-serde 0.5.0", "scale-info", "uint 0.10.0", ] +[[package]] +name = "prioritized-metered-channel" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a172e6cc603231f2cf004232eabcecccc0da53ba576ab286ef7baa0cfc7927ad" +dependencies = [ + "coarsetime", + "crossbeam-queue", + "derive_more 0.99.20", + "futures", + "futures-timer", + "nanorand", + "thiserror 1.0.69", + "tracing", +] + [[package]] name = "proc-macro-crate" version = "1.1.3" @@ -14248,23 +14017,12 @@ dependencies = [ ] [[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.114", -] - -[[package]] -name = "proc-macro-warning" -version = "0.4.2" +name = "proc-macro-error2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ + "proc-macro-error-attr2", "proc-macro2", "quote", "syn 2.0.114", @@ -14320,21 +14078,9 @@ dependencies = [ [[package]] name = "prometheus-client" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c99afa9a01501019ac3a14d71d9f94050346f55ca471ce90c799a15c58f61e2" -dependencies = [ - "dtoa", - "itoa", - "parking_lot 0.12.5", - "prometheus-client-derive-encode", -] - -[[package]] -name = "prometheus-client" -version = "0.23.1" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf41c1a7c32ed72abe5082fb19505b969095c12da9f5732a4bc9878757fd087c" +checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", @@ -14361,27 +14107,17 @@ checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.10.0", + "bitflags 2.13.0", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", "rand_xorshift", - "regex-syntax", + "regex-syntax 0.8.8", "rusty-fork", "tempfile", "unarray", ] -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive 0.11.9", -] - [[package]] name = "prost" version = "0.12.6" @@ -14403,43 +14139,30 @@ dependencies = [ ] [[package]] -name = "prost-build" -version = "0.11.9" +name = "prost" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" dependencies = [ "bytes", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", - "log", - "multimap 0.8.3", - "petgraph", - "prettyplease 0.1.25", - "prost 0.11.9", - "prost-types 0.11.9", - "regex", - "syn 1.0.109", - "tempfile", - "which", + "prost-derive 0.14.4", ] [[package]] name = "prost-build" -version = "0.12.6" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "bytes", "heck 0.5.0", - "itertools 0.12.1", + "itertools 0.14.0", "log", - "multimap 0.10.1", + "multimap", "once_cell", - "petgraph", - "prettyplease 0.2.37", - "prost 0.12.6", - "prost-types 0.12.6", + "petgraph 0.6.5", + "prettyplease", + "prost 0.13.5", + "prost-types 0.13.5", "regex", "syn 2.0.114", "tempfile", @@ -14447,37 +14170,23 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.13.5" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" dependencies = [ "heck 0.5.0", - "itertools 0.13.0", + "itertools 0.14.0", "log", - "multimap 0.10.1", - "once_cell", - "petgraph", - "prettyplease 0.2.37", - "prost 0.13.5", - "prost-types 0.13.5", + "multimap", + "petgraph 0.8.3", + "prettyplease", + "prost 0.14.4", + "prost-types 0.14.4", "regex", "syn 2.0.114", "tempfile", ] -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "prost-derive" version = "0.12.6" @@ -14498,40 +14207,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.114", ] [[package]] -name = "prost-reflect" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37587d5a8a1b3dc9863403d084fc2254b91ab75a702207098837950767e2260b" -dependencies = [ - "logos", - "miette", - "prost 0.13.5", - "prost-types 0.13.5", -] - -[[package]] -name = "prost-types" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" -dependencies = [ - "prost 0.11.9", -] - -[[package]] -name = "prost-types" -version = "0.12.6" +name = "prost-derive" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ - "prost 0.12.6", + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.114", ] [[package]] @@ -14544,30 +14236,12 @@ dependencies = [ ] [[package]] -name = "protox" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "424c2bd294b69c49b949f3619362bc3c5d28298cd1163b6d1a62df37c16461aa" -dependencies = [ - "bytes", - "miette", - "prost 0.13.5", - "prost-reflect", - "prost-types 0.13.5", - "protox-parse", - "thiserror 2.0.17", -] - -[[package]] -name = "protox-parse" -version = "0.8.0" +name = "prost-types" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57927f9dbeeffcce7192404deee6157a640cbb3fe8ac11eabbe571565949ab75" +checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" dependencies = [ - "logos", - "miette", - "prost-types 0.13.5", - "thiserror 2.0.17", + "prost 0.14.4", ] [[package]] @@ -14623,19 +14297,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "quick-protobuf-codec" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ededb1cd78531627244d51dd0c7139fbe736c7d57af0092a76f0ffb2f56e98" -dependencies = [ - "asynchronous-codec 0.6.2", - "bytes", - "quick-protobuf", - "thiserror 1.0.69", - "unsigned-varint 0.7.2", -] - [[package]] name = "quick-protobuf-codec" version = "0.3.1" @@ -14659,42 +14320,6 @@ dependencies = [ "serde", ] -[[package]] -name = "quinn" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8b432585672228923edbbf64b8b12c14e1112f62e88737655b4a083dbcd78e" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto 0.9.6", - "quinn-udp 0.3.2", - "rustc-hash 1.1.0", - "rustls 0.20.9", - "thiserror 1.0.69", - "tokio", - "tracing", - "webpki", -] - -[[package]] -name = "quinn" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" -dependencies = [ - "bytes", - "futures-io", - "pin-project-lite", - "quinn-proto 0.10.6", - "quinn-udp 0.4.1", - "rustc-hash 1.1.0", - "rustls 0.21.12", - "thiserror 1.0.69", - "tokio", - "tracing", -] - [[package]] name = "quinn" version = "0.11.9" @@ -14705,10 +14330,10 @@ dependencies = [ "cfg_aliases 0.2.1", "futures-io", "pin-project-lite", - "quinn-proto 0.11.13", - "quinn-udp 0.5.14", + "quinn-proto", + "quinn-udp", "rustc-hash 2.1.1", - "rustls 0.23.36", + "rustls", "socket2 0.6.1", "thiserror 2.0.17", "tokio", @@ -14716,41 +14341,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "quinn-proto" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" -dependencies = [ - "bytes", - "rand 0.8.5", - "ring 0.16.20", - "rustc-hash 1.1.0", - "rustls 0.20.9", - "slab", - "thiserror 1.0.69", - "tinyvec", - "tracing", - "webpki", -] - -[[package]] -name = "quinn-proto" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141bf7dfde2fbc246bfd3fe12f2455aa24b0fbd9af535d8c86c7bd1381ff2b1a" -dependencies = [ - "bytes", - "rand 0.8.5", - "ring 0.16.20", - "rustc-hash 1.1.0", - "rustls 0.21.12", - "slab", - "thiserror 1.0.69", - "tinyvec", - "tracing", -] - [[package]] name = "quinn-proto" version = "0.11.13" @@ -14764,7 +14354,7 @@ dependencies = [ "rand 0.9.2", "ring 0.17.14", "rustc-hash 2.1.1", - "rustls 0.23.36", + "rustls", "rustls-pki-types", "slab", "thiserror 2.0.17", @@ -14773,32 +14363,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "quinn-udp" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4" -dependencies = [ - "libc", - "quinn-proto 0.9.6", - "socket2 0.4.10", - "tracing", - "windows-sys 0.42.0", -] - -[[package]] -name = "quinn-udp" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" -dependencies = [ - "bytes", - "libc", - "socket2 0.5.10", - "tracing", - "windows-sys 0.48.0", -] - [[package]] name = "quinn-udp" version = "0.5.14" @@ -14828,27 +14392,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "ractor" -version = "0.15.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12c86deb2af198b10a04c4fb3fba73baf3bb300df765a29272f0e5583da7510" -dependencies = [ - "async-trait", - "bon", - "dashmap 6.1.0", - "futures", - "js-sys", - "once_cell", - "strum 0.28.0", - "tokio", - "tokio_with_wasm", - "tracing", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-time", -] - [[package]] name = "radium" version = "0.7.0" @@ -14969,7 +14512,7 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", ] [[package]] @@ -15000,29 +14543,16 @@ dependencies = [ [[package]] name = "rcgen" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" dependencies = [ - "pem 1.1.1", + "pem", "ring 0.16.20", "time", "yasna", ] -[[package]] -name = "rcgen" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" -dependencies = [ - "pem 3.0.6", - "ring 0.17.14", - "rustls-pki-types", - "time", - "yasna", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -15038,7 +14568,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", ] [[package]] @@ -15047,7 +14577,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", ] [[package]] @@ -15116,8 +14646,17 @@ checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.13", + "regex-syntax 0.8.8", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -15128,9 +14667,15 @@ checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.8", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.8" @@ -15179,7 +14724,7 @@ dependencies = [ "http-body 1.0.1", "http-body-util", "hyper 1.8.1", - "hyper-rustls 0.27.7", + "hyper-rustls", "hyper-tls", "hyper-util", "js-sys", @@ -15187,8 +14732,8 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", - "quinn 0.11.9", - "rustls 0.23.36", + "quinn", + "rustls", "rustls-pki-types", "serde", "serde_json", @@ -15196,7 +14741,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", - "tokio-rustls 0.26.4", + "tokio-rustls", "tower 0.5.2", "tower-http 0.6.8", "tower-service", @@ -15220,21 +14765,21 @@ dependencies = [ "http-body 1.0.1", "http-body-util", "hyper 1.8.1", - "hyper-rustls 0.27.7", + "hyper-rustls", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", - "quinn 0.11.9", - "rustls 0.23.36", + "quinn", + "rustls", "rustls-pki-types", "rustls-platform-verifier 0.6.2", "serde", "serde_json", "sync_wrapper", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tower 0.5.2", "tower-http 0.6.8", "tower-service", @@ -15310,9 +14855,9 @@ dependencies = [ [[package]] name = "rocksdb" -version = "0.21.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" +checksum = "ddb7af00d2b17dbd07d82c0063e25411959748ff03e8d4f96134c2ff41fce34f" dependencies = [ "libc", "librocksdb-sys", @@ -15341,6 +14886,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" dependencies = [ + "async-global-executor", "futures", "log", "netlink-packet-core", @@ -15500,47 +15046,24 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.10.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" -dependencies = [ - "bitflags 2.10.0", - "errno", - "libc", - "linux-raw-sys 0.11.0", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "ring 0.16.20", - "sct", - "webpki", + "bitflags 2.13.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", ] [[package]] -name = "rustls" -version = "0.21.12" +name = "rustix" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "log", - "ring 0.17.14", - "rustls-webpki 0.101.7", - "sct", + "bitflags 2.13.0", + "errno", + "libc", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] @@ -15559,18 +15082,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe 0.1.6", - "rustls-pemfile", - "schannel", - "security-framework 2.11.1", -] - [[package]] name = "rustls-native-certs" version = "0.8.3" @@ -15583,15 +15094,6 @@ dependencies = [ "security-framework 3.5.1", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustls-pki-types" version = "1.13.2" @@ -15613,8 +15115,8 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.36", - "rustls-native-certs 0.8.3", + "rustls", + "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki 0.103.8", "security-framework 3.5.1", @@ -15634,8 +15136,8 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.36", - "rustls-native-certs 0.8.3", + "rustls", + "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki 0.103.8", "security-framework 3.5.1", @@ -15722,6 +15224,15 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher 0.4.4", +] + [[package]] name = "same-file" version = "1.0.6" @@ -15733,24 +15244,25 @@ dependencies = [ [[package]] name = "sc-authority-discovery" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.56.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "futures", "futures-timer", "ip_network", - "libp2p 0.52.4", "linked_hash_set", "log", - "multihash 0.19.3", "parity-scale-codec", "prost 0.12.6", - "prost-build 0.12.6", + "prost-build 0.13.5", "rand 0.8.5", "sc-client-api", "sc-network", "sc-network-types", + "sc-service", + "serde", + "serde_json", "sp-api", "sp-authority-discovery", "sp-blockchain", @@ -15759,31 +15271,31 @@ dependencies = [ "sp-runtime", "substrate-prometheus-endpoint", "thiserror 1.0.69", + "tokio", ] [[package]] name = "sc-block-builder" -version = "0.42.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.49.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "sp-api", "sp-block-builder", "sp-blockchain", "sp-core", + "sp-externalities", "sp-inherents", "sp-runtime", - "sp-trie", ] [[package]] name = "sc-chain-spec" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "49.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", "docify", - "log", "memmap2 0.9.9", "parity-scale-codec", "sc-chain-spec-derive", @@ -15795,7 +15307,7 @@ dependencies = [ "serde_json", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "sp-genesis-builder", "sp-io", "sp-runtime", @@ -15806,7 +15318,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "12.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -15816,10 +15328,11 @@ dependencies = [ [[package]] name = "sc-cli" -version = "0.47.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.58.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", + "bip39", "chrono", "clap 4.5.54", "fdlimit", @@ -15828,7 +15341,6 @@ dependencies = [ "libp2p-identity", "log", "names", - "parity-bip39", "parity-scale-codec", "rand 0.8.5", "regex", @@ -15841,6 +15353,7 @@ dependencies = [ "sc-service", "sc-telemetry", "sc-tracing", + "sc-transaction-pool", "sc-utils", "serde", "serde_json", @@ -15857,8 +15370,8 @@ dependencies = [ [[package]] name = "sc-client-api" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "fnv", "futures", @@ -15876,7 +15389,6 @@ dependencies = [ "sp-externalities", "sp-runtime", "sp-state-machine", - "sp-statement-store", "sp-storage", "sp-trie", "substrate-prometheus-endpoint", @@ -15884,8 +15396,8 @@ dependencies = [ [[package]] name = "sc-client-db" -version = "0.44.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.52.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "hash-db", "kvdb", @@ -15906,23 +15418,24 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-trie", + "substrate-prometheus-endpoint", + "sysinfo", ] [[package]] name = "sc-consensus" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.55.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "futures", "log", - "mockall 0.11.4", + "mockall", "parking_lot 0.12.5", "sc-client-api", "sc-network-types", "sc-utils", "serde", - "sp-api", "sp-blockchain", "sp-consensus", "sp-core", @@ -15934,8 +15447,8 @@ dependencies = [ [[package]] name = "sc-consensus-babe" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.56.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "fork-tree", @@ -15960,18 +15473,19 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-slots", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "sp-inherents", "sp-keystore", "sp-runtime", + "sp-timestamp", "substrate-prometheus-endpoint", "thiserror 1.0.69", ] [[package]] name = "sc-consensus-babe-rpc" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.56.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "futures", "jsonrpsee", @@ -15992,8 +15506,8 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.55.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "fork-tree", "parity-scale-codec", @@ -16005,10 +15519,10 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa" -version = "0.30.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.41.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "ahash", + "ahash 0.8.12", "array-bytes", "async-trait", "dyn-clone", @@ -16023,6 +15537,7 @@ dependencies = [ "sc-block-builder", "sc-chain-spec", "sc-client-api", + "sc-client-db", "sc-consensus", "sc-network", "sc-network-common", @@ -16040,7 +15555,7 @@ dependencies = [ "sp-consensus", "sp-consensus-grandpa", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", @@ -16049,8 +15564,8 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa-rpc" -version = "0.30.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.41.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "finality-grandpa", "futures", @@ -16069,8 +15584,8 @@ dependencies = [ [[package]] name = "sc-consensus-slots" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.55.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "futures", @@ -16088,11 +15603,12 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-state-machine", + "sp-trie", ] [[package]] name = "sc-executor" -version = "0.40.1" +version = "0.48.0" dependencies = [ "parity-scale-codec", "parking_lot 0.12.5", @@ -16114,7 +15630,7 @@ dependencies = [ [[package]] name = "sc-executor-common" -version = "0.35.0" +version = "0.44.0" dependencies = [ "polkavm", "sp-allocator", @@ -16126,7 +15642,7 @@ dependencies = [ [[package]] name = "sc-executor-polkavm" -version = "0.32.0" +version = "0.41.0" dependencies = [ "log", "polkavm", @@ -16136,7 +15652,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" -version = "0.35.0" +version = "0.44.0" dependencies = [ "cargo_metadata", "log", @@ -16157,8 +15673,8 @@ dependencies = [ [[package]] name = "sc-informant" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.55.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "console 0.15.11", "futures", @@ -16166,7 +15682,6 @@ dependencies = [ "log", "sc-client-api", "sc-network", - "sc-network-common", "sc-network-sync", "sp-blockchain", "sp-runtime", @@ -16174,8 +15689,8 @@ dependencies = [ [[package]] name = "sc-keystore" -version = "33.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "40.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", "parking_lot 0.12.5", @@ -16188,7 +15703,8 @@ dependencies = [ [[package]] name = "sc-mixnet" -version = "0.15.0" +version = "0.26.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", "arrayvec 0.7.6", @@ -16210,37 +15726,35 @@ dependencies = [ "sp-keystore", "sp-mixnet", "sp-runtime", - "thiserror 2.0.17", + "thiserror 1.0.69", ] [[package]] name = "sc-network" -version = "0.45.6" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.56.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", "async-channel 1.9.0", "async-trait", "asynchronous-codec 0.6.2", "bytes", - "cid 0.9.0", "either", "fnv", "futures", "futures-timer", "ip_network", - "libp2p 0.52.4", + "libp2p", "linked_hash_set", "litep2p", "log", - "mockall 0.11.4", - "once_cell", + "mockall", "parity-scale-codec", "parking_lot 0.12.5", "partial_sort", "pin-project", "prost 0.12.6", - "prost-build 0.12.6", + "prost-build 0.13.5", "rand 0.8.5", "sc-client-api", "sc-network-common", @@ -16266,28 +15780,20 @@ dependencies = [ [[package]] name = "sc-network-common" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.53.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "async-trait", "bitflags 1.3.2", - "futures", - "libp2p-identity", "parity-scale-codec", - "prost-build 0.12.6", - "sc-consensus", - "sc-network-types", - "sp-consensus", - "sp-consensus-grandpa", "sp-runtime", ] [[package]] name = "sc-network-gossip" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.56.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "ahash", + "ahash 0.8.12", "futures", "futures-timer", "log", @@ -16303,8 +15809,8 @@ dependencies = [ [[package]] name = "sc-network-light" -version = "0.44.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.55.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", "async-channel 1.9.0", @@ -16312,7 +15818,7 @@ dependencies = [ "log", "parity-scale-codec", "prost 0.12.6", - "prost-build 0.12.6", + "prost-build 0.13.5", "sc-client-api", "sc-network", "sc-network-types", @@ -16322,23 +15828,44 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "sc-network-statement" +version = "0.38.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "array-bytes", + "async-channel 1.9.0", + "futures", + "governor", + "log", + "parity-scale-codec", + "rand 0.8.5", + "sc-network", + "sc-network-common", + "sc-network-sync", + "sc-network-types", + "sp-consensus", + "sp-runtime", + "sp-statement-store", + "substrate-prometheus-endpoint", + "tokio", +] + [[package]] name = "sc-network-sync" -version = "0.44.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.55.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", "async-channel 1.9.0", "async-trait", "fork-tree", "futures", - "futures-timer", - "libp2p 0.52.4", "log", - "mockall 0.11.4", + "mockall", "parity-scale-codec", "prost 0.12.6", - "prost-build 0.12.6", + "prost-build 0.13.5", "sc-client-api", "sc-consensus", "sc-network", @@ -16350,7 +15877,6 @@ dependencies = [ "sp-arithmetic", "sp-blockchain", "sp-consensus", - "sp-consensus-grandpa", "sp-core", "sp-runtime", "substrate-prometheus-endpoint", @@ -16361,8 +15887,8 @@ dependencies = [ [[package]] name = "sc-network-transactions" -version = "0.44.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.55.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", "futures", @@ -16380,42 +15906,46 @@ dependencies = [ [[package]] name = "sc-network-types" -version = "0.12.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.20.2" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "bs58 0.5.1", + "bs58", + "bytes", "ed25519-dalek", "libp2p-identity", + "libp2p-kad", "litep2p", "log", "multiaddr 0.18.2", - "multihash 0.19.3", + "multihash 0.19.5", "rand 0.8.5", + "serde", + "serde_with", "thiserror 1.0.69", "zeroize", ] [[package]] name = "sc-offchain" -version = "40.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "51.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "array-bytes", "bytes", "fnv", "futures", "futures-timer", - "hyper 0.14.32", - "hyper-rustls 0.24.2", - "log", + "http-body-util", + "hyper 1.8.1", + "hyper-rustls", + "hyper-util", "num_cpus", "once_cell", "parity-scale-codec", "parking_lot 0.12.5", "rand 0.8.5", + "rustls", "sc-client-api", "sc-network", - "sc-network-common", "sc-network-types", "sc-transaction-pool-api", "sc-utils", @@ -16431,8 +15961,8 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" -version = "0.18.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.20.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -16440,9 +15970,10 @@ dependencies = [ [[package]] name = "sc-rpc" -version = "40.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "51.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ + "async-channel 1.9.0", "futures", "jsonrpsee", "log", @@ -16453,6 +15984,7 @@ dependencies = [ "sc-client-api", "sc-mixnet", "sc-rpc-api", + "sc-statement-store", "sc-tracing", "sc-transaction-pool-api", "sc-utils", @@ -16472,8 +16004,8 @@ dependencies = [ [[package]] name = "sc-rpc-api" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.55.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -16486,14 +16018,15 @@ dependencies = [ "sp-core", "sp-rpc", "sp-runtime", + "sp-statement-store", "sp-version", "thiserror 1.0.69", ] [[package]] name = "sc-rpc-server" -version = "17.1.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "28.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "dyn-clone", "forwarded-header-value", @@ -16516,13 +16049,14 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.56.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", "futures", "futures-util", "hex", + "itertools 0.11.0", "jsonrpsee", "log", "parity-scale-codec", @@ -16532,7 +16066,6 @@ dependencies = [ "sc-client-api", "sc-rpc", "sc-transaction-pool-api", - "sc-utils", "schnellru", "serde", "sp-api", @@ -16541,6 +16074,7 @@ dependencies = [ "sp-rpc", "sp-runtime", "sp-version", + "substrate-prometheus-endpoint", "thiserror 1.0.69", "tokio", "tokio-stream", @@ -16549,7 +16083,7 @@ dependencies = [ [[package]] name = "sc-runtime-test" version = "2.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "sp-core", "sp-io", @@ -16558,10 +16092,25 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "sc-runtime-utilities" +version = "0.8.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "parity-scale-codec", + "sc-executor", + "sc-executor-common", + "sp-core", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", + "sp-state-machine", + "sp-wasm-interface", + "thiserror 1.0.69", +] + [[package]] name = "sc-service" -version = "0.46.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.57.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "directories", @@ -16624,8 +16173,8 @@ dependencies = [ [[package]] name = "sc-state-db" -version = "0.36.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.42.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "log", "parity-scale-codec", @@ -16633,10 +16182,35 @@ dependencies = [ "sp-core", ] +[[package]] +name = "sc-statement-store" +version = "27.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "async-channel 1.9.0", + "futures", + "itertools 0.11.0", + "log", + "parity-db", + "parking_lot 0.12.5", + "sc-client-api", + "sc-keystore", + "sc-network-statement", + "sc-utils", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-runtime", + "sp-statement-store", + "sp-storage", + "substrate-prometheus-endpoint", + "tokio", +] + [[package]] name = "sc-sync-state-rpc" -version = "0.45.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.56.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -16654,8 +16228,8 @@ dependencies = [ [[package]] name = "sc-sysinfo" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "47.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "derive_more 0.99.20", "futures", @@ -16668,24 +16242,22 @@ dependencies = [ "serde", "serde_json", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "sp-io", - "sp-std", ] [[package]] name = "sc-telemetry" -version = "25.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "30.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "chrono", "futures", - "libp2p 0.52.4", + "libp2p", "log", "parking_lot 0.12.5", "pin-project", "rand 0.8.5", - "sc-network", "sc-utils", "serde", "serde_json", @@ -16695,13 +16267,12 @@ dependencies = [ [[package]] name = "sc-tracing" -version = "37.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "chrono", "console 0.15.11", "is-terminal", - "lazy_static", "libc", "log", "parity-scale-codec", @@ -16724,8 +16295,8 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" -version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "11.1.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -16735,14 +16306,15 @@ dependencies = [ [[package]] name = "sc-transaction-pool" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "futures", "futures-timer", + "indexmap 2.14.0", + "itertools 0.11.0", "linked-hash-map", - "log", "parity-scale-codec", "parking_lot 0.12.5", "sc-client-api", @@ -16752,39 +16324,44 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "sp-runtime", "sp-tracing", "sp-transaction-pool", + "strum 0.26.3", "substrate-prometheus-endpoint", "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tracing", ] [[package]] name = "sc-transaction-pool-api" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "44.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "futures", + "indexmap 2.14.0", "log", "parity-scale-codec", "serde", "sp-blockchain", "sp-core", "sp-runtime", + "strum 0.26.3", "thiserror 1.0.69", ] [[package]] name = "sc-utils" -version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "20.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-channel 1.9.0", "futures", "futures-timer", - "lazy_static", "log", "parking_lot 0.12.5", "prometheus 0.13.4", @@ -16988,7 +16565,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "356285bbf17bea63d9e52e96bd18f039672ac92b55b8cb997d6162a2a37d1649" dependencies = [ - "ahash", + "ahash 0.8.12", "cfg-if", "hashbrown 0.13.2", ] @@ -17031,36 +16608,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2" [[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", -] - -[[package]] -name = "sctp-proto" -version = "0.2.2" +name = "scrypt" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6220f78bb44c15f326b0596113305f6101097a18755d53727a575c97e09fb24" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" dependencies = [ - "bytes", - "crc", - "fxhash", - "log", - "rand 0.8.5", - "slab", - "thiserror 1.0.69", + "password-hash", + "pbkdf2", + "salsa20", + "sha2 0.10.9", ] -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "sec1" version = "0.7.3" @@ -17076,6 +16634,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "secp256k1-sys 0.8.2", +] + [[package]] name = "secp256k1" version = "0.28.2" @@ -17091,12 +16658,21 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ - "bitcoin_hashes 0.14.1", + "bitcoin_hashes", "rand 0.8.5", "secp256k1-sys 0.10.1", "serde", ] +[[package]] +name = "secp256k1-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4473013577ec77b4ee3668179ef1186df3146e2cf2d927bd200974c6fe60fd99" +dependencies = [ + "cc", +] + [[package]] name = "secp256k1-sys" version = "0.9.2" @@ -17124,13 +16700,22 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secrecy" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -17143,7 +16728,7 @@ version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -17379,27 +16964,17 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.10.7", - "sha1-asm", ] [[package]] name = "sha1" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha1-asm" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286acebaf8b67c1130aedffad26f594eff0c1292389158135327d2e23aed582b" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cc", + "cfg-if", + "cpufeatures", + "digest 0.10.7", ] [[package]] @@ -17508,11 +17083,11 @@ checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "simple-dns" -version = "0.5.7" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae9a3fcdadafb6d97f4c0e007e4247b114ee0f119f650c3cbf3a8b3a1479694" +checksum = "7a75cbde1bf934313596a004973e462f9a82caa814dcf1a5f507bdf51597eeb4" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", ] [[package]] @@ -17589,7 +17164,7 @@ dependencies = [ "base64 0.22.1", "bip39", "blake2-rfc", - "bs58 0.5.1", + "bs58", "chacha20", "crossbeam-queue", "derive_more 2.1.1", @@ -17641,7 +17216,7 @@ dependencies = [ "async-lock", "base64 0.22.1", "blake2-rfc", - "bs58 0.5.1", + "bs58", "derive_more 2.1.1", "either", "event-listener 5.4.1", @@ -17712,16 +17287,6 @@ dependencies = [ "subtle 2.6.1", ] -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.10" @@ -17770,8 +17335,8 @@ dependencies = [ [[package]] name = "sp-api" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "docify", "hash-db", @@ -17792,8 +17357,8 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" -version = "20.0.3" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "27.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "Inflector", "blake2 0.10.6", @@ -17806,8 +17371,8 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "scale-info", @@ -17818,8 +17383,8 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "28.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "docify", "integer-sqrt", @@ -17832,8 +17397,8 @@ dependencies = [ [[package]] name = "sp-authority-discovery" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "scale-info", @@ -17844,8 +17409,8 @@ dependencies = [ [[package]] name = "sp-block-builder" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "sp-api", "sp-inherents", @@ -17854,8 +17419,8 @@ dependencies = [ [[package]] name = "sp-blockchain" -version = "37.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "44.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "futures", "parity-scale-codec", @@ -17873,23 +17438,41 @@ dependencies = [ [[package]] name = "sp-consensus" -version = "0.40.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "futures", "log", - "sp-core", + "sp-api", + "sp-externalities", "sp-inherents", "sp-runtime", "sp-state-machine", + "sp-trie", "thiserror 1.0.69", ] +[[package]] +name = "sp-consensus-aura" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-consensus-slots", + "sp-inherents", + "sp-runtime", + "sp-timestamp", +] + [[package]] name = "sp-consensus-babe" -version = "0.40.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "parity-scale-codec", @@ -17906,8 +17489,8 @@ dependencies = [ [[package]] name = "sp-consensus-grandpa" -version = "21.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "28.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "finality-grandpa", "log", @@ -17923,8 +17506,8 @@ dependencies = [ [[package]] name = "sp-consensus-slots" -version = "0.40.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.47.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "scale-info", @@ -17934,40 +17517,41 @@ dependencies = [ [[package]] name = "sp-core" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "40.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ + "ark-vrf", "array-bytes", + "bip39", "bitflags 1.3.2", "blake2 0.10.6", "bounded-collections", - "bs58 0.5.1", - "dyn-clonable", + "bs58", + "dyn-clone", "ed25519-zebra", "futures", "hash-db", "hash256-std-hasher", - "impl-serde 0.4.0", + "impl-serde 0.5.0", "itertools 0.11.0", "k256", "libsecp256k1", "log", "merlin", - "parity-bip39", "parity-scale-codec", "parking_lot 0.12.5", "paste", - "primitive-types 0.12.2", + "primitive-types 0.13.1", "rand 0.8.5", "scale-info", "schnorrkel", "secp256k1 0.28.2", - "secrecy", + "secrecy 0.8.0", "serde", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sha2 0.10.9", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "sp-debug-derive", "sp-externalities", - "sp-runtime-interface", "sp-std", "sp-storage", "ss58-registry", @@ -17980,21 +17564,25 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" -version = "0.14.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.20.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "ark-bls12-377", + "ark-bls12-377 0.5.0", "ark-bls12-377-ext", - "ark-bls12-381", + "ark-bls12-381 0.5.0", "ark-bls12-381-ext", "ark-bw6-761", "ark-bw6-761-ext", - "ark-ec", + "ark-ec 0.5.0", "ark-ed-on-bls12-377", "ark-ed-on-bls12-377-ext", "ark-ed-on-bls12-381-bandersnatch", "ark-ed-on-bls12-381-bandersnatch-ext", - "ark-scale", + "ark-pallas", + "ark-pallas-ext", + "ark-scale 0.0.13", + "ark-vesta", + "ark-vesta-ext", "sp-runtime-interface", ] @@ -18015,7 +17603,7 @@ dependencies = [ [[package]] name = "sp-crypto-hashing" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "blake2b_simd", "byteorder", @@ -18028,27 +17616,29 @@ dependencies = [ [[package]] name = "sp-crypto-hashing-proc-macro" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "syn 2.0.114", ] [[package]] name = "sp-database" -version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "10.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "kvdb", + "kvdb-rocksdb", "parking_lot 0.12.5", ] [[package]] name = "sp-debug-derive" -version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "15.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ + "proc-macro-warning", "proc-macro2", "quote", "syn 2.0.114", @@ -18056,8 +17646,8 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.29.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.32.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "environmental", "parity-scale-codec", @@ -18066,8 +17656,8 @@ dependencies = [ [[package]] name = "sp-genesis-builder" -version = "0.15.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.22.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "scale-info", @@ -18078,8 +17668,8 @@ dependencies = [ [[package]] name = "sp-inherents" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -18091,8 +17681,8 @@ dependencies = [ [[package]] name = "sp-io" -version = "38.0.2" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "45.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "bytes", "docify", @@ -18104,7 +17694,7 @@ dependencies = [ "rustversion", "secp256k1 0.28.2", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "sp-externalities", "sp-keystore", "sp-runtime-interface", @@ -18117,8 +17707,8 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "39.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "sp-core", "sp-runtime", @@ -18127,8 +17717,8 @@ dependencies = [ [[package]] name = "sp-keystore" -version = "0.40.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.46.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "parking_lot 0.12.5", @@ -18138,8 +17728,8 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" -version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "11.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "thiserror 1.0.69", "zstd 0.12.4", @@ -18147,18 +17737,18 @@ dependencies = [ [[package]] name = "sp-metadata-ir" -version = "0.7.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.12.3" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "frame-metadata 16.0.0", + "frame-metadata 23.0.1", "parity-scale-codec", "scale-info", ] [[package]] name = "sp-mixnet" -version = "0.12.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.19.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "scale-info", @@ -18166,10 +17756,27 @@ dependencies = [ "sp-application-crypto", ] +[[package]] +name = "sp-mmr-primitives" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "log", + "parity-scale-codec", + "polkadot-ckb-merkle-mountain-range", + "scale-info", + "serde", + "sp-api", + "sp-core", + "sp-debug-derive", + "sp-runtime", + "thiserror 1.0.69", +] + [[package]] name = "sp-npos-elections" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "scale-info", @@ -18181,8 +17788,8 @@ dependencies = [ [[package]] name = "sp-offchain" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "sp-api", "sp-core", @@ -18191,18 +17798,17 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "13.0.2" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "backtrace", - "lazy_static", "regex", ] [[package]] name = "sp-rpc" -version = "32.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "38.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "rustc-hash 1.1.0", "serde", @@ -18211,9 +17817,11 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "39.0.5" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "46.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ + "binary-merkle-tree 16.1.1 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", + "bytes", "docify", "either", "hash256-std-hasher", @@ -18231,20 +17839,22 @@ dependencies = [ "sp-core", "sp-io", "sp-std", + "sp-trie", "sp-weights", + "strum 0.26.3", "tracing", + "tuplex", ] [[package]] name = "sp-runtime-interface" -version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", "polkavm-derive", - "primitive-types 0.12.2", "sp-externalities", "sp-runtime-interface-proc-macro", "sp-std", @@ -18256,7 +17866,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "18.0.0" +version = "21.0.0" dependencies = [ "Inflector", "expander", @@ -18268,8 +17878,8 @@ dependencies = [ [[package]] name = "sp-session" -version = "36.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "43.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", "scale-info", @@ -18282,8 +17892,8 @@ dependencies = [ [[package]] name = "sp-staking" -version = "36.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "43.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -18295,8 +17905,8 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.43.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.50.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "hash-db", "log", @@ -18315,21 +17925,23 @@ dependencies = [ [[package]] name = "sp-statement-store" -version = "18.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "25.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "aes-gcm", "curve25519-dalek", "ed25519-dalek", + "frame-support", "hkdf", "parity-scale-codec", "rand 0.8.5", "scale-info", + "serde", "sha2 0.10.9", "sp-api", "sp-application-crypto", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0)", "sp-externalities", "sp-runtime", "sp-runtime-interface", @@ -18340,14 +17952,14 @@ dependencies = [ [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" [[package]] name = "sp-storage" -version = "21.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "23.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "impl-serde 0.4.0", + "impl-serde 0.5.0", "parity-scale-codec", "ref-cast", "serde", @@ -18356,8 +17968,8 @@ dependencies = [ [[package]] name = "sp-timestamp" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "parity-scale-codec", @@ -18368,10 +17980,11 @@ dependencies = [ [[package]] name = "sp-tracing" -version = "17.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "19.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", + "regex", "tracing", "tracing-core", "tracing-subscriber", @@ -18379,8 +17992,8 @@ dependencies = [ [[package]] name = "sp-transaction-pool" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "sp-api", "sp-runtime", @@ -18388,12 +18001,13 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" -version = "34.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "41.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "parity-scale-codec", "scale-info", + "sp-api", "sp-core", "sp-inherents", "sp-runtime", @@ -18402,12 +18016,13 @@ dependencies = [ [[package]] name = "sp-trie" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "43.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "ahash", + "ahash 0.8.12", + "foldhash 0.1.5", "hash-db", - "lazy_static", + "hashbrown 0.15.5", "memory-db", "nohash-hasher", "parity-scale-codec", @@ -18417,6 +18032,7 @@ dependencies = [ "schnellru", "sp-core", "sp-externalities", + "substrate-prometheus-endpoint", "thiserror 1.0.69", "tracing", "trie-db", @@ -18425,14 +18041,15 @@ dependencies = [ [[package]] name = "sp-version" -version = "37.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "44.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ - "impl-serde 0.4.0", + "impl-serde 0.5.0", "parity-scale-codec", "parity-wasm", "scale-info", "serde", + "sp-core", "sp-crypto-hashing-proc-macro", "sp-runtime", "sp-std", @@ -18442,10 +18059,11 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" -version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "15.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "parity-scale-codec", + "proc-macro-warning", "proc-macro2", "quote", "syn 2.0.114", @@ -18453,7 +18071,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "21.0.1" +version = "24.0.0" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -18475,8 +18093,8 @@ dependencies = [ [[package]] name = "sp-weights" -version = "31.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "34.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "bounded-collections", "parity-scale-codec", @@ -18550,6 +18168,71 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "staging-xcm" +version = "22.0.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "array-bytes", + "bounded-collections", + "derive-where", + "environmental", + "frame-support", + "hex-literal", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "serde", + "sp-runtime", + "sp-weights", + "tracing", + "xcm-procedural", +] + +[[package]] +name = "staging-xcm-builder" +version = "26.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "environmental", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "pallet-asset-conversion", + "pallet-transaction-payment", + "parity-scale-codec", + "polkadot-parachain-primitives", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-weights", + "staging-xcm", + "staging-xcm-executor", + "tracing", +] + +[[package]] +name = "staging-xcm-executor" +version = "25.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "environmental", + "frame-benchmarking", + "frame-support", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-weights", + "staging-xcm", + "tracing", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -18590,26 +18273,6 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceb97b7225c713c2fd4db0153cb6b3cab244eb37900c3f634ed4d43310d8c34" -[[package]] -name = "str0m" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6706347e49b13373f7ddfafad47df7583ed52083d6fc8a594eb2c80497ef959d" -dependencies = [ - "combine", - "crc", - "fastrand", - "hmac 0.12.1", - "once_cell", - "openssl", - "openssl-sys", - "sctp-proto", - "serde", - "sha-1", - "thiserror 1.0.69", - "tracing", -] - [[package]] name = "string-interner" version = "0.17.0" @@ -18690,15 +18353,6 @@ dependencies = [ "strum_macros 0.27.2", ] -[[package]] -name = "strum" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" -dependencies = [ - "strum_macros 0.28.0", -] - [[package]] name = "strum_macros" version = "0.24.3" @@ -18737,22 +18391,10 @@ dependencies = [ "syn 2.0.114", ] -[[package]] -name = "strum_macros" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.114", -] - [[package]] name = "substrate-bip39" -version = "0.6.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.6.1" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "hmac 0.12.1", "pbkdf2", @@ -18764,12 +18406,12 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" [[package]] name = "substrate-frame-rpc-system" -version = "39.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "50.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "docify", "frame-system-rpc-runtime-api", @@ -18788,8 +18430,8 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" -version = "0.17.5" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.17.7" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "http-body-util", "hyper 1.8.1", @@ -18802,8 +18444,8 @@ dependencies = [ [[package]] name = "substrate-rpc-client" -version = "0.44.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "0.55.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "async-trait", "jsonrpsee", @@ -18815,8 +18457,8 @@ dependencies = [ [[package]] name = "substrate-state-trie-migration-rpc" -version = "38.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +version = "49.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -18833,7 +18475,7 @@ dependencies = [ [[package]] name = "substrate-test-client" version = "2.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=298f676c91d64f15f38ea7fd78f125c5889ab09c#298f676c91d64f15f38ea7fd78f125c5889ab09c" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" dependencies = [ "array-bytes", "async-trait", @@ -18843,7 +18485,6 @@ dependencies = [ "sc-client-db", "sc-consensus", "sc-executor", - "sc-offchain", "sc-service", "serde", "serde_json", @@ -18853,13 +18494,12 @@ dependencies = [ "sp-keyring", "sp-keystore", "sp-runtime", - "sp-state-machine", "tokio", ] [[package]] name = "substrate-wasm-builder" -version = "24.0.2" +version = "32.0.0" dependencies = [ "array-bytes", "build-helper", @@ -18897,12 +18537,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "subtle-ng" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" - [[package]] name = "subxt" version = "0.44.2" @@ -19053,11 +18687,41 @@ dependencies = [ "serde", "serde_json", "subxt-core", - "subxt-lightclient", + "subxt-lightclient", + "thiserror 2.0.17", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "subxt-signer" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "963a6b53626fabc94544fdd64b03b639d5b9762efcd52e417d5292b119622a15" +dependencies = [ + "base64 0.22.1", + "bip32", + "bip39", + "cfg-if", + "crypto_secretbox", + "hex", + "hmac 0.12.1", + "keccak-hash", + "parity-scale-codec", + "pbkdf2", + "regex", + "schnorrkel", + "scrypt", + "secp256k1 0.30.0", + "secrecy 0.10.3", + "serde", + "serde_json", + "sha2 0.10.9", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subxt-core", "thiserror 2.0.17", - "tokio-util", - "tracing", - "url", + "zeroize", ] [[package]] @@ -19137,13 +18801,28 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "sysinfo" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "windows 0.52.0", +] + [[package]] name = "system-configuration" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -19333,11 +19012,22 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "tikv-jemalloc-ctl" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "661f1f6a57b3a36dc9174a2c10f19513b4866816e13425d3e418b11cc37bc24c" +dependencies = [ + "libc", + "paste", + "tikv-jemalloc-sys", +] + [[package]] name = "tikv-jemalloc-sys" -version = "0.5.4+5.3.0-patched" +version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1" +checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b" dependencies = [ "cc", "libc", @@ -19432,7 +19122,6 @@ dependencies = [ "signal-hook-registry", "socket2 0.6.1", "tokio-macros", - "tracing", "windows-sys 0.61.2", ] @@ -19457,34 +19146,13 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-retry" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" -dependencies = [ - "pin-project", - "rand 0.8.5", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.36", + "rustls", "tokio", ] @@ -19502,17 +19170,18 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1" dependencies = [ "futures-util", "log", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", + "rustls", + "rustls-native-certs", + "rustls-pki-types", "tokio", - "tokio-rustls 0.24.1", - "tungstenite 0.20.1", + "tokio-rustls", + "tungstenite 0.27.0", ] [[package]] @@ -19523,10 +19192,10 @@ checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", - "rustls 0.23.36", + "rustls", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tungstenite 0.28.0", "webpki-roots 0.26.11", ] @@ -19545,30 +19214,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio_with_wasm" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34e40fbbbd95441133fe9483f522db15dbfd26dc636164ebd8f2dd28759a6aa6" -dependencies = [ - "js-sys", - "tokio", - "tokio_with_wasm_proc", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "tokio_with_wasm_proc" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01145a2c788d6aae4cd653afec1e8332534d7d783d01897cefcafe4428de992" -dependencies = [ - "quote", - "syn 2.0.114", -] - [[package]] name = "toml" version = "0.5.11" @@ -19706,7 +19351,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "bytes", "http 1.4.0", "http-body 1.0.1", @@ -19722,7 +19367,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "bytes", "futures-util", "http 1.4.0", @@ -19801,13 +19446,38 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-gum" +version = "24.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "coarsetime", + "polkadot-primitives", + "tracing", + "tracing-gum-proc-macro", +] + +[[package]] +name = "tracing-gum-proc-macro" +version = "5.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "expander", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "tracing-log" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ + "ahash 0.7.8", "log", + "lru 0.7.8", "once_cell", "tracing-core", ] @@ -19824,15 +19494,15 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", "once_cell", "parking_lot 0.12.5", - "regex-automata", + "regex", "serde", "serde_json", "sharded-slab", @@ -19847,9 +19517,9 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.29.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c992b4f40c234a074d48a757efeabb1a6be88af84c0c23f7ca158950cb0ae7f" +checksum = "a7795f2df2ef744e4ffb2125f09325e60a21d305cc3ecece0adeef03f7a9e560" dependencies = [ "hash-db", "log", @@ -19866,78 +19536,6 @@ dependencies = [ "hash-db", ] -[[package]] -name = "trust-dns-proto" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner 0.5.1", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.2.3", - "ipnet", - "lazy_static", - "rand 0.8.5", - "smallvec", - "socket2 0.4.10", - "thiserror 1.0.69", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "trust-dns-proto" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner 0.6.1", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.4.0", - "ipnet", - "once_cell", - "rand 0.8.5", - "smallvec", - "thiserror 1.0.69", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "trust-dns-resolver" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" -dependencies = [ - "cfg-if", - "futures-util", - "ipconfig", - "lru-cache", - "once_cell", - "parking_lot 0.12.5", - "rand 0.8.5", - "resolv-conf", - "smallvec", - "thiserror 1.0.69", - "tokio", - "tracing", - "trust-dns-proto 0.23.2", -] - [[package]] name = "try-lock" version = "0.2.5" @@ -19968,20 +19566,20 @@ checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" dependencies = [ - "byteorder", "bytes", "data-encoding", - "http 0.2.12", + "http 1.4.0", "httparse", "log", - "rand 0.8.5", - "rustls 0.21.12", + "rand 0.9.2", + "rustls", + "rustls-pki-types", "sha1", - "thiserror 1.0.69", + "thiserror 2.0.17", "url", "utf-8", ] @@ -19998,13 +19596,19 @@ dependencies = [ "httparse", "log", "rand 0.9.2", - "rustls 0.23.36", + "rustls", "rustls-pki-types", "sha1", "thiserror 2.0.17", "utf-8", ] +[[package]] +name = "tuplex" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "676ac81d5454c4dcf37955d34fa8626ede3490f744b86ca14a7b90168d2a08aa" + [[package]] name = "twox-hash" version = "1.6.3" @@ -20077,12 +19681,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" - [[package]] name = "unicode-ident" version = "1.0.22" @@ -20156,7 +19754,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" dependencies = [ - "asynchronous-codec 0.7.0", "bytes", "tokio-util", ] @@ -20180,7 +19777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", - "idna 1.1.0", + "idna", "percent-encoding", "serde", "serde_derive", @@ -20221,6 +19818,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" + [[package]] name = "vara-runtime" version = "2.0.0" @@ -20272,6 +19875,7 @@ dependencies = [ "pallet-grandpa-signer", "pallet-identity", "pallet-im-online", + "pallet-migrations", "pallet-multisig", "pallet-nomination-pools", "pallet-nomination-pools-runtime-api", @@ -20354,12 +19958,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6bfb937b3d12077654a9e43e32a4e9c20177dd9fea0f3aba673e7840bb54f32" dependencies = [ - "ark-bls12-377", - "ark-bls12-381", - "ark-ec", + "ark-bls12-377 0.4.0", + "ark-bls12-381 0.4.0", + "ark-ec 0.4.2", "ark-ff 0.4.2", "ark-serialize 0.4.2", - "ark-serialize-derive", + "ark-serialize-derive 0.4.2", "arrayref", "digest 0.10.7", "rand 0.8.5", @@ -20370,6 +19974,52 @@ dependencies = [ "zeroize", ] +[[package]] +name = "w3f-pcs" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbe7a8d5c914b69392ab3b267f679a2e546fe29afaddce47981772ac71bd02e1" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "merlin", +] + +[[package]] +name = "w3f-plonk-common" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aca389e494fe08c5c108b512e2328309036ee1c0bc7bdfdb743fef54d448c8c" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "getrandom_or_panic", + "rand_core 0.6.4", + "w3f-pcs", +] + +[[package]] +name = "w3f-ring-proof" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a639379402ad51504575dbd258740383291ac8147d3b15859bdf1ea48c677de" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "ark-transcript", + "w3f-pcs", + "w3f-plonk-common", +] + [[package]] name = "wait-timeout" version = "0.2.1" @@ -20446,6 +20096,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasix" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae86f02046da16a333a9129d31451423e1657737ecdafed4193838a5f54c5cfe" +dependencies = [ + "wasi", +] + [[package]] name = "wasm-bindgen" version = "0.2.106" @@ -20687,7 +20346,7 @@ version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d0fd5f4f2c4fe0c98554bb7293108ed2b1d0c124dce0974f999de7d517d37bc" dependencies = [ - "ahash", + "ahash 0.8.12", "hashbrown 0.14.5", "string-interner", ] @@ -20756,7 +20415,7 @@ version = "0.221.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d06bfa36ab3ac2be0dee563380147a5b81ba10dd8885d7fbbc9eb574be67d185" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", ] [[package]] @@ -20765,7 +20424,7 @@ version = "0.230.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808198a69b5a0535583370a51d459baa14261dfab04800c4864ee9e1a14346ed" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "indexmap 2.14.0", "semver 1.0.27", ] @@ -20775,7 +20434,7 @@ name = "wasmparser" version = "0.230.0" source = "git+https://github.com/gear-tech/wasm-tools?branch=gear-stable-1.230#d6846c156c140bb59e7ff3286f02fc67a91233f7" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "indexmap 2.14.0", ] @@ -20785,7 +20444,7 @@ version = "0.246.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71cde4757396defafd25417cfb36aa3161027d06d865b0c24baaae229aac005d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "hashbrown 0.16.1", "indexmap 2.14.0", "semver 1.0.27", @@ -20798,7 +20457,7 @@ version = "0.250.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071d99cdfb8111603ed05500506c3298a940b58d609dd0259d3981785dd33556" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.13.0", "indexmap 2.14.0", "semver 1.0.27", ] @@ -20842,10 +20501,13 @@ checksum = "af4eccc0728f061979efa8ff4c962cff7041fead4baadb74973f01b9c47158a4" dependencies = [ "addr2line 0.26.1", "async-trait", - "bitflags 2.10.0", + "bitflags 2.13.0", "bumpalo", "cc", "cfg-if", + "fxprof-processed-profile", + "gimli 0.33.0", + "ittapi", "libc", "log", "mach2 0.4.3", @@ -20858,6 +20520,7 @@ dependencies = [ "rustix 1.1.3", "serde", "serde_derive", + "serde_json", "smallvec", "target-lexicon", "wasmparser 0.246.2", @@ -20984,6 +20647,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84f364747aa74c686b18925918e5cfd615a73c9613c7a31fc1cd86f42df12fbe" dependencies = [ "cc", + "object 0.39.1", + "rustix 1.1.3", "wasmtime-internal-versioned-export-macros", ] @@ -21096,16 +20761,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", -] - [[package]] name = "webpki-root-certs" version = "0.26.11" @@ -21226,6 +20881,16 @@ dependencies = [ "wasmtime-internal-cranelift", ] +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.53.0" @@ -21246,6 +20911,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.53.0" @@ -21334,21 +21008,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -21717,23 +21376,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "x509-parser" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" -dependencies = [ - "asn1-rs 0.5.2", - "data-encoding", - "der-parser 8.2.0", - "lazy_static", - "nom 7.1.3", - "oid-registry 0.6.1", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - [[package]] name = "x509-parser" version = "0.16.0" @@ -21768,6 +21410,17 @@ dependencies = [ "time", ] +[[package]] +name = "xcm-procedural" +version = "11.0.2" +source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0#e3737178ec726cffe506c907263aaaa417893fd0" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "xml-rs" version = "0.8.28" @@ -21800,9 +21453,9 @@ dependencies = [ [[package]] name = "yamux" -version = "0.13.8" +version = "0.13.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deab71f2e20691b4728b349c6cee8fc7223880fa67b6b4f92225ec32225447e5" +checksum = "1991f6690292030e31b0144d73f5e8368936c58e45e7068254f7138b23b00672" dependencies = [ "futures", "log", diff --git a/Cargo.toml b/Cargo.toml index ea9efda81ea..7d741b9105e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ members = [ "substrate/runtime-executor/common", "substrate/runtime-executor/polkavm", "substrate/runtime-executor/wasmtime", - "substrate/sc-mixnet", "substrate/sp-allocator", "substrate/sp-runtime-interface-proc-macro", "substrate/sp-wasm-interface", @@ -56,8 +55,6 @@ members = [ "vara/tools/regression-analysis/junit-common", # ethexe "ethexe/*", - "ethexe/malachite/core", - "ethexe/malachite/service", "ethexe/runtime/common", "ethexe/service/utils", # sdk @@ -202,7 +199,7 @@ parity-wasm = "0.45.0" parity-scale-codec = { version = "3.7.5", default-features = false } parking_lot = "0.12.3" path-clean = "1.0.1" -primitive-types = { version = "0.12.2", default-features = false } +primitive-types = { version = "0.13.1", default-features = false } proc-macro-crate = "3.0.0" proc-macro2 = { version = "1", default-features = false } prometheus = { version = "0.14.0", default-features = false } @@ -224,6 +221,7 @@ serde_json = { version = "1.0.135", default-features = false, features = [ ] } serde-json-wasm = { version = "1.0.1", default-features = false } sha-1 = "0.10.1" +shlex = "1.3.0" snapbox = "0.6.24" static_init = "1.0.3" subxt = "0.44.0" @@ -233,7 +231,20 @@ tokio = { version = "1.38.0" } lru = "0.16.1" url = "2.5.2" wat = "1.0.71" -wasmtime = { version = "44.0.1", default-features = false, features = ["anyhow", "winch"] } +wasmtime = { version = "44.0.1", default-features = false, features = [ + "addr2line", + "anyhow", + "cache", + "cranelift", + "demangle", + "gc", + "gc-null", + "parallel-compilation", + "pooling-allocator", + "profiling", + "threads", + "winch", +] } wasmparser = { version = "0.230", default-features = false, features = ["validate", "features"] } which = "4.4.2" winapi = "0.3.9" @@ -370,165 +381,147 @@ ethexe-compute = { path = "ethexe/compute", default-features = false } ethexe-blob-loader = { path = "ethexe/blob-loader", default-features = false } ethexe-db-init = { path = "ethexe/db/init", default-features = false } ethexe-node-wrapper = {path = "ethexe/node-wrapper", default-features = false} -ethexe-malachite = { path = "ethexe/malachite/service", default-features = false } -ethexe-malachite-core = { path = "ethexe/malachite/core", default-features = false } - -# libp2p-identity for ethexe-malachite-core's swarm peer-id derivation. libp2p-identity = { version = "0.2", default-features = false, features = ["secp256k1"] } # Pinned at the version `ethexe-db`'s librocksdb-sys uses — only one # `links = "rocksdb"` crate may live in the dependency graph. -rocksdb = { version = "0.21", default-features = false, features = ["snappy"] } - -# Malachite BFT engine — canonical fork at circlefin/malachite, pinned so -# all sub-crates share the same snapshot. -malachitebft-app-channel = { package = "arc-malachitebft-app-channel", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-app = { package = "arc-malachitebft-app", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-codec = { package = "arc-malachitebft-codec", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-core-consensus = { package = "arc-malachitebft-core-consensus", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-core-types = { package = "arc-malachitebft-core-types", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-engine = { package = "arc-malachitebft-engine", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-proto = { package = "arc-malachitebft-proto", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-signing = { package = "arc-malachitebft-signing", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-signing-ed25519 = { package = "arc-malachitebft-signing-ed25519", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-signing-ecdsa = { package = "arc-malachitebft-signing-ecdsa", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7", default-features = false, features = ["k256", "rand", "serde", "std"] } -malachitebft-sync = { package = "arc-malachitebft-sync", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } -malachitebft-test = { package = "arc-malachitebft-test", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +rocksdb = { version = "0.24", default-features = false, features = ["snappy"] } # Common executor between `sandbox-host` and `lazy-pages-fuzzer` wasmi = { version = "0.38" } # Substrate deps -bp-header-chain = { version = "0.18.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } +bp-header-chain = { version = "0.26.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } binary-merkle-tree = { version = "16.1.1", default-features = false } -frame-benchmarking = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -frame-benchmarking-cli = { version = "43.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -frame-election-provider-support = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -frame-executive = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -frame-support = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -frame-support-test = { version = "3.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -frame-system = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -frame-system-benchmarking = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -frame-remote-externalities = { version = "0.46.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -frame-try-runtime = { version = "0.44.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -frame-system-rpc-runtime-api = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } +frame-benchmarking = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +frame-benchmarking-cli = { version = "54.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +frame-election-provider-support = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +frame-executive = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +frame-support = { version = "46.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +frame-support-test = { version = "3.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +frame-system = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +frame-system-benchmarking = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +frame-remote-externalities = { version = "0.57.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +frame-try-runtime = { version = "0.52.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +frame-system-rpc-runtime-api = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } frame-metadata = { version = "16.0.0", default-features = false } -frame-metadata-hash-extension = { default-features = false, git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } +frame-metadata-hash-extension = { version = "0.14.0", default-features = false, git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } polkavm-linker = "0.9.2" -generate-bags = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -pallet-authorship = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-authority-discovery = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-babe = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-bags-list = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-bounties = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-child-bounties = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-balances = { version = "39.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-conviction-voting = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-election-provider-multi-phase = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-grandpa = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-identity = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-im-online = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-multisig = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-nomination-pools = { version = "35.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-nomination-pools-runtime-api = { version = "33.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-offences = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-preimage = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-proxy = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-ranked-collective = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-referenda = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-scheduler = { version = "39.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-session = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-staking = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-staking-runtime-api = { version = "24.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-staking-reward-fn = { version = "22.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-sudo = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-timestamp = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-transaction-payment = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-transaction-payment-rpc = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-treasury = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-utility = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-vesting = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -pallet-whitelist = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.17.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-authority-discovery = { version = "0.45.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-block-builder = { version = "0.42.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-consensus = { version = "0.44.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-consensus-babe = { version = "0.45.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-consensus-babe-rpc = { version = "0.45.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-consensus-slots = { version = "0.44.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-crypto-ec-utils = { version = "0.14.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-debug-derive = { version = "14.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sc-chain-spec = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-cli = { version = "0.47.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-client-api = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } +generate-bags = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +pallet-authorship = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-authority-discovery = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-babe = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-bags-list = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-bounties = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-child-bounties = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-balances = { version = "47.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-conviction-voting = { version = "46.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-election-provider-multi-phase = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-grandpa = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-identity = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-im-online = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-migrations = { version = "16.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-multisig = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-nomination-pools = { version = "44.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-nomination-pools-runtime-api = { version = "42.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-offences = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-preimage = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-proxy = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-ranked-collective = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-referenda = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-scheduler = { version = "47.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-session = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-staking = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-staking-runtime-api = { version = "31.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-staking-reward-fn = { version = "24.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-sudo = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-timestamp = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-transaction-payment = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-transaction-payment-rpc = { version = "49.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-treasury = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-utility = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-vesting = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +pallet-whitelist = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.17.7", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-authority-discovery = { version = "0.56.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-block-builder = { version = "0.49.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-consensus = { version = "0.55.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-consensus-babe = { version = "0.56.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-consensus-babe-rpc = { version = "0.56.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-consensus-slots = { version = "0.55.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-crypto-ec-utils = { version = "0.20.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-debug-derive = { version = "15.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sc-chain-spec = { version = "49.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-cli = { version = "0.58.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-client-api = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } sc-executor = { path = "substrate/runtime-executor" } sc-executor-common = { path = "substrate/runtime-executor/common" } sc-executor-polkavm = { path = "substrate/runtime-executor/polkavm" } sc-executor-wasmtime = { path = "substrate/runtime-executor/wasmtime" } -sc-mixnet = { path = "substrate/sc-mixnet", default-features = false } -sc-consensus-grandpa = { version = "0.30.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-consensus-grandpa-rpc = { version = "0.30.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-network = { version = "0.45.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-network-sync = { version = "0.44.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-network-types = { version = "0.12.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-offchain = { version = "40.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-proposer-metrics = { version = "0.18.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-service = { version = "0.46.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-telemetry = { version = "25.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-rpc = { version = "40.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-runtime-test = { version = "2.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-sync-state-rpc = { version = "0.45.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-sysinfo = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-transaction-pool = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-transaction-pool-api = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sc-tracing = { version = "37.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } +sc-mixnet = { version = "0.26.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sc-consensus-grandpa = { version = "0.41.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-consensus-grandpa-rpc = { version = "0.41.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-network = { version = "0.56.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-network-sync = { version = "0.55.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-network-types = { version = "0.20.2", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-offchain = { version = "51.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-proposer-metrics = { version = "0.20.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-service = { version = "0.57.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-telemetry = { version = "30.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-rpc = { version = "51.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-runtime-test = { version = "2.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-sync-state-rpc = { version = "0.56.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-sysinfo = { version = "47.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-transaction-pool = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-transaction-pool-api = { version = "44.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sc-tracing = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } sp-allocator = { path = "substrate/sp-allocator", default-features = false } -sp-api = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-authority-discovery = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-arithmetic = { version = "26.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-blockchain = { version = "37.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-block-builder = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-core = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-consensus = { version = "0.40.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-consensus-babe = { version = "0.40.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-consensus-slots = { version = "0.40.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-application-crypto = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-externalities = { version = "0.29.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-consensus-grandpa = { version = "21.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-genesis-builder = { version = "0.15.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-inherents = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-io = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-keyring = { version = "39.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-keystore = { version = "0.40.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-maybe-compressed-blob = { version = "11.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-mixnet = { version = "0.12.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-npos-elections = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-offchain = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-rpc = { version = "32.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-runtime = { version = "39.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-runtime-interface = { version = "28.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-session = { version = "36.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-std = { version = "14.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-state-machine = { version = "0.43.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-staking = { version = "36.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-storage = { version = "21.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-timestamp = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-tracing = { version = "17.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-transaction-pool = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-transaction-storage-proof = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-trie = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } -sp-version = { version = "37.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false } +sp-api = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-authority-discovery = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-arithmetic = { version = "28.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-blockchain = { version = "44.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-block-builder = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-core = { version = "40.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-consensus = { version = "0.47.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-consensus-babe = { version = "0.47.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-consensus-slots = { version = "0.47.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-application-crypto = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-externalities = { version = "0.32.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-consensus-grandpa = { version = "28.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-genesis-builder = { version = "0.22.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-inherents = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-io = { version = "45.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-keyring = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-keystore = { version = "0.46.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-maybe-compressed-blob = { version = "11.1.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-mixnet = { version = "0.19.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-npos-elections = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-offchain = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-rpc = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-runtime = { version = "46.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-runtime-interface = { version = "34.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-session = { version = "43.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-std = { version = "14.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-state-machine = { version = "0.50.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-staking = { version = "43.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-storage = { version = "23.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-timestamp = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-tracing = { version = "19.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-transaction-pool = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-transaction-storage-proof = { version = "41.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-trie = { version = "43.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } +sp-version = { version = "44.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false } sp-wasm-interface = { path = "substrate/sp-wasm-interface", default-features = false } -sp-panic-handler = { version = "13.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } +sp-panic-handler = { version = "13.0.2", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } sp-wasm-interface-common = { path = "substrate/sp-wasm-interface-common", default-features = false } -substrate-build-script-utils = { version = "11.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -substrate-frame-rpc-system = { version = "39.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -substrate-rpc-client = { version = "0.44.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -substrate-state-trie-migration-rpc = { version = "38.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -substrate-test-client = { version = "2.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } +substrate-build-script-utils = { version = "11.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +substrate-frame-rpc-system = { version = "50.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +substrate-rpc-client = { version = "0.55.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +substrate-state-trie-migration-rpc = { version = "49.0.0", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +substrate-test-client = { version = "2.0.1", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } substrate-wasm-builder = { path = "substrate/substrate-wasm-builder" } # Examples @@ -722,7 +715,6 @@ sc-executor = { path = "substrate/runtime-executor" } sc-executor-common = { path = "substrate/runtime-executor/common" } sc-executor-polkavm = { path = "substrate/runtime-executor/polkavm" } sc-executor-wasmtime = { path = "substrate/runtime-executor/wasmtime" } -sc-mixnet = { path = "substrate/sc-mixnet" } sp-runtime-interface-proc-macro = { path = "substrate/sp-runtime-interface-proc-macro" } sp-wasm-interface = { path = "substrate/sp-wasm-interface" } substrate-wasm-builder = { path = "substrate/substrate-wasm-builder" } diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index cabf140e2c4..bbd9dc04c29 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -13,12 +13,17 @@ Some local crates contain copied or modified source files from `paritytech/polka Source reference: +Current migration source reference: + `substrate/sp-allocator` was sourced from the Gear Polkadot SDK fork `gear-polkadot-stable2409-wasm32v1-none` at `1d1b394647eb26c094cf50c759b900dc5faa3b80`, derived from Parity Polkadot SDK `sc-allocator`. These copied source files retain the upstream copyright notices and their original SPDX headers. See [`substrate/README.md`](substrate/README.md) for the shared fork, provenance, and publishing notice. Related Gear-authored compatibility crate: `substrate/sp-wasm-interface-common` keeps the upstream-compatible local package name `sp-wasm-interface-common` and is published by Gear as `gsp-wasm-interface-common`, but its source files are not copied Polkadot SDK source. +`substrate/sc-mixnet` was removed during the stable2603-3 migration; Gear now +uses upstream `sc-mixnet` from the Polkadot SDK source reference above. + Additional third-party file: `substrate/runtime-executor/wasmtime/src/test-guard-page-skip.wat` is a modified WebAssembly testsuite fixture from , licensed under Apache-2.0. Apache-2.0 license text: diff --git a/TODOS.md b/TODOS.md new file mode 100644 index 00000000000..8a56d48c474 --- /dev/null +++ b/TODOS.md @@ -0,0 +1,14 @@ +# TODOs + +## Polkadot SDK stable2603 Follow-Ups + +- Evaluate stable2603 `system_version >= 3` pending-code runtime-upgrade + semantics in a dedicated branch. This migration intentionally keeps + `system_version = 1`. +- Run try-runtime against production and development snapshots for the wired + identity lazy migration and child-bounties v0-to-v1 migration, confirming + storage versions, cardinality, and weight bounds. +- Revisit ethexe Malachite once its `libp2p` dependency can coexist with the + stable2603 Polkadot SDK graph. The current blocker is the exact + `libp2p-swarm-derive` conflict between stable2603 `sc-network` and + Malachite's `libp2p` stack. diff --git a/docs/polkadot-sdk-stable2603-3-migration.md b/docs/polkadot-sdk-stable2603-3-migration.md new file mode 100644 index 00000000000..21cdeffb532 --- /dev/null +++ b/docs/polkadot-sdk-stable2603-3-migration.md @@ -0,0 +1,98 @@ +# Polkadot SDK stable2603-3 Migration Notes + +Target SDK revision: `e3737178ec726cffe506c907263aaaa417893fd0` +(`polkadot-stable2603-3`). + +This note records the maintainer decisions for the direct migration from the +stable2409-era dependency graph to stable2603-3. + +## Release Checklist + +The migration scope covers every non-RC stable release note from stable2412 +through stable2603-3: + +- `stable2412`, `stable2412-1` through `stable2412-11` +- `stable2503`, `stable2503-1` through `stable2503-11` +- `stable2506`, `stable2506-1`, `stable2506-2`, `stable2506-3`, `stable2506-4`, + `stable2506-5`, `stable2506-6`, `stable2506-7`, `stable2506-9`, + `stable2506-10`, `stable2506-11` +- `stable2509`, `stable2509-1` through `stable2509-8` +- `stable2512`, `stable2512-1`, `stable2512-2`, `stable2512-3`, `stable2512-5` +- `stable2603`, `stable2603-1`, `stable2603-2`, `stable2603-3` + +Standalone-chain impact areas checked in this branch: + +- Runtime version field rename from `state_version` to `system_version` +- `SignedExtension` to `TransactionExtension` for custom payment and staking + blacklist extensions +- Stable2603 transaction pool and BABE proposer APIs +- Stable2603 offchain bare transaction creation API +- FRAME config additions across balances, transaction payment, session, + scheduler, identity, proxy, multisig, treasury, staking, bags-list, + nomination pools, and election provider multi-phase +- Runtime API shape changes for block builder lazy blocks and session keys +- Local copied executor/runtime-interface/wasm-builder crate compatibility +- Removal of local `substrate/sc-mixnet` in favor of upstream `sc-mixnet` + +## Source Identity + +The workspace is pinned to the Polkadot SDK git source: + +```text +git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cffe506c907263aaaa417893fd0 +``` + +`cargo tree -p gear-cli --all-targets --locked -i sc-mixnet` resolves +`sc-mixnet v0.26.0` from that upstream source only. + +## Runtime Semantics + +`vara-runtime` intentionally keeps: + +```rust +system_version: 1 +``` + +This preserves the pre-stable2603 pending-code runtime-upgrade semantics for +this branch. Do not raise this to `3` or higher without a dedicated runtime +upgrade review and try-runtime evidence. + +The runtime migration set remains limited to the existing Gear migrations plus +the stable2603-compatible FRAME migrations whose storage versions are proven by +snapshot or live-state evidence. Unversioned cleanups remain out of scope. + +In this branch: + +- `pallet_migrations` is wired at runtime pallet index `32` and runs + `pallet_identity::migration::v2::LazyMigrationV1ToV2` as the + multi-block identity migration. +- `pallet_child_bounties::migration::MigrateV0ToV1` is wired into the + single-block runtime migration tuple with a transfer-weight guard based on + balances transfer weight plus one storage read. +- Staking slashes resolve to Treasury and election rewards are routed through + the Gear staking-rewards pool instead of being left as no-op handlers. + +## Local Fork Matrix + +| Local path | Upstream package | stable2603 action | +| --- | --- | --- | +| `substrate/sc-mixnet` | `sc-mixnet` | Deleted; use upstream stable2603-3 | +| `substrate/runtime-executor` | `sc-executor` | Keep Gear fork for sandbox/lazy-pages compatibility | +| `substrate/runtime-executor/common` | `sc-executor-common` | Refreshed for stable2603 compatibility | +| `substrate/runtime-executor/polkavm` | `sc-executor-polkavm` | Refreshed for stable2603 compatibility | +| `substrate/runtime-executor/wasmtime` | `sc-executor-wasmtime` | Refreshed for stable2603 compatibility | +| `substrate/sp-runtime-interface-proc-macro` | `sp-runtime-interface-proc-macro` | Refreshed with Gear runtime-interface compatibility | +| `substrate/sp-wasm-interface` | `sp-wasm-interface` | Keep compatibility-only fork | +| `substrate/sp-wasm-interface-common` | local compatibility crate | Keep compatibility-only fork | +| `substrate/substrate-wasm-builder` | `substrate-wasm-builder` | Refreshed for stable2603 compatibility | + +## Deferred Items + +- Evaluate `system_version >= 3` pending-code runtime-upgrade semantics. +- Re-enable or realign ethexe Malachite integration after resolving the + stable2603 `libp2p` version conflict. The concrete resolver blocker is + stable2603 `sc-network` pulling `libp2p` 0.54 / `libp2p-swarm` 0.45 while + Malachite pulls `libp2p` 0.56 / `libp2p-swarm` 0.47, whose exact + `libp2p-swarm-derive` requirements cannot coexist in the same workspace. +- Run try-runtime against production and development snapshots before shipping + the wired identity and child-bounties runtime migrations. diff --git a/ethexe/cli/Cargo.toml b/ethexe/cli/Cargo.toml index 185e256c3b6..9db483eef03 100644 --- a/ethexe/cli/Cargo.toml +++ b/ethexe/cli/Cargo.toml @@ -18,7 +18,6 @@ path = "src/main.rs" [dependencies] ethexe-compute.workspace = true ethexe-network.workspace = true -ethexe-malachite.workspace = true ethexe-prometheus.workspace = true ethexe-rpc = { workspace = true, features = ["client"] } ethexe-service.workspace = true diff --git a/ethexe/common/src/gear.rs b/ethexe/common/src/gear.rs index 3f987ebbcb1..48a6c07a3e0 100644 --- a/ethexe/common/src/gear.rs +++ b/ethexe/common/src/gear.rs @@ -12,6 +12,10 @@ use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; use sha3::Digest as _; +fn u256_to_be_bytes(value: U256) -> [u8; 32] { + value.to_big_endian() +} + // TODO: support query from router. pub const COMPUTATION_THRESHOLD: u64 = 2_500_000_000; pub const WVARA_PER_SECOND: u128 = 10_000_000_000_000; @@ -96,7 +100,7 @@ impl ToDigest for OperatorRewardsCommitment { fn update_hasher(&self, hasher: &mut sha3::Keccak256) { let OperatorRewardsCommitment { amount, root } = self; - hasher.update(<[u8; 32]>::from(*amount)); + hasher.update(u256_to_be_bytes(*amount)); hasher.update(root); } } @@ -126,10 +130,10 @@ impl ToDigest for StakerRewardsCommitment { .iter() .for_each(|StakerRewards { vault, amount }| { hasher.update(vault); - hasher.update(<[u8; 32]>::from(*amount)); + hasher.update(u256_to_be_bytes(*amount)); }); - hasher.update(<[u8; 32]>::from(*total_amount)); + hasher.update(u256_to_be_bytes(*total_amount)); hasher.update(token); } } @@ -237,8 +241,8 @@ impl ToDigest for ValidatorsCommitment { } = self; hasher.update([*has_aggregated_public_key as u8]); - hasher.update(<[u8; 32]>::from(aggregated_public_key.x)); - hasher.update(<[u8; 32]>::from(aggregated_public_key.y)); + hasher.update(u256_to_be_bytes(aggregated_public_key.x)); + hasher.update(u256_to_be_bytes(aggregated_public_key.y)); hasher.update( validators .iter() diff --git a/ethexe/db/Cargo.toml b/ethexe/db/Cargo.toml index 1e6105b9302..cd37f1db4ac 100644 --- a/ethexe/db/Cargo.toml +++ b/ethexe/db/Cargo.toml @@ -40,12 +40,12 @@ futures.workspace = true [target.'cfg(target_env = "msvc")'.dependencies.rocksdb] default-features = false features = ["snappy"] -version = "0.21" +version = "0.24" [target.'cfg(not(target_env = "msvc"))'.dependencies.rocksdb] default-features = false features = ["snappy", "jemalloc"] -version = "0.21" +version = "0.24" [dev-dependencies] scopeguard.workspace = true diff --git a/ethexe/ethereum/src/abi/mod.rs b/ethexe/ethereum/src/abi/mod.rs index 11eeda7936c..2a2ecd4538e 100644 --- a/ethexe/ethereum/src/abi/mod.rs +++ b/ethexe/ethereum/src/abi/mod.rs @@ -218,8 +218,7 @@ pub mod utils { } pub fn u256_to_uint256(value: U256) -> Uint256 { - let mut bytes = [0u8; Uint256::BYTES]; - value.to_little_endian(&mut bytes); + let bytes = value.to_little_endian(); Uint256::from_le_bytes(bytes) } diff --git a/ethexe/network/Cargo.toml b/ethexe/network/Cargo.toml index c57cdb0da4e..a27c653f352 100644 --- a/ethexe/network/Cargo.toml +++ b/ethexe/network/Cargo.toml @@ -23,8 +23,8 @@ ethexe-common.workspace = true gprimitives = { workspace = true, features = ["std", "codec"] } # libp2p -libp2p = { version = "0.56.0", features = ["mdns", "gossipsub", "kad", "identify", "ping", "secp256k1", "request-response", "quic", "tcp", "dns", "tls", "tokio", "macros", "plaintext", "yamux", "metrics"] } -libp2p-gossipsub = { version = "0.49.4", features = ["metrics"] } +libp2p = { version = "0.54.1", features = ["mdns", "gossipsub", "kad", "identify", "ping", "secp256k1", "request-response", "quic", "tcp", "dns", "tls", "tokio", "macros", "plaintext", "yamux", "metrics"] } +libp2p-gossipsub = "0.47.0" # other deps tokio = { workspace = true, features = ["macros", "sync"] } @@ -41,7 +41,7 @@ auto_impl.workspace = true lru.workspace = true indexmap.workspace = true ip_network.workspace = true -prometheus-client = "0.23.1" # specific version that lip2p uses +prometheus-client = "0.22.3" # specific version that libp2p uses metrics.workspace = true metrics-derive.workspace = true assert_matches.workspace = true @@ -50,7 +50,7 @@ assert_matches.workspace = true gear-workspace-hack.workspace = true [dev-dependencies] -libp2p-swarm-test = { version = "0.6.0", default-features = false, features = ["tokio"] } +libp2p-swarm-test = { version = "0.4.0", default-features = false } tokio = { workspace = true, features = ["full", "test-util"] } tracing-subscriber.workspace = true proptest = { workspace = true } diff --git a/ethexe/network/src/db_sync/mod.rs b/ethexe/network/src/db_sync/mod.rs index 3a3f0d82e37..af31732fee8 100644 --- a/ethexe/network/src/db_sync/mod.rs +++ b/ethexe/network/src/db_sync/mod.rs @@ -408,7 +408,6 @@ impl Behaviour { match event { request_response::Event::Message { peer, - connection_id: _, message: Message::Request { request_id: _, @@ -434,7 +433,6 @@ impl Behaviour { } request_response::Event::Message { peer: _, - connection_id: _, message: Message::Response { request_id, @@ -445,7 +443,6 @@ impl Behaviour { } request_response::Event::OutboundFailure { peer, - connection_id: _, request_id, error, } => { @@ -461,7 +458,6 @@ impl Behaviour { } request_response::Event::InboundFailure { peer, - connection_id: _, request_id: _, error: InboundFailure::UnsupportedProtocols, } => { diff --git a/ethexe/network/src/gossipsub.rs b/ethexe/network/src/gossipsub.rs index 72b79e177d7..580a5ea8483 100644 --- a/ethexe/network/src/gossipsub.rs +++ b/ethexe/network/src/gossipsub.rs @@ -73,7 +73,7 @@ impl MessageValidator { &propagation_source, acceptance, ); - debug_assert!(validated); + debug_assert!(validated.unwrap_or(false)); message } } @@ -123,12 +123,13 @@ impl Behaviour { .validate_messages() .build() .map_err(|e| anyhow!("`gossipsub::ConfigBuilder::build()` error: {e}"))?; - let mut inner = gossipsub::Behaviour::new(MessageAuthenticity::Signed(keypair), inner) - .map_err(|e| anyhow!("`gossipsub::Behaviour` error: {e}"))? - .with_metrics( - registry.sub_registry_with_prefix("libp2p_gossipsub"), - MetricsConfig::default(), - ); + let mut inner = gossipsub::Behaviour::new_with_metrics( + MessageAuthenticity::Signed(keypair), + inner, + registry.sub_registry_with_prefix("libp2p_gossipsub"), + MetricsConfig::default(), + ) + .map_err(|e| anyhow!("`gossipsub::Behaviour` error: {e}"))?; inner .with_peer_score(PeerScoreParams::default(), PeerScoreThresholds::default()) .map_err(|e| anyhow!("`gossipsub` scoring parameters error: {e}"))?; @@ -189,7 +190,7 @@ impl Behaviour { &propagation_source, MessageAcceptance::Reject, ); - debug_assert!(validated); + debug_assert!(validated.unwrap_or(false)); self.peer_score.invalid_data(source); return Poll::Pending; } @@ -215,14 +216,6 @@ impl Behaviour { log::trace!("peer doesn't support gossipsub: {peer_id}"); Poll::Pending } - gossipsub::Event::SlowPeer { - peer_id, - failed_messages: _, - } => { - // TODO: consider to score peer - log::trace!("SlowPeer received {peer_id}"); - Poll::Pending - } } } } @@ -310,7 +303,7 @@ impl NetworkBehaviour for Behaviour { Ok(_msg_id) => { let _ = self.message_queue.pop_front().expect("checked above"); } - Err(PublishError::NoPeersSubscribedToTopic) => break, + Err(PublishError::InsufficientPeers) => break, Err(error) => { let message = self.message_queue.pop_front().expect("checked above"); return Poll::Ready(ToSwarm::GenerateEvent(Event::PublishFailure { diff --git a/ethexe/network/src/injected.rs b/ethexe/network/src/injected.rs index 8b3f1c05ee4..b8d1eda150a 100644 --- a/ethexe/network/src/injected.rs +++ b/ethexe/network/src/injected.rs @@ -188,11 +188,14 @@ impl Behaviour { } for (recipient, identity) in recipients { - let id = self.inner.send_request_with_addresses( - &identity.peer_id(), - InnerRequest(transaction.clone()), - identity.addresses().iter().cloned().collect(), - ); + let peer_id = identity.peer_id(); + for address in identity.addresses() { + self.inner.add_address(&peer_id, address.clone()); + } + + let id = self + .inner + .send_request(&peer_id, InnerRequest(transaction.clone())); self.pending_requests.insert(id, tx_hash); self.transaction_cache @@ -210,7 +213,6 @@ impl Behaviour { match event { request_response::Event::Message { peer, - connection_id: _, message: Message::Request { request_id: _, @@ -235,7 +237,6 @@ impl Behaviour { } request_response::Event::Message { peer: _, - connection_id: _, message: Message::Response { request_id, @@ -255,7 +256,6 @@ impl Behaviour { } request_response::Event::OutboundFailure { peer, - connection_id: _, request_id, error, } => { @@ -278,7 +278,6 @@ impl Behaviour { } request_response::Event::InboundFailure { peer, - connection_id: _, request_id: _, error: InboundFailure::UnsupportedProtocols, } => { diff --git a/ethexe/network/src/peer_score.rs b/ethexe/network/src/peer_score.rs index a30691712d9..e24eb2ec75c 100644 --- a/ethexe/network/src/peer_score.rs +++ b/ethexe/network/src/peer_score.rs @@ -11,7 +11,7 @@ use libp2p::{ }, }; use std::{ - collections::{HashMap, VecDeque}, + collections::{HashMap, HashSet, VecDeque}, task::{Context, Poll}, time::Duration, }; @@ -158,6 +158,7 @@ pub(crate) struct Behaviour { pending_events: VecDeque, config: Config, block_list: BlockListBehaviour, + blocked_peers: HashSet, handle: Handle, rx: mpsc::UnboundedReceiver<(PeerId, ScoreDecreaseReason)>, peers: HashMap, @@ -174,6 +175,7 @@ impl Behaviour { driver: time::interval(config.driver_time), config, block_list: BlockListBehaviour::default(), + blocked_peers: HashSet::new(), handle, rx, peers: HashMap::new(), @@ -198,6 +200,7 @@ impl Behaviour { if was_blocked && !now_blocked { self.block_list.unblock_peer(peer_id); + self.blocked_peers.remove(&peer_id); self.pending_events .push_back(Event::PeerUnblocked { peer_id }); } @@ -205,7 +208,7 @@ impl Behaviour { // remove the peer score entry if it is not updated for a long time if entry.is_expired(self.config.forget_time) { // should be unblocked during decay - debug_assert!(!self.block_list.blocked_peers().contains(&peer_id)); + debug_assert!(!self.blocked_peers.contains(&peer_id)); return false; } @@ -214,7 +217,7 @@ impl Behaviour { self.metrics .blocked_peers - .set(self.block_list.blocked_peers().len() as f64); + .set(self.blocked_peers.len() as f64); } fn on_score_decrease(&mut self, peer_id: PeerId, reason: ScoreDecreaseReason) -> Option { @@ -226,6 +229,7 @@ impl Behaviour { if !was_blocked && now_blocked { self.block_list.block_peer(peer_id); + self.blocked_peers.insert(peer_id); return Some(Event::PeerBlocked { peer_id, last_reason: reason, diff --git a/ethexe/network/src/slots.rs b/ethexe/network/src/slots.rs index 9a40c53dc06..62e693bf842 100644 --- a/ethexe/network/src/slots.rs +++ b/ethexe/network/src/slots.rs @@ -45,6 +45,8 @@ use tokio::{ time::{Instant, Interval}, }; +type PendingEvent = ToSwarm>; + #[derive(Clone, metrics_derive::Metrics)] #[metrics(scope = "ethexe_network_slots")] struct Metrics { @@ -249,7 +251,7 @@ pub struct Behaviour { config: Config, pending_outbound_peers: ConnectionMap, peers: HashMap, - pending_events: VecDeque>, + pending_events: VecDeque, addresses: PeerAddresses, driver: Interval, metrics: Metrics, diff --git a/ethexe/rpc/src/apis/mod.rs b/ethexe/rpc/src/apis/mod.rs index 4f7edad8228..a20015c4862 100644 --- a/ethexe/rpc/src/apis/mod.rs +++ b/ethexe/rpc/src/apis/mod.rs @@ -13,7 +13,7 @@ pub use crate::apis::{ block::BlockClient, code::CodeClient, dev::DevClient, - info::{InfoClient, RPC_VERSION}, + info::InfoClient, injected::InjectedClient, program::{CalculateReplyForHandleResult, FullProgramState, ProgramClient}, }; @@ -23,6 +23,7 @@ pub use block::{BlockApi, BlockServer}; pub use code::{CodeApi, CodeServer}; #[cfg(feature = "server")] pub use dev::{DevApi, DevServer}; +pub use info::RPC_VERSION; #[cfg(feature = "server")] pub use info::{InfoApi, InfoServer}; #[cfg(feature = "server")] diff --git a/ethexe/service/Cargo.toml b/ethexe/service/Cargo.toml index 00eb0b3c584..6ccddddd216 100644 --- a/ethexe/service/Cargo.toml +++ b/ethexe/service/Cargo.toml @@ -19,7 +19,6 @@ ethexe-observer.workspace = true ethexe-blob-loader.workspace = true ethexe-processor.workspace = true ethexe-consensus.workspace = true -ethexe-malachite.workspace = true ethexe-ethereum.workspace = true ethexe-common = { workspace = true, features = ["std", "mock"] } ethexe-runtime-common.workspace = true diff --git a/protocol/core/src/limited/vec.rs b/protocol/core/src/limited/vec.rs index 1e18e726488..ad11c1e1ca2 100644 --- a/protocol/core/src/limited/vec.rs +++ b/protocol/core/src/limited/vec.rs @@ -22,7 +22,7 @@ use scale_decode::{ use scale_encode::EncodeAsType; use scale_info::{ TypeInfo, - scale::{Decode, Encode}, + scale::{Decode, DecodeWithMemTracking, Encode}, }; /// Vector with limited length. @@ -65,6 +65,8 @@ impl Decode for LimitedVec { } } +impl DecodeWithMemTracking for LimitedVec {} + impl MaxEncodedLen for LimitedVec { fn max_encoded_len() -> usize { assert!( diff --git a/protocol/core/src/message/common.rs b/protocol/core/src/message/common.rs index 6839e04e5f0..e2a3788dd43 100644 --- a/protocol/core/src/message/common.rs +++ b/protocol/core/src/message/common.rs @@ -10,14 +10,16 @@ use crate::{ }; use core::ops::Deref; use gear_core_errors::{ReplyCode, SignalCode}; -use parity_scale_codec::{Decode, Encode}; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}; use scale_decode::DecodeAsType; use scale_encode::EncodeAsType; use scale_info::TypeInfo; /// An entity that is used for interaction between actors. /// Can transfer value and executes by programs in corresponding function: init, handle or handle_reply. -#[derive(Clone, Debug, PartialEq, Eq, Decode, DecodeAsType, Encode, EncodeAsType)] +#[derive( + Clone, Debug, PartialEq, Eq, Decode, DecodeAsType, DecodeWithMemTracking, Encode, EncodeAsType, +)] pub struct Message { /// Message id. id: MessageId, @@ -159,6 +161,7 @@ impl Message { Hash, Decode, DecodeAsType, + DecodeWithMemTracking, Encode, EncodeAsType, TypeInfo, @@ -212,7 +215,18 @@ impl MessageDetails { /// Part of [`ReplyMessage`](crate::message::ReplyMessage) logic, containing data about on which message id /// this replies and its status code. #[derive( - Clone, Copy, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo, + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + Decode, + DecodeAsType, + DecodeWithMemTracking, + Encode, + EncodeAsType, + TypeInfo, )] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct ReplyDetails { @@ -246,7 +260,18 @@ impl ReplyDetails { /// Signal details data. #[derive( - Clone, Copy, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo, + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + Decode, + DecodeAsType, + DecodeWithMemTracking, + Encode, + EncodeAsType, + TypeInfo, )] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct SignalDetails { @@ -279,7 +304,9 @@ impl SignalDetails { } /// Message with entry point. -#[derive(Clone, Debug, PartialEq, Eq, Decode, DecodeAsType, Encode, EncodeAsType)] +#[derive( + Clone, Debug, PartialEq, Eq, Decode, DecodeAsType, DecodeWithMemTracking, Encode, EncodeAsType, +)] pub struct Dispatch { /// Entry point for the message. kind: DispatchKind, diff --git a/protocol/core/src/message/context.rs b/protocol/core/src/message/context.rs index fe92e1acb9a..e5e8065306e 100644 --- a/protocol/core/src/message/context.rs +++ b/protocol/core/src/message/context.rs @@ -15,7 +15,7 @@ use alloc::{ vec::Vec, }; use gear_core_errors::{ExecutionError, ExtError, MessageError as Error, MessageError}; -use parity_scale_codec::{Decode, Encode}; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}; use scale_decode::DecodeAsType; use scale_encode::EncodeAsType; use scale_info::TypeInfo; @@ -132,7 +132,9 @@ impl ContextOutcome { } } /// Store of current temporary message execution context. -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Decode, Encode, TypeInfo)] +#[derive( + Clone, Debug, Default, PartialEq, Eq, Hash, Decode, DecodeWithMemTracking, Encode, TypeInfo, +)] pub struct OutgoingPayloads { handles: BTreeMap>, reply: Option, @@ -141,7 +143,18 @@ pub struct OutgoingPayloads { /// Store of previous message execution context. #[derive( - Clone, Debug, Default, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo, + Clone, + Debug, + Default, + PartialEq, + Eq, + Hash, + Decode, + DecodeAsType, + DecodeWithMemTracking, + Encode, + EncodeAsType, + TypeInfo, )] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct ContextStore { diff --git a/protocol/core/src/message/mod.rs b/protocol/core/src/message/mod.rs index 8270282343c..f3eddca54f4 100644 --- a/protocol/core/src/message/mod.rs +++ b/protocol/core/src/message/mod.rs @@ -30,7 +30,7 @@ pub use user::{UserMessage, UserStoredMessage}; use core::fmt::Debug; use gear_wasm_instrument::syscalls::SyscallName; -use parity_scale_codec::{Decode, Encode}; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}; use scale_info::TypeInfo; /// Gas limit type for message. @@ -55,6 +55,7 @@ pub type Salt = crate::buffer::Payload; Hash, Decode, DecodeAsType, + DecodeWithMemTracking, Encode, EncodeAsType, TypeInfo, diff --git a/protocol/core/src/message/stored.rs b/protocol/core/src/message/stored.rs index 3fb3597c761..9cf07a34e52 100644 --- a/protocol/core/src/message/stored.rs +++ b/protocol/core/src/message/stored.rs @@ -11,7 +11,7 @@ use crate::{ }; use core::ops::Deref; use gear_core_errors::ReplyCode; -use parity_scale_codec::{Decode, Encode}; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}; use scale_decode::DecodeAsType; use scale_encode::EncodeAsType; use scale_info::TypeInfo; @@ -20,7 +20,17 @@ use scale_info::TypeInfo; /// /// Gasless Message for storing. #[derive( - Clone, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo, + Clone, + Debug, + PartialEq, + Eq, + Hash, + Decode, + DecodeAsType, + DecodeWithMemTracking, + Encode, + EncodeAsType, + TypeInfo, )] pub struct StoredMessage { /// Message id. @@ -145,7 +155,17 @@ impl StoredMessage { /// Stored message with entry point and previous execution context, if exists. #[derive( - Clone, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo, + Clone, + Debug, + PartialEq, + Eq, + Hash, + Decode, + DecodeAsType, + DecodeWithMemTracking, + Encode, + EncodeAsType, + TypeInfo, )] pub struct StoredDispatch { /// Entry point. @@ -222,7 +242,17 @@ impl From for StoredDispatch { /// but delayed messages always don't have [`ContextStore`] /// so we designate this fact via new type. #[derive( - Clone, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo, + Clone, + Debug, + PartialEq, + Eq, + Hash, + Decode, + DecodeAsType, + DecodeWithMemTracking, + Encode, + EncodeAsType, + TypeInfo, )] pub struct StoredDelayedDispatch { /// Entry point. diff --git a/protocol/core/src/message/user.rs b/protocol/core/src/message/user.rs index 89e83355329..0b769614a0b 100644 --- a/protocol/core/src/message/user.rs +++ b/protocol/core/src/message/user.rs @@ -9,14 +9,24 @@ use crate::{ }; use core::convert::TryFrom; use gear_core_errors::ReplyCode; -use parity_scale_codec::{Decode, Encode}; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}; use scale_decode::DecodeAsType; use scale_encode::EncodeAsType; use scale_info::TypeInfo; /// Message sent to user and deposited as event. #[derive( - Clone, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo, + Clone, + Debug, + PartialEq, + Eq, + Hash, + Decode, + DecodeAsType, + DecodeWithMemTracking, + Encode, + EncodeAsType, + TypeInfo, )] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct UserMessage { @@ -136,7 +146,17 @@ impl From for StoredMessage { /// May be represented only with `DispatchKind::Handle`, /// so does not contain message details. #[derive( - Clone, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo, + Clone, + Debug, + PartialEq, + Eq, + Hash, + Decode, + DecodeAsType, + DecodeWithMemTracking, + Encode, + EncodeAsType, + TypeInfo, )] pub struct UserStoredMessage { /// Message id. diff --git a/protocol/core/src/reservation.rs b/protocol/core/src/reservation.rs index e6132f58cf6..6d9ad2cb24e 100644 --- a/protocol/core/src/reservation.rs +++ b/protocol/core/src/reservation.rs @@ -13,7 +13,7 @@ use scale_decode::DecodeAsType; use scale_encode::EncodeAsType; use scale_info::{ TypeInfo, - scale::{Decode, Encode}, + scale::{Decode, DecodeWithMemTracking, Encode}, }; /// An unchangeable wrapper over u64 value, which is required @@ -36,6 +36,7 @@ use scale_info::{ PartialOrd, Decode, DecodeAsType, + DecodeWithMemTracking, Encode, EncodeAsType, TypeInfo, diff --git a/protocol/errors/src/simple.rs b/protocol/errors/src/simple.rs index b2143440351..ef97f49efa6 100644 --- a/protocol/errors/src/simple.rs +++ b/protocol/errors/src/simple.rs @@ -8,7 +8,7 @@ use enum_iterator::Sequence; use serde::{Deserialize, Serialize}; #[cfg(feature = "codec")] use { - parity_scale_codec::{Decode, Encode}, + parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}, scale_decode::DecodeAsType, scale_encode::EncodeAsType, scale_info::TypeInfo, @@ -19,7 +19,14 @@ use { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Sequence, thiserror::Error)] #[cfg_attr( feature = "codec", - derive(Encode, EncodeAsType, Decode, DecodeAsType, TypeInfo) + derive( + Encode, + EncodeAsType, + Decode, + DecodeAsType, + DecodeWithMemTracking, + TypeInfo + ) )] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub enum ReplyCode { @@ -99,7 +106,14 @@ impl ReplyCode { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Sequence, thiserror::Error)] #[cfg_attr( feature = "codec", - derive(Encode, EncodeAsType, Decode, DecodeAsType, TypeInfo) + derive( + Encode, + EncodeAsType, + Decode, + DecodeAsType, + DecodeWithMemTracking, + TypeInfo + ) )] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub enum SuccessReplyReason { @@ -138,7 +152,14 @@ impl SuccessReplyReason { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Sequence, thiserror::Error)] #[cfg_attr( feature = "codec", - derive(Encode, EncodeAsType, Decode, DecodeAsType, TypeInfo) + derive( + Encode, + EncodeAsType, + Decode, + DecodeAsType, + DecodeWithMemTracking, + TypeInfo + ) )] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub enum ErrorReplyReason { @@ -216,7 +237,14 @@ impl ErrorReplyReason { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Sequence, thiserror::Error)] #[cfg_attr( feature = "codec", - derive(Encode, EncodeAsType, Decode, DecodeAsType, TypeInfo) + derive( + Encode, + EncodeAsType, + Decode, + DecodeAsType, + DecodeWithMemTracking, + TypeInfo + ) )] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub enum SimpleExecutionError { @@ -275,7 +303,14 @@ impl SimpleExecutionError { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Sequence, thiserror::Error)] #[cfg_attr( feature = "codec", - derive(Encode, EncodeAsType, Decode, DecodeAsType, TypeInfo) + derive( + Encode, + EncodeAsType, + Decode, + DecodeAsType, + DecodeWithMemTracking, + TypeInfo + ) )] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub enum SimpleUnavailableActorError { @@ -332,7 +367,14 @@ impl SimpleUnavailableActorError { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Sequence, thiserror::Error)] #[cfg_attr( feature = "codec", - derive(Encode, EncodeAsType, Decode, DecodeAsType, TypeInfo) + derive( + Encode, + EncodeAsType, + Decode, + DecodeAsType, + DecodeWithMemTracking, + TypeInfo + ) )] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub enum SignalCode { diff --git a/protocol/gprimitives/src/lib.rs b/protocol/gprimitives/src/lib.rs index af6b8819976..55083fa8913 100644 --- a/protocol/gprimitives/src/lib.rs +++ b/protocol/gprimitives/src/lib.rs @@ -36,7 +36,7 @@ use scale_encode::EncodeAsType; #[cfg(feature = "codec")] use scale_info::{ TypeInfo, - scale::{self, Decode, Encode, MaxEncodedLen}, + scale::{self, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}, }; #[cfg(all(feature = "serde", not(feature = "ethexe")))] use serde::de; @@ -68,7 +68,7 @@ pub enum ConversionError { /// message sending. #[repr(transparent)] #[derive(Clone, Copy, Debug, PartialEq, Eq, From, Into, Zeroable, Pod)] -#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, MaxEncodedLen), codec(crate = scale))] +#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, DecodeWithMemTracking, MaxEncodedLen), codec(crate = scale))] pub struct MessageHandle(u32); /// Program (actor) identifier. @@ -99,7 +99,7 @@ pub struct MessageHandle(u32); )] #[as_ref(forward)] #[as_mut(forward)] -#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, MaxEncodedLen), codec(crate = scale))] +#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, DecodeWithMemTracking, MaxEncodedLen), codec(crate = scale))] pub struct ActorId([u8; 32]); macros::impl_primitive!(new zero into_bytes from_h256 into_h256 try_from_slice debug, ActorId); @@ -346,7 +346,7 @@ impl<'de> Deserialize<'de> for ActorId { )] #[as_ref(forward)] #[as_mut(forward)] -#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, MaxEncodedLen), codec(crate = scale))] +#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, DecodeWithMemTracking, MaxEncodedLen), codec(crate = scale))] pub struct MessageId([u8; 32]); macros::impl_primitive!(new zero into_bytes from_u64 from_h256 into_h256 from_str display debug serde, MessageId); @@ -378,7 +378,7 @@ macros::impl_primitive!(new zero into_bytes from_u64 from_h256 into_h256 from_st )] #[as_ref(forward)] #[as_mut(forward)] -#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, MaxEncodedLen), codec(crate = scale))] +#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, DecodeWithMemTracking, MaxEncodedLen), codec(crate = scale))] pub struct CodeId([u8; 32]); macros::impl_primitive!(new zero into_bytes from_u64 from_h256 into_h256 from_str try_from_slice display debug serde, CodeId); @@ -406,7 +406,7 @@ macros::impl_primitive!(new zero into_bytes from_u64 from_h256 into_h256 from_st )] #[as_ref(forward)] #[as_mut(forward)] -#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, MaxEncodedLen), codec(crate = scale))] +#[cfg_attr(feature = "codec", derive(TypeInfo, Encode, EncodeAsType, Decode, DecodeAsType, DecodeWithMemTracking, MaxEncodedLen), codec(crate = scale))] pub struct ReservationId([u8; 32]); macros::impl_primitive!(new zero into_bytes from_u64 from_h256 into_h256 from_str display debug serde, ReservationId); diff --git a/protocol/sandbox/src/host_executor.rs b/protocol/sandbox/src/host_executor.rs index a81b65023f0..c2dd4cde347 100644 --- a/protocol/sandbox/src/host_executor.rs +++ b/protocol/sandbox/src/host_executor.rs @@ -11,7 +11,6 @@ use crate::{ use alloc::{format, string::String}; use gear_sandbox_env::WasmReturnValue; use gear_sandbox_interface::sandbox; -use sp_core::RuntimeDebug; use sp_std::{marker, mem, prelude::*, rc::Rc, slice, vec}; use sp_wasm_interface_common::HostPointer; @@ -41,7 +40,7 @@ mod ffi { pub trait AsContext {} -#[derive(RuntimeDebug)] +#[derive(Debug)] pub struct Store(T); impl SandboxStore for Store { diff --git a/protocol/sandbox/src/lib.rs b/protocol/sandbox/src/lib.rs index 1b4d91f02da..17108efdd56 100644 --- a/protocol/sandbox/src/lib.rs +++ b/protocol/sandbox/src/lib.rs @@ -44,12 +44,11 @@ pub use gear_sandbox_env::HostError; pub use sp_wasm_interface_common::{IntoValue, ReturnValue, TryFromValue, Value}; use alloc::string::String; -use sp_core::RuntimeDebug; use sp_std::prelude::*; use sp_wasm_interface_common::HostPointer; /// Error that can occur while using this crate. -#[derive(RuntimeDebug)] +#[derive(Debug)] pub enum Error { /// Module is not valid, couldn't be instantiated. Module, @@ -179,7 +178,7 @@ pub trait SandboxEnvironmentBuilder: Sized { } /// Error that can occur while using this crate. -#[derive(RuntimeDebug)] +#[derive(Debug)] pub enum GlobalsSetError { /// A global variable is not found. NotFound, diff --git a/substrate/README.md b/substrate/README.md index 907448d0cc5..2c5226852b4 100644 --- a/substrate/README.md +++ b/substrate/README.md @@ -1,6 +1,6 @@ # Gear-maintained Polkadot SDK crates -This directory contains selected Polkadot SDK crates copied into the Gear workspace from Polkadot SDK `stable2409`, source reference [`298f676c91d64f15f38ea7fd78f125c5889ab09c`](https://github.com/paritytech/polkadot-sdk/tree/298f676c91d64f15f38ea7fd78f125c5889ab09c), plus Gear-local compatibility crates needed to isolate the remaining fork delta. +This directory contains selected Polkadot SDK crates copied into the Gear workspace and refreshed for Polkadot SDK `polkadot-stable2603-3`, source reference [`e3737178ec726cffe506c907263aaaa417893fd0`](https://github.com/paritytech/polkadot-sdk/tree/e3737178ec726cffe506c907263aaaa417893fd0), plus Gear-local compatibility crates needed to isolate the remaining fork delta. Copied crates are modified under the terms of their upstream open-source licenses. Original SPDX headers and upstream copyright notices remain in the copied source files; original copyright ownership remains with the upstream rightsholders as indicated there, including Parity Technologies where present. Gear maintains local changes to isolate the remaining fork delta while the rest of the workspace depends on upstream Polkadot SDK. @@ -18,6 +18,9 @@ Local Cargo package names intentionally stay compatible with upstream package na | `substrate/runtime-executor` | `sc-executor` | not published by Gear | GPL-3.0-or-later WITH Classpath-exception-2.0 | | `substrate/substrate-wasm-builder` | `substrate-wasm-builder` | `gsubstrate-wasm-builder` | Apache-2.0 | +`sc-mixnet` is no longer copied locally. Gear resolves it from upstream +Polkadot SDK `polkadot-stable2603-3`. + ## Gear Compatibility Crates | Local path | Upstream-compatible package name | Gear publish name | License | diff --git a/substrate/runtime-executor/Cargo.toml b/substrate/runtime-executor/Cargo.toml index d1c5ee11e08..d8c96d820a0 100644 --- a/substrate/runtime-executor/Cargo.toml +++ b/substrate/runtime-executor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sc-executor" -version = "0.40.1" +version = "0.48.0" authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/substrate/runtime-executor/common/Cargo.toml b/substrate/runtime-executor/common/Cargo.toml index 71817cc65d2..7e868784c8b 100644 --- a/substrate/runtime-executor/common/Cargo.toml +++ b/substrate/runtime-executor/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sc-executor-common" -version = "0.35.0" +version = "0.44.0" authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/substrate/runtime-executor/polkavm/Cargo.toml b/substrate/runtime-executor/polkavm/Cargo.toml index 685a2256d6b..c67b46dc7cd 100644 --- a/substrate/runtime-executor/polkavm/Cargo.toml +++ b/substrate/runtime-executor/polkavm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sc-executor-polkavm" -version = "0.32.0" +version = "0.41.0" authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/substrate/runtime-executor/wasmtime/Cargo.toml b/substrate/runtime-executor/wasmtime/Cargo.toml index f271fe3d4b0..bbcbe649771 100644 --- a/substrate/runtime-executor/wasmtime/Cargo.toml +++ b/substrate/runtime-executor/wasmtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sc-executor-wasmtime" -version = "0.35.0" +version = "0.44.0" authors.workspace = true edition.workspace = true rust-version.workspace = true @@ -24,10 +24,16 @@ parking_lot = { workspace = true, default-features = true } # When bumping wasmtime do not forget to also bump rustix # to exactly the same version as used by wasmtime! wasmtime = { features = [ + "addr2line", "cache", "cranelift", + "demangle", + "gc", + "gc-null", "parallel-compilation", "pooling-allocator", + "profiling", + "threads", ], workspace = true } sp-allocator.workspace = true sp-allocator.default-features = true diff --git a/substrate/sc-mixnet/Cargo.toml b/substrate/sc-mixnet/Cargo.toml deleted file mode 100644 index 7200e77de22..00000000000 --- a/substrate/sc-mixnet/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -description = "Substrate mixnet service" -name = "sc-mixnet" -version = "0.15.0" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -authors = ["Parity Technologies "] -edition = "2021" -homepage.workspace = true -repository = "https://github.com/paritytech/substrate/" -readme = "README.md" - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -array-bytes = { workspace = true, default-features = true } -arrayvec = { workspace = true } -blake2 = { workspace = true, default-features = true } -bytes = { workspace = true, default-features = true } -codec = { features = ["derive"], workspace = true } -futures = { workspace = true } -futures-timer = { workspace = true } -log = { workspace = true, default-features = true } -mixnet = { workspace = true } -parking_lot = { workspace = true, default-features = true } -sc-client-api.workspace = true -sc-client-api.default-features = true -sc-network.workspace = true -sc-network.default-features = true -sc-network-types.workspace = true -sc-network-types.default-features = true -sc-transaction-pool-api.workspace = true -sc-transaction-pool-api.default-features = true -sp-api.workspace = true -sp-api.default-features = true -sp-consensus.workspace = true -sp-consensus.default-features = true -sp-core.workspace = true -sp-core.default-features = true -sp-keystore.workspace = true -sp-keystore.default-features = true -sp-mixnet.workspace = true -sp-mixnet.default-features = true -sp-runtime.workspace = true -sp-runtime.default-features = true -thiserror = { workspace = true } diff --git a/substrate/sc-mixnet/README.md b/substrate/sc-mixnet/README.md deleted file mode 100644 index c43a0d7f17b..00000000000 --- a/substrate/sc-mixnet/README.md +++ /dev/null @@ -1,8 +0,0 @@ -Substrate mixnet service. - -License: GPL-3.0-or-later WITH Classpath-exception-2.0 - - -## Release - -Polkadot SDK stable2409 diff --git a/substrate/sc-mixnet/src/api.rs b/substrate/sc-mixnet/src/api.rs deleted file mode 100644 index 0bffe649ffb..00000000000 --- a/substrate/sc-mixnet/src/api.rs +++ /dev/null @@ -1,61 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -use super::{config::Config, error::Error, request::Request}; -use futures::{ - channel::{mpsc, oneshot}, - SinkExt, -}; -use sp_core::Bytes; -use std::future::Future; - -/// The other end of an [`Api`]. This should be passed to [`run`](super::run::run). -pub struct ApiBackend { - pub(super) request_receiver: mpsc::Receiver, -} - -/// Interface to the mixnet service. -#[derive(Clone)] -pub struct Api { - request_sender: mpsc::Sender, -} - -impl Api { - /// Create a new `Api`. The [`ApiBackend`] should be passed to [`run`](super::run::run). - pub fn new(config: &Config) -> (Self, ApiBackend) { - let (request_sender, request_receiver) = mpsc::channel(config.substrate.request_buffer); - (Self { request_sender }, ApiBackend { request_receiver }) - } - - /// Submit an extrinsic via the mixnet. - /// - /// Returns a [`Future`] which returns another `Future`. - /// - /// The first `Future` resolves as soon as there is space in the mixnet service queue. The - /// second `Future` resolves once a reply is received over the mixnet (or sooner if there is an - /// error). - /// - /// The first `Future` references `self`, but the second does not. This makes it possible to - /// submit concurrent mixnet requests using a single `Api` instance. - pub async fn submit_extrinsic( - &mut self, - extrinsic: Bytes, - ) -> impl Future> { - let (reply_sender, reply_receiver) = oneshot::channel(); - let res = self - .request_sender - .feed(Request::SubmitExtrinsic { - extrinsic, - reply_sender, - }) - .await; - async move { - res.map_err(|_| Error::ServiceUnavailable)?; - reply_receiver - .await - .map_err(|_| Error::ServiceUnavailable)? - } - } -} diff --git a/substrate/sc-mixnet/src/config.rs b/substrate/sc-mixnet/src/config.rs deleted file mode 100644 index 5e2941dba1f..00000000000 --- a/substrate/sc-mixnet/src/config.rs +++ /dev/null @@ -1,75 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -pub use mixnet::core::Config as CoreConfig; -use std::time::Duration; - -/// Substrate-specific mixnet configuration. -#[derive(Clone, Debug)] -pub struct SubstrateConfig { - /// Attempt to register the local node as a mixnode? - pub register: bool, - /// Maximum number of incoming mixnet connections to accept from non-mixnodes. If the local - /// node will never be a mixnode, this can be set to 0. - pub num_gateway_slots: u32, - - /// Number of requests to the mixnet service that can be buffered, in addition to the one per - /// [`Api`](super::api::Api) instance. Note that this does not include requests that are being - /// actively handled. - pub request_buffer: usize, - /// Used to determine the number of SURBs to include in request messages: the maximum number of - /// SURBs needed for a single reply is multiplied by this. This should not be set to 0. - pub surb_factor: usize, - - /// Maximum number of submit extrinsic requests waiting for their delay to elapse. When at the - /// limit, any submit extrinsic requests that arrive will simply be dropped. - pub extrinsic_queue_capacity: usize, - /// Mean delay between receiving a submit extrinsic request and actually submitting the - /// extrinsic. This should really be the same for all nodes! - pub mean_extrinsic_delay: Duration, - /// Maximum number of extrinsics being actively submitted. If a submit extrinsic request's - /// delay elapses and we are already at this limit, the request will simply be dropped. - pub max_pending_extrinsics: usize, -} - -impl Default for SubstrateConfig { - fn default() -> Self { - Self { - register: true, - num_gateway_slots: 150, - - request_buffer: 4, - surb_factor: 2, - - extrinsic_queue_capacity: 50, - mean_extrinsic_delay: Duration::from_secs(1), - max_pending_extrinsics: 20, - } - } -} - -/// Mixnet configuration. -#[derive(Clone, Debug)] -pub struct Config { - /// Core configuration. - pub core: CoreConfig, - /// Request manager configuration. - pub request_manager: mixnet::request_manager::Config, - /// Reply manager configuration. - pub reply_manager: mixnet::reply_manager::Config, - /// Substrate-specific configuration. - pub substrate: SubstrateConfig, -} - -impl Default for Config { - fn default() -> Self { - Self { - core: Default::default(), - request_manager: Default::default(), - reply_manager: Default::default(), - substrate: Default::default(), - } - } -} diff --git a/substrate/sc-mixnet/src/error.rs b/substrate/sc-mixnet/src/error.rs deleted file mode 100644 index 5c4d9ab7d5f..00000000000 --- a/substrate/sc-mixnet/src/error.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -use codec::{Decode, Encode}; -use mixnet::core::PostErr; - -/// Error handling a request. Sent in replies over the mixnet. -#[derive(Debug, thiserror::Error, Decode, Encode)] -pub enum RemoteErr { - /// An error that doesn't map to any of the other variants. - #[error("{0}")] - Other(String), - /// Failed to decode the request. - #[error("Failed to decode the request: {0}")] - Decode(String), -} - -/// Mixnet error. -#[derive(Debug, thiserror::Error)] -pub enum Error { - /// Failed to communicate with the mixnet service. Possibly it panicked. The node probably - /// needs to be restarted. - #[error( - "Failed to communicate with the mixnet service; the node probably needs to be restarted" - )] - ServiceUnavailable, - /// Did not receive a reply after the configured number of attempts. - #[error("Did not receive a reply from the mixnet after the configured number of attempts")] - NoReply, - /// Received a malformed reply. - #[error("Received a malformed reply from the mixnet")] - BadReply, - /// Failed to post the request to the mixnet. Note that some [`PostErr`] variants, eg - /// [`PostErr::NotEnoughSpaceInQueue`], are handled internally and will never be returned from - /// the top-level API. - #[error("Failed to post the request to the mixnet: {0}")] - Post(#[from] PostErr), - /// Error reported by destination mixnode. - #[error("Error reported by the destination mixnode: {0}")] - Remote(#[from] RemoteErr), -} diff --git a/substrate/sc-mixnet/src/extrinsic_queue.rs b/substrate/sc-mixnet/src/extrinsic_queue.rs deleted file mode 100644 index c39d8ca6d4f..00000000000 --- a/substrate/sc-mixnet/src/extrinsic_queue.rs +++ /dev/null @@ -1,91 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -//! [`ExtrinsicQueue`] is a queue for extrinsics received from the mixnet. These extrinsics are -//! explicitly delayed by a random amount, to decorrelate the times at which they are received from -//! the times at which they are broadcast to peers. - -use mixnet::reply_manager::ReplyContext; -use std::{cmp::Ordering, collections::BinaryHeap, time::Instant}; - -/// An extrinsic that should be submitted to the transaction pool after `deadline`. `Eq` and `Ord` -/// are implemented for this to support use in `BinaryHeap`s. Only `deadline` is compared. -struct DelayedExtrinsic { - /// When the extrinsic should actually be submitted to the pool. - deadline: Instant, - extrinsic: E, - reply_context: ReplyContext, -} - -impl PartialEq for DelayedExtrinsic { - fn eq(&self, other: &Self) -> bool { - self.deadline == other.deadline - } -} - -impl Eq for DelayedExtrinsic {} - -impl PartialOrd for DelayedExtrinsic { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for DelayedExtrinsic { - fn cmp(&self, other: &Self) -> Ordering { - // Extrinsics with the earliest deadline considered greatest - self.deadline.cmp(&other.deadline).reverse() - } -} - -pub struct ExtrinsicQueue { - capacity: usize, - queue: BinaryHeap>, - next_deadline_changed: bool, -} - -impl ExtrinsicQueue { - pub fn new(capacity: usize) -> Self { - Self { - capacity, - queue: BinaryHeap::with_capacity(capacity), - next_deadline_changed: false, - } - } - - pub fn next_deadline(&self) -> Option { - self.queue.peek().map(|extrinsic| extrinsic.deadline) - } - - pub fn next_deadline_changed(&mut self) -> bool { - let changed = self.next_deadline_changed; - self.next_deadline_changed = false; - changed - } - - pub fn has_space(&self) -> bool { - self.queue.len() < self.capacity - } - - pub fn insert(&mut self, deadline: Instant, extrinsic: E, reply_context: ReplyContext) { - debug_assert!(self.has_space()); - let prev_deadline = self.next_deadline(); - self.queue.push(DelayedExtrinsic { - deadline, - extrinsic, - reply_context, - }); - if self.next_deadline() != prev_deadline { - self.next_deadline_changed = true; - } - } - - pub fn pop(&mut self) -> Option<(E, ReplyContext)> { - self.next_deadline_changed = true; - self.queue - .pop() - .map(|extrinsic| (extrinsic.extrinsic, extrinsic.reply_context)) - } -} diff --git a/substrate/sc-mixnet/src/lib.rs b/substrate/sc-mixnet/src/lib.rs deleted file mode 100644 index 0edf40e1906..00000000000 --- a/substrate/sc-mixnet/src/lib.rs +++ /dev/null @@ -1,36 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -//! Substrate mixnet service. This implements the [Substrate Mix Network -//! Specification](https://paritytech.github.io/mixnet-spec/). - -#![warn(missing_docs)] -#![forbid(unsafe_code)] -#![allow( - clippy::borrowed_box, - clippy::derivable_impls, - clippy::too_many_arguments -)] - -mod api; -mod config; -mod error; -mod extrinsic_queue; -mod maybe_inf_delay; -mod packet_dispatcher; -mod peer_id; -mod protocol; -mod request; -mod run; -mod sync_with_runtime; - -pub use self::{ - api::{Api, ApiBackend}, - config::{Config, CoreConfig, SubstrateConfig}, - error::{Error, RemoteErr}, - protocol::{peers_set_config, protocol_name}, - run::run, -}; -pub use mixnet::core::{KxSecret, PostErr, TopologyErr}; diff --git a/substrate/sc-mixnet/src/maybe_inf_delay.rs b/substrate/sc-mixnet/src/maybe_inf_delay.rs deleted file mode 100644 index 895a713bba9..00000000000 --- a/substrate/sc-mixnet/src/maybe_inf_delay.rs +++ /dev/null @@ -1,108 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -use futures::{future::FusedFuture, FutureExt}; -use futures_timer::Delay; -use std::{ - future::Future, - pin::Pin, - task::{Context, Poll, Waker}, - time::Duration, -}; - -enum Inner { - Infinite { - /// Waker from the most recent `poll` call. If `None`, either `poll` has not been called - /// yet, we returned `Poll::Ready` from the last call, or the waker is attached to `delay`. - waker: Option, - delay: Option, - }, - Finite(Delay), -} - -/// Like [`Delay`] but the duration can be infinite (in which case the future will never fire). -/// Unlike [`Delay`], implements [`FusedFuture`], with [`is_terminated`](Self::is_terminated) -/// returning `true` when the delay is infinite. As with [`Delay`], once [`poll`](Self::poll) -/// returns [`Poll::Ready`], it will continue to do so until [`reset`](Self::reset) is called. -pub struct MaybeInfDelay(Inner); - -impl MaybeInfDelay { - /// Create a new `MaybeInfDelay` future. If `duration` is [`Some`], the future will fire after - /// the given duration has elapsed. If `duration` is [`None`], the future will "never" fire - /// (although see [`reset`](Self::reset)). - pub fn new(duration: Option) -> Self { - match duration { - Some(duration) => Self(Inner::Finite(Delay::new(duration))), - None => Self(Inner::Infinite { - waker: None, - delay: None, - }), - } - } - - /// Reset the timer. `duration` is handled just like in [`new`](Self::new). Note that while - /// this is similar to `std::mem::replace(&mut self, MaybeInfDelay::new(duration))`, with - /// `replace` you would have to manually ensure [`poll`](Self::poll) was called again; with - /// `reset` this is not necessary. - pub fn reset(&mut self, duration: Option) { - match duration { - Some(duration) => match &mut self.0 { - Inner::Infinite { waker, delay } => { - let mut delay = match delay.take() { - Some(mut delay) => { - delay.reset(duration); - delay - } - None => Delay::new(duration), - }; - if let Some(waker) = waker.take() { - let mut cx = Context::from_waker(&waker); - match delay.poll_unpin(&mut cx) { - Poll::Pending => (), // Waker attached to delay - Poll::Ready(_) => waker.wake(), - } - } - self.0 = Inner::Finite(delay); - } - Inner::Finite(delay) => delay.reset(duration), - }, - None => { - self.0 = match std::mem::replace( - &mut self.0, - Inner::Infinite { - waker: None, - delay: None, - }, - ) { - Inner::Finite(delay) => Inner::Infinite { - waker: None, - delay: Some(delay), - }, - infinite => infinite, - } - } - } - } -} - -impl Future for MaybeInfDelay { - type Output = (); - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - match &mut self.0 { - Inner::Infinite { waker, .. } => { - *waker = Some(cx.waker().clone()); - Poll::Pending - } - Inner::Finite(delay) => delay.poll_unpin(cx), - } - } -} - -impl FusedFuture for MaybeInfDelay { - fn is_terminated(&self) -> bool { - matches!(self.0, Inner::Infinite { .. }) - } -} diff --git a/substrate/sc-mixnet/src/packet_dispatcher.rs b/substrate/sc-mixnet/src/packet_dispatcher.rs deleted file mode 100644 index 3416e4dc2ee..00000000000 --- a/substrate/sc-mixnet/src/packet_dispatcher.rs +++ /dev/null @@ -1,194 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -//! [`AddressedPacket`] dispatching. - -use super::peer_id::{from_core_peer_id, to_core_peer_id}; -use arrayvec::ArrayVec; -use log::{debug, warn}; -use mixnet::core::{AddressedPacket, NetworkStatus, Packet, PeerId as CorePeerId}; -use parking_lot::Mutex; -use sc_network::NotificationService; -use sc_network_types::PeerId; -use std::{collections::HashMap, future::Future, sync::Arc}; - -const LOG_TARGET: &str = "mixnet"; - -/// Packet queue for a peer. -/// -/// Ideally we would use `Rc>`, but that would prevent the top-level future from being -/// automatically marked `Send`. I believe it would be safe to manually mark it `Send`, but using -/// `Arc>` here is not really a big deal. -struct PeerQueue(Mutex, 2>>); - -impl PeerQueue { - fn new() -> Self { - Self(Mutex::new(ArrayVec::new())) - } - - /// Push `packet` onto the queue. Returns `true` if the queue was previously empty. Fails if - /// the queue is full. - fn push(&self, packet: Box) -> Result { - let mut queue = self.0.lock(); - if queue.is_full() { - Err(()) - } else { - let was_empty = queue.is_empty(); - queue.push(packet); - Ok(was_empty) - } - } - - /// Drop all packets from the queue. - fn clear(&self) { - let mut queue = self.0.lock(); - queue.clear(); - } - - /// Pop the packet at the head of the queue and return it, or, if the queue is empty, return - /// `None`. Also returns `true` if there are more packets in the queue. - fn pop(&self) -> (Option>, bool) { - let mut queue = self.0.lock(); - let packet = queue.pop(); - (packet, !queue.is_empty()) - } -} - -/// A peer which has packets ready to send but is not currently being serviced. -pub struct ReadyPeer { - id: PeerId, - /// The peer's packet queue. Not empty. - queue: Arc, -} - -impl ReadyPeer { - /// If a future is returned, and if that future returns `Some`, this function should be - /// called again to send the next packet queued for the peer; `self` is placed in the `Some` - /// to make this straightforward. Otherwise, we have either sent or dropped all packets - /// queued for the peer, and it can be forgotten about for the time being. - pub fn send_packet( - self, - notification_service: &Box, - ) -> Option>> { - match notification_service.message_sink(&self.id) { - None => { - debug!( - target: LOG_TARGET, - "Failed to get message sink for peer ID {}", self.id, - ); - self.queue.clear(); - None - } - Some(sink) => Some(async move { - let (packet, more_packets) = self.queue.pop(); - let packet = packet.expect("Should only be called if there is a packet to send"); - - match sink - .send_async_notification((packet as Box<[_]>).into()) - .await - { - Ok(_) => more_packets.then_some(self), - Err(err) => { - debug!( - target: LOG_TARGET, - "Failed to send packet to peer ID {}: {err}", self.id, - ); - self.queue.clear(); - None - } - } - }), - } - } -} - -pub struct PacketDispatcher { - /// Peer ID of the local node. Only used to implement [`NetworkStatus`]. - local_peer_id: CorePeerId, - /// Packet queue for each connected peer. These queues are very short and only exist to give - /// packets somewhere to sit while waiting for notification senders to be ready. - peer_queues: HashMap>, -} - -impl PacketDispatcher { - pub fn new(local_peer_id: &CorePeerId) -> Self { - Self { - local_peer_id: *local_peer_id, - peer_queues: HashMap::new(), - } - } - - pub fn add_peer(&mut self, id: &PeerId) { - let Some(core_id) = to_core_peer_id(id) else { - debug!(target: LOG_TARGET, - "Cannot add peer; failed to convert libp2p peer ID {id} to mixnet peer ID"); - return; - }; - if self - .peer_queues - .insert(core_id, Arc::new(PeerQueue::new())) - .is_some() - { - warn!(target: LOG_TARGET, "Two stream opened notifications for peer ID {id}"); - } - } - - pub fn remove_peer(&mut self, id: &PeerId) { - let Some(core_id) = to_core_peer_id(id) else { - debug!(target: LOG_TARGET, - "Cannot remove peer; failed to convert libp2p peer ID {id} to mixnet peer ID"); - return; - }; - if self.peer_queues.remove(&core_id).is_none() { - warn!(target: LOG_TARGET, "Stream closed notification for unknown peer ID {id}"); - } - } - - /// If the peer is not connected or the peer's packet queue is full, the packet is dropped. - /// Otherwise the packet is pushed onto the peer's queue, and if the queue was previously empty - /// a [`ReadyPeer`] is returned. - pub fn dispatch(&mut self, packet: AddressedPacket) -> Option { - let Some(queue) = self.peer_queues.get_mut(&packet.peer_id) else { - debug!(target: LOG_TARGET, "Dropped packet to mixnet peer ID {:x?}; not connected", - packet.peer_id); - return None; - }; - - match queue.push(packet.packet) { - Err(_) => { - debug!( - target: LOG_TARGET, - "Dropped packet to mixnet peer ID {:x?}; peer queue full", packet.peer_id - ); - None - } - Ok(true) => { - // Queue was empty. Construct and return a ReadyPeer. - let Some(id) = from_core_peer_id(&packet.peer_id) else { - debug!(target: LOG_TARGET, "Cannot send packet; \ - failed to convert mixnet peer ID {:x?} to libp2p peer ID", - packet.peer_id); - queue.clear(); - return None; - }; - Some(ReadyPeer { - id, - queue: queue.clone(), - }) - } - Ok(false) => None, // Queue was not empty - } - } -} - -impl NetworkStatus for PacketDispatcher { - fn local_peer_id(&self) -> CorePeerId { - self.local_peer_id - } - - fn is_connected(&self, peer_id: &CorePeerId) -> bool { - self.peer_queues.contains_key(peer_id) - } -} diff --git a/substrate/sc-mixnet/src/peer_id.rs b/substrate/sc-mixnet/src/peer_id.rs deleted file mode 100644 index dced375265f..00000000000 --- a/substrate/sc-mixnet/src/peer_id.rs +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -use mixnet::core::PeerId as CorePeerId; -use sc_network_types::PeerId; - -/// Convert a libp2p [`PeerId`] into a mixnet core [`PeerId`](CorePeerId). -/// -/// This will succeed only if `peer_id` is an Ed25519 public key ("hashed" using the identity -/// hasher). Returns `None` on failure. -pub fn to_core_peer_id(peer_id: &PeerId) -> Option { - peer_id.into_ed25519() -} - -/// Convert a mixnet core [`PeerId`](CorePeerId) into a libp2p [`PeerId`]. -/// -/// This will succeed only if `peer_id` represents a point on the Ed25519 curve. Returns `None` on -/// failure. -pub fn from_core_peer_id(core_peer_id: &CorePeerId) -> Option { - PeerId::from_ed25519(core_peer_id) -} diff --git a/substrate/sc-mixnet/src/protocol.rs b/substrate/sc-mixnet/src/protocol.rs deleted file mode 100644 index 7a425aaf07b..00000000000 --- a/substrate/sc-mixnet/src/protocol.rs +++ /dev/null @@ -1,67 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -use super::config::Config; -use mixnet::core::PACKET_SIZE; -use sc_network::{ - config::{NonReservedPeerMode, SetConfig}, - peer_store::PeerStoreProvider, - service::NotificationMetrics, - NetworkBackend, NotificationService, ProtocolName, -}; -use sp_runtime::traits::Block as BlockT; - -/// Returns the protocol name to use for the mixnet controlled by the given chain. -pub fn protocol_name(genesis_hash: &[u8], fork_id: Option<&str>) -> ProtocolName { - let name = if let Some(fork_id) = fork_id { - format!( - "/{}/{}/mixnet/1", - array_bytes::bytes2hex("", genesis_hash), - fork_id - ) - } else { - format!("/{}/mixnet/1", array_bytes::bytes2hex("", genesis_hash)) - }; - name.into() -} - -/// Returns the peers set configuration for the mixnet protocol. -pub fn peers_set_config::Hash>>( - name: ProtocolName, - config: &Config, - metrics: NotificationMetrics, - peerstore_handle: std::sync::Arc, -) -> ( - Network::NotificationProtocolConfig, - Box, -) { - let set_config = if config.substrate.num_gateway_slots != 0 { - // out_peers is always 0; we are only interested in connecting to mixnodes, which we do by - // setting them as reserved nodes - SetConfig { - in_peers: config.substrate.num_gateway_slots, - out_peers: 0, - reserved_nodes: Vec::new(), - non_reserved_mode: NonReservedPeerMode::Accept, - } - } else { - SetConfig { - in_peers: 0, - out_peers: 0, - reserved_nodes: Vec::new(), - non_reserved_mode: NonReservedPeerMode::Deny, - } - }; - - Network::notification_config( - name, - Vec::new(), - PACKET_SIZE as u64, - None, - set_config, - metrics, - peerstore_handle, - ) -} diff --git a/substrate/sc-mixnet/src/request.rs b/substrate/sc-mixnet/src/request.rs deleted file mode 100644 index 932b253022a..00000000000 --- a/substrate/sc-mixnet/src/request.rs +++ /dev/null @@ -1,112 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -//! Sender-side request logic. Some things from this module are also used on the receiver side, eg -//! [`extrinsic_delay`], but most of the receiver-side request logic lives elsewhere. - -use super::{config::SubstrateConfig, error::Error}; -use blake2::{ - digest::{consts::U16, Mac}, - Blake2bMac, -}; -use codec::{Decode, DecodeAll}; -use futures::channel::oneshot; -use log::debug; -use mixnet::core::{Delay, MessageId, PostErr, Scattered}; -use sp_core::Bytes; -use std::time::Duration; - -const LOG_TARGET: &str = "mixnet"; - -fn send_err(reply_sender: oneshot::Sender>, err: Error) { - if let Err(Err(err)) = reply_sender.send(Err(err)) { - debug!(target: LOG_TARGET, "Failed to inform requester of error: {err}"); - } -} - -fn send_reply(reply_sender: oneshot::Sender>, mut data: &[u8]) { - let res = match Result::decode_all(&mut data) { - Ok(res) => res.map_err(Error::Remote), - Err(_) => Err(Error::BadReply), - }; - match reply_sender.send(res) { - Ok(_) => (), - Err(Ok(_)) => debug!(target: LOG_TARGET, "Failed to send reply to requester"), - Err(Err(err)) => debug!(target: LOG_TARGET, "Failed to inform requester of error: {err}"), - } -} - -/// First byte of a submit extrinsic request, identifying it as such. -pub const SUBMIT_EXTRINSIC: u8 = 1; - -const EXTRINSIC_DELAY_PERSONA: &[u8; 16] = b"submit-extrn-dly"; - -/// Returns the artificial delay that should be inserted between receipt of a submit extrinsic -/// request with the given message ID and import of the extrinsic into the local transaction pool. -pub fn extrinsic_delay(message_id: &MessageId, config: &SubstrateConfig) -> Duration { - let h = Blake2bMac::::new_with_salt_and_personal(message_id, b"", EXTRINSIC_DELAY_PERSONA) - .expect("Key, salt, and persona sizes are fixed and small enough"); - let delay = Delay::exp(h.finalize().into_bytes().as_ref()); - delay.to_duration(config.mean_extrinsic_delay) -} - -/// Request parameters and local reply channel. Stored by the -/// [`RequestManager`](mixnet::request_manager::RequestManager). -pub enum Request { - SubmitExtrinsic { - extrinsic: Bytes, - reply_sender: oneshot::Sender>, - }, -} - -impl Request { - /// Forward an error to the user of the mixnet service. - fn send_err(self, err: Error) { - match self { - Request::SubmitExtrinsic { reply_sender, .. } => send_err(reply_sender, err), - } - } - - /// Forward a reply to the user of the mixnet service. - pub fn send_reply(self, data: &[u8]) { - match self { - Request::SubmitExtrinsic { reply_sender, .. } => send_reply(reply_sender, data), - } - } -} - -impl mixnet::request_manager::Request for Request { - type Context = SubstrateConfig; - - fn with_data(&self, f: impl FnOnce(Scattered) -> T, _context: &Self::Context) -> T { - match self { - Request::SubmitExtrinsic { extrinsic, .. } => { - f([&[SUBMIT_EXTRINSIC][..], extrinsic.as_ref()] - .as_slice() - .into()) - } - } - } - - fn num_surbs(&self, context: &Self::Context) -> usize { - match self { - Request::SubmitExtrinsic { .. } => context.surb_factor, - } - } - - fn handling_delay(&self, message_id: &MessageId, context: &Self::Context) -> Duration { - match self { - Request::SubmitExtrinsic { .. } => extrinsic_delay(message_id, context), - } - } - - fn handle_post_err(self, err: PostErr, _context: &Self::Context) { - self.send_err(err.into()); - } - - fn handle_retry_limit_reached(self, _context: &Self::Context) { - self.send_err(Error::NoReply); - } -} diff --git a/substrate/sc-mixnet/src/run.rs b/substrate/sc-mixnet/src/run.rs deleted file mode 100644 index 12ce17b9c2e..00000000000 --- a/substrate/sc-mixnet/src/run.rs +++ /dev/null @@ -1,380 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -//! Top-level mixnet service function. - -use super::{ - api::ApiBackend, - config::{Config, SubstrateConfig}, - error::RemoteErr, - extrinsic_queue::ExtrinsicQueue, - maybe_inf_delay::MaybeInfDelay, - packet_dispatcher::PacketDispatcher, - peer_id::to_core_peer_id, - request::{extrinsic_delay, Request, SUBMIT_EXTRINSIC}, - sync_with_runtime::sync_with_runtime, -}; -use bytes::Bytes; -use codec::{Decode, DecodeAll, Encode}; -use futures::{ - future::{pending, Either}, - stream::FuturesUnordered, - FutureExt, StreamExt, -}; -use log::{debug, error, trace, warn}; -use mixnet::{ - core::{Events, Message, Mixnet, Packet}, - reply_manager::{ReplyContext, ReplyManager}, - request_manager::RequestManager, -}; -use sc_client_api::{BlockchainEvents, HeaderBackend}; -use sc_network::{ - service::traits::{NetworkService, NotificationEvent, ValidationResult}, - NetworkPeers, NetworkStateInfo, NotificationService, ProtocolName, -}; -use sc_transaction_pool_api::{ - LocalTransactionPool, OffchainTransactionPoolFactory, TransactionPool, -}; -use sp_api::{ApiExt, ProvideRuntimeApi}; -use sp_consensus::SyncOracle; -use sp_keystore::{KeystoreExt, KeystorePtr}; -use sp_mixnet::{runtime_api::MixnetApi, types::Mixnode}; -use sp_runtime::{ - traits::{Block, Header}, - transaction_validity::TransactionSource, - Saturating, -}; -use std::{ - sync::Arc, - time::{Duration, Instant}, -}; - -const LOG_TARGET: &str = "mixnet"; - -const MIN_BLOCKS_BETWEEN_REGISTRATION_ATTEMPTS: u32 = 3; - -fn complete_submit_extrinsic( - reply_manager: &mut ReplyManager, - reply_context: ReplyContext, - data: Result<(), RemoteErr>, - mixnet: &mut Mixnet, -) { - reply_manager.complete(reply_context, data.encode(), mixnet); -} - -fn handle_packet( - packet: &Packet, - mixnet: &mut Mixnet, - request_manager: &mut RequestManager, - reply_manager: &mut ReplyManager, - extrinsic_queue: &mut ExtrinsicQueue, - config: &SubstrateConfig, -) { - match mixnet.handle_packet(packet) { - Some(Message::Request(message)) => { - let Some((reply_context, data)) = reply_manager.insert(message, mixnet) else { - return; - }; - - match data.as_slice() { - [SUBMIT_EXTRINSIC, encoded_extrinsic @ ..] => { - if !extrinsic_queue.has_space() { - debug!(target: LOG_TARGET, "No space in extrinsic queue; dropping request"); - // We don't send a reply in this case; we want the requester to retry - reply_manager.abandon(reply_context); - return; - } - - // Decode the extrinsic - let mut encoded_extrinsic = encoded_extrinsic; - let extrinsic = match E::decode_all(&mut encoded_extrinsic) { - Ok(extrinsic) => extrinsic, - Err(err) => { - complete_submit_extrinsic( - reply_manager, - reply_context, - Err(RemoteErr::Decode(format!("Bad extrinsic: {}", err))), - mixnet, - ); - return; - } - }; - - let deadline = - Instant::now() + extrinsic_delay(reply_context.message_id(), config); - extrinsic_queue.insert(deadline, extrinsic, reply_context); - } - _ => { - debug!(target: LOG_TARGET, "Unrecognised request; discarding"); - // To keep things simple we don't bother sending a reply in this case. The - // requester will give up and try another mixnode eventually. - reply_manager.abandon(reply_context); - } - } - } - Some(Message::Reply(message)) => { - let Some(request) = request_manager.remove(&message.request_id) else { - trace!( - target: LOG_TARGET, - "Received reply to already-completed request with message ID {:x?}", - message.request_id - ); - return; - }; - request.send_reply(&message.data); - } - None => (), - } -} - -fn time_until(instant: Instant) -> Duration { - instant.saturating_duration_since(Instant::now()) -} - -/// Run the mixnet service. If `keystore` is `None`, the service will not attempt to register the -/// local node as a mixnode, even if `config.register` is `true`. -pub async fn run( - config: Config, - mut api_backend: ApiBackend, - client: Arc, - sync: Arc, - network: Arc, - protocol_name: ProtocolName, - transaction_pool: Arc

, - keystore: Option, - mut notification_service: Box, -) where - B: Block, - C: BlockchainEvents + ProvideRuntimeApi + HeaderBackend, - C::Api: MixnetApi, - S: SyncOracle, - P: TransactionPool + LocalTransactionPool + 'static, -{ - let local_peer_id = network.local_peer_id(); - let Some(local_peer_id) = to_core_peer_id(&local_peer_id) else { - error!(target: LOG_TARGET, - "Failed to convert libp2p local peer ID {local_peer_id} to mixnet peer ID; \ - mixnet not running"); - return; - }; - - let offchain_transaction_pool_factory = - OffchainTransactionPoolFactory::new(transaction_pool.clone()); - - let mut mixnet = Mixnet::new(config.core); - // It would make sense to reset this to 0 when the session changes, but registrations aren't - // allowed at the start of a session anyway, so it doesn't really matter - let mut min_register_block = 0u32.into(); - let mut packet_dispatcher = PacketDispatcher::new(&local_peer_id); - let mut request_manager = RequestManager::new(config.request_manager); - let mut reply_manager = ReplyManager::new(config.reply_manager); - let mut extrinsic_queue = ExtrinsicQueue::new(config.substrate.extrinsic_queue_capacity); - - let mut finality_notifications = client.finality_notification_stream(); - // Import notifications only used for triggering registration attempts - let mut import_notifications = if config.substrate.register && keystore.is_some() { - Some(client.import_notification_stream()) - } else { - None - }; - let mut next_forward_packet_delay = MaybeInfDelay::new(None); - let mut next_authored_packet_delay = MaybeInfDelay::new(None); - let mut ready_peers = FuturesUnordered::new(); - let mut next_retry_delay = MaybeInfDelay::new(None); - let mut next_extrinsic_delay = MaybeInfDelay::new(None); - let mut submit_extrinsic_results = FuturesUnordered::new(); - - loop { - let mut next_request = if request_manager.has_space() { - Either::Left(api_backend.request_receiver.select_next_some()) - } else { - Either::Right(pending()) - }; - - let mut next_import_notification = import_notifications.as_mut().map_or_else( - || Either::Right(pending()), - |notifications| Either::Left(notifications.select_next_some()), - ); - - futures::select! { - request = next_request => - request_manager.insert(request, &mut mixnet, &packet_dispatcher, &config.substrate), - - notification = finality_notifications.select_next_some() => { - // To avoid trying to connect to old mixnodes, ignore finality notifications while - // offline or major syncing. This is a bit racy but should be good enough. - if !sync.is_offline() && !sync.is_major_syncing() { - let api = client.runtime_api(); - sync_with_runtime(&mut mixnet, api, notification.hash); - request_manager.update_session_status( - &mut mixnet, &packet_dispatcher, &config.substrate); - } - } - - notification = next_import_notification => { - if notification.is_new_best && (*notification.header.number() >= min_register_block) { - let mut api = client.runtime_api(); - api.register_extension(KeystoreExt(keystore.clone().expect( - "Import notification stream only setup if we have a keystore"))); - api.register_extension(offchain_transaction_pool_factory - .offchain_transaction_pool(notification.hash)); - let session_index = mixnet.session_status().current_index; - let mixnode = Mixnode { - kx_public: *mixnet.next_kx_public(), - peer_id: local_peer_id, - external_addresses: network.external_addresses().into_iter() - .map(|addr| addr.to_string().into_bytes()).collect(), - }; - match api.maybe_register(notification.hash, session_index, mixnode) { - Ok(true) => min_register_block = notification.header.number().saturating_add( - MIN_BLOCKS_BETWEEN_REGISTRATION_ATTEMPTS.into()), - Ok(false) => (), - Err(err) => debug!(target: LOG_TARGET, - "Error trying to register for the next session: {err}"), - } - } - } - - event = notification_service.next_event().fuse() => match event { - None => todo!(), - Some(NotificationEvent::ValidateInboundSubstream { result_tx, .. }) => { - let _ = result_tx.send(ValidationResult::Accept); - }, - Some(NotificationEvent::NotificationStreamOpened { peer, .. }) => { - packet_dispatcher.add_peer(&peer); - }, - Some(NotificationEvent::NotificationStreamClosed { peer }) => { - packet_dispatcher.remove_peer(&peer); - }, - Some(NotificationEvent::NotificationReceived { peer, notification }) => { - let notification: Bytes = notification.into(); - - match notification.as_ref().try_into() { - Ok(packet) => handle_packet(packet, - &mut mixnet, &mut request_manager, &mut reply_manager, - &mut extrinsic_queue, &config.substrate), - Err(_) => debug!(target: LOG_TARGET, - "Dropped incorrectly sized packet ({} bytes) from {peer}", - notification.len(), - ), - } - }, - }, - - _ = next_forward_packet_delay => { - if let Some(packet) = mixnet.pop_next_forward_packet() { - if let Some(ready_peer) = packet_dispatcher.dispatch(packet) { - if let Some(fut) = ready_peer.send_packet(¬ification_service) { - ready_peers.push(fut); - } - } - } else { - warn!(target: LOG_TARGET, - "Next forward packet deadline reached, but no packet in queue; \ - this is a bug"); - } - } - - _ = next_authored_packet_delay => { - if let Some(packet) = mixnet.pop_next_authored_packet(&packet_dispatcher) { - if let Some(ready_peer) = packet_dispatcher.dispatch(packet) { - if let Some(fut) = ready_peer.send_packet(¬ification_service) { - ready_peers.push(fut); - } - } - } - } - - ready_peer = ready_peers.select_next_some() => { - if let Some(ready_peer) = ready_peer { - if let Some(fut) = ready_peer.send_packet(¬ification_service) { - ready_peers.push(fut); - } - } - } - - _ = next_retry_delay => { - if !request_manager.pop_next_retry(&mut mixnet, &packet_dispatcher, &config.substrate) { - warn!(target: LOG_TARGET, - "Next retry deadline reached, but no request in retry queue; \ - this is a bug"); - } - } - - _ = next_extrinsic_delay => { - if let Some((extrinsic, reply_context)) = extrinsic_queue.pop() { - if submit_extrinsic_results.len() < config.substrate.max_pending_extrinsics { - let fut = transaction_pool.submit_one( - client.info().best_hash, - TransactionSource::External, - extrinsic); - submit_extrinsic_results.push(async move { - (fut.await, reply_context) - }); - } else { - // There are already too many pending extrinsics, just drop this one. We - // don't send a reply; we want the requester to retry. - debug!(target: LOG_TARGET, - "Too many pending extrinsics; dropped submit extrinsic request"); - reply_manager.abandon(reply_context); - } - } else { - warn!(target: LOG_TARGET, - "Next extrinsic deadline reached, but no extrinsic in queue; \ - this is a bug"); - } - } - - res_reply_context = submit_extrinsic_results.select_next_some() => { - let (res, reply_context) = res_reply_context; - let res = match res { - Ok(_) => Ok(()), - Err(err) => Err(RemoteErr::Other(err.to_string())), - }; - complete_submit_extrinsic(&mut reply_manager, reply_context, res, &mut mixnet); - } - } - - let events = mixnet.take_events(); - if !events.is_empty() { - if events.contains(Events::RESERVED_PEERS_CHANGED) { - let reserved_peer_addrs = mixnet - .reserved_peers() - .flat_map(|mixnode| mixnode.extra.iter()) // External addresses - .cloned() - .collect(); - if let Err(err) = - network.set_reserved_peers(protocol_name.clone(), reserved_peer_addrs) - { - debug!(target: LOG_TARGET, "Setting reserved peers failed: {err}"); - } - } - if events.contains(Events::NEXT_FORWARD_PACKET_DEADLINE_CHANGED) { - next_forward_packet_delay - .reset(mixnet.next_forward_packet_deadline().map(time_until)); - } - if events.contains(Events::NEXT_AUTHORED_PACKET_DEADLINE_CHANGED) { - next_authored_packet_delay.reset(mixnet.next_authored_packet_delay()); - } - if events.contains(Events::SPACE_IN_AUTHORED_PACKET_QUEUE) { - // Note this may cause the next retry deadline to change, but should not trigger - // any mixnet events - request_manager.process_post_queues( - &mut mixnet, - &packet_dispatcher, - &config.substrate, - ); - } - } - - if request_manager.next_retry_deadline_changed() { - next_retry_delay.reset(request_manager.next_retry_deadline().map(time_until)); - } - - if extrinsic_queue.next_deadline_changed() { - next_extrinsic_delay.reset(extrinsic_queue.next_deadline().map(time_until)); - } - } -} diff --git a/substrate/sc-mixnet/src/sync_with_runtime.rs b/substrate/sc-mixnet/src/sync_with_runtime.rs deleted file mode 100644 index fbcea458ff5..00000000000 --- a/substrate/sc-mixnet/src/sync_with_runtime.rs +++ /dev/null @@ -1,219 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -//! [`sync_with_runtime`] synchronises the session status and mixnode sets from the blockchain -//! runtime to the core mixnet state. It is called every time a block is finalised. - -use super::peer_id::from_core_peer_id; -use log::{debug, info}; -use mixnet::core::{ - Mixnet, Mixnode as CoreMixnode, MixnodesErr as CoreMixnodesErr, RelSessionIndex, - SessionPhase as CoreSessionPhase, SessionStatus as CoreSessionStatus, -}; -use sc_network_types::{ - multiaddr::{multiaddr, Multiaddr, Protocol}, - PeerId, -}; -use sp_api::{ApiError, ApiRef}; -use sp_mixnet::{ - runtime_api::MixnetApi, - types::{ - Mixnode as RuntimeMixnode, MixnodesErr as RuntimeMixnodesErr, - SessionPhase as RuntimeSessionPhase, SessionStatus as RuntimeSessionStatus, - }, -}; -use sp_runtime::traits::Block; - -const LOG_TARGET: &str = "mixnet"; - -/// Convert a [`RuntimeSessionStatus`] to a [`CoreSessionStatus`]. -/// -/// The [`RuntimeSessionStatus`] and [`CoreSessionStatus`] types are effectively the same. -/// [`RuntimeSessionStatus`] is used in the runtime to avoid depending on the [`mixnet`] crate -/// there. -fn to_core_session_status(status: RuntimeSessionStatus) -> CoreSessionStatus { - CoreSessionStatus { - current_index: status.current_index, - phase: match status.phase { - RuntimeSessionPhase::CoverToCurrent => CoreSessionPhase::CoverToCurrent, - RuntimeSessionPhase::RequestsToCurrent => CoreSessionPhase::RequestsToCurrent, - RuntimeSessionPhase::CoverToPrev => CoreSessionPhase::CoverToPrev, - RuntimeSessionPhase::DisconnectFromPrev => CoreSessionPhase::DisconnectFromPrev, - }, - } -} - -fn parse_external_addresses(external_addresses: Vec>) -> Vec { - external_addresses - .into_iter() - .flat_map(|addr| { - let addr = match String::from_utf8(addr) { - Ok(addr) => addr, - Err(addr) => { - debug!( - target: LOG_TARGET, - "Mixnode external address {:x?} is not valid UTF-8", - addr.into_bytes(), - ); - return None; - } - }; - match addr.parse() { - Ok(addr) => Some(addr), - Err(err) => { - debug!( - target: LOG_TARGET, - "Could not parse mixnode address {addr}: {err}", - ); - None - } - } - }) - .collect() -} - -/// Modify `external_addresses` such that there is at least one address and the final component of -/// each address matches `peer_id`. -fn fixup_external_addresses(external_addresses: &mut Vec, peer_id: &PeerId) { - // Ensure the final component of each address matches peer_id - external_addresses.retain_mut(|addr| match PeerId::try_from_multiaddr(addr) { - Some(addr_peer_id) if addr_peer_id == *peer_id => true, - Some(_) => { - debug!( - target: LOG_TARGET, - "Mixnode address {} does not match mixnode peer ID {}, ignoring", - addr, - peer_id - ); - false - } - None if matches!(addr.iter().last(), Some(Protocol::P2p(_))) => { - debug!( - target: LOG_TARGET, - "Mixnode address {} has unrecognised P2P protocol, ignoring", - addr - ); - false - } - None => { - addr.push(Protocol::P2p(*peer_id.as_ref())); - true - } - }); - - // If there are no addresses, insert one consisting of just the peer ID - if external_addresses.is_empty() { - external_addresses.push(multiaddr!(P2p(*peer_id.as_ref()))); - } -} - -/// Convert a [`RuntimeMixnode`] to a [`CoreMixnode`]. If the conversion fails, an error message is -/// logged, but a [`CoreMixnode`] is still returned. -/// -/// It would be possible to handle conversion failure in a better way, but this would complicate -/// things for what should be a rare case. Note that even if the conversion here succeeds, there is -/// no guarantee that we will be able to connect to the mixnode or send packets to it. The most -/// common failure case is expected to be that a mixnode is simply unreachable over the network. -fn into_core_mixnode(mixnode: RuntimeMixnode) -> CoreMixnode> { - let external_addresses = if let Some(peer_id) = from_core_peer_id(&mixnode.peer_id) { - let mut external_addresses = parse_external_addresses(mixnode.external_addresses); - fixup_external_addresses(&mut external_addresses, &peer_id); - external_addresses - } else { - debug!( - target: LOG_TARGET, - "Failed to convert mixnet peer ID {:x?} to libp2p peer ID", - mixnode.peer_id, - ); - Vec::new() - }; - - CoreMixnode { - kx_public: mixnode.kx_public, - peer_id: mixnode.peer_id, - extra: external_addresses, - } -} - -fn maybe_set_mixnodes( - mixnet: &mut Mixnet>, - rel_session_index: RelSessionIndex, - mixnodes: &dyn Fn() -> Result, RuntimeMixnodesErr>, ApiError>, -) { - let current_session_index = mixnet.session_status().current_index; - mixnet.maybe_set_mixnodes(rel_session_index, &mut || { - // Note that RelSessionIndex::Prev + 0 would panic, but this closure will not get called in - // that case so we are fine. Do not move this out of the closure! - let session_index = rel_session_index + current_session_index; - match mixnodes() { - Ok(Ok(mixnodes)) => Ok(mixnodes.into_iter().map(into_core_mixnode).collect()), - Ok(Err(err)) => { - info!(target: LOG_TARGET, "Session {session_index}: Mixnet disabled: {err}"); - Err(CoreMixnodesErr::Permanent) // Disable the session slot - } - Err(err) => { - debug!( - target: LOG_TARGET, - "Session {session_index}: Error getting mixnodes from runtime: {err}" - ); - Err(CoreMixnodesErr::Transient) // Just leave the session slot empty; try again next block - } - } - }); -} - -pub fn sync_with_runtime(mixnet: &mut Mixnet>, api: ApiRef, hash: B::Hash) -where - B: Block, - A: MixnetApi, -{ - let session_status = match api.session_status(hash) { - Ok(session_status) => session_status, - Err(err) => { - debug!(target: LOG_TARGET, "Error getting session status from runtime: {err}"); - return; - } - }; - mixnet.set_session_status(to_core_session_status(session_status)); - - maybe_set_mixnodes(mixnet, RelSessionIndex::Prev, &|| api.prev_mixnodes(hash)); - maybe_set_mixnodes(mixnet, RelSessionIndex::Current, &|| { - api.current_mixnodes(hash) - }); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn fixup_empty_external_addresses() { - let peer_id = PeerId::random(); - let mut external_addresses = Vec::new(); - fixup_external_addresses(&mut external_addresses, &peer_id); - assert_eq!(external_addresses, vec![multiaddr!(P2p(peer_id))]); - } - - #[test] - fn fixup_misc_external_addresses() { - let peer_id = PeerId::random(); - let other_peer_id = PeerId::random(); - let mut external_addresses = vec![ - multiaddr!(Tcp(0u16), P2p(peer_id)), - multiaddr!(Tcp(1u16), P2p(other_peer_id)), - multiaddr!(Tcp(2u16)), - Multiaddr::empty(), - ]; - fixup_external_addresses(&mut external_addresses, &peer_id); - assert_eq!( - external_addresses, - vec![ - multiaddr!(Tcp(0u16), P2p(peer_id)), - multiaddr!(Tcp(2u16), P2p(peer_id)), - multiaddr!(P2p(peer_id)), - ] - ); - } -} diff --git a/substrate/sp-runtime-interface-proc-macro/Cargo.toml b/substrate/sp-runtime-interface-proc-macro/Cargo.toml index c5e92dd081d..607887c4121 100644 --- a/substrate/sp-runtime-interface-proc-macro/Cargo.toml +++ b/substrate/sp-runtime-interface-proc-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-runtime-interface-proc-macro" -version = "18.0.0" +version = "21.0.0" authors.workspace = true edition.workspace = true license = "Apache-2.0" diff --git a/substrate/sp-runtime-interface-proc-macro/src/lib.rs b/substrate/sp-runtime-interface-proc-macro/src/lib.rs index ed825e97df1..afc48b47957 100644 --- a/substrate/sp-runtime-interface-proc-macro/src/lib.rs +++ b/substrate/sp-runtime-interface-proc-macro/src/lib.rs @@ -18,24 +18,15 @@ //! This crate provides procedural macros for usage within the context of the Substrate runtime //! interface. //! -//! The following macros are provided: -//! -//! 1. The [`#[runtime_interface]`](attr.runtime_interface.html) attribute macro for generating the -//! runtime interfaces. -//! 2. The [`PassByCodec`](derive.PassByCodec.html) derive macro for implementing `PassBy` with -//! `Codec`. -//! 3. The [`PassByEnum`](derive.PassByInner.html) derive macro for implementing `PassBy` with -//! `Enum`. -//! 4. The [`PassByInner`](derive.PassByInner.html) derive macro for implementing `PassBy` with -//! `Inner`. +//! It provides the [`#[runtime_interface]`](attr.runtime_interface.html) attribute macro +//! for generating the runtime interfaces. use syn::{ - DeriveInput, ItemTrait, Result, Token, + ItemTrait, Result, Token, parse::{Parse, ParseStream}, parse_macro_input, }; -mod pass_by; mod runtime_interface; mod utils; @@ -91,27 +82,3 @@ pub fn runtime_interface( .unwrap_or_else(|e| e.to_compile_error()) .into() } - -#[proc_macro_derive(PassByCodec)] -pub fn pass_by_codec(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - pass_by::codec_derive_impl(input) - .unwrap_or_else(|e| e.to_compile_error()) - .into() -} - -#[proc_macro_derive(PassByInner)] -pub fn pass_by_inner(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - pass_by::inner_derive_impl(input) - .unwrap_or_else(|e| e.to_compile_error()) - .into() -} - -#[proc_macro_derive(PassByEnum)] -pub fn pass_by_enum(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - pass_by::enum_derive_impl(input) - .unwrap_or_else(|e| e.to_compile_error()) - .into() -} diff --git a/substrate/sp-runtime-interface-proc-macro/src/pass_by/codec.rs b/substrate/sp-runtime-interface-proc-macro/src/pass_by/codec.rs deleted file mode 100644 index 984f8f121ec..00000000000 --- a/substrate/sp-runtime-interface-proc-macro/src/pass_by/codec.rs +++ /dev/null @@ -1,59 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Derive macro implementation of `PassBy` with the associated type set to `Codec`. -//! -//! It is required that the type implements `Encode` and `Decode` from the `parity-scale-codec` -//! crate. - -use crate::utils::{generate_crate_access, generate_runtime_interface_include}; - -use syn::{DeriveInput, Generics, Result, parse_quote}; - -use quote::quote; - -use proc_macro2::TokenStream; - -/// The derive implementation for `PassBy` with `Codec`. -pub fn derive_impl(mut input: DeriveInput) -> Result { - add_trait_bounds(&mut input.generics); - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - let crate_include = generate_runtime_interface_include(); - let crate_ = generate_crate_access(); - let ident = input.ident; - - let res = quote! { - const _: () = { - #crate_include - - impl #impl_generics #crate_::pass_by::PassBy for #ident #ty_generics #where_clause { - type PassBy = #crate_::pass_by::Codec<#ident>; - } - }; - }; - - Ok(res) -} - -/// Add the `codec::Codec` trait bound to every type parameter. -fn add_trait_bounds(generics: &mut Generics) { - let crate_ = generate_crate_access(); - - generics - .type_params_mut() - .for_each(|type_param| type_param.bounds.push(parse_quote!(#crate_::codec::Codec))); -} diff --git a/substrate/sp-runtime-interface-proc-macro/src/pass_by/enum_.rs b/substrate/sp-runtime-interface-proc-macro/src/pass_by/enum_.rs deleted file mode 100644 index 7667a651946..00000000000 --- a/substrate/sp-runtime-interface-proc-macro/src/pass_by/enum_.rs +++ /dev/null @@ -1,108 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Derive macro implementation of `PassBy` with the associated type set to `Enum`. -//! -//! Besides `PassBy`, `TryFrom` and `From for u8` are implemented for the type. - -use crate::utils::{generate_crate_access, generate_runtime_interface_include}; - -use syn::{Data, DeriveInput, Error, Fields, Ident, Result}; - -use quote::quote; - -use proc_macro2::{Span, TokenStream}; - -/// The derive implementation for `PassBy` with `Enum`. -pub fn derive_impl(input: DeriveInput) -> Result { - let crate_include = generate_runtime_interface_include(); - let crate_ = generate_crate_access(); - let ident = input.ident; - let enum_fields = get_enum_field_idents(&input.data)? - .enumerate() - .map(|(i, v)| { - let i = i as u8; - - v.map(|v| (quote!(#i => Ok(#ident::#v)), quote!(#ident::#v => #i))) - }) - .collect::>>()?; - let try_from_variants = enum_fields.iter().map(|i| &i.0); - let into_variants = enum_fields.iter().map(|i| &i.1); - - let res = quote! { - const _: () = { - #crate_include - - impl #crate_::pass_by::PassBy for #ident { - type PassBy = #crate_::pass_by::Enum<#ident>; - } - - impl TryFrom for #ident { - type Error = (); - - fn try_from(inner: u8) -> core::result::Result { - match inner { - #( #try_from_variants, )* - _ => Err(()), - } - } - } - - impl From<#ident> for u8 { - fn from(var: #ident) -> u8 { - match var { - #( #into_variants ),* - } - } - } - }; - }; - - Ok(res) -} - -/// Get the enum fields idents of the given `data` object as iterator. -/// -/// Returns an error if the number of variants is greater than `256`, the given `data` is not an -/// enum or a variant is not an unit. -fn get_enum_field_idents(data: &Data) -> Result>> { - match data { - Data::Enum(d) => { - if d.variants.len() <= 256 { - Ok(d.variants.iter().map(|v| { - if let Fields::Unit = v.fields { - Ok(&v.ident) - } else { - Err(Error::new( - Span::call_site(), - "`PassByEnum` only supports unit variants.", - )) - } - })) - } else { - Err(Error::new( - Span::call_site(), - "`PassByEnum` only supports `256` variants.", - )) - } - } - _ => Err(Error::new( - Span::call_site(), - "`PassByEnum` only supports enums as input type.", - )), - } -} diff --git a/substrate/sp-runtime-interface-proc-macro/src/pass_by/inner.rs b/substrate/sp-runtime-interface-proc-macro/src/pass_by/inner.rs deleted file mode 100644 index 2afdd3deab5..00000000000 --- a/substrate/sp-runtime-interface-proc-macro/src/pass_by/inner.rs +++ /dev/null @@ -1,110 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Derive macro implementation of `PassBy` with the associated type set to `Inner` and of the -//! helper trait `PassByInner`. -//! -//! It is required that the type is a newtype struct, otherwise an error is generated. - -use crate::utils::{generate_crate_access, generate_runtime_interface_include}; - -use syn::{Data, DeriveInput, Error, Fields, Generics, Ident, Result, Type, parse_quote}; - -use quote::quote; - -use proc_macro2::{Span, TokenStream}; - -/// The derive implementation for `PassBy` with `Inner` and `PassByInner`. -pub fn derive_impl(mut input: DeriveInput) -> Result { - add_trait_bounds(&mut input.generics); - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - let crate_include = generate_runtime_interface_include(); - let crate_ = generate_crate_access(); - let ident = input.ident; - let (inner_ty, inner_name) = extract_inner_ty_and_name(&input.data)?; - - let access_inner = match inner_name { - Some(ref name) => quote!(self.#name), - None => quote!(self.0), - }; - - let from_inner = match inner_name { - Some(name) => quote!(Self { #name: inner }), - None => quote!(Self(inner)), - }; - - let res = quote! { - const _: () = { - #crate_include - - impl #impl_generics #crate_::pass_by::PassBy for #ident #ty_generics #where_clause { - type PassBy = #crate_::pass_by::Inner; - } - - impl #impl_generics #crate_::pass_by::PassByInner for #ident #ty_generics #where_clause { - type Inner = #inner_ty; - - fn into_inner(self) -> Self::Inner { - #access_inner - } - - fn inner(&self) -> &Self::Inner { - &#access_inner - } - - fn from_inner(inner: Self::Inner) -> Self { - #from_inner - } - } - }; - }; - - Ok(res) -} - -/// Add the `RIType` trait bound to every type parameter. -fn add_trait_bounds(generics: &mut Generics) { - let crate_ = generate_crate_access(); - - generics - .type_params_mut() - .for_each(|type_param| type_param.bounds.push(parse_quote!(#crate_::RIType))); -} - -/// Extract the inner type and optional name from given input data. -/// -/// It also checks that the input data is a newtype struct. -fn extract_inner_ty_and_name(data: &Data) -> Result<(Type, Option)> { - if let Data::Struct(struct_data) = data { - match &struct_data.fields { - Fields::Named(named) if named.named.len() == 1 => { - let field = &named.named[0]; - return Ok((field.ty.clone(), field.ident.clone())); - } - Fields::Unnamed(unnamed) if unnamed.unnamed.len() == 1 => { - let field = &unnamed.unnamed[0]; - return Ok((field.ty.clone(), field.ident.clone())); - } - _ => {} - } - } - - Err(Error::new( - Span::call_site(), - "Only newtype/one field structs are supported by `PassByInner`!", - )) -} diff --git a/substrate/sp-runtime-interface-proc-macro/src/pass_by/mod.rs b/substrate/sp-runtime-interface-proc-macro/src/pass_by/mod.rs deleted file mode 100644 index f3d51d36248..00000000000 --- a/substrate/sp-runtime-interface-proc-macro/src/pass_by/mod.rs +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! All the `PassBy*` derive implementations. - -mod codec; -mod enum_; -mod inner; - -pub use self::codec::derive_impl as codec_derive_impl; -pub use enum_::derive_impl as enum_derive_impl; -pub use inner::derive_impl as inner_derive_impl; diff --git a/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/bare_function_interface.rs b/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/bare_function_interface.rs index d206c3f2497..447e2dc79d3 100644 --- a/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/bare_function_interface.rs +++ b/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/bare_function_interface.rs @@ -32,7 +32,7 @@ use crate::utils::{ RuntimeInterfaceFunction, create_exchangeable_host_function_ident, create_function_ident_with_version, generate_crate_access, get_function_argument_names, - get_function_arguments, get_runtime_interface, + get_function_arguments, get_runtime_interface, host_inner_return_ty, pat_ty_to_host_inner, }; use syn::{ @@ -99,16 +99,20 @@ fn function_for_method( }) } -/// Generates the bare function implementation for `cfg(not(feature = "std"))`. +/// Generates the bare function implementation for `cfg(substrate_runtime)`. fn function_no_std_impl( method: &RuntimeInterfaceFunction, is_wasm_only: bool, ) -> Result { + let should_trap_on_return = method.should_trap_on_return(); + let mut method = (*method).clone(); + crate::utils::unpack_inner_types_in_signature(&mut method.sig); + let function_name = &method.sig.ident; let host_function_name = create_exchangeable_host_function_ident(&method.sig.ident); let args = get_function_arguments(&method.sig); let arg_names = get_function_argument_names(&method.sig); - let return_value = if method.should_trap_on_return() { + let return_value = if should_trap_on_return { syn::ReturnType::Type( ]>::default(), Box::new( @@ -121,13 +125,13 @@ fn function_no_std_impl( } else { method.sig.output.clone() }; - let maybe_unreachable = if method.should_trap_on_return() { + let maybe_unreachable = if should_trap_on_return { quote! { ; #[cfg(target_family = "wasm")] { core::arch::wasm32::unreachable(); } - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] + #[cfg(target_arch = "riscv64")] unsafe { core::arch::asm!("unimp", options(noreturn)); } } } else { @@ -147,7 +151,7 @@ fn function_no_std_impl( Ok(quote! { #cfg_wasm_only - #[cfg(not(feature = "std"))] + #[cfg(substrate_runtime)] #( #attrs )* pub fn #function_name( #( #args, )* ) #return_value { // Call the host function @@ -157,14 +161,16 @@ fn function_no_std_impl( }) } -/// Generate call to latest function version for `cfg((feature = "std")` +/// Generate call to latest function version for `cfg(not(substrate_runtime))` /// /// This should generate simple `fn func(..) { func_version_(..) }`. fn function_std_latest_impl(method: &TraitItemFn, latest_version: u32) -> Result { let function_name = &method.sig.ident; - let args = get_function_arguments(&method.sig).map(FnArg::Typed); + let args = get_function_arguments(&method.sig) + .map(pat_ty_to_host_inner) + .map(FnArg::Typed); let arg_names = get_function_argument_names(&method.sig).collect::>(); - let return_value = &method.sig.output; + let return_value = host_inner_return_ty(&method.sig.output); let attrs = method .attrs .iter() @@ -173,7 +179,7 @@ fn function_std_latest_impl(method: &TraitItemFn, latest_version: u32) -> Result create_function_ident_with_version(&method.sig.ident, latest_version); Ok(quote_spanned! { method.span() => - #[cfg(feature = "std")] + #[cfg(not(substrate_runtime))] #( #attrs )* pub fn #function_name( #( #args, )* ) #return_value { #latest_function_name( @@ -183,7 +189,7 @@ fn function_std_latest_impl(method: &TraitItemFn, latest_version: u32) -> Result }) } -/// Generates the bare function implementation for `cfg(feature = "std")`. +/// Generates the bare function implementation for `cfg(not(substrate_runtime))`. fn function_std_impl( trait_name: &Ident, method: &TraitItemFn, @@ -195,20 +201,23 @@ fn function_std_impl( let function_name_str = function_name.to_string(); let crate_ = generate_crate_access(); - let args = get_function_arguments(&method.sig).map(FnArg::Typed).chain( - // Add the function context as last parameter when this is a wasm only interface. - iter::from_fn(|| { - if is_wasm_only { - Some(parse_quote!( - mut __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext - )) - } else { - None - } - }) - .take(1), - ); - let return_value = &method.sig.output; + let args = get_function_arguments(&method.sig) + .map(pat_ty_to_host_inner) + .map(FnArg::Typed) + .chain( + // Add the function context as last parameter when this is a wasm only interface. + iter::from_fn(|| { + if is_wasm_only { + Some(parse_quote!( + mut __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext + )) + } else { + None + } + }) + .take(1), + ); + let return_value = host_inner_return_ty(&method.sig.output); let attrs = method .attrs .iter() @@ -226,7 +235,7 @@ fn function_std_impl( }; Ok(quote_spanned! { method.span() => - #[cfg(feature = "std")] + #[cfg(not(substrate_runtime))] #( #attrs )* fn #function_name( #( #args, )* ) #return_value { #call_to_trait diff --git a/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/host_function_interface.rs b/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/host_function_interface.rs index 48fb11aefdf..0b79361620c 100644 --- a/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/host_function_interface.rs +++ b/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/host_function_interface.rs @@ -22,11 +22,10 @@ //! executor. These implementations call the bare function interface. use crate::utils::{ - RuntimeInterface, RuntimeInterfaceFunction, create_exchangeable_host_function_ident, + RuntimeInterfaceFunction, create_exchangeable_host_function_ident, create_function_ident_with_version, create_host_function_ident, generate_crate_access, - get_function_argument_names, get_function_argument_names_and_types_without_ref, - get_function_argument_types, get_function_argument_types_ref_and_mut, - get_function_argument_types_without_ref, get_function_arguments, get_runtime_interface, + get_function_argument_names, get_function_argument_names_and_types, + get_function_argument_types, get_function_arguments, get_runtime_interface, }; use syn::{ @@ -45,29 +44,25 @@ use std::iter::Iterator; /// implementations for the host functions on the host. pub fn generate(trait_def: &ItemTrait, is_wasm_only: bool) -> Result { let trait_name = &trait_def.ident; - let interface = get_runtime_interface(trait_def)?; - let extern_host_function_impls = interface.latest_versions_to_call().try_fold( - TokenStream::new(), - |mut t, (version, method)| { + let extern_host_function_impls = get_runtime_interface(trait_def)? + .latest_versions_to_call() + .try_fold(TokenStream::new(), |mut t, (version, method)| { t.extend(generate_extern_host_function(method, version, trait_name)?); Ok::<_, Error>(t) - }, - )?; - let exchangeable_host_functions = - interface - .latest_versions_to_call() - .try_fold(TokenStream::new(), |mut t, (_, m)| { - t.extend(generate_exchangeable_host_function(m)?); - Ok::<_, Error>(t) - })?; - let host_functions_struct = - generate_host_functions_struct(trait_def, &interface, is_wasm_only)?; + })?; + let exchangeable_host_functions = get_runtime_interface(trait_def)? + .latest_versions_to_call() + .try_fold(TokenStream::new(), |mut t, (_, m)| { + t.extend(generate_exchangeable_host_function(m)?); + Ok::<_, Error>(t) + })?; + let host_functions_struct = generate_host_functions_struct(trait_def, is_wasm_only)?; Ok(quote! { /// The implementations of the extern host functions. This special implementation module /// is required to change the extern host functions signature to /// `unsafe fn name(args) -> ret` to make the function implementations exchangeable. - #[cfg(not(feature = "std"))] + #[cfg(substrate_runtime)] mod extern_host_function_impls { use super::*; @@ -87,12 +82,14 @@ fn generate_extern_host_function( trait_name: &Ident, ) -> Result { let crate_ = generate_crate_access(); - let args = get_function_arguments(&method.sig); - let arg_types = get_function_argument_types_without_ref(&method.sig); - let arg_types2 = get_function_argument_types_without_ref(&method.sig); + + let mut unpacked_sig = method.sig.clone(); + crate::utils::unpack_inner_types_in_signature(&mut unpacked_sig); + let unpacked_args = get_function_arguments(&unpacked_sig); + let unpacked_return_value = &unpacked_sig.output; + + let arg_types = get_function_argument_types(&method.sig); let arg_names = get_function_argument_names(&method.sig); - let arg_names2 = get_function_argument_names(&method.sig); - let arg_names3 = get_function_argument_names(&method.sig); let function = &method.sig.ident; let ext_function = create_host_function_ident(&method.sig.ident, version, trait_name); let doc_string = format!( @@ -110,32 +107,57 @@ fn generate_extern_host_function( }; let convert_return_value = match return_value { - ReturnType::Default => quote!(), + ReturnType::Default => quote! { __runtime_interface_result_ }, ReturnType::Type(_, ty) => quote! { - <#ty as #crate_::wasm::FromFFIValue>::from_ffi_value(result) + <#ty as #crate_::wasm::FromFFIValue>::from_ffi_value(__runtime_interface_result_) }, }; + let mut call_into_ffi_value = Vec::new(); + let mut drop_args = Vec::new(); + let mut ffi_names = Vec::new(); + for (nth, arg) in get_function_arguments(&method.sig).enumerate() { + let arg_name = &arg.pat; + let arg_ty = &arg.ty; + let ffi_name = Ident::new( + &format!("__runtime_interface_ffi_value_{}_", nth), + arg.pat.span(), + ); + let destructor_name = Ident::new( + &format!("__runtime_interface_arg_destructor_{}_", nth), + arg.pat.span(), + ); + + ffi_names.push(ffi_name.clone()); + + call_into_ffi_value.push(quote! { + let mut #arg_name = #arg_name; + let (#ffi_name, #destructor_name) = <#arg_ty as #crate_::wasm::IntoFFIValue>::into_ffi_value(&mut #arg_name); + }); + + drop_args.push(quote! { + #[allow(dropping_copy_types)] + ::core::mem::drop(#destructor_name); + }); + } + + // Drop in the reverse order to construction. + drop_args.reverse(); + Ok(quote! { #(#cfg_attrs)* #[doc = #doc_string] - pub fn #function ( #( #args ),* ) #return_value { - #[cfg_attr(any(target_arch = "riscv32", target_arch = "riscv64"), #crate_::polkavm::polkavm_import(abi = #crate_::polkavm::polkavm_abi))] + pub fn #function ( #( #unpacked_args ),* ) #unpacked_return_value { + #[cfg_attr(target_arch = "riscv64", #crate_::polkavm::polkavm_import(abi = #crate_::polkavm::polkavm_abi))] unsafe extern "C" { pub fn #ext_function ( #( #arg_names: <#arg_types as #crate_::RIType>::FFIType ),* ) #ffi_return_value; } - // Generate all wrapped ffi values. - #( - let #arg_names2 = <#arg_types2 as #crate_::wasm::IntoFFIValue>::into_ffi_value( - &#arg_names2, - ); - )* - - let result = unsafe { #ext_function( #( #arg_names3.get() ),* ) }; - + #(#call_into_ffi_value)* + let __runtime_interface_result_ = unsafe { #ext_function( #( #ffi_names ),* ) }; + #(#drop_args)* #convert_return_value } }) @@ -143,6 +165,9 @@ fn generate_extern_host_function( /// Generate the host exchangeable function for the given method. fn generate_exchangeable_host_function(method: &TraitItemFn) -> Result { + let mut method = method.clone(); + crate::utils::unpack_inner_types_in_signature(&mut method.sig); + let crate_ = generate_crate_access(); let arg_types = get_function_argument_types(&method.sig); let function = &method.sig.ident; @@ -156,7 +181,7 @@ fn generate_exchangeable_host_function(method: &TraitItemFn) -> Result Result Result { let crate_ = generate_crate_access(); @@ -178,7 +202,7 @@ fn generate_host_functions_struct( let mut register_bodies = Vec::new(); let mut append_hf_bodies = Vec::new(); - for (version, method) in interface.all_versions() { + for (version, method) in get_runtime_interface(trait_def)?.all_versions() { let (implementation, register_body, append_hf_body) = generate_host_function_implementation(&trait_def.ident, method, version, is_wasm_only)?; host_function_impls.push(implementation); @@ -190,10 +214,10 @@ fn generate_host_functions_struct( #(#host_function_impls)* /// Provides implementations for the extern host functions. - #[cfg(feature = "std")] + #[cfg(not(substrate_runtime))] pub struct HostFunctions; - #[cfg(feature = "std")] + #[cfg(not(substrate_runtime))] impl #crate_::sp_wasm_interface::HostFunctions for HostFunctions { fn host_functions() -> Vec<&'static dyn #crate_::sp_wasm_interface::Function> { let mut host_functions_list = Vec::new(); @@ -230,13 +254,13 @@ fn generate_host_function_implementation( let signature = generate_wasm_interface_signature_for_host_function(&method.sig)?; let fn_name = create_function_ident_with_version(&method.sig.ident, version); - let ref_and_mut = get_function_argument_types_ref_and_mut(&method.sig); // List of variable names containing WASM FFI-compatible arguments. let mut ffi_names = Vec::new(); // List of `$name: $ty` tokens containing WASM FFI-compatible arguments. let mut ffi_args_prototype = Vec::new(); + let mut ffi_arg_types = Vec::new(); // List of variable names containing arguments already converted into native Rust types. // Also includes the preceding `&` or `&mut`. To be used to call the actual implementation of @@ -254,9 +278,7 @@ fn generate_host_function_implementation( // List of code snippets to convert static FFI args (`u32`, etc.) into native Rust types. let mut convert_args_static_ffi_to_host = Vec::new(); - for ((host_name, host_ty), ref_and_mut) in - get_function_argument_names_and_types_without_ref(&method.sig).zip(ref_and_mut) - { + for (host_name, host_ty) in get_function_argument_names_and_types(&method.sig) { let ffi_name = generate_ffi_value_var_name(&host_name)?; let host_name_ident = match *host_name { Pat::Ident(ref pat_ident) => pat_ident.ident.clone(), @@ -267,6 +289,7 @@ fn generate_host_function_implementation( let ffi_ty = quote! { <#host_ty as #crate_::RIType>::FFIType }; ffi_args_prototype.push(quote! { #ffi_name: #ffi_ty }); + ffi_arg_types.push(ffi_ty.clone()); ffi_names.push(quote! { #ffi_name }); let convert_arg_error = format!( @@ -275,35 +298,24 @@ fn generate_host_function_implementation( ); convert_args_static_ffi_to_host.push(quote! { let mut #host_name = <#host_ty as #crate_::host::FromFFIValue>::from_ffi_value(__function_context__, #ffi_name) - .map_err(|err| format!("{}: {}", err, #convert_arg_error))?; + .map_err(|err| #crate_::alloc::format!("{}: {}", err, #convert_arg_error))?; }); - let ref_and_mut_tokens = - ref_and_mut.map(|(token_ref, token_mut)| quote!(#token_ref #token_mut)); - - host_names_with_ref.push(quote! { #ref_and_mut_tokens #host_name }); - - if ref_and_mut - .map(|(_, token_mut)| token_mut.is_some()) - .unwrap_or(false) - { - copy_data_into_ref_mut_args.push(quote! { - <#host_ty as #crate_::host::IntoPreallocatedFFIValue>::into_preallocated_ffi_value( - #host_name, - __function_context__, - #ffi_name, - )?; - }); - } + host_names_with_ref.push( + quote! { <#host_ty as #crate_::host::FromFFIValue>::take_from_owned(&mut #host_name) }, + ); + copy_data_into_ref_mut_args.push(quote! { + <#host_ty as #crate_::host::FromFFIValue>::write_back_into_runtime(#host_name, __function_context__, #ffi_name)?; + }); let arg_count_mismatch_error = format!( "missing argument '{}': number of arguments given to '{}' from interface '{}' does not match the expected number of arguments", host_name_ident, method.sig.ident, trait_name ); convert_args_dynamic_ffi_to_static_ffi.push(quote! { - let #ffi_name = args.next().ok_or_else(|| #arg_count_mismatch_error.to_owned())?; + let #ffi_name = args.next().ok_or_else(|| #crate_::alloc::borrow::ToOwned::to_owned(#arg_count_mismatch_error))?; let #ffi_name: #ffi_ty = #crate_::sp_wasm_interface::TryFromValue::try_from_value(#ffi_name) - .ok_or_else(|| #convert_arg_error.to_owned())?; + .ok_or_else(|| #crate_::alloc::borrow::ToOwned::to_owned(#convert_arg_error))?; }); } @@ -354,16 +366,16 @@ fn generate_host_function_implementation( let implementation = quote! { #(#cfg_attrs)* - #[cfg(feature = "std")] + #[cfg(not(substrate_runtime))] struct #struct_name; #(#cfg_attrs)* - #[cfg(feature = "std")] + #[cfg(not(substrate_runtime))] impl #struct_name { fn call( __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext, #(#ffi_args_prototype),* - ) -> std::result::Result<#ffi_return_ty, String> { + ) -> ::core::result::Result<#ffi_return_ty, #crate_::alloc::string::String> { #(#convert_args_static_ffi_to_host)* let __result__ = #fn_name(#(#host_names_with_ref),*); #(#copy_data_into_ref_mut_args)* @@ -373,7 +385,7 @@ fn generate_host_function_implementation( } #(#cfg_attrs)* - #[cfg(feature = "std")] + #[cfg(not(substrate_runtime))] impl #crate_::sp_wasm_interface::Function for #struct_name { fn name(&self) -> &str { #name @@ -387,7 +399,7 @@ fn generate_host_function_implementation( &self, __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext, args: &mut dyn Iterator, - ) -> std::result::Result, String> { + ) -> ::core::result::Result, #crate_::alloc::string::String> { #(#convert_args_dynamic_ffi_to_static_ffi)* let __result__ = Self::call( __function_context__, @@ -401,10 +413,16 @@ fn generate_host_function_implementation( let register_body = quote! { #(#cfg_attrs)* - registry.register_static( + registry.register_static::< + ( + #crate_::sp_wasm_interface::wasmtime::Caller<'_, T::State>, + #(#ffi_arg_types,)* + ), + #crate_::sp_wasm_interface::wasmtime::Result<#ffi_return_ty>, + >( #crate_::sp_wasm_interface::Function::name(&#struct_name), |mut caller: #crate_::sp_wasm_interface::wasmtime::Caller, #(#ffi_args_prototype),*| - -> std::result::Result<#ffi_return_ty, #crate_::sp_wasm_interface::wasmtime::Error> + -> #crate_::sp_wasm_interface::wasmtime::Result<#ffi_return_ty> { T::with_function_context(caller, move |__function_context__| { let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { @@ -417,12 +435,12 @@ fn generate_host_function_implementation( Ok(result) => result, Err(panic) => { let message = - if let Some(message) = panic.downcast_ref::() { - format!("host code panicked while being called by the runtime: {}", message) + if let Some(message) = panic.downcast_ref::<#crate_::alloc::string::String>() { + #crate_::alloc::format!("host code panicked while being called by the runtime: {}", message) } else if let Some(message) = panic.downcast_ref::<&'static str>() { - format!("host code panicked while being called by the runtime: {}", message) + #crate_::alloc::format!("host code panicked while being called by the runtime: {}", message) } else { - "host code panicked while being called by the runtime".to_owned() + #crate_::alloc::borrow::ToOwned::to_owned("host code panicked while being called by the runtime") }; return Err(#crate_::sp_wasm_interface::wasmtime::Error::msg(message)); } @@ -449,7 +467,7 @@ fn generate_wasm_interface_signature_for_host_function(sig: &Signature) -> Resul }, ReturnType::Default => quote!(None), }; - let arg_types = get_function_argument_types_without_ref(sig).map(|ty| { + let arg_types = get_function_argument_types(sig).map(|ty| { quote! { <<#ty as #crate_::RIType>::FFIType as #crate_::sp_wasm_interface::IntoValue>::VALUE_TYPE } @@ -457,7 +475,7 @@ fn generate_wasm_interface_signature_for_host_function(sig: &Signature) -> Resul Ok(quote! { #crate_::sp_wasm_interface::Signature { - args: std::borrow::Cow::Borrowed(&[ #( #arg_types ),* ][..]), + args: #crate_::alloc::borrow::Cow::Borrowed(&[ #( #arg_types ),* ][..]), return_value: #return_value, } }) diff --git a/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/trait_decl_impl.rs b/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/trait_decl_impl.rs index a6ca530c675..66df605da25 100644 --- a/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/trait_decl_impl.rs +++ b/substrate/sp-runtime-interface-proc-macro/src/runtime_interface/trait_decl_impl.rs @@ -19,8 +19,8 @@ //! default implementations and implements the trait for `&mut dyn Externalities`. use crate::utils::{ - RuntimeInterface, create_function_ident_with_version, generate_crate_access, - get_function_argument_types_without_ref, get_runtime_interface, + create_function_ident_with_version, generate_crate_access, get_function_argument_types, + get_runtime_interface, }; use syn::{ @@ -36,9 +36,8 @@ use quote::quote; /// Process the given trait definition, by checking that the definition is valid, fold it to the /// essential definition and implement this essential definition for `dyn Externalities`. pub fn process(trait_def: &ItemTrait, is_wasm_only: bool) -> Result { - let interface = get_runtime_interface(trait_def)?; - let impl_trait = impl_trait_for_externalities(trait_def, &interface, is_wasm_only)?; - let essential_trait_def = declare_essential_trait(trait_def, &interface)?; + let impl_trait = impl_trait_for_externalities(trait_def, is_wasm_only)?; + let essential_trait_def = declare_essential_trait(trait_def)?; Ok(quote! { #impl_trait @@ -79,6 +78,7 @@ impl ToEssentialTraitDef { fn process(&mut self, method: &TraitItemFn, version: u32) { let mut folded = self.fold_trait_item_fn(method.clone()); folded.sig.ident = create_function_ident_with_version(&folded.sig.ident, version); + crate::utils::unpack_inner_types_in_signature(&mut folded.sig); self.methods.push(folded); } @@ -99,7 +99,7 @@ impl Fold for ToEssentialTraitDef { self.push_error(&method, "Methods need to have an implementation."); } - let arg_types = get_function_argument_types_without_ref(&method.sig); + let arg_types = get_function_argument_types(&method.sig); arg_types .filter_map(|ty| match *ty { Type::ImplTrait(impl_trait) => Some(impl_trait), @@ -130,10 +130,7 @@ impl Fold for ToEssentialTraitDef { } } -fn declare_essential_trait( - trait_def: &ItemTrait, - interface: &RuntimeInterface, -) -> Result { +fn declare_essential_trait(trait_def: &ItemTrait) -> Result { let trait_ = &trait_def.ident; if let Some(param) = trait_def.generics.params.first() { @@ -143,6 +140,7 @@ fn declare_essential_trait( )); } + let interface = get_runtime_interface(trait_def)?; let mut folder = ToEssentialTraitDef::new(); for (version, interface_method) in interface.all_versions() { folder.process(interface_method, version); @@ -157,17 +155,15 @@ fn declare_essential_trait( } /// Implements the given trait definition for `dyn Externalities`. -fn impl_trait_for_externalities( - trait_def: &ItemTrait, - interface: &RuntimeInterface, - is_wasm_only: bool, -) -> Result { +fn impl_trait_for_externalities(trait_def: &ItemTrait, is_wasm_only: bool) -> Result { let trait_ = &trait_def.ident; let crate_ = generate_crate_access(); + let interface = get_runtime_interface(trait_def)?; let methods = interface.all_versions().map(|(version, method)| { let mut cloned = (*method).clone(); cloned.attrs.retain(|a| !a.path().is_ident("version")); cloned.sig.ident = create_function_ident_with_version(&cloned.sig.ident, version); + crate::utils::unpack_inner_types_in_signature(&mut cloned.sig); cloned }); @@ -178,7 +174,7 @@ fn impl_trait_for_externalities( }; Ok(quote! { - #[cfg(feature = "std")] + #[cfg(not(substrate_runtime))] impl #trait_ for #impl_type { #( #methods )* } diff --git a/substrate/sp-runtime-interface-proc-macro/src/utils.rs b/substrate/sp-runtime-interface-proc-macro/src/utils.rs index 9eb685939b7..7a1c46dc3e1 100644 --- a/substrate/sp-runtime-interface-proc-macro/src/utils.rs +++ b/substrate/sp-runtime-interface-proc-macro/src/utils.rs @@ -133,7 +133,7 @@ impl RuntimeInterfaceFunctionSet { .insert(version.version, RuntimeInterfaceFunction::new(trait_item)?); if self .latest_version_to_call - .is_none_or(|v| v < version.version) + .map_or(true, |v| v < version.version) && version.is_callable() { self.latest_version_to_call = Some(version.version); @@ -234,7 +234,7 @@ pub fn get_function_arguments(sig: &Signature) -> impl Iterator wild.span(), ); - *res.pat = parse_quote!( #ident ); + res.pat = Box::new(parse_quote!( #ident )) } res @@ -251,41 +251,11 @@ pub fn get_function_argument_types(sig: &Signature) -> impl Iterator impl Iterator> + '_ { - get_function_arguments(sig) - .map(|pt| pt.ty) - .map(|ty| match *ty { - Type::Reference(type_ref) => type_ref.elem, - _ => ty, - }) -} - -/// Returns the function argument names and types, minus any `self`. If any of the arguments -/// is a reference, the underlying type without the ref is returned. -pub fn get_function_argument_names_and_types_without_ref( +/// Returns the function argument names and types, minus any `self`. +pub fn get_function_argument_names_and_types( sig: &Signature, ) -> impl Iterator, Box)> + '_ { - get_function_arguments(sig).map(|pt| match *pt.ty { - Type::Reference(type_ref) => (pt.pat, type_ref.elem), - _ => (pt.pat, pt.ty), - }) -} - -/// Returns the `&`/`&mut` for all function argument types, minus the `self` arg. If a function -/// argument is not a reference, `None` is returned. -pub fn get_function_argument_types_ref_and_mut( - sig: &Signature, -) -> impl Iterator)>> + '_ { - get_function_arguments(sig) - .map(|pt| pt.ty) - .map(|ty| match *ty { - Type::Reference(type_ref) => Some((type_ref.and_token, type_ref.mutability)), - _ => None, - }) + get_function_arguments(sig).map(|pt| (pt.pat, pt.ty)) } /// Returns an iterator over all trait methods for the given trait definition. @@ -394,3 +364,37 @@ pub fn get_runtime_interface(trait_def: &ItemTrait) -> Result Ok(RuntimeInterface { items: functions }) } + +pub fn host_inner_arg_ty(ty: &syn::Type) -> syn::Type { + let crate_ = generate_crate_access(); + syn::parse2::(quote! { <#ty as #crate_::RIType>::Inner }) + .expect("parsing doesn't fail") +} + +pub fn pat_ty_to_host_inner(mut pat: syn::PatType) -> syn::PatType { + pat.ty = Box::new(host_inner_arg_ty(&pat.ty)); + pat +} + +pub fn host_inner_return_ty(ty: &syn::ReturnType) -> syn::ReturnType { + let crate_ = generate_crate_access(); + match ty { + syn::ReturnType::Default => syn::ReturnType::Default, + syn::ReturnType::Type(arrow, ty) => { + syn::parse2::(quote! { #arrow <#ty as #crate_::RIType>::Inner }) + .expect("parsing doesn't fail") + } + } +} + +pub fn unpack_inner_types_in_signature(sig: &mut syn::Signature) { + sig.output = crate::utils::host_inner_return_ty(&sig.output); + for arg in sig.inputs.iter_mut() { + match arg { + syn::FnArg::Typed(pat_ty) => { + *pat_ty = crate::utils::pat_ty_to_host_inner(pat_ty.clone()); + } + syn::FnArg::Receiver(..) => {} + } + } +} diff --git a/substrate/sp-wasm-interface-common/src/lib.rs b/substrate/sp-wasm-interface-common/src/lib.rs index 7fc46bf0632..aa6c4dbb9d5 100644 --- a/substrate/sp-wasm-interface-common/src/lib.rs +++ b/substrate/sp-wasm-interface-common/src/lib.rs @@ -183,12 +183,20 @@ impl PointerType for u32 {} impl PointerType for u64 {} /// Type to represent a pointer in wasm at the host. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq)] pub struct Pointer { ptr: u32, _marker: PhantomData, } +impl Copy for Pointer {} + +impl Clone for Pointer { + fn clone(&self) -> Self { + *self + } +} + impl Pointer { /// Create a new instance of `Self`. pub fn new(ptr: u32) -> Self { diff --git a/substrate/sp-wasm-interface/Cargo.toml b/substrate/sp-wasm-interface/Cargo.toml index 244387b7a5a..348cdba78ad 100644 --- a/substrate/sp-wasm-interface/Cargo.toml +++ b/substrate/sp-wasm-interface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sp-wasm-interface" -version = "21.0.1" +version = "24.0.0" authors.workspace = true edition.workspace = true rust-version.workspace = true @@ -21,7 +21,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { features = ["derive"], workspace = true } impl-trait-for-tuples = { workspace = true } log = { optional = true, workspace = true, default-features = true } -wasmtime = { features = ["runtime"], optional = true, workspace = true } +wasmtime = { optional = true, workspace = true } anyhow = { optional = true, workspace = true } sp-wasm-interface-common = { workspace = true, default-features = false } sp-allocator = { workspace = true, default-features = false } diff --git a/substrate/sp-wasm-interface/src/lib.rs b/substrate/sp-wasm-interface/src/lib.rs index 72183038359..a8694b3375d 100644 --- a/substrate/sp-wasm-interface/src/lib.rs +++ b/substrate/sp-wasm-interface/src/lib.rs @@ -62,8 +62,7 @@ if_wasmtime_is_enabled! { // Reexport wasmtime so that its types are accessible from the procedural macro. pub use wasmtime; - // Wasmtime uses anyhow types but doesn't reexport them. - pub use anyhow; + pub use wasmtime::anyhow; } /// Result type used by traits in this crate. diff --git a/substrate/substrate-wasm-builder/Cargo.toml b/substrate/substrate-wasm-builder/Cargo.toml index 15c73df13be..dc19e719318 100644 --- a/substrate/substrate-wasm-builder/Cargo.toml +++ b/substrate/substrate-wasm-builder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate-wasm-builder" -version = "24.0.2" +version = "32.0.0" authors.workspace = true description = "Utility for building WASM binaries" edition.workspace = true diff --git a/utils/gear-workspace-hack/Cargo.toml b/utils/gear-workspace-hack/Cargo.toml index 1e05a03c11f..260c09dcc70 100644 --- a/utils/gear-workspace-hack/Cargo.toml +++ b/utils/gear-workspace-hack/Cargo.toml @@ -19,192 +19,191 @@ publish = false [target.'cfg(not(target_arch = "wasm32"))'.dependencies.frame-executive] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.frame-support] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" -features = ["experimental"] +rev = "e3737178ec726cffe506c907263aaaa417893fd0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies.frame-try-runtime] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-authority-discovery] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-authorship] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-babe] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-bags-list] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-balances] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-bounties] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-child-bounties] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-conviction-voting] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-election-provider-multi-phase] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-grandpa] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-identity] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-im-online] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-multisig] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-nomination-pools] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-offences] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-preimage] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-proxy] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-ranked-collective] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-referenda] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-scheduler] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-session] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["historical", "std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-sudo] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-timestamp] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-transaction-payment] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-treasury] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-utility] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-vesting] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-whitelist] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["std"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.sc-client-db] git = "https://github.com/paritytech/polkadot-sdk.git" -rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["rocksdb", "test-helpers"] @@ -226,67 +225,77 @@ alloy-sol-type-parser = { version = "1", default-features = false, features = [" alloy-sol-types = { version = "1", features = ["json"] } anyhow = { version = "1" } arbitrary = { version = "1", default-features = false, features = ["derive"] } -ark-bls12-381 = { version = "0.4", default-features = false, features = ["curve", "std"] } -ark-bls12-381-ext = { version = "0.4", default-features = false, features = ["std"] } -ark-ec = { version = "0.4", features = ["parallel"] } -ark-ff = { version = "0.4", default-features = false, features = ["std"] } -ark-models-ext = { version = "0.4", default-features = false, features = ["std"] } -ark-scale = { version = "0.0.12", default-features = false, features = ["hazmat", "std"] } -ark-serialize = { version = "0.4", default-features = false, features = ["derive", "std"] } -ark-std = { version = "0.4", default-features = false, features = ["parallel"] } +ark-bls12-381-9fbad63c4bcf4a8f = { package = "ark-bls12-381", version = "0.4", default-features = false, features = ["curve", "std"] } +ark-bls12-381-d8f496e17d97b5cb = { package = "ark-bls12-381", version = "0.5", default-features = false, features = ["curve", "std"] } +ark-bls12-381-ext = { version = "0.5", default-features = false, features = ["std"] } +ark-ec-9fbad63c4bcf4a8f = { package = "ark-ec", version = "0.4", features = ["std"] } +ark-ec-d8f496e17d97b5cb = { package = "ark-ec", version = "0.5", default-features = false, features = ["parallel"] } +ark-ff-9fbad63c4bcf4a8f = { package = "ark-ff", version = "0.4", default-features = false, features = ["std"] } +ark-ff-d8f496e17d97b5cb = { package = "ark-ff", version = "0.5", default-features = false, features = ["std"] } +ark-models-ext = { version = "0.5", default-features = false, features = ["std"] } +ark-scale-c7d3f9b296863baf = { package = "ark-scale", version = "0.0.13", default-features = false, features = ["hazmat", "std"] } +ark-scale-e9ecf5c1847bd87 = { package = "ark-scale", version = "0.0.12", default-features = false, features = ["hazmat", "std"] } +ark-serialize-9fbad63c4bcf4a8f = { package = "ark-serialize", version = "0.4", default-features = false, features = ["derive", "std"] } +ark-serialize-d8f496e17d97b5cb = { package = "ark-serialize", version = "0.5", default-features = false, features = ["derive", "parallel", "std"] } +ark-std-9fbad63c4bcf4a8f = { package = "ark-std", version = "0.4", default-features = false, features = ["std"] } +ark-std-d8f496e17d97b5cb = { package = "ark-std", version = "0.5", default-features = false, features = ["parallel"] } arrayvec = { version = "0.7", features = ["serde"] } base64 = { version = "0.22" } -binary-merkle-tree = { version = "16", default-features = false, features = ["std"] } +binary-merkle-tree-8ee676a8f9a6c413 = { package = "binary-merkle-tree", version = "16", default-features = false, features = ["std"] } +binary-merkle-tree-963a482513f5037f = { package = "binary-merkle-tree", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +bip39 = { version = "2", features = ["rand"] } bitflags = { version = "2", default-features = false, features = ["std"] } -bitvec = { version = "1" } +bitvec = { version = "1", features = ["serde"] } blake2 = { version = "0.10" } blake2b_simd = { version = "1", default-features = false, features = ["std"] } -bounded-collections = { version = "0.2", default-features = false, features = ["std"] } -bp-header-chain = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -bp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } +bounded-collections = { version = "0.3", default-features = false, features = ["std"] } +bp-header-chain = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +bp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } bs58 = { version = "0.5", features = ["check"] } bumpalo = { version = "3", features = ["allocator-api2"] } byte-slice-cast = { version = "1", default-features = false, features = ["std"] } bytemuck = { version = "1", default-features = false, features = ["const_zeroed", "derive", "min_const_generics", "must_cast"] } -byteorder = { version = "1", features = ["i128"] } +byteorder = { version = "1" } bytes = { version = "1", features = ["serde"] } clap = { version = "4", features = ["derive", "env", "string", "wrap_help"] } clap_builder = { version = "4", default-features = false, features = ["color", "env", "std", "string", "suggestions", "usage", "wrap_help"] } concurrent-queue = { version = "2" } const-hex = { version = "1", features = ["core-error", "serde"] } cranelift-bitset = { version = "0.131", default-features = false, features = ["enable-serde"] } -cranelift-codegen = { version = "0.131", default-features = false, features = ["host-arch", "pulley", "std", "timing", "unwind"] } crc32fast = { version = "1" } crossbeam-channel = { version = "0.5" } crossbeam-epoch = { version = "0.9" } +crossbeam-queue = { version = "0.3" } crossbeam-utils = { version = "0.8" } crunchy = { version = "0.2", features = ["std"] } crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +cumulus-primitives-core = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } curve25519-dalek = { version = "4", features = ["digest", "legacy_compatibility"] } data-encoding = { version = "2" } -der = { version = "0.7", default-features = false, features = ["oid", "pem", "std"] } +der = { version = "0.7", default-features = false, features = ["oid", "std", "zeroize"] } derive_more-f595c2ba2a3f28df = { package = "derive_more", version = "2", default-features = false, features = ["full", "std"] } digest-274715c4dabd11b0 = { package = "digest", version = "0.9", default-features = false, features = ["std"] } digest-93f6ce9d446188ac = { package = "digest", version = "0.10", features = ["mac", "oid", "std"] } -ecdsa = { version = "0.16", default-features = false, features = ["pem", "serde", "signing", "std", "verifying"] } +ecdsa = { version = "0.16", default-features = false, features = ["pkcs8", "serde", "signing", "std", "verifying"] } ed25519 = { version = "2", default-features = false, features = ["alloc", "std"] } ed25519-dalek = { version = "2", features = ["rand_core"] } ed25519-zebra = { version = "4", default-features = false, features = ["std"] } either = { version = "1", features = ["serde", "use_std"] } -elliptic-curve = { version = "0.13", default-features = false, features = ["digest", "hazmat", "pem", "serde", "std"] } +elliptic-curve = { version = "0.13", default-features = false, features = ["arithmetic", "digest", "hazmat", "serde", "std"] } enumflags2 = { version = "0.7", default-features = false, features = ["std"] } +env_filter = { version = "0.1" } environmental = { version = "1" } -event-listener = { version = "5" } -event-listener-strategy = { version = "0.5" } finality-grandpa = { version = "0.16", features = ["derive-codec"] } fixed-hash = { version = "0.8", default-features = false, features = ["std"] } fnv = { version = "1" } -foldhash = { version = "0.2", default-features = false, features = ["std"] } +foldhash-6f8ce4dd05d13bba = { package = "foldhash", version = "0.2", default-features = false, features = ["std"] } +foldhash-c65f7effa3be6d31 = { package = "foldhash", version = "0.1", default-features = false, features = ["std"] } form_urlencoded = { version = "1" } -frame-metadata-8ee676a8f9a6c413 = { package = "frame-metadata", version = "16" } -frame-metadata-e761569b921b4a02 = { package = "frame-metadata", version = "23", default-features = false, features = ["current", "std"] } -frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } +frame-metadata = { version = "23", default-features = false, features = ["std", "unstable"] } +frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +frame-storage-access-test-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } futures = { version = "0.3", features = ["bilock", "thread-pool", "unstable"] } futures-channel = { version = "0.3", features = ["sink", "unstable"] } futures-core = { version = "0.3", features = ["unstable"] } @@ -302,23 +311,26 @@ getrandom-6f8ce4dd05d13bba = { package = "getrandom", version = "0.2", default-f getrandom_or_panic = { version = "0.0.3", default-features = false, features = ["std"] } hash-db = { version = "0.16" } hash256-std-hasher = { version = "0.15", default-features = false, features = ["std"] } +hashbrown-3575ec1268b04181 = { package = "hashbrown", version = "0.15" } hashbrown-582f2526e08bb6a0 = { package = "hashbrown", version = "0.14", features = ["raw"] } hashbrown-594e8ee84c453af0 = { package = "hashbrown", version = "0.13", features = ["raw"] } +hashbrown-5ef9efb8ec2df382 = { package = "hashbrown", version = "0.12", features = ["raw"] } hashbrown-9067fe90e8c1f593 = { package = "hashbrown", version = "0.17", default-features = false, features = ["default-hasher"] } hashbrown-986da7b5efc2b80e = { package = "hashbrown", version = "0.16", features = ["serde"] } -hex = { version = "0.4", features = ["serde"] } +hex = { version = "0.4" } hkdf = { version = "0.12", default-features = false, features = ["std"] } hmac = { version = "0.12", default-features = false, features = ["reset", "std"] } http-body-util = { version = "0.1" } -hyper-582f2526e08bb6a0 = { package = "hyper", version = "0.14", features = ["client", "http1", "http2", "runtime", "server", "stream"] } +hyper-582f2526e08bb6a0 = { package = "hyper", version = "0.14", features = ["client", "http1", "http2", "server", "stream", "tcp"] } hyper-dff4ba8e3ae991db = { package = "hyper", version = "1", features = ["client", "http1", "http2", "server"] } -hyper-util = { version = "0.1", features = ["client-legacy", "server-auto", "service"] } -idna = { version = "1", default-features = false, features = ["compiled_data", "std"] } -impl-codec = { version = "0.6", default-features = false, features = ["std"] } -impl-serde = { version = "0.4" } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "rustls-native-certs", "tls12"] } +hyper-util = { version = "0.1", features = ["client-legacy", "server-auto", "server-graceful", "service"] } +impl-codec = { version = "0.7", default-features = false, features = ["std"] } +impl-serde = { version = "0.5", default-features = false, features = ["std"] } indexmap = { version = "2", features = ["serde"] } ipnet = { version = "2" } -itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } +itertools-582f2526e08bb6a0 = { package = "itertools", version = "0.14" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13", default-features = false, features = ["use_std"] } itertools-93f6ce9d446188ac = { package = "itertools", version = "0.10" } js-sys = { version = "0.3" } jsonrpsee = { version = "0.24", default-features = false, features = ["client", "macros", "server"] } @@ -327,21 +339,16 @@ jsonrpsee-core = { version = "0.24", features = ["async-client", "async-wasm-cli k256 = { version = "0.13", features = ["serde"] } keccak = { version = "0.1", default-features = false, features = ["asm"] } libc = { version = "0.2" } -libp2p-11df1a741327a505 = { package = "libp2p", version = "0.56", default-features = false, features = ["cbor", "dns", "ecdsa", "ed25519", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "serde", "tcp", "tls", "tokio", "yamux"] } -libp2p-b21d60becc0929df = { package = "libp2p", version = "0.52", default-features = false, features = ["dns", "ed25519", "identify", "kad", "macros", "mdns", "noise", "ping", "request-response", "tcp", "tokio", "wasm-ext", "websocket", "yamux"] } -libp2p-core = { version = "0.43", default-features = false, features = ["serde"] } -libp2p-gossipsub = { version = "0.49", default-features = false, features = ["metrics", "serde"] } -libp2p-identity = { version = "0.2", default-features = false, features = ["ecdsa", "ed25519", "peerid", "rand", "secp256k1", "serde"] } -libp2p-kad = { version = "0.48", default-features = false, features = ["serde"] } -libp2p-request-response = { version = "0.29", default-features = false, features = ["cbor"] } -libsecp256k1 = { version = "0.7" } +libp2p = { version = "0.54", default-features = false, features = ["dns", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "tcp", "tls", "tokio", "websocket", "yamux"] } +libp2p-identity = { version = "0.2", default-features = false, features = ["ed25519", "peerid", "rand", "secp256k1", "serde"] } +libp2p-swarm = { version = "0.45", default-features = false, features = ["async-std", "macros", "tokio"] } +libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context", "std"] } libsecp256k1-core = { version = "0.3" } log = { version = "0.4", default-features = false, features = ["std"] } macro_magic = { version = "0.5", features = ["proc_support"] } memchr = { version = "2" } -memory-db = { version = "0.32", default-features = false, features = ["std"] } +memory-db = { version = "0.34", default-features = false, features = ["std"] } merlin = { version = "3", default-features = false, features = ["std"] } -multihash = { version = "0.19", features = ["serde-codec"] } names = { version = "0.14" } nom = { version = "7" } num-bigint = { version = "0.4" } @@ -349,26 +356,32 @@ num-integer = { version = "0.1", default-features = false, features = ["i128", " num-rational = { version = "0.4", features = ["num-bigint-std"] } num-traits = { version = "0.2", features = ["i128", "libm"] } numerated = { version = "2", default-features = false, features = ["mock"] } -once_cell = { version = "1" } -pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -pallet-staking-reward-fn = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -pallet-staking-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -parity-bip39 = { version = "2", features = ["rand"] } -parity-scale-codec = { version = "3", features = ["bytes", "derive", "full", "max-encoded-len"] } +once_cell = { version = "1", features = ["critical-section"] } +pallet-asset-conversion = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +pallet-broker = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +pallet-migrations = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std", "try-runtime"] } +pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +pallet-staking-reward-fn = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +pallet-staking-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +parity-scale-codec = { version = "3", features = ["bit-vec", "bytes", "derive", "full", "max-encoded-len"] } parity-wasm = { git = "https://github.com/gear-tech/parity-wasm", branch = "v0.45.0-sign-ext" } pbkdf2 = { version = "0.12", features = ["std"] } percent-encoding = { version = "2" } -pkcs8 = { version = "0.10", default-features = false, features = ["pem", "std"] } +pkcs8 = { version = "0.10", default-features = false, features = ["std"] } +polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks", "wasm-api"] } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +polkadot-sdk-frame = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime", "runtime-benchmarks", "std", "try-runtime"] } polkavm-common = { version = "0.9", features = ["alloc", "logging"] } portable-atomic = { version = "1", features = ["require-cas"] } ppv-lite86 = { version = "0.2", default-features = false, features = ["simd", "std"] } predicates = { version = "3" } -primitive-types-594e8ee84c453af0 = { package = "primitive-types", version = "0.13", default-features = false, features = ["scale-info", "serde", "serde_no_std"] } -primitive-types-5ef9efb8ec2df382 = { package = "primitive-types", version = "0.12", default-features = false, features = ["byteorder", "rustc-hex", "scale-info", "serde", "serde_no_std"] } +primitive-types = { version = "0.13", default-features = false, features = ["byteorder", "num-traits", "rustc-hex", "scale-info", "serde", "serde_no_std"] } proc-macro2 = { version = "1", features = ["span-locations"] } proptest = { version = "1", features = ["alloc", "no_std"] } -prost = { version = "0.12", features = ["prost-derive"] } +prost = { version = "0.13", features = ["prost-derive"] } pulley-interpreter = { version = "44", default-features = false, features = ["disas", "interp", "std"] } quanta = { version = "0.12" } quote = { version = "1" } @@ -379,21 +392,26 @@ rand_chacha-468e82937335b1c9 = { package = "rand_chacha", version = "0.3" } rand_core-274715c4dabd11b0 = { package = "rand_core", version = "0.9", default-features = false, features = ["os_rng", "std"] } rand_core-3b31131e45eafb45 = { package = "rand_core", version = "0.6", default-features = false, features = ["std"] } regex = { version = "1" } -regex-automata = { version = "0.4", default-features = false, features = ["dfa-build", "dfa-onepass", "hybrid", "meta", "nfa-backtrack", "perf-inline", "perf-literal", "std", "unicode"] } +regex-automata = { version = "0.4", default-features = false, features = ["dfa-onepass", "dfa-search", "hybrid", "meta", "nfa-backtrack", "perf-inline", "perf-literal", "std", "unicode"] } regex-syntax = { version = "0.8" } reqwest = { version = "0.12", default-features = false, features = ["default-tls", "json", "rustls-tls"] } ring = { version = "0.17", features = ["std"] } +ripemd = { version = "0.1" } ruint = { version = "1", default-features = false, features = ["alloy-rlp", "serde", "std"] } +rustc-demangle = { version = "0.1", default-features = false, features = ["std"] } rustc-hash-dff4ba8e3ae991db = { package = "rustc-hash", version = "1" } rustc-hash-f595c2ba2a3f28df = { package = "rustc-hash", version = "2" } rustc-hex = { version = "2", default-features = false, features = ["std"] } +rustix = { version = "1", default-features = false, features = ["fs", "mm", "net", "param", "std", "use-libc"] } +rustls = { version = "0.23", default-features = false, features = ["logging", "ring", "std", "tls12"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["ring", "std"] } scale-bits = { version = "0.7" } scale-decode = { version = "0.16" } scale-encode = { version = "0.10" } scale-info = { version = "2", features = ["bit-vec", "decode", "derive", "docs", "serde"] } scale-type-resolver = { version = "0.2" } schnorrkel = { version = "0.11", features = ["preaudit_deprecated"] } -sec1 = { version = "0.7", features = ["pem", "serde", "std", "subtle"] } +sec1 = { version = "0.7", features = ["serde", "std", "subtle"] } secp256k1 = { version = "0.28", features = ["global-context", "recovery"] } secrecy = { version = "0.8" } semver = { version = "1", features = ["serde"] } @@ -401,58 +419,67 @@ serde = { version = "1", features = ["alloc", "derive", "rc"] } serde-json-wasm = { version = "1", default-features = false, features = ["std"] } serde_core = { version = "1", features = ["alloc", "rc"] } serde_json = { version = "1", features = ["alloc", "arbitrary_precision", "raw_value", "unbounded_depth"] } +serde_with = { version = "3", default-features = false, features = ["hex", "macros", "std"] } sha1 = { version = "0.10" } sha2 = { version = "0.10" } sha3 = { version = "0.10", features = ["asm"] } signature = { version = "2", default-features = false, features = ["digest", "rand_core", "std"] } smallvec = { version = "1", default-features = false, features = ["const_new", "serde", "union"] } soketto = { version = "0.8", features = ["http"] } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", features = ["frame-metadata"] } -sp-application-crypto = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-arithmetic = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-consensus-babe = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-crypto-ec-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["bls12-381", "std"] } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["frame-metadata"] } +sp-application-crypto = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-arithmetic = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["serde"] } +sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-consensus-babe = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-crypto-ec-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["bls12-381", "std"] } +sp-crypto-hashing-36ef8854180fd332 = { package = "sp-crypto-hashing", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } sp-crypto-hashing-c65f7effa3be6d31 = { package = "sp-crypto-hashing", version = "0.1", default-features = false, features = ["std"] } -sp-crypto-hashing-d9686075916df9f5 = { package = "sp-crypto-hashing", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-externalities = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", features = ["disable_oom", "disable_panic_handler", "improved_panic_error_reporting"] } -sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-metadata-ir = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -sp-npos-elections = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-runtime-interface = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", features = ["disable_target_static_assertions"] } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-state-machine = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-trie = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -spki = { version = "0.7", default-features = false, features = ["pem", "std"] } +sp-database = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["rocksdb"] } +sp-externalities = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["disable_oom", "disable_panic_handler", "improved_panic_error_reporting"] } +sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-metadata-ir = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-npos-elections = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-runtime-interface = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-state-machine = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-trie = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +spki = { version = "0.7", default-features = false, features = ["std"] } ss58-registry = { version = "1", default-features = false, features = ["std"] } stable_deref_trait = { version = "1", default-features = false, features = ["std"] } +staging-xcm = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +staging-xcm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +staging-xcm-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } strum-2f80eeee3b1b6c7e = { package = "strum", version = "0.26", features = ["derive"] } strum-754bda37e0fb3874 = { package = "strum", version = "0.27", default-features = false, features = ["derive", "std"] } strum-adf3d7031871b0af = { package = "strum", version = "0.24", features = ["derive"] } -substrate-bip39 = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } +substrate-bip39 = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } subtle = { version = "2" } +subxt = { version = "0.44" } subxt-metadata = { version = "0.44", default-features = false, features = ["std"] } +subxt-rpcs = { version = "0.44", default-features = false, features = ["jsonrpsee", "native", "subxt"] } syn-f595c2ba2a3f28df = { package = "syn", version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] } thiserror = { version = "2" } time = { version = "0.3", features = ["formatting", "macros", "parsing"] } tiny-keccak = { version = "2", features = ["keccak", "shake"] } -tokio = { version = "1", features = ["full", "test-util", "tracing"] } +tokio = { version = "1", features = ["full", "test-util"] } +tokio-rustls = { version = "0.26", default-features = false, features = ["logging", "ring", "tls12"] } tokio-stream = { version = "0.1", features = ["sync"] } tokio-util = { version = "0.7", features = ["codec", "compat", "io"] } toml_datetime = { version = "0.7", features = ["serde"] } @@ -460,27 +487,25 @@ toml_edit = { version = "0.22", features = ["serde"] } toml_parser = { version = "1" } tracing = { version = "0.1", features = ["log"] } tracing-core = { version = "0.1" } -tracing-log = { version = "0.2" } +tracing-log = { version = "0.2", features = ["interest-cache"] } tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "parking_lot", "time"] } -trie-db = { version = "0.29" } +trie-db = { version = "0.31" } trie-root = { version = "0.18", default-features = false, features = ["std"] } trybuild = { version = "1", default-features = false, features = ["diff"] } +tuplex = { version = "0.1", default-features = false, features = ["std"] } twox-hash = { version = "1", default-features = false, features = ["digest_0_10", "std"] } -uint-274715c4dabd11b0 = { package = "uint", version = "0.9" } -uint-93f6ce9d446188ac = { package = "uint", version = "0.10" } +uint = { version = "0.10" } unicode-normalization = { version = "0.1", default-features = false, features = ["std"] } -unsigned-varint-c38e5c1d305a1b54 = { package = "unsigned-varint", version = "0.8", default-features = false, features = ["asynchronous_codec", "codec"] } +unsigned-varint-c38e5c1d305a1b54 = { package = "unsigned-varint", version = "0.8", default-features = false, features = ["codec"] } unsigned-varint-ca01ad9e24f5d932 = { package = "unsigned-varint", version = "0.7", default-features = false, features = ["asynchronous_codec", "futures"] } url = { version = "2", features = ["serde"] } +uuid = { version = "1", features = ["v4"] } wasm-bindgen = { version = "0.2" } wasm-encoder = { version = "0.230", default-features = false, features = ["std", "wasmparser"] } wasmi = { version = "0.38", features = ["extra-checks"] } wasmparser = { version = "0.230", default-features = false, features = ["component-model", "features", "simd", "std", "validate"] } -wasmtime = { version = "44", default-features = false, features = ["anyhow", "cache", "cranelift", "parallel-compilation", "pooling-allocator", "winch"] } wasmtime-internal-core = { version = "44", default-features = false, features = ["anyhow", "serde", "std"] } -wasmtime-internal-cranelift = { version = "44", default-features = false, features = ["pulley"] } winnow = { version = "0.7" } -x25519-dalek = { version = "2", features = ["static_secrets"] } zeroize = { version = "1", features = ["derive", "std"] } [target.'cfg(not(any(target_arch = "wasm32", loom)))'.build-dependencies] @@ -503,29 +528,37 @@ alloy-sol-type-parser = { version = "1", default-features = false, features = [" alloy-sol-types = { version = "1", features = ["json"] } anyhow = { version = "1" } arbitrary = { version = "1", default-features = false, features = ["derive"] } -ark-bls12-381 = { version = "0.4", default-features = false, features = ["curve", "std"] } -ark-bls12-381-ext = { version = "0.4", default-features = false, features = ["std"] } -ark-ec = { version = "0.4", features = ["parallel"] } -ark-ff = { version = "0.4", default-features = false, features = ["std"] } -ark-models-ext = { version = "0.4", default-features = false, features = ["std"] } -ark-scale = { version = "0.0.12", default-features = false, features = ["hazmat", "std"] } -ark-serialize = { version = "0.4", default-features = false, features = ["derive", "std"] } -ark-std = { version = "0.4", default-features = false, features = ["parallel"] } +ark-bls12-381-9fbad63c4bcf4a8f = { package = "ark-bls12-381", version = "0.4", default-features = false, features = ["curve", "std"] } +ark-bls12-381-d8f496e17d97b5cb = { package = "ark-bls12-381", version = "0.5", default-features = false, features = ["curve", "std"] } +ark-bls12-381-ext = { version = "0.5", default-features = false, features = ["std"] } +ark-ec-9fbad63c4bcf4a8f = { package = "ark-ec", version = "0.4", features = ["std"] } +ark-ec-d8f496e17d97b5cb = { package = "ark-ec", version = "0.5", default-features = false, features = ["parallel"] } +ark-ff-9fbad63c4bcf4a8f = { package = "ark-ff", version = "0.4", default-features = false, features = ["std"] } +ark-ff-d8f496e17d97b5cb = { package = "ark-ff", version = "0.5", default-features = false, features = ["std"] } +ark-models-ext = { version = "0.5", default-features = false, features = ["std"] } +ark-scale-c7d3f9b296863baf = { package = "ark-scale", version = "0.0.13", default-features = false, features = ["hazmat", "std"] } +ark-scale-e9ecf5c1847bd87 = { package = "ark-scale", version = "0.0.12", default-features = false, features = ["hazmat", "std"] } +ark-serialize-9fbad63c4bcf4a8f = { package = "ark-serialize", version = "0.4", default-features = false, features = ["derive", "std"] } +ark-serialize-d8f496e17d97b5cb = { package = "ark-serialize", version = "0.5", default-features = false, features = ["derive", "parallel", "std"] } +ark-std-9fbad63c4bcf4a8f = { package = "ark-std", version = "0.4", default-features = false, features = ["std"] } +ark-std-d8f496e17d97b5cb = { package = "ark-std", version = "0.5", default-features = false, features = ["parallel"] } arrayvec = { version = "0.7", features = ["serde"] } base64 = { version = "0.22" } -binary-merkle-tree = { version = "16", default-features = false, features = ["std"] } +binary-merkle-tree-8ee676a8f9a6c413 = { package = "binary-merkle-tree", version = "16", default-features = false, features = ["std"] } +binary-merkle-tree-963a482513f5037f = { package = "binary-merkle-tree", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +bip39 = { version = "2", features = ["rand"] } bitflags = { version = "2", default-features = false, features = ["std"] } -bitvec = { version = "1" } +bitvec = { version = "1", features = ["serde"] } blake2 = { version = "0.10" } blake2b_simd = { version = "1", default-features = false, features = ["std"] } -bounded-collections = { version = "0.2", default-features = false, features = ["std"] } -bp-header-chain = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -bp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } +bounded-collections = { version = "0.3", default-features = false, features = ["std"] } +bp-header-chain = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +bp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } bs58 = { version = "0.5", features = ["check"] } bumpalo = { version = "3", features = ["allocator-api2"] } byte-slice-cast = { version = "1", default-features = false, features = ["std"] } bytemuck = { version = "1", default-features = false, features = ["const_zeroed", "derive", "min_const_generics", "must_cast"] } -byteorder = { version = "1", features = ["i128"] } +byteorder = { version = "1" } bytes = { version = "1", features = ["serde"] } cc = { version = "1", default-features = false, features = ["parallel"] } clap = { version = "4", features = ["derive", "env", "string", "wrap_help"] } @@ -533,42 +566,43 @@ clap_builder = { version = "4", default-features = false, features = ["color", " concurrent-queue = { version = "2" } const-hex = { version = "1", features = ["core-error", "serde"] } cranelift-bitset = { version = "0.131", default-features = false, features = ["enable-serde"] } -cranelift-codegen = { version = "0.131", default-features = false, features = ["host-arch", "pulley", "std", "timing", "unwind"] } -cranelift-codegen-meta = { version = "0.131", default-features = false, features = ["pulley"] } crc32fast = { version = "1" } crossbeam-channel = { version = "0.5" } crossbeam-epoch = { version = "0.9" } +crossbeam-queue = { version = "0.3" } crossbeam-utils = { version = "0.8" } crunchy = { version = "0.2", features = ["std"] } crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +cumulus-primitives-core = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } curve25519-dalek = { version = "4", features = ["digest", "legacy_compatibility"] } data-encoding = { version = "2" } -der = { version = "0.7", default-features = false, features = ["oid", "pem", "std"] } +der = { version = "0.7", default-features = false, features = ["oid", "std", "zeroize"] } derive_more-2247a326473123a6 = { package = "derive_more", version = "0.99" } derive_more-f595c2ba2a3f28df = { package = "derive_more", version = "2", default-features = false, features = ["full", "std"] } digest-274715c4dabd11b0 = { package = "digest", version = "0.9", default-features = false, features = ["std"] } digest-93f6ce9d446188ac = { package = "digest", version = "0.10", features = ["mac", "oid", "std"] } displaydoc = { version = "0.2" } -ecdsa = { version = "0.16", default-features = false, features = ["pem", "serde", "signing", "std", "verifying"] } +ecdsa = { version = "0.16", default-features = false, features = ["pkcs8", "serde", "signing", "std", "verifying"] } ed25519 = { version = "2", default-features = false, features = ["alloc", "std"] } ed25519-dalek = { version = "2", features = ["rand_core"] } ed25519-zebra = { version = "4", default-features = false, features = ["std"] } either = { version = "1", features = ["serde", "use_std"] } -elliptic-curve = { version = "0.13", default-features = false, features = ["digest", "hazmat", "pem", "serde", "std"] } +elliptic-curve = { version = "0.13", default-features = false, features = ["arithmetic", "digest", "hazmat", "serde", "std"] } enumflags2 = { version = "0.7", default-features = false, features = ["std"] } +env_filter = { version = "0.1" } environmental = { version = "1" } -event-listener = { version = "5" } -event-listener-strategy = { version = "0.5" } finality-grandpa = { version = "0.16", features = ["derive-codec"] } fixed-hash = { version = "0.8", default-features = false, features = ["std"] } fnv = { version = "1" } -foldhash = { version = "0.2", default-features = false, features = ["std"] } +foldhash-6f8ce4dd05d13bba = { package = "foldhash", version = "0.2", default-features = false, features = ["std"] } +foldhash-c65f7effa3be6d31 = { package = "foldhash", version = "0.1", default-features = false, features = ["std"] } form_urlencoded = { version = "1" } -frame-metadata-8ee676a8f9a6c413 = { package = "frame-metadata", version = "16" } -frame-metadata-e761569b921b4a02 = { package = "frame-metadata", version = "23", default-features = false, features = ["current", "std"] } -frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -frame-support-procedural = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["experimental", "std"] } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } +frame-metadata = { version = "23", default-features = false, features = ["std", "unstable"] } +frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +frame-storage-access-test-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } +frame-support-procedural = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["experimental", "std"] } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } futures = { version = "0.3", features = ["bilock", "thread-pool", "unstable"] } futures-channel = { version = "0.3", features = ["sink", "unstable"] } futures-core = { version = "0.3", features = ["unstable"] } @@ -584,23 +618,26 @@ getrandom-6f8ce4dd05d13bba = { package = "getrandom", version = "0.2", default-f getrandom_or_panic = { version = "0.0.3", default-features = false, features = ["std"] } hash-db = { version = "0.16" } hash256-std-hasher = { version = "0.15", default-features = false, features = ["std"] } +hashbrown-3575ec1268b04181 = { package = "hashbrown", version = "0.15" } hashbrown-582f2526e08bb6a0 = { package = "hashbrown", version = "0.14", features = ["raw"] } hashbrown-594e8ee84c453af0 = { package = "hashbrown", version = "0.13", features = ["raw"] } +hashbrown-5ef9efb8ec2df382 = { package = "hashbrown", version = "0.12", features = ["raw"] } hashbrown-9067fe90e8c1f593 = { package = "hashbrown", version = "0.17", default-features = false, features = ["default-hasher"] } hashbrown-986da7b5efc2b80e = { package = "hashbrown", version = "0.16", features = ["serde"] } -hex = { version = "0.4", features = ["serde"] } +hex = { version = "0.4" } hkdf = { version = "0.12", default-features = false, features = ["std"] } hmac = { version = "0.12", default-features = false, features = ["reset", "std"] } http-body-util = { version = "0.1" } -hyper-582f2526e08bb6a0 = { package = "hyper", version = "0.14", features = ["client", "http1", "http2", "runtime", "server", "stream"] } +hyper-582f2526e08bb6a0 = { package = "hyper", version = "0.14", features = ["client", "http1", "http2", "server", "stream", "tcp"] } hyper-dff4ba8e3ae991db = { package = "hyper", version = "1", features = ["client", "http1", "http2", "server"] } -hyper-util = { version = "0.1", features = ["client-legacy", "server-auto", "service"] } -idna = { version = "1", default-features = false, features = ["compiled_data", "std"] } -impl-codec = { version = "0.6", default-features = false, features = ["std"] } -impl-serde = { version = "0.4" } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "rustls-native-certs", "tls12"] } +hyper-util = { version = "0.1", features = ["client-legacy", "server-auto", "server-graceful", "service"] } +impl-codec = { version = "0.7", default-features = false, features = ["std"] } +impl-serde = { version = "0.5", default-features = false, features = ["std"] } indexmap = { version = "2", features = ["serde"] } ipnet = { version = "2" } -itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } +itertools-582f2526e08bb6a0 = { package = "itertools", version = "0.14" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13", default-features = false, features = ["use_std"] } itertools-93f6ce9d446188ac = { package = "itertools", version = "0.10" } js-sys = { version = "0.3" } jsonrpsee = { version = "0.24", default-features = false, features = ["client", "macros", "server"] } @@ -609,21 +646,16 @@ jsonrpsee-core = { version = "0.24", features = ["async-client", "async-wasm-cli k256 = { version = "0.13", features = ["serde"] } keccak = { version = "0.1", default-features = false, features = ["asm"] } libc = { version = "0.2" } -libp2p-11df1a741327a505 = { package = "libp2p", version = "0.56", default-features = false, features = ["cbor", "dns", "ecdsa", "ed25519", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "serde", "tcp", "tls", "tokio", "yamux"] } -libp2p-b21d60becc0929df = { package = "libp2p", version = "0.52", default-features = false, features = ["dns", "ed25519", "identify", "kad", "macros", "mdns", "noise", "ping", "request-response", "tcp", "tokio", "wasm-ext", "websocket", "yamux"] } -libp2p-core = { version = "0.43", default-features = false, features = ["serde"] } -libp2p-gossipsub = { version = "0.49", default-features = false, features = ["metrics", "serde"] } -libp2p-identity = { version = "0.2", default-features = false, features = ["ecdsa", "ed25519", "peerid", "rand", "secp256k1", "serde"] } -libp2p-kad = { version = "0.48", default-features = false, features = ["serde"] } -libp2p-request-response = { version = "0.29", default-features = false, features = ["cbor"] } -libsecp256k1 = { version = "0.7" } +libp2p = { version = "0.54", default-features = false, features = ["dns", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "tcp", "tls", "tokio", "websocket", "yamux"] } +libp2p-identity = { version = "0.2", default-features = false, features = ["ed25519", "peerid", "rand", "secp256k1", "serde"] } +libp2p-swarm = { version = "0.45", default-features = false, features = ["async-std", "macros", "tokio"] } +libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context", "std"] } libsecp256k1-core = { version = "0.3" } log = { version = "0.4", default-features = false, features = ["std"] } macro_magic = { version = "0.5", features = ["proc_support"] } memchr = { version = "2" } -memory-db = { version = "0.32", default-features = false, features = ["std"] } +memory-db = { version = "0.34", default-features = false, features = ["std"] } merlin = { version = "3", default-features = false, features = ["std"] } -multihash = { version = "0.19", features = ["serde-codec"] } names = { version = "0.14" } nom = { version = "7" } num-bigint = { version = "0.4" } @@ -631,27 +663,34 @@ num-integer = { version = "0.1", default-features = false, features = ["i128", " num-rational = { version = "0.4", features = ["num-bigint-std"] } num-traits = { version = "0.2", features = ["i128", "libm"] } numerated = { version = "2", default-features = false, features = ["mock"] } -once_cell = { version = "1" } -pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -pallet-staking-reward-fn = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -pallet-staking-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -parity-bip39 = { version = "2", features = ["rand"] } -parity-scale-codec = { version = "3", features = ["bytes", "derive", "full", "max-encoded-len"] } +once_cell = { version = "1", features = ["critical-section"] } +pallet-asset-conversion = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +pallet-broker = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +pallet-migrations = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std", "try-runtime"] } +pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +pallet-staking-reward-fn = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +pallet-staking-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +parity-scale-codec = { version = "3", features = ["bit-vec", "bytes", "derive", "full", "max-encoded-len"] } parity-scale-codec-derive = { version = "3", default-features = false, features = ["max-encoded-len"] } parity-wasm = { git = "https://github.com/gear-tech/parity-wasm", branch = "v0.45.0-sign-ext" } pbkdf2 = { version = "0.12", features = ["std"] } percent-encoding = { version = "2" } -pkcs8 = { version = "0.10", default-features = false, features = ["pem", "std"] } +petgraph = { version = "0.6" } +pkcs8 = { version = "0.10", default-features = false, features = ["std"] } +polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks", "wasm-api"] } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +polkadot-sdk-frame = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime", "runtime-benchmarks", "std", "try-runtime"] } polkavm-common = { version = "0.9", features = ["alloc", "logging"] } portable-atomic = { version = "1", features = ["require-cas"] } ppv-lite86 = { version = "0.2", default-features = false, features = ["simd", "std"] } predicates = { version = "3" } -primitive-types-594e8ee84c453af0 = { package = "primitive-types", version = "0.13", default-features = false, features = ["scale-info", "serde", "serde_no_std"] } -primitive-types-5ef9efb8ec2df382 = { package = "primitive-types", version = "0.12", default-features = false, features = ["byteorder", "rustc-hex", "scale-info", "serde", "serde_no_std"] } +primitive-types = { version = "0.13", default-features = false, features = ["byteorder", "num-traits", "rustc-hex", "scale-info", "serde", "serde_no_std"] } proc-macro2 = { version = "1", features = ["span-locations"] } proptest = { version = "1", features = ["alloc", "no_std"] } -prost = { version = "0.12", features = ["prost-derive"] } +prost = { version = "0.13", features = ["prost-derive"] } pulley-interpreter = { version = "44", default-features = false, features = ["disas", "interp", "std"] } quanta = { version = "0.12" } quote = { version = "1" } @@ -662,14 +701,19 @@ rand_chacha-468e82937335b1c9 = { package = "rand_chacha", version = "0.3" } rand_core-274715c4dabd11b0 = { package = "rand_core", version = "0.9", default-features = false, features = ["os_rng", "std"] } rand_core-3b31131e45eafb45 = { package = "rand_core", version = "0.6", default-features = false, features = ["std"] } regex = { version = "1" } -regex-automata = { version = "0.4", default-features = false, features = ["dfa-build", "dfa-onepass", "hybrid", "meta", "nfa-backtrack", "perf-inline", "perf-literal", "std", "unicode"] } +regex-automata = { version = "0.4", default-features = false, features = ["dfa-onepass", "dfa-search", "hybrid", "meta", "nfa-backtrack", "perf-inline", "perf-literal", "std", "unicode"] } regex-syntax = { version = "0.8" } reqwest = { version = "0.12", default-features = false, features = ["default-tls", "json", "rustls-tls"] } ring = { version = "0.17", features = ["std"] } +ripemd = { version = "0.1" } ruint = { version = "1", default-features = false, features = ["alloy-rlp", "serde", "std"] } +rustc-demangle = { version = "0.1", default-features = false, features = ["std"] } rustc-hash-dff4ba8e3ae991db = { package = "rustc-hash", version = "1" } rustc-hash-f595c2ba2a3f28df = { package = "rustc-hash", version = "2" } rustc-hex = { version = "2", default-features = false, features = ["std"] } +rustix = { version = "1", default-features = false, features = ["fs", "mm", "net", "param", "std", "use-libc"] } +rustls = { version = "0.23", default-features = false, features = ["logging", "ring", "std", "tls12"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["ring", "std"] } scale-bits = { version = "0.7" } scale-decode = { version = "0.16" } scale-encode = { version = "0.10" } @@ -677,7 +721,7 @@ scale-info = { version = "2", features = ["bit-vec", "decode", "derive", "docs", scale-info-derive = { version = "2", default-features = false, features = ["docs"] } scale-type-resolver = { version = "0.2" } schnorrkel = { version = "0.11", features = ["preaudit_deprecated"] } -sec1 = { version = "0.7", features = ["pem", "serde", "std", "subtle"] } +sec1 = { version = "0.7", features = ["serde", "std", "subtle"] } secp256k1 = { version = "0.28", features = ["global-context", "recovery"] } secrecy = { version = "0.8" } semver = { version = "1", features = ["serde"] } @@ -685,61 +729,70 @@ serde = { version = "1", features = ["alloc", "derive", "rc"] } serde-json-wasm = { version = "1", default-features = false, features = ["std"] } serde_core = { version = "1", features = ["alloc", "rc"] } serde_json = { version = "1", features = ["alloc", "arbitrary_precision", "raw_value", "unbounded_depth"] } +serde_with = { version = "3", default-features = false, features = ["hex", "macros", "std"] } sha1 = { version = "0.10" } sha2 = { version = "0.10" } sha3 = { version = "0.10", features = ["asm"] } signature = { version = "2", default-features = false, features = ["digest", "rand_core", "std"] } smallvec = { version = "1", default-features = false, features = ["const_new", "serde", "union"] } soketto = { version = "0.8", features = ["http"] } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", features = ["frame-metadata"] } -sp-api-proc-macro = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -sp-application-crypto = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-arithmetic = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-consensus-babe = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-crypto-ec-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["bls12-381", "std"] } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["frame-metadata"] } +sp-api-proc-macro = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-application-crypto = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-arithmetic = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["serde"] } +sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-consensus-babe = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-crypto-ec-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["bls12-381", "std"] } +sp-crypto-hashing-36ef8854180fd332 = { package = "sp-crypto-hashing", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } sp-crypto-hashing-c65f7effa3be6d31 = { package = "sp-crypto-hashing", version = "0.1", default-features = false, features = ["std"] } -sp-crypto-hashing-d9686075916df9f5 = { package = "sp-crypto-hashing", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-debug-derive = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["force-debug", "std"] } -sp-externalities = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", features = ["disable_oom", "disable_panic_handler", "improved_panic_error_reporting"] } -sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-metadata-ir = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -sp-npos-elections = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-runtime-interface = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", features = ["disable_target_static_assertions"] } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-state-machine = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } -sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-trie = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c" } -spki = { version = "0.7", default-features = false, features = ["pem", "std"] } +sp-database = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["rocksdb"] } +sp-debug-derive = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-externalities = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["disable_oom", "disable_panic_handler", "improved_panic_error_reporting"] } +sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-metadata-ir = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-npos-elections = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-runtime-interface = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-state-machine = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } +sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-trie = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } +spki = { version = "0.7", default-features = false, features = ["std"] } ss58-registry = { version = "1", default-features = false, features = ["std"] } stable_deref_trait = { version = "1", default-features = false, features = ["std"] } +staging-xcm = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +staging-xcm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } +staging-xcm-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } strum-2f80eeee3b1b6c7e = { package = "strum", version = "0.26", features = ["derive"] } strum-754bda37e0fb3874 = { package = "strum", version = "0.27", default-features = false, features = ["derive", "std"] } strum-adf3d7031871b0af = { package = "strum", version = "0.24", features = ["derive"] } -substrate-bip39 = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "298f676c91d64f15f38ea7fd78f125c5889ab09c", default-features = false, features = ["std"] } +substrate-bip39 = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } subtle = { version = "2" } +subxt = { version = "0.44" } subxt-metadata = { version = "0.44", default-features = false, features = ["std"] } +subxt-rpcs = { version = "0.44", default-features = false, features = ["jsonrpsee", "native", "subxt"] } syn-dff4ba8e3ae991db = { package = "syn", version = "1", features = ["extra-traits", "full", "visit"] } syn-f595c2ba2a3f28df = { package = "syn", version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] } thiserror = { version = "2" } time = { version = "0.3", features = ["formatting", "macros", "parsing"] } tiny-keccak = { version = "2", features = ["keccak", "shake"] } -tokio = { version = "1", features = ["full", "test-util", "tracing"] } +tokio = { version = "1", features = ["full", "test-util"] } +tokio-rustls = { version = "0.26", default-features = false, features = ["logging", "ring", "tls12"] } tokio-stream = { version = "0.1", features = ["sync"] } tokio-util = { version = "0.7", features = ["codec", "compat", "io"] } toml_datetime = { version = "0.7", features = ["serde"] } @@ -747,161 +800,199 @@ toml_edit = { version = "0.22", features = ["serde"] } toml_parser = { version = "1" } tracing = { version = "0.1", features = ["log"] } tracing-core = { version = "0.1" } -tracing-log = { version = "0.2" } +tracing-log = { version = "0.2", features = ["interest-cache"] } tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "parking_lot", "time"] } -trie-db = { version = "0.29" } +trie-db = { version = "0.31" } trie-root = { version = "0.18", default-features = false, features = ["std"] } trybuild = { version = "1", default-features = false, features = ["diff"] } +tuplex = { version = "0.1", default-features = false, features = ["std"] } twox-hash = { version = "1", default-features = false, features = ["digest_0_10", "std"] } -uint-274715c4dabd11b0 = { package = "uint", version = "0.9" } -uint-93f6ce9d446188ac = { package = "uint", version = "0.10" } +uint = { version = "0.10" } unicode-normalization = { version = "0.1", default-features = false, features = ["std"] } -unsigned-varint-c38e5c1d305a1b54 = { package = "unsigned-varint", version = "0.8", default-features = false, features = ["asynchronous_codec", "codec"] } +unsigned-varint-c38e5c1d305a1b54 = { package = "unsigned-varint", version = "0.8", default-features = false, features = ["codec"] } unsigned-varint-ca01ad9e24f5d932 = { package = "unsigned-varint", version = "0.7", default-features = false, features = ["asynchronous_codec", "futures"] } url = { version = "2", features = ["serde"] } +uuid = { version = "1", features = ["v4"] } wasm-bindgen = { version = "0.2" } wasm-encoder = { version = "0.230", default-features = false, features = ["std", "wasmparser"] } wasmi = { version = "0.38", features = ["extra-checks"] } wasmparser = { version = "0.230", default-features = false, features = ["component-model", "features", "simd", "std", "validate"] } -wasmtime = { version = "44", default-features = false, features = ["anyhow", "cache", "cranelift", "parallel-compilation", "pooling-allocator", "winch"] } wasmtime-internal-core = { version = "44", default-features = false, features = ["anyhow", "serde", "std"] } -wasmtime-internal-cranelift = { version = "44", default-features = false, features = ["pulley"] } winnow = { version = "0.7" } -x25519-dalek = { version = "2", features = ["static_secrets"] } zeroize = { version = "1", features = ["derive", "std"] } [target.'cfg(all(target_arch = "x86_64", target_vendor = "unknown", target_os = "linux", target_env = "gnu", not(any(target_arch = "wasm32", loom))))'.dependencies] errno = { version = "0.3" } -hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } -hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } +event-listener = { version = "5" } +event-listener-strategy = { version = "0.5" } +futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } +idna = { version = "1" } +if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -librocksdb-sys = { version = "0.11", features = ["jemalloc", "snappy"] } -linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl"] } +libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } +librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } +linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +log = { version = "0.4", default-features = false, features = ["kv_unstable"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } +netlink-proto = { version = "0.11", default-features = false, features = ["smol_socket", "tokio_socket"] } +netlink-sys = { version = "0.8", features = ["smol_socket", "tokio_socket"] } nix = { version = "0.26" } -once_cell = { version = "1", default-features = false, features = ["critical-section"] } -openssl = { version = "0.10", features = ["vendored"] } -openssl-sys = { version = "0.9", default-features = false, features = ["vendored"] } -rocksdb = { version = "0.21", default-features = false, features = ["jemalloc", "snappy"] } -rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "use-libc"] } -rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs", "logging", "ring", "std", "tls12"] } -rustls-webpki = { version = "0.103", features = ["aws-lc-rs", "ring"] } -sha-1 = { version = "0.10", features = ["asm"] } -tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs", "logging", "ring", "tls12"] } -unicode-normalization = { version = "0.1" } +rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } +rtnetlink = { version = "0.13", default-features = false, features = ["smol_socket", "tokio_socket"] } +rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } +tikv-jemalloc-sys = { version = "0.6", features = ["stats", "unprefixed_malloc_on_supported_platforms"] } +tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } +yasna = { version = "0.5", features = ["std", "time"] } zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] } [target.'cfg(all(target_arch = "x86_64", target_vendor = "unknown", target_os = "linux", target_env = "gnu", not(any(target_arch = "wasm32", loom))))'.build-dependencies] errno = { version = "0.3" } -hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } -hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } +event-listener = { version = "5" } +event-listener-strategy = { version = "0.5" } +futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } +idna = { version = "1" } +if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -librocksdb-sys = { version = "0.11", features = ["jemalloc", "snappy"] } -linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl"] } +libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } +librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } +linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +log = { version = "0.4", default-features = false, features = ["kv_unstable"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } +netlink-proto = { version = "0.11", default-features = false, features = ["smol_socket", "tokio_socket"] } +netlink-sys = { version = "0.8", features = ["smol_socket", "tokio_socket"] } nix = { version = "0.26" } -once_cell = { version = "1", default-features = false, features = ["critical-section"] } -openssl = { version = "0.10", features = ["vendored"] } -openssl-sys = { version = "0.9", default-features = false, features = ["vendored"] } -rocksdb = { version = "0.21", default-features = false, features = ["jemalloc", "snappy"] } -rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "use-libc"] } -rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs", "logging", "ring", "std", "tls12"] } -rustls-webpki = { version = "0.103", features = ["aws-lc-rs", "ring"] } -sha-1 = { version = "0.10", features = ["asm"] } -tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs", "logging", "ring", "tls12"] } -unicode-normalization = { version = "0.1" } +rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } +rtnetlink = { version = "0.13", default-features = false, features = ["smol_socket", "tokio_socket"] } +rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } +tikv-jemalloc-sys = { version = "0.6", features = ["stats", "unprefixed_malloc_on_supported_platforms"] } +tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } +yasna = { version = "0.5", features = ["std", "time"] } zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] } [target.'cfg(all(target_arch = "aarch64", target_vendor = "unknown", target_os = "linux", target_env = "gnu", not(any(target_arch = "wasm32", loom))))'.dependencies] errno = { version = "0.3" } -hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } -hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } +event-listener = { version = "5" } +event-listener-strategy = { version = "0.5" } +futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } +idna = { version = "1" } +if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -librocksdb-sys = { version = "0.11", features = ["jemalloc", "snappy"] } -linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl"] } +libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } +librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } +linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +log = { version = "0.4", default-features = false, features = ["kv_unstable"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } +netlink-proto = { version = "0.11", default-features = false, features = ["smol_socket", "tokio_socket"] } +netlink-sys = { version = "0.8", features = ["smol_socket", "tokio_socket"] } nix = { version = "0.26" } -once_cell = { version = "1", default-features = false, features = ["critical-section"] } -openssl = { version = "0.10", features = ["vendored"] } -openssl-sys = { version = "0.9", default-features = false, features = ["vendored"] } -rocksdb = { version = "0.21", default-features = false, features = ["jemalloc", "snappy"] } -rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "use-libc"] } -rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs", "logging", "ring", "std", "tls12"] } -rustls-webpki = { version = "0.103", features = ["aws-lc-rs", "ring"] } -sha-1 = { version = "0.10", features = ["asm"] } -tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs", "logging", "ring", "tls12"] } -unicode-normalization = { version = "0.1" } +rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } +rtnetlink = { version = "0.13", default-features = false, features = ["smol_socket", "tokio_socket"] } +rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } +tikv-jemalloc-sys = { version = "0.6", features = ["stats", "unprefixed_malloc_on_supported_platforms"] } +tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } +yasna = { version = "0.5", features = ["std", "time"] } zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] } [target.'cfg(all(target_arch = "aarch64", target_vendor = "unknown", target_os = "linux", target_env = "gnu", not(any(target_arch = "wasm32", loom))))'.build-dependencies] errno = { version = "0.3" } -hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } -hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } +event-listener = { version = "5" } +event-listener-strategy = { version = "0.5" } +futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } +idna = { version = "1" } +if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -librocksdb-sys = { version = "0.11", features = ["jemalloc", "snappy"] } -linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl"] } +libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } +librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } +linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +log = { version = "0.4", default-features = false, features = ["kv_unstable"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } +netlink-proto = { version = "0.11", default-features = false, features = ["smol_socket", "tokio_socket"] } +netlink-sys = { version = "0.8", features = ["smol_socket", "tokio_socket"] } nix = { version = "0.26" } -once_cell = { version = "1", default-features = false, features = ["critical-section"] } -openssl = { version = "0.10", features = ["vendored"] } -openssl-sys = { version = "0.9", default-features = false, features = ["vendored"] } -rocksdb = { version = "0.21", default-features = false, features = ["jemalloc", "snappy"] } -rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "use-libc"] } -rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs", "logging", "ring", "std", "tls12"] } -rustls-webpki = { version = "0.103", features = ["aws-lc-rs", "ring"] } -sha-1 = { version = "0.10", features = ["asm"] } -tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs", "logging", "ring", "tls12"] } -unicode-normalization = { version = "0.1" } +rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } +rtnetlink = { version = "0.13", default-features = false, features = ["smol_socket", "tokio_socket"] } +rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } +tikv-jemalloc-sys = { version = "0.6", features = ["stats", "unprefixed_malloc_on_supported_platforms"] } +tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } +yasna = { version = "0.5", features = ["std", "time"] } zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] } [target.'cfg(all(target_arch = "aarch64", target_vendor = "apple", target_os = "macos", not(any(target_arch = "wasm32", loom))))'.dependencies] errno = { version = "0.3" } -hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } -hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } +event-listener-strategy = { version = "0.5" } +futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } +idna = { version = "1" } +if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -librocksdb-sys = { version = "0.11", features = ["jemalloc", "snappy"] } +libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } +librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } +log = { version = "0.4", default-features = false, features = ["kv_unstable"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } -once_cell = { version = "1", default-features = false, features = ["critical-section"] } -openssl-sys = { version = "0.9", default-features = false, features = ["vendored"] } -rocksdb = { version = "0.21", default-features = false, features = ["jemalloc", "snappy"] } -rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "use-libc"] } -rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs", "logging", "ring", "std", "tls12"] } -rustls-webpki = { version = "0.103", features = ["aws-lc-rs", "ring"] } +rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } +rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } security-framework = { version = "3", features = ["OSX_10_14"] } security-framework-sys = { version = "2", features = ["OSX_10_14"] } -sha-1 = { version = "0.10", features = ["asm"] } -tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs", "logging", "ring", "tls12"] } -unicode-normalization = { version = "0.1" } +tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } +yasna = { version = "0.5", features = ["std", "time"] } zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] } [target.'cfg(all(target_arch = "aarch64", target_vendor = "apple", target_os = "macos", not(any(target_arch = "wasm32", loom))))'.build-dependencies] errno = { version = "0.3" } -hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } -hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "http1", "http2", "logging", "ring", "tls12", "webpki-tokio"] } +event-listener-strategy = { version = "0.5" } +futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } +idna = { version = "1" } +if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -librocksdb-sys = { version = "0.11", features = ["jemalloc", "snappy"] } +libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } +librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } +log = { version = "0.4", default-features = false, features = ["kv_unstable"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } -once_cell = { version = "1", default-features = false, features = ["critical-section"] } -openssl-sys = { version = "0.9", default-features = false, features = ["vendored"] } -rocksdb = { version = "0.21", default-features = false, features = ["jemalloc", "snappy"] } -rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "use-libc"] } -rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs", "logging", "ring", "std", "tls12"] } -rustls-webpki = { version = "0.103", features = ["aws-lc-rs", "ring"] } +rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } +rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } security-framework = { version = "3", features = ["OSX_10_14"] } security-framework-sys = { version = "2", features = ["OSX_10_14"] } -sha-1 = { version = "0.10", features = ["asm"] } -tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs", "logging", "ring", "tls12"] } -unicode-normalization = { version = "0.1" } +tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } +yasna = { version = "0.5", features = ["std", "time"] } zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] } ### END HAKARI SECTION diff --git a/vara/common/src/event.rs b/vara/common/src/event.rs index 62dde33dcec..a1239eef942 100644 --- a/vara/common/src/event.rs +++ b/vara/common/src/event.rs @@ -8,7 +8,7 @@ use gear_core::{env::MessageWaitedType, ids::MessageId}; use sp_runtime::{ - codec::{self, Decode, Encode}, + codec::{self, Decode, DecodeWithMemTracking, Encode}, scale_info::{self, TypeInfo}, }; @@ -16,7 +16,7 @@ use sp_runtime::{ /// /// Same as `gear_core::message::DispatchKind`, /// but with additional info about reply. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] +#[derive(Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum MessageEntry { @@ -31,7 +31,7 @@ pub enum MessageEntry { } /// Status of dispatch dequeue and execution. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] +#[derive(Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum DispatchStatus { @@ -67,7 +67,7 @@ pub trait SystemReason: Sized { impl SystemReason for () {} /// Composite reason type for any action happened on chain. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] +#[derive(Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum Reason { @@ -84,7 +84,9 @@ pub enum Reason { } /// Runtime reason for messages waiting. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, RuntimeReason)] +#[derive( + Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo, RuntimeReason, +)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum MessageWaitedRuntimeReason { @@ -112,7 +114,9 @@ impl From for MessageWaitedRuntimeReason { } /// System reason for messages waiting. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, SystemReason)] +#[derive( + Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo, SystemReason, +)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum MessageWaitedSystemReason {} @@ -121,7 +125,9 @@ pub enum MessageWaitedSystemReason {} pub type MessageWaitedReason = Reason; /// Runtime reason for messages waking. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, RuntimeReason)] +#[derive( + Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo, RuntimeReason, +)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum MessageWokenRuntimeReason { @@ -130,7 +136,9 @@ pub enum MessageWokenRuntimeReason { } /// System reason for messages waking. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, SystemReason)] +#[derive( + Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo, SystemReason, +)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum MessageWokenSystemReason { @@ -149,7 +157,7 @@ pub enum MessageWokenSystemReason { pub type MessageWokenReason = Reason; /// Type of changes applied to code in storage. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] +#[derive(Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum CodeChangeKind { @@ -170,7 +178,9 @@ pub enum CodeChangeKind { } /// Runtime reason for messages reading from `Mailbox`. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, RuntimeReason)] +#[derive( + Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo, RuntimeReason, +)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum UserMessageReadRuntimeReason { @@ -181,7 +191,9 @@ pub enum UserMessageReadRuntimeReason { } /// System reason for messages reading from `Mailbox`. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, SystemReason)] +#[derive( + Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo, SystemReason, +)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum UserMessageReadSystemReason { @@ -193,7 +205,7 @@ pub enum UserMessageReadSystemReason { pub type UserMessageReadReason = Reason; /// Type of changes applied to program in storage. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] +#[derive(Debug, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum ProgramChangeKind { diff --git a/vara/common/src/gas_provider/auxiliary.rs b/vara/common/src/gas_provider/auxiliary.rs index e7a92dc4f0c..9cb73c5a6ca 100644 --- a/vara/common/src/gas_provider/auxiliary.rs +++ b/vara/common/src/gas_provider/auxiliary.rs @@ -13,7 +13,7 @@ use core::{ cell::{Ref, RefMut}, marker::PhantomData, }; -use sp_core::H256; +use primitive_types::H256; use std::thread::LocalKey; /// Balance type used in the gas tree. diff --git a/vara/common/src/gas_provider/mod.rs b/vara/common/src/gas_provider/mod.rs index d408d852c3c..589e455fb77 100644 --- a/vara/common/src/gas_provider/mod.rs +++ b/vara/common/src/gas_provider/mod.rs @@ -3,7 +3,7 @@ use super::*; use frame_support::traits::tokens::Balance as BalanceTrait; -use sp_runtime::{RuntimeDebug, traits::Zero}; +use sp_runtime::traits::Zero; use sp_std::marker::PhantomData; mod error; diff --git a/vara/common/src/gas_provider/negative_imbalance.rs b/vara/common/src/gas_provider/negative_imbalance.rs index 429627f1268..2dd0c592919 100644 --- a/vara/common/src/gas_provider/negative_imbalance.rs +++ b/vara/common/src/gas_provider/negative_imbalance.rs @@ -5,7 +5,7 @@ use super::*; /// Opaque, move-only struct with private field to denote that value has been /// destroyed without any equal and opposite accounting. -#[derive(RuntimeDebug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] pub struct NegativeImbalance(Balance); impl NegativeImbalance { diff --git a/vara/common/src/gas_provider/node.rs b/vara/common/src/gas_provider/node.rs index 5fc23d64cb7..c33add01293 100644 --- a/vara/common/src/gas_provider/node.rs +++ b/vara/common/src/gas_provider/node.rs @@ -8,7 +8,7 @@ use gear_core::ids::ReservationId; use scale_decode::DecodeAsType; use scale_encode::EncodeAsType; use sp_runtime::{ - codec::{self, MaxEncodedLen}, + codec::{self, DecodeWithMemTracking, MaxEncodedLen}, scale_info, traits::Zero, }; @@ -27,6 +27,7 @@ use sp_runtime::{ EncodeAsType, Decode, DecodeAsType, + DecodeWithMemTracking, TypeInfo, )] #[codec(crate = codec)] @@ -77,7 +78,19 @@ impl From for GasNodeId { } } -#[derive(Clone, Copy, Decode, Encode, Debug, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[derive( + Clone, + Copy, + Decode, + DecodeWithMemTracking, + Encode, + Debug, + Default, + PartialEq, + Eq, + TypeInfo, + MaxEncodedLen, +)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub struct NodeLock([Balance; cardinality::()]); @@ -132,7 +145,9 @@ impl NodeLock { } /// Node of the ['Tree'] gas tree -#[derive(Clone, Decode, Debug, Encode, MaxEncodedLen, TypeInfo, PartialEq, Eq)] +#[derive( + Clone, Decode, DecodeWithMemTracking, Debug, Encode, MaxEncodedLen, TypeInfo, PartialEq, Eq, +)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub enum GasNode { @@ -204,7 +219,19 @@ pub enum GasNode { } /// Children references convenience struct -#[derive(Clone, Copy, Default, Decode, Debug, Encode, MaxEncodedLen, TypeInfo, PartialEq, Eq)] +#[derive( + Clone, + Copy, + Default, + Decode, + DecodeWithMemTracking, + Debug, + Encode, + MaxEncodedLen, + TypeInfo, + PartialEq, + Eq, +)] #[codec(crate = codec)] #[scale_info(crate = scale_info)] pub struct ChildrenRefs { diff --git a/vara/common/src/gas_provider/positive_imbalance.rs b/vara/common/src/gas_provider/positive_imbalance.rs index def6c851610..37218dd1fc9 100644 --- a/vara/common/src/gas_provider/positive_imbalance.rs +++ b/vara/common/src/gas_provider/positive_imbalance.rs @@ -5,7 +5,7 @@ use super::*; /// Opaque, move-only struct with private field to denote that value has been /// created without any equal and opposite accounting -#[derive(RuntimeDebug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] pub struct PositiveImbalance(Balance); impl PositiveImbalance { diff --git a/vara/common/src/lib.rs b/vara/common/src/lib.rs index 9b41c5ed093..5e24cfb4787 100644 --- a/vara/common/src/lib.rs +++ b/vara/common/src/lib.rs @@ -33,7 +33,7 @@ use frame_support::{ sp_runtime::{ self, generic::{CheckedExtrinsic, UncheckedExtrinsic}, - traits::{Dispatchable, SignedExtension}, + traits::{Dispatchable, TransactionExtension}, }, traits::Get, }; @@ -220,7 +220,7 @@ impl ExtractCall for UncheckedExtrinsic where Call: Dispatchable + Clone, - Extra: SignedExtension, + Extra: TransactionExtension, { fn extract_call(&self) -> Call { self.function.clone() diff --git a/vara/node/authorship/src/authorship.rs b/vara/node/authorship/src/authorship.rs index 17efa87f8cb..a9496b54470 100644 --- a/vara/node/authorship/src/authorship.rs +++ b/vara/node/authorship/src/authorship.rs @@ -6,7 +6,6 @@ use futures::{ channel::oneshot, future, future::{Either, Future, FutureExt}, - select, }; use futures_timer::Delay; use log::{debug, error, info, trace, warn}; @@ -14,10 +13,10 @@ use pallet_gear_rpc_runtime_api::GearApi as GearRuntimeApi; use parity_scale_codec::Encode; use sc_block_builder::BlockBuilderApi; use sc_telemetry::{CONSENSUS_INFO, TelemetryHandle, telemetry}; -use sc_transaction_pool_api::{InPoolTransaction, TransactionPool}; +use sc_transaction_pool_api::{InPoolTransaction, TransactionPool, TxInvalidityReportMap}; use sp_api::{ApiExt, ApiRef, CallApiAt, ProvideRuntimeApi}; use sp_blockchain::{ApplyExtrinsicFailed::Validity, Error::ApplyExtrinsicFailed, HeaderBackend}; -use sp_consensus::{DisableProofRecording, EnableProofRecording, ProofRecording, Proposal}; +use sp_consensus::{Proposal, ProposeArgs}; use sp_core::traits::SpawnNamed; use sp_inherents::InherentData; use sp_runtime::{ @@ -49,6 +48,20 @@ const DEFAULT_SOFT_DEADLINE_PERCENT: Percent = Percent::from_percent(50); const LOG_TARGET: &str = "gear::authorship"; +pub trait ProofRecording { + const ENABLED: bool; +} + +pub struct DisableProofRecording; +impl ProofRecording for DisableProofRecording { + const ENABLED: bool = false; +} + +pub struct EnableProofRecording; +impl ProofRecording for EnableProofRecording { + const ENABLED: bool = true; +} + /// A unit type wrapper to express a duration multiplier. #[derive(Clone, Copy)] pub struct DurationMultiplier(pub f32); @@ -278,7 +291,7 @@ where C: HeaderBackend + ProvideRuntimeApi + CallApiAt + Send + Sync + 'static, C::Api: ApiExt + BlockBuilderApi + GearRuntimeApi + Clone + Deconstructable, - PR: ProofRecording, + PR: ProofRecording + Send + Sync + 'static, { type CreateProposer = future::Ready>; type Proposer = Proposer; @@ -315,23 +328,23 @@ where C: HeaderBackend + ProvideRuntimeApi + CallApiAt + Send + Sync + 'static, C::Api: ApiExt + BlockBuilderApi + GearRuntimeApi + Clone + Deconstructable, - PR: ProofRecording, + PR: ProofRecording + Send + Sync + 'static, { - type Proposal = - Pin, Self::Error>> + Send>>; + type Proposal = Pin, Self::Error>> + Send>>; type Error = sp_blockchain::Error; - type ProofRecording = PR; - type Proof = PR::Proof; - fn propose( - self, - inherent_data: InherentData, - inherent_digests: Digest, - max_duration: Duration, - block_size_limit: Option, - ) -> Self::Proposal { + fn propose(self, args: ProposeArgs) -> Self::Proposal { + let ProposeArgs { + inherent_data, + inherent_digests, + max_duration, + block_size_limit, + storage_proof_recorder, + extra_extensions: _, + } = args; let (tx, rx) = oneshot::channel(); let spawn_handle = self.spawn_handle.clone(); + let record_proof = PR::ENABLED || storage_proof_recorder.is_some(); spawn_handle.spawn_blocking( "gear-authorship-proposer", @@ -340,7 +353,13 @@ where // leave some time for evaluation and block finalization (33%) let deadline = (self.now)() + (max_duration / 3) * 2; let res = self - .propose_with(inherent_data, inherent_digests, deadline, block_size_limit) + .propose_with( + inherent_data, + inherent_digests, + deadline, + block_size_limit, + record_proof, + ) .await; if tx.send(res).is_err() { trace!(target: "gear::authorship", "Could not send block production result to proposer!"); @@ -364,7 +383,7 @@ where C: HeaderBackend + ProvideRuntimeApi + CallApiAt + Send + Sync + 'static, C::Api: ApiExt + BlockBuilderApi + GearRuntimeApi + Clone + Deconstructable, - PR: ProofRecording, + PR: ProofRecording + Send + Sync + 'static, { async fn propose_with( self, @@ -372,12 +391,13 @@ where inherent_digests: Digest, deadline: Instant, block_size_limit: Option, - ) -> Result, sp_blockchain::Error> { + record_proof: bool, + ) -> Result, sp_blockchain::Error> { let block_timer = Instant::now(); let mut block_builder = BlockBuilderBuilder::new(self.client.as_ref()) .on_parent_block(self.parent_hash) .with_parent_block_number(self.parent_number) - .with_proof_recording(PR::ENABLED) + .with_proof_recording(record_proof) .with_inherent_digests(inherent_digests) .build()?; @@ -390,16 +410,12 @@ where .apply_extrinsics(&mut block_builder, deadline, block_size_limit) .await?; - let (block, storage_changes, proof) = block_builder.build()?.into_inner(); + let (block, storage_changes) = block_builder.build()?.into_inner(); let block_took = block_timer.elapsed(); - let proof = - PR::into_proof(proof).map_err(|e| sp_blockchain::Error::Application(Box::new(e)))?; - self.print_summary(&block, end_reason, block_took, block_timer.elapsed()); Ok(Proposal { block, - proof, storage_changes, }) } @@ -469,23 +485,13 @@ where let soft_deadline = now + Duration::from_micros(self.soft_deadline_percent.mul_floor(left_micros)); let mut skipped = 0; - let mut unqueue_invalid = Vec::new(); - - let mut t1 = self.transaction_pool.ready_at(self.parent_number).fuse(); - let mut t2 = - futures_timer::Delay::new(deadline.saturating_duration_since((self.now)()) / 8).fuse(); - - let mut pending_iterator = select! { - res = t1 => res, - _ = t2 => { - warn!(target: LOG_TARGET, - "Timeout fired waiting for transaction pool at block #{}. \ - Proceeding with production.", - self.parent_number, - ); - self.transaction_pool.ready() - }, - }; + let mut unqueue_invalid = TxInvalidityReportMap::new(); + + let delay = deadline.saturating_duration_since((self.now)()) / 8; + let mut pending_iterator = self + .transaction_pool + .ready_at_with_timeout(self.parent_hash, delay) + .await; let block_size_limit = block_size_limit.unwrap_or(self.default_block_size_limit); @@ -515,7 +521,7 @@ where break EndProposingReason::HitDeadline; } - let pending_tx_data = pending_tx.data().clone(); + let pending_tx_data = (**pending_tx.data()).clone(); let pending_tx_hash = pending_tx.hash().clone(); let block_size = @@ -581,7 +587,12 @@ where target: LOG_TARGET, "[{pending_tx_hash:?}] Invalid transaction: {e}" ); - unqueue_invalid.push(pending_tx_hash); + let error_to_report = match e { + ApplyExtrinsicFailed(Validity(e)) => Some(e), + _ => None, + }; + + unqueue_invalid.insert(pending_tx_hash, error_to_report); } } }; @@ -593,7 +604,9 @@ where ); } - self.transaction_pool.remove_invalid(&unqueue_invalid); + self.transaction_pool + .report_invalid(Some(self.parent_hash), unqueue_invalid) + .await; // Attempt to apply pseudo-inherent on top of the current overlay in a separate thread. // In case the timeout was hit at previous step, adjust the `max_gas`. diff --git a/vara/node/authorship/src/block_builder.rs b/vara/node/authorship/src/block_builder.rs index 37d2c88142b..b7b6e4f5560 100644 --- a/vara/node/authorship/src/block_builder.rs +++ b/vara/node/authorship/src/block_builder.rs @@ -298,10 +298,8 @@ where /// Consume the builder to build a valid `Block` containing all pushed extrinsics. /// - /// Returns the build `Block`, the changes to the storage and an optional `StorageProof` - /// supplied by `self.api`, combined as [`BuiltBlock`]. - /// The storage proof will be `Some(_)` when proof recording was enabled. - pub fn build(mut self) -> Result, Error> { + /// Returns the build `Block` and the changes to the storage, combined as [`BuiltBlock`]. + pub fn build(self) -> Result, Error> { let header = self.api.finalize_block(self.parent_hash)?; debug_assert_eq!( @@ -312,8 +310,6 @@ where ), ); - let proof = self.api.extract_proof(); - let state = self.call_api_at.state_at(self.parent_hash)?; let storage_changes = self @@ -324,7 +320,6 @@ where Ok(BuiltBlock { block: ::new(header, self.extrinsics), storage_changes, - proof, }) } diff --git a/vara/node/service/Cargo.toml b/vara/node/service/Cargo.toml index 766092507d7..916960fdd0d 100644 --- a/vara/node/service/Cargo.toml +++ b/vara/node/service/Cargo.toml @@ -65,7 +65,7 @@ sc-sysinfo.workspace = true sp-core = { workspace = true, features = ["std"] } sp-crypto-ec-utils = { workspace = true, features = ["std", "bls12-381"] } sp-api = { workspace = true, features = ["std"] } -sp-authority-discovery = { workspace = true, optional = true, features = ["std"] } +sp-authority-discovery = { workspace = true, features = ["std"] } sp-consensus.workspace = true sp-consensus-babe = { workspace = true, features = ["std"] } sp-io = { workspace = true, features = ["std"] } @@ -101,7 +101,6 @@ gear-workspace-hack.workspace = true [features] vara-native = [ "vara-runtime", - "sp-authority-discovery" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/vara/node/service/src/client.rs b/vara/node/service/src/client.rs index b4aa9a42296..abc91b16d76 100644 --- a/vara/node/service/src/client.rs +++ b/vara/node/service/src/client.rs @@ -186,6 +186,7 @@ macro_rules! with_client { match $self { #[cfg(feature = "vara-native")] Self::Vara($client) => { $( $code )* }, + Self::Unsupported => panic!("native runtime support is not enabled"), } } } @@ -195,6 +196,7 @@ macro_rules! with_client { pub enum Client { #[cfg(feature = "vara-native")] Vara(Arc>), + Unsupported, } #[cfg(feature = "vara-native")] diff --git a/vara/node/service/src/lib.rs b/vara/node/service/src/lib.rs index 3bb01680b63..1d213c0f429 100644 --- a/vara/node/service/src/lib.rs +++ b/vara/node/service/src/lib.rs @@ -28,6 +28,7 @@ pub use client::*; pub use sc_client_api::AuxStore; use sc_consensus_babe::{self, SlotProportion}; pub use sp_blockchain::{HeaderBackend, HeaderMetadata}; +use sp_consensus_babe::inherents::BabeCreateInherentDataProviders; #[cfg(feature = "vara-native")] pub use vara_runtime; @@ -58,7 +59,16 @@ type FullGrandpaBlockImport = >; /// The transaction pool type definition. -type TransactionPool = sc_transaction_pool::FullPool>; +type TransactionPool = + sc_transaction_pool::TransactionPoolHandle>; + +type FullBabeBlockImport = sc_consensus_babe::BabeBlockImport< + Block, + FullClient, + FullGrandpaBlockImport, + BabeCreateInherentDataProviders, + FullSelectChain, +>; /// The minimum period of blocks on which justifications will be /// imported and generated. @@ -130,18 +140,14 @@ pub fn new_partial( FullBackend, FullSelectChain, sc_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool>, + TransactionPool, ( impl Fn( sc_rpc::SubscriptionTaskExecutor, ) -> Result, sc_service::Error> + use, ( - sc_consensus_babe::BabeBlockImport< - Block, - FullClient, - FullGrandpaBlockImport, - >, + FullBabeBlockImport, sc_consensus_grandpa::LinkHalf, FullSelectChain>, sc_consensus_babe::BabeLink, ), @@ -188,6 +194,7 @@ where config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, + vec![Arc::new(sc_consensus_grandpa::GrandpaPruningFilter)], )?; let client = Arc::new(client); @@ -200,12 +207,15 @@ where let select_chain = sc_consensus::LongestChain::new(backend.clone()); - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), + let transaction_pool = Arc::from( + sc_transaction_pool::Builder::new( + task_manager.spawn_essential_handle(), + client.clone(), + config.role.is_authority().into(), + ) + .with_options(config.transaction_pool.clone()) + .with_prometheus(config.prometheus_registry()) + .build(), ); let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( @@ -217,37 +227,37 @@ where )?; let justification_import = grandpa_block_import.clone(); + let babe_config = sc_consensus_babe::configuration(&*client)?; + let slot_duration = babe_config.slot_duration(); let (block_import, babe_link) = sc_consensus_babe::block_import( - sc_consensus_babe::configuration(&*client)?, + babe_config, grandpa_block_import, client.clone(), - )?; - - let slot_duration = babe_link.config().slot_duration(); - let (import_queue, babe_worker_handle) = sc_consensus_babe::import_queue( - sc_consensus_babe::ImportQueueParams { - link: babe_link.clone(), - block_import: block_import.clone(), - justification_import: Some(Box::new(justification_import)), - client: client.clone(), - select_chain: select_chain.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + Arc::new(move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = + let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); - Ok((slot, timestamp)) - }, + Ok((slot, timestamp)) + }) as BabeCreateInherentDataProviders, + select_chain.clone(), + OffchainTransactionPoolFactory::new(transaction_pool.clone()), + )?; + let (import_queue, babe_worker_handle) = + sc_consensus_babe::import_queue(sc_consensus_babe::ImportQueueParams { + link: babe_link.clone(), + block_import: block_import.clone(), + justification_import: Some(Box::new(justification_import)), + client: client.clone(), + slot_duration, spawner: &task_manager.spawn_essential_handle(), registry: config.prometheus_registry(), telemetry: telemetry.as_ref().map(|x| x.handle()), - offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool.clone()), - }, - )?; + })?; let import_setup = (block_import, grandpa_link, babe_link); @@ -344,11 +354,7 @@ pub fn new_full_base::Hash>, RuntimeA config: Configuration, disable_hardware_benchmarks: bool, with_startup_data: impl FnOnce( - &sc_consensus_babe::BabeBlockImport< - Block, - FullClient, - FullGrandpaBlockImport, - >, + &FullBabeBlockImport, &sc_consensus_babe::BabeLink, ), max_gas: Option, @@ -418,13 +424,14 @@ where Vec::default(), )); - let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = + let (network, system_rpc_tx, tx_handler_controller, sync_service) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, net_config, client: client.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), + spawn_essential_handle: task_manager.spawn_essential_handle(), import_queue, block_announce_validator_builder: None, warp_sync_config: Some(WarpSyncConfig::WithProvider(warp_sync)), @@ -454,6 +461,7 @@ where tx_handler_controller, sync_service: sync_service.clone(), telemetry: telemetry.as_mut(), + tracing_execute_block: None, })?; if let Some(hwbench) = hwbench { @@ -516,6 +524,7 @@ where sp_transaction_storage_proof::registration::new_data_provider( &*client_clone, &parent, + Default::default(), )?; Ok((slot, timestamp, storage_proof)) @@ -567,6 +576,7 @@ where Box::pin(dht_event_stream), authority_discovery_role, prometheus_registry.clone(), + task_manager.spawn_handle(), ); task_manager.spawn_handle().spawn( @@ -639,13 +649,12 @@ where network_provider: Arc::new(network.clone()), enable_http_requests: true, custom_extensions: |_| vec![], - }) + })? .run(client.clone(), task_manager.spawn_handle()) .boxed(), ); } - network_starter.start_network(); Ok(NewFullBase { task_manager, client, diff --git a/vara/node/testing/Cargo.toml b/vara/node/testing/Cargo.toml index eccb0e87621..2f67b7d6d89 100644 --- a/vara/node/testing/Cargo.toml +++ b/vara/node/testing/Cargo.toml @@ -18,7 +18,7 @@ runtime-primitives.workspace = true vara-runtime = { workspace = true, features = ["dev"] } gear-runtime-interface.workspace = true service = { workspace = true, features = ["vara-native"] } -sc-service = { workspace = true, features = [ "test-helpers", "rocksdb" ] } +sc-service = { workspace = true, features = ["rocksdb"] } substrate-test-client.workspace = true # Substrate Primitives diff --git a/vara/pallets/gear-builtin/src/bls12_381.rs b/vara/pallets/gear-builtin/src/bls12_381.rs index dabc28e77b2..3dab9179764 100644 --- a/vara/pallets/gear-builtin/src/bls12_381.rs +++ b/vara/pallets/gear-builtin/src/bls12_381.rs @@ -2,11 +2,27 @@ // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 use super::*; -use builtins_common::bls12_381::{self, Bls12_381Ops, BlsOpsGasCost}; +use builtins_common::bls12_381::{ + self, Bls12_381Ops, BlsOpsGasCost, + ark_bls12_381::{Bls12_381, g1::Config as G1Config, g2::Config as G2Config}, + ark_ec::{ + AffineRepr, CurveGroup, + pairing::Pairing, + short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig}, + }, + ark_scale::{ + ArkScale, ArkScaleMaxEncodedLen, HOST_CALL, MaxEncodedLen, + hazmat::ArkScaleProjective, + scale::{Decode, Encode}, + }, + ark_serialize::CanonicalSerialize, +}; use core::marker::PhantomData; use gear_runtime_interface::gear_bls_12_381 as gear_ri_bls12_381; use sp_crypto_ec_utils::bls12_381::host_calls as sp_ri_sp_crypto_bls12_381; +type ArkScaleHost = ArkScale; + pub struct Actor(PhantomData); impl BuiltinActor for Actor { @@ -82,47 +98,62 @@ struct Bls12_381OpsRi; impl Bls12_381Ops for Bls12_381OpsRi { fn multi_miller_loop(g1: Vec, g2: Vec) -> Result, BuiltinActorError> { - sp_ri_sp_crypto_bls12_381::bls12_381_multi_miller_loop(g1, g2).map_err(|_| { - BuiltinActorError::Custom(LimitedStr::from_small_str( - "Multi Miller loop host-call failed", - )) - }) - } - - fn final_exponentiation(f: Vec) -> Result, BuiltinActorError> { - sp_ri_sp_crypto_bls12_381::bls12_381_final_exponentiation(f).map_err(|_| { + let mut out = buffer_for::<::TargetField>(); + sp_ri_sp_crypto_bls12_381::bls12_381_multi_miller_loop(&g1, &g2, &mut out).map_err( + |_| { + BuiltinActorError::Custom(LimitedStr::from_small_str( + "Multi Miller loop host-call failed", + )) + }, + )?; + Ok(out) + } + + fn final_exponentiation(mut f: Vec) -> Result, BuiltinActorError> { + sp_ri_sp_crypto_bls12_381::bls12_381_final_exponentiation(&mut f).map_err(|_| { BuiltinActorError::Custom(LimitedStr::from_small_str( "Final exponentiation host-call failed", )) - }) + })?; + Ok(f) } fn msm_g1(bases: Vec, scalars: Vec) -> Result, BuiltinActorError> { - sp_ri_sp_crypto_bls12_381::bls12_381_msm_g1(bases, scalars).map_err(|_| { + let mut out = buffer_for::>(); + sp_ri_sp_crypto_bls12_381::bls12_381_msm_g1(&bases, &scalars, &mut out).map_err(|_| { BuiltinActorError::Custom(LimitedStr::from_small_str("MSM G1 computation failed")) - }) + })?; + encode_affine_as_projective::(out) } fn msm_g2(bases: Vec, scalars: Vec) -> Result, BuiltinActorError> { - sp_ri_sp_crypto_bls12_381::bls12_381_msm_g2(bases, scalars).map_err(|_| { + let mut out = buffer_for::>(); + sp_ri_sp_crypto_bls12_381::bls12_381_msm_g2(&bases, &scalars, &mut out).map_err(|_| { BuiltinActorError::Custom(LimitedStr::from_small_str("MSM G2 computation failed")) - }) + })?; + encode_affine_as_projective::(out) } fn projective_mul_g1(base: Vec, scalar: Vec) -> Result, BuiltinActorError> { - sp_ri_sp_crypto_bls12_381::bls12_381_mul_projective_g1(base, scalar).map_err(|_| { + let base = encode_projective_as_affine::(base)?; + let mut out = buffer_for::>(); + sp_ri_sp_crypto_bls12_381::bls12_381_mul_g1(&base, &scalar, &mut out).map_err(|_| { BuiltinActorError::Custom(LimitedStr::from_small_str( "Projective multiplication G1 failed", )) - }) + })?; + encode_affine_as_projective::(out) } fn projective_mul_g2(base: Vec, scalar: Vec) -> Result, BuiltinActorError> { - sp_ri_sp_crypto_bls12_381::bls12_381_mul_projective_g2(base, scalar).map_err(|_| { + let base = encode_projective_as_affine::(base)?; + let mut out = buffer_for::>(); + sp_ri_sp_crypto_bls12_381::bls12_381_mul_g2(&base, &scalar, &mut out).map_err(|_| { BuiltinActorError::Custom(LimitedStr::from_small_str( "Projective multiplication G2 failed", )) - }) + })?; + encode_affine_as_projective::(out) } fn aggregate_g1(points: Vec) -> Result, BuiltinActorError> { @@ -136,3 +167,30 @@ impl Bls12_381Ops for Bls12_381OpsRi { }) } } + +fn buffer_for() -> Vec +where + T: CanonicalSerialize + ArkScaleMaxEncodedLen, +{ + sp_std::vec![0; ArkScaleHost::::max_encoded_len()] +} + +fn encode_projective_as_affine(base: Vec) -> Result, BuiltinActorError> +where + C: SWCurveConfig, +{ + let point = ArkScaleProjective::>::decode(&mut &base[..]) + .map_err(|_| BuiltinActorError::DecodingError)? + .0; + Ok(ArkScaleHost::from(point.into_affine()).encode()) +} + +fn encode_affine_as_projective(affine: Vec) -> Result, BuiltinActorError> +where + C: SWCurveConfig, +{ + let affine = ArkScaleHost::>::decode(&mut &affine[..]) + .map_err(|_| BuiltinActorError::DecodingError)? + .0; + Ok(ArkScaleProjective::from(affine.into_group()).encode()) +} diff --git a/vara/pallets/gear-builtin/src/lib.rs b/vara/pallets/gear-builtin/src/lib.rs index 467e49d7bb6..9cb9a18a0b9 100644 --- a/vara/pallets/gear-builtin/src/lib.rs +++ b/vara/pallets/gear-builtin/src/lib.rs @@ -209,7 +209,7 @@ pub mod pallet { let call_info = call.get_dispatch_info(); // Necessary upfront gas sufficiency checks - let gas_cost = call_info.weight.ref_time(); + let gas_cost = call_info.total_weight().ref_time(); context.can_charge_gas(gas_cost)?; // Execute call diff --git a/vara/pallets/gear-eth-bridge/primitives/src/lib.rs b/vara/pallets/gear-eth-bridge/primitives/src/lib.rs index 699a64edc7f..8fc433f4f8b 100644 --- a/vara/pallets/gear-eth-bridge/primitives/src/lib.rs +++ b/vara/pallets/gear-eth-bridge/primitives/src/lib.rs @@ -13,10 +13,115 @@ extern crate alloc; use alloc::vec::Vec; use binary_merkle_tree::MerkleProof; -use gprimitives::{ActorId, H160, H256, U256}; -use parity_scale_codec::{Decode, Encode}; +use gprimitives::{ActorId, U256}; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; use scale_info::TypeInfo; +/// Ethereum address used by the bridge. +#[derive( + Clone, + Copy, + Debug, + Default, + Encode, + Decode, + PartialEq, + Eq, + PartialOrd, + Ord, + TypeInfo, + MaxEncodedLen, +)] +#[cfg_attr(feature = "std", derive(serde::Deserialize, serde::Serialize))] +pub struct H160(gprimitives::H160); + +impl DecodeWithMemTracking for H160 {} + +impl H160 { + /// Zero address. + pub fn zero() -> Self { + Self(gprimitives::H160::zero()) + } + + /// Returns bytes of the address. + pub fn as_bytes(&self) -> &[u8] { + self.0.as_bytes() + } +} + +impl From for H160 { + fn from(value: gprimitives::H160) -> Self { + Self(value) + } +} + +impl From for gprimitives::H160 { + fn from(value: H160) -> Self { + value.0 + } +} + +/// Ethereum/Gear bridge hash. +#[derive( + Clone, + Copy, + Debug, + Default, + Encode, + Decode, + PartialEq, + Eq, + PartialOrd, + Ord, + TypeInfo, + MaxEncodedLen, +)] +#[cfg_attr(feature = "std", derive(serde::Deserialize, serde::Serialize))] +pub struct H256(gprimitives::H256); + +impl DecodeWithMemTracking for H256 {} + +impl H256 { + /// Zero hash. + pub fn zero() -> Self { + Self(gprimitives::H256::zero()) + } + + /// Returns the hash as bytes. + pub fn as_bytes(&self) -> &[u8] { + self.0.as_bytes() + } + + /// Returns the underlying fixed-size byte array. + pub fn to_fixed_bytes(self) -> [u8; 32] { + self.0.to_fixed_bytes() + } +} + +impl AsRef<[u8]> for H256 { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + +impl From for H256 { + fn from(value: gprimitives::H256) -> Self { + Self(value) + } +} + +impl From for gprimitives::H256 { + fn from(value: H256) -> Self { + value.0 + } +} + +impl From<[u8; 32]> for H256 { + fn from(value: [u8; 32]) -> Self { + Self(value.into()) + } +} + /// Type representing merkle proof of message's inclusion into bridging queue. #[derive(Clone, Debug, Default, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, TypeInfo)] #[cfg_attr(feature = "std", derive(serde::Deserialize, serde::Serialize))] @@ -33,14 +138,16 @@ pub struct Proof { pub leaf: H256, } -impl From> for Proof { - fn from(value: MerkleProof) -> Self { +impl DecodeWithMemTracking for Proof {} + +impl From> for Proof { + fn from(value: MerkleProof) -> Self { Self { - root: value.root, - proof: value.proof, + root: value.root.into(), + proof: value.proof.into_iter().map(Into::into).collect(), number_of_leaves: value.number_of_leaves as u64, leaf_index: value.leaf_index as u64, - leaf: value.leaf, + leaf: value.leaf.into(), } } } @@ -54,6 +161,8 @@ pub struct EthMessage { payload: Vec, } +impl DecodeWithMemTracking for EthMessage {} + impl EthMessage { /// Creates a new [`EthMessage`] with unchecked parameters. /// diff --git a/vara/pallets/gear-eth-bridge/src/builtin.rs b/vara/pallets/gear-eth-bridge/src/builtin.rs index 9a2093c7f9d..573346a5186 100644 --- a/vara/pallets/gear-eth-bridge/src/builtin.rs +++ b/vara/pallets/gear-eth-bridge/src/builtin.rs @@ -13,8 +13,9 @@ use gear_core::{ limited::LimitedStr, message::{StoredDispatch, Value}, }; -use gprimitives::{ActorId, H160}; +use gprimitives::ActorId; use pallet_gear_builtin::{BuiltinActor, BuiltinReply}; +use pallet_gear_eth_bridge_primitives::H160; use parity_scale_codec::{Decode, Encode}; use sp_runtime::traits::UniqueSaturatedInto; use sp_std::vec::Vec; @@ -57,7 +58,7 @@ where destination, payload, } => Ok(BuiltinReply { - payload: send_message_request::(source, destination, payload, context)?, + payload: send_message_request::(source, destination.into(), payload, context)?, value: refund, }), } @@ -88,7 +89,7 @@ where Response::EthMessageQueued { block_number, - hash, + hash: hash.into(), nonce, queue_id, } diff --git a/vara/pallets/gear-eth-bridge/src/internal.rs b/vara/pallets/gear-eth-bridge/src/internal.rs index 216d2406387..597b120485f 100644 --- a/vara/pallets/gear-eth-bridge/src/internal.rs +++ b/vara/pallets/gear-eth-bridge/src/internal.rs @@ -14,8 +14,8 @@ use builtins_common::eth_bridge; use common::Origin; use frame_support::{Blake2_256, StorageHasher, ensure, traits::Get, weights::Weight}; use frame_system::pallet_prelude::{BlockNumberFor, HeaderFor}; -use gprimitives::{ActorId, H160, H256, U256}; -use pallet_gear_eth_bridge_primitives::EthMessage; +use gprimitives::{ActorId, U256}; +use pallet_gear_eth_bridge_primitives::{EthMessage, H160, H256}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_runtime::{ @@ -203,7 +203,9 @@ impl Pallet { } // Calculating new root. - let root = binary_merkle_tree::merkle_root_raw::(queue); + let root = H256::from(binary_merkle_tree::merkle_root_raw::( + queue.iter().copied().map(Into::::into), + )); // Updating queue merkle root in storage. QueueMerkleRoot::::put(root); @@ -391,10 +393,11 @@ impl EthMessageExt for EthMessage { fn hash(&self) -> H256 { eth_bridge::bridge_call_hash( self.nonce(), - self.source(), - self.destination(), + self.source().into(), + self.destination().into(), self.payload(), Keccak256::hash, ) + .into() } } diff --git a/vara/pallets/gear-eth-bridge/src/lib.rs b/vara/pallets/gear-eth-bridge/src/lib.rs index 6adf355ce45..f3a8ac40529 100644 --- a/vara/pallets/gear-eth-bridge/src/lib.rs +++ b/vara/pallets/gear-eth-bridge/src/lib.rs @@ -15,7 +15,7 @@ pub use builtin::Actor; pub use pallet::*; -pub use pallet_gear_eth_bridge_primitives::{EthMessage, Proof}; +pub use pallet_gear_eth_bridge_primitives::{EthMessage, H160, H256, Proof}; pub use weights::WeightInfo; /// Pallet migrations. @@ -57,7 +57,7 @@ pub mod pallet { ensure_root, ensure_signed, pallet_prelude::{BlockNumberFor, OriginFor}, }; - use gprimitives::{H160, H256, U256}; + use gprimitives::U256; use sp_runtime::{ BoundToRuntimeAppPublic, traits::{Keccak256, Zero}, @@ -442,7 +442,10 @@ pub mod pallet { // Generating proof. let idx = u32::try_from(idx).expect("queue index fits into u32"); - let proof = binary_merkle_tree::merkle_proof_raw::(queue, idx); + let proof = binary_merkle_tree::merkle_proof_raw::( + queue.iter().copied().map(Into::::into), + idx, + ); // Returning appropriate type. Some(proof.into()) diff --git a/vara/pallets/gear-eth-bridge/src/migrations/reset.rs b/vara/pallets/gear-eth-bridge/src/migrations/reset.rs index a61ef555ed3..bf5ca43a6fe 100644 --- a/vara/pallets/gear-eth-bridge/src/migrations/reset.rs +++ b/vara/pallets/gear-eth-bridge/src/migrations/reset.rs @@ -11,7 +11,7 @@ use frame_support::{ pallet_prelude::Weight, traits::{Get, OnRuntimeUpgrade}, }; -use gprimitives::H256; +use pallet_gear_eth_bridge_primitives::H256; #[cfg(feature = "try-runtime")] use {sp_runtime::TryRuntimeError, sp_std::vec::Vec}; diff --git a/vara/pallets/gear-eth-bridge/src/migrations/set_hash.rs b/vara/pallets/gear-eth-bridge/src/migrations/set_hash.rs index b19c7919e39..a8cff44d037 100644 --- a/vara/pallets/gear-eth-bridge/src/migrations/set_hash.rs +++ b/vara/pallets/gear-eth-bridge/src/migrations/set_hash.rs @@ -9,7 +9,7 @@ use frame_support::{ pallet_prelude::Weight, traits::{Get, OnRuntimeUpgrade}, }; -use gprimitives::H256; +use pallet_gear_eth_bridge_primitives::H256; #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; use sp_runtime::{RuntimeAppPublic, sp_std::vec::Vec}; diff --git a/vara/pallets/gear-voucher/src/internal.rs b/vara/pallets/gear-voucher/src/internal.rs index ded7a7e7018..a444a34a300 100644 --- a/vara/pallets/gear-voucher/src/internal.rs +++ b/vara/pallets/gear-voucher/src/internal.rs @@ -136,6 +136,7 @@ pub trait PrepaidCallsDispatcher { TypeInfo, Encode, Decode, + DecodeWithMemTracking, MaxEncodedLen, )] pub struct VoucherId([u8; 32]); @@ -187,7 +188,9 @@ impl VoucherInfo { } /// Prepaid call to be executed on-chain. -#[derive(Debug, Clone, Encode, Decode, TypeInfo, PartialEq, Eq, PartialOrd, Ord)] +#[derive( + Debug, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, PartialEq, Eq, PartialOrd, Ord, +)] pub enum PrepaidCall { SendMessage { destination: ActorId, diff --git a/vara/pallets/gear/src/schedule.rs b/vara/pallets/gear/src/schedule.rs index c6c26c34baf..88dba46eb24 100644 --- a/vara/pallets/gear/src/schedule.rs +++ b/vara/pallets/gear/src/schedule.rs @@ -23,10 +23,7 @@ use pallet_gear_proc_macro::{ScheduleDebug, WeightDebug}; use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; -use sp_runtime::{ - RuntimeDebug, - codec::{Decode, Encode}, -}; +use sp_runtime::codec::{Decode, Encode}; use sp_std::{marker::PhantomData, vec::Vec}; /// How many API calls are executed in a single batch. The reason for increasing the amount @@ -140,7 +137,7 @@ pub struct Schedule { /// values will break existing programs which are above the new limits when a /// re-instrumentation is triggered. #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[derive(Clone, Encode, Decode, PartialEq, Eq, Debug, TypeInfo)] pub struct Limits { /// Maximum allowed stack height in number of elements. /// diff --git a/vara/pallets/grandpa-signer/src/lib.rs b/vara/pallets/grandpa-signer/src/lib.rs index d7da78349fb..58392299fdc 100644 --- a/vara/pallets/grandpa-signer/src/lib.rs +++ b/vara/pallets/grandpa-signer/src/lib.rs @@ -8,13 +8,13 @@ use frame_support::{ }; use frame_system::{ ensure_root, - offchain::{SendTransactionTypes, SubmitTransaction}, + offchain::{CreateBare, SubmitTransaction}, pallet_prelude::*, }; use log::{debug, trace}; use sp_core::ed25519; use sp_runtime::{ - RuntimeDebug, Saturating, + Saturating, traits::{SaturatedConversion, Verify}, transaction_validity::{ InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity, @@ -44,7 +44,7 @@ pub const KEY_TYPE: sp_core::crypto::KeyTypeId = sp_consensus_grandpa::KEY_TYPE; pub mod pallet { use super::*; - #[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen, RuntimeDebug)] + #[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen, Debug)] #[scale_info(skip_type_params(T))] pub struct SigningRequest { pub id: RequestId, @@ -54,11 +54,19 @@ pub mod pallet { pub expires_at: Option>, } - #[derive(RuntimeDebug)] struct SubmissionContext { request: SigningRequest, } + impl sp_std::fmt::Debug for SubmissionContext { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + f.debug_struct("SubmissionContext") + .field("request_id", &self.request.id) + .field("set_id", &self.request.set_id) + .finish() + } + } + #[pallet::pallet] #[pallet::without_storage_info] pub struct Pallet(_PhantomData); @@ -436,7 +444,7 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet where - T: SendTransactionTypes>, + T: CreateBare>, T::AuthorityId: From, T::AuthoritySignature: From, { @@ -507,9 +515,8 @@ pub mod pallet { authority, signature, }; - match SubmitTransaction::>::submit_unsigned_transaction( - call.into(), - ) { + let xt = T::create_bare(call.into()); + match SubmitTransaction::>::submit_transaction(xt) { Ok(()) => { submissions = submissions.saturating_add(1); submitted = true; diff --git a/vara/pallets/payment/src/lib.rs b/vara/pallets/payment/src/lib.rs index af2d3f1db5a..bb6fbbf1ea4 100644 --- a/vara/pallets/payment/src/lib.rs +++ b/vara/pallets/payment/src/lib.rs @@ -18,9 +18,12 @@ use pallet_transaction_payment::{ RuntimeDispatchInfo, }; use sp_runtime::{ - FixedPointNumber, FixedPointOperand, Perquintill, SaturatedConversion, - traits::{Bounded, Convert, DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SignedExtension}, - transaction_validity::TransactionValidityError, + FixedPointNumber, FixedPointOperand, Perquintill, SaturatedConversion, impl_tx_ext_default, + traits::{ + Bounded, Convert, DispatchInfoOf, Dispatchable, Implication, PostDispatchInfoOf, + TransactionExtension, + }, + transaction_validity::{TransactionSource, TransactionValidityError, ValidTransaction}, }; use sp_std::borrow::Cow; @@ -41,7 +44,8 @@ mod tests; /// A wrapper around the `pallet_transaction_payment::ChargeTransactionPayment`. /// Adjusts `DispatchInfo` to reflect custom fee add-ons. -#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] +#[derive(Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo)] +#[scale_info(skip_type_params(T))] pub struct CustomChargeTransactionPayment(ChargeTransactionPayment); impl CustomChargeTransactionPayment @@ -65,56 +69,84 @@ impl sp_std::fmt::Debug for CustomChargeTransactionPayment { } } -// Follow pallet-transaction-payment implementation -impl SignedExtension for CustomChargeTransactionPayment +impl TransactionExtension> for CustomChargeTransactionPayment where T: TypeInfo, + T::RuntimeOrigin: From>> + Clone, BalanceOf: Send + Sync + From + FixedPointOperand, CallOf: Dispatchable, { - const IDENTIFIER: &'static str = as SignedExtension>::IDENTIFIER; - type AccountId = as SignedExtension>::AccountId; - type Call = CallOf; - type AdditionalSigned = as SignedExtension>::AdditionalSigned; - type Pre = as SignedExtension>::Pre; - fn additional_signed(&self) -> Result { - self.0.additional_signed() + const IDENTIFIER: &'static str = + as TransactionExtension>>::IDENTIFIER; + type Implicit = as TransactionExtension>>::Implicit; + type Val = as TransactionExtension>>::Val; + type Pre = as TransactionExtension>>::Pre; + + fn implicit(&self) -> Result { + self.0.implicit() + } + + fn weight(&self, call: &CallOf) -> Weight { + self.0.weight(call) } fn validate( &self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, + origin: as Dispatchable>::RuntimeOrigin, + call: &CallOf, + info: &DispatchInfoOf>, len: usize, - ) -> TransactionValidity { + self_implicit: Self::Implicit, + inherited_implication: &impl Implication, + source: TransactionSource, + ) -> Result< + ( + ValidTransaction, + Self::Val, + as Dispatchable>::RuntimeOrigin, + ), + TransactionValidityError, + > { // Override DispatchInfo struct for call variants exempted from weight fee multiplication let info = Self::pre_dispatch_info(call, info); - let payer = Self::fee_payer_account(call, who); - self.0.validate(&payer, call, &info, len) + let payment_origin = if let Ok(who) = frame_system::ensure_signed(origin.clone()) { + let payer = Self::fee_payer_account(call, &who); + frame_system::RawOrigin::Signed(payer.into_owned()).into() + } else { + origin.clone() + }; + let (validity, val, _) = self.0.validate( + payment_origin, + call, + &info, + len, + self_implicit, + inherited_implication, + source, + )?; + Ok((validity, val, origin)) } - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, + val: Self::Val, + origin: & as Dispatchable>::RuntimeOrigin, + call: &CallOf, + info: &DispatchInfoOf>, len: usize, ) -> Result { // Override DispatchInfo struct for call variants exempted from weight fee multiplication let info = Self::pre_dispatch_info(call, info); - // Replace payer if delegated - let payer = Self::fee_payer_account(call, who); - self.0.pre_dispatch(&payer, call, &info, len) + self.0.prepare(val, origin, call, &info, len) } - fn post_dispatch( - maybe_pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + fn post_dispatch_details( + pre: Self::Pre, + info: &DispatchInfoOf>, + post_info: &PostDispatchInfoOf>, len: usize, result: &sp_runtime::DispatchResult, - ) -> Result<(), TransactionValidityError> { + ) -> Result { // There is no easy way to modify the original `DispatchInfo` struct similarly // it's done in `pre_dispatch()` because a call is not supplied. // However, we can just leave it as is and yet get the correct fee refund if any: @@ -125,10 +157,12 @@ where // weight normalization before returning it from the extrinsic. // // TODO: still think of a more robust way to deal with fee refunds - as SignedExtension>::post_dispatch( - maybe_pre, info, post_info, len, result, + as TransactionExtension>>::post_dispatch_details( + pre, info, post_info, len, result, ) } + + impl_tx_ext_default!(CallOf;); } impl CustomChargeTransactionPayment @@ -154,11 +188,11 @@ where let multiplier = TransactionPayment::::next_fee_multiplier(); if multiplier > Multiplier::saturating_from_integer(1) { let mut info: DispatchInfo = *info; - info.weight = Weight::from_parts( + info.call_weight = Weight::from_parts( multiplier .reciprocal() // take inverse .unwrap_or_else(Multiplier::max_value) - .saturating_mul_int(info.weight.ref_time()), + .saturating_mul_int(info.call_weight.ref_time()), 0, ); Cow::Owned(info) @@ -224,7 +258,7 @@ impl Pallet { /// Modification of the `pallet_transaction_payment::Pallet::query_info()` /// that is aware of the transaction fee customization based on a specific call pub fn query_info< - Extrinsic: sp_runtime::traits::Extrinsic + GetDispatchInfo + ExtractCall>, + Extrinsic: sp_runtime::traits::ExtrinsicLike + GetDispatchInfo + ExtractCall>, >( unchecked_extrinsic: Extrinsic, len: u32, @@ -234,7 +268,8 @@ impl Pallet { BalanceOf: FixedPointOperand, { let DispatchInfo { - weight, + call_weight, + extension_weight, class, pays_fee, } = ::get_dispatch_info(&unchecked_extrinsic); @@ -243,21 +278,22 @@ impl Pallet { let call: CallOf = >>::extract_call(&unchecked_extrinsic); // If call is exempted from weight multiplication pre-divide it with the fee multiplier - let adjusted_weight = if !T::ExtraFeeCallFilter::contains(&call) { + let adjusted_call_weight = if !T::ExtraFeeCallFilter::contains(&call) { Weight::from_parts( TransactionPayment::::next_fee_multiplier() .reciprocal() .unwrap_or_else(Multiplier::max_value) - .saturating_mul_int(weight.ref_time()), + .saturating_mul_int(call_weight.ref_time()), 0, ) } else { - weight + call_weight }; TransactionPayment::::compute_fee( len, &DispatchInfo { - weight: adjusted_weight, + call_weight: adjusted_call_weight, + extension_weight, class, pays_fee, }, @@ -269,7 +305,7 @@ impl Pallet { }; RuntimeDispatchInfo { - weight, + weight: call_weight.saturating_add(extension_weight), class, partial_fee, } @@ -277,7 +313,7 @@ impl Pallet { /// Modification of the `pallet_transaction_payment::Pallet::query_fee_details()` pub fn query_fee_details< - Extrinsic: sp_runtime::traits::Extrinsic + GetDispatchInfo + ExtractCall>, + Extrinsic: sp_runtime::traits::ExtrinsicLike + GetDispatchInfo + ExtractCall>, >( unchecked_extrinsic: Extrinsic, len: u32, @@ -287,7 +323,8 @@ impl Pallet { BalanceOf: FixedPointOperand, { let DispatchInfo { - weight, + call_weight, + extension_weight, class, pays_fee, } = ::get_dispatch_info(&unchecked_extrinsic); @@ -297,21 +334,22 @@ impl Pallet { if unchecked_extrinsic.is_signed().unwrap_or(false) { let call: CallOf = >>::extract_call(&unchecked_extrinsic); - let adjusted_weight = if !T::ExtraFeeCallFilter::contains(&call) { + let adjusted_call_weight = if !T::ExtraFeeCallFilter::contains(&call) { Weight::from_parts( TransactionPayment::::next_fee_multiplier() .reciprocal() .unwrap_or_else(Multiplier::max_value) - .saturating_mul_int(weight.ref_time()), + .saturating_mul_int(call_weight.ref_time()), 0, ) } else { - weight + call_weight }; TransactionPayment::::compute_fee_details( len, &DispatchInfo { - weight: adjusted_weight, + call_weight: adjusted_call_weight, + extension_weight, class, pays_fee, }, diff --git a/vara/pallets/staking-rewards/src/extension.rs b/vara/pallets/staking-rewards/src/extension.rs index cfc54740b32..6630a0c4b0c 100644 --- a/vara/pallets/staking-rewards/src/extension.rs +++ b/vara/pallets/staking-rewards/src/extension.rs @@ -2,62 +2,70 @@ // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 use crate::Config; -use frame_support::{dispatch::DispatchInfo, traits::Contains}; +use frame_support::{dispatch::DispatchInfo, traits::Contains, weights::Weight}; use scale_info::TypeInfo; use sp_runtime::{ - codec::{Decode, Encode}, - traits::{DispatchInfoOf, Dispatchable, SignedExtension}, - transaction_validity::{InvalidTransaction, TransactionValidity, TransactionValidityError}, + codec::{Decode, DecodeWithMemTracking, Encode}, + traits::{DispatchInfoOf, Dispatchable, Implication, TransactionExtension}, + transaction_validity::{ + InvalidTransaction, TransactionSource, TransactionValidityError, ValidTransaction, + }, }; /// Filter `Staking::bond()` extrinsic sent from accounts that are not allowed to stake. /// /// This will remain until all locked tokens for accounts in question are fully vested. -#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, TypeInfo)] +#[derive(Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, Default, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct StakingBlackList(sp_std::marker::PhantomData); impl StakingBlackList { - /// Creates new `SignedExtension` to check the call validity. + /// Creates new transaction extension to check the call validity. pub fn new() -> Self { Self(Default::default()) } } -impl SignedExtension for StakingBlackList +impl TransactionExtension for StakingBlackList where - T::RuntimeCall: Dispatchable, + T::RuntimeOrigin: Clone, + T::RuntimeCall: Dispatchable, { const IDENTIFIER: &'static str = "StakingBlackList"; - type AccountId = T::AccountId; - type Call = T::RuntimeCall; - type AdditionalSigned = (); + type Implicit = (); + type Val = (); type Pre = (); - fn additional_signed(&self) -> Result { - Ok(()) + + fn weight(&self, _: &T::RuntimeCall) -> Weight { + Weight::zero() } + fn validate( &self, - from: &Self::AccountId, - call: &Self::Call, - _: &DispatchInfoOf, + origin: T::RuntimeOrigin, + call: &T::RuntimeCall, + _: &DispatchInfoOf, _: usize, - ) -> TransactionValidity { + _: Self::Implicit, + _: &impl Implication, + _: TransactionSource, + ) -> Result<(ValidTransaction, Self::Val, T::RuntimeOrigin), TransactionValidityError> { if T::BondCallFilter::contains(call) { - if T::AccountFilter::contains(from) { - Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) - } else { - Ok(Default::default()) + if let Ok(from) = frame_system::ensure_signed(origin.clone()) { + if T::AccountFilter::contains(&from) { + return Err(TransactionValidityError::Invalid(InvalidTransaction::Call)); + } } - } else { - Ok(Default::default()) } + Ok((Default::default(), (), origin)) } - fn pre_dispatch( + + fn prepare( self, - _: &Self::AccountId, - _: &Self::Call, - _: &DispatchInfoOf, + _: Self::Val, + _: &T::RuntimeOrigin, + _: &T::RuntimeCall, + _: &DispatchInfoOf, _: usize, ) -> Result { Ok(()) diff --git a/vara/pallets/staking-rewards/src/lib.rs b/vara/pallets/staking-rewards/src/lib.rs index cf7a747384a..b7d98555321 100644 --- a/vara/pallets/staking-rewards/src/lib.rs +++ b/vara/pallets/staking-rewards/src/lib.rs @@ -39,8 +39,9 @@ mod tests; use frame_support::{ PalletId, traits::{ - Contains, Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, WithdrawReasons, - fungible, + Contains, Get, Imbalance, OnUnbalanced, + fungible::{self, Balanced, Inspect, Mutate}, + tokens::Preservation, }, weights::Weight, }; @@ -60,12 +61,8 @@ pub use weights::WeightInfo; pub type BalanceOf = ::CurrencyBalance; pub type CurrencyOf = ::Currency; -pub type PositiveImbalanceOf = <::Currency as Currency< - ::AccountId, ->>::PositiveImbalance; -pub type NegativeImbalanceOf = <::Currency as Currency< - ::AccountId, ->>::NegativeImbalance; +pub type PositiveImbalanceOf = fungible::Debt, CurrencyOf>; +pub type NegativeImbalanceOf = fungible::Credit, CurrencyOf>; type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; pub(crate) type AccountIdOf = ::AccountId; @@ -180,14 +177,14 @@ pub mod pallet { let amount = self .pool_balance .saturating_add(T::Currency::minimum_balance()); - if T::Currency::free_balance(&account_id) < amount { + if T::Currency::balance(&account_id) < amount { // Set the staking rewards pool account balance to the initial value. // Dropping the resulting imbalance as the funds are minted out of thin air. - let _ = T::Currency::make_free_balance_be(&account_id, amount); + let _ = T::Currency::set_balance(&account_id, amount); } // create account for the rent pool - let _ = T::Currency::make_free_balance_be( + let _ = T::Currency::set_balance( &Pallet::::rent_pool_account_id(), T::Currency::minimum_balance(), ); @@ -254,7 +251,7 @@ pub mod pallet { &who, &Self::account_id(), value, - ExistenceRequirement::AllowDeath, + Preservation::Expendable, ) .map_err(|e| { log::error!("Failed to replenish the staking rewards pool: {e:?}"); @@ -278,7 +275,7 @@ pub mod pallet { &from, &Self::account_id(), value, - ExistenceRequirement::AllowDeath, + Preservation::Expendable, ) .map_err(|e| { log::error!("Failed to replenish the staking rewards pool: {e:?}"); @@ -302,7 +299,7 @@ pub mod pallet { &Self::account_id(), &to, value, - ExistenceRequirement::AllowDeath, + Preservation::Expendable, ) .map_err(|e| { log::error!("Failed to withdraw funds from the staking rewards pool: {e:?}"); @@ -358,7 +355,7 @@ pub mod pallet { /// Return the amount in the staking rewards pool. // The existential deposit is not a part of the pool so rewards account never gets deleted. pub fn pool() -> BalanceOf { - T::Currency::free_balance(&Self::account_id()) + T::Currency::balance(&Self::account_id()) // Must never be less than 0 but better be safe. .saturating_sub(T::Currency::minimum_balance()) } @@ -410,7 +407,7 @@ pub mod pallet { /// Return the amount in the rent pool. // The existential deposit is not a part of the pool so the account never gets deleted. pub fn rent_pool_balance() -> BalanceOf { - T::Currency::free_balance(&Self::rent_pool_account_id()) + T::Currency::balance(&Self::rent_pool_account_id()) // Must never be less than 0 but better be safe. .saturating_sub(T::Currency::minimum_balance()) } @@ -433,13 +430,16 @@ fn pay_rent_rewards_out(maybe_active_era_info: Option) for (account_id, points) in reward_points.individual { let payout = funds.saturating_mul(u128::from(points)) / total; if payout > 0 { - CurrencyOf::::transfer( + if let Err(e) = CurrencyOf::::transfer( &pallet::Pallet::::rent_pool_account_id(), &account_id, payout.unique_saturated_into(), - ExistenceRequirement::KeepAlive, - ) - .unwrap_or_else(|e| log::error!("Failed to transfer rent reward: {e:?}; account_id = {account_id:#?}, points = {points}, payout = {payout}")); + Preservation::Preserve, + ) { + log::error!( + "Failed to transfer rent reward: {e:?}; account_id = {account_id:#?}, points = {points}, payout = {payout}" + ); + } } } } @@ -474,15 +474,9 @@ impl OnUnbalanced> for Pallet { fn on_nonzero_unbalanced(minted: PositiveImbalanceOf) { let amount = minted.peek(); - if let Ok(burned) = T::Currency::withdraw( - &Self::account_id(), - amount, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive, - ) { + if T::Currency::settle(&Self::account_id(), minted, Preservation::Preserve).is_ok() { // Offsetting rewards against rewards pool until the latter is not depleted. - // After that the positive imbalance is dropped adding up to the total supply. - let _ = minted.offset(burned); + // After that the imbalance is dropped according to the currency implementation. Self::deposit_event(Event::Burned { amount }); } else { @@ -501,11 +495,12 @@ impl OnUnbalanced> for OffsetPool { let numeric_amount = amount.peek(); // Should resolve into existing but resolving with creation is a safer bet anyway - T::Currency::resolve_creating(&Pallet::::account_id(), amount); - - Pallet::deposit_event(Event::::Minted { - amount: numeric_amount, - }); + match T::Currency::resolve(&Pallet::::account_id(), amount) { + Ok(()) => Pallet::deposit_event(Event::::Minted { + amount: numeric_amount, + }), + Err(amount) => log::error!("Balanced::resolve() err: {:?}", amount.peek()), + } } } @@ -549,12 +544,8 @@ where // Try to burn the respective amount from the staking rewards pool and drop // the output to offset the total issuance increase which should have taken place // somewhere upstream when the incoming negative imbalance `amount` was created - let _ = T::Currency::withdraw( - &Pallet::::account_id(), - numeric_amount, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive, - ); + let debt = T::Currency::rescind(numeric_amount); + let _ = T::Currency::settle(&Pallet::::account_id(), debt, Preservation::Preserve); U::on_unbalanced(amount); } diff --git a/vara/runtime/common/src/apis.rs b/vara/runtime/common/src/apis.rs index 277f92f72b0..43f5e904ef0 100644 --- a/vara/runtime/common/src/apis.rs +++ b/vara/runtime/common/src/apis.rs @@ -12,7 +12,7 @@ macro_rules! impl_runtime_apis_plus_common { VERSION } - fn execute_block(block: Block) { + fn execute_block(block: ::LazyBlock) { Executive::execute_block(block); } @@ -49,7 +49,7 @@ macro_rules! impl_runtime_apis_plus_common { } fn check_inherents( - block: Block, + block: ::LazyBlock, data: sp_inherents::InherentData, ) -> sp_inherents::CheckInherentsResult { data.check_extrinsics(&block) @@ -73,8 +73,8 @@ macro_rules! impl_runtime_apis_plus_common { } impl sp_session::SessionKeys for Runtime { - fn generate_session_keys(seed: Option>) -> Vec { - SessionKeys::generate(seed) + fn generate_session_keys(owner: Vec, seed: Option>) -> sp_session::OpaqueGeneratedSessionKeys { + SessionKeys::generate(&owner, seed).into() } fn decode_session_keys( diff --git a/vara/runtime/interface/sandbox/src/lib.rs b/vara/runtime/interface/sandbox/src/lib.rs index 0d175fc6571..c5a843fde1b 100644 --- a/vara/runtime/interface/sandbox/src/lib.rs +++ b/vara/runtime/interface/sandbox/src/lib.rs @@ -7,7 +7,11 @@ #[cfg(feature = "std")] pub use gear_sandbox_host::sandbox::{SandboxBackend, env::Instantiate}; -use sp_runtime_interface::{Pointer, runtime_interface}; +use sp_runtime_interface::{ + Pointer, + pass_by::{AllocateAndReturnByCodec, PassFatPointerAndDecode, PassFatPointerAndRead}, + runtime_interface, +}; type HostPointer = u64; @@ -25,8 +29,8 @@ pub trait Sandbox { fn instantiate( &mut self, dispatch_thunk_id: u32, - wasm_code: &[u8], - raw_env_def: &[u8], + wasm_code: PassFatPointerAndRead<&[u8]>, + raw_env_def: PassFatPointerAndRead<&[u8]>, state_ptr: Pointer, ) -> u32 { #[cfg(feature = "host-api")] @@ -48,8 +52,8 @@ pub trait Sandbox { fn instantiate( &mut self, dispatch_thunk_id: u32, - wasm_code: &[u8], - raw_env_def: &[u8], + wasm_code: PassFatPointerAndRead<&[u8]>, + raw_env_def: PassFatPointerAndRead<&[u8]>, state_ptr: Pointer, ) -> u32 { #[cfg(feature = "host-api")] @@ -70,8 +74,8 @@ pub trait Sandbox { fn invoke( &mut self, instance_idx: u32, - function: &str, - args: &[u8], + function: PassFatPointerAndRead<&str>, + args: PassFatPointerAndRead<&[u8]>, return_val_ptr: Pointer, return_val_len: u32, state_ptr: Pointer, @@ -155,8 +159,8 @@ pub trait Sandbox { fn get_global_val( &mut self, instance_idx: u32, - name: &str, - ) -> Option { + name: PassFatPointerAndRead<&str>, + ) -> AllocateAndReturnByCodec> { #[cfg(feature = "host-api")] return detail::get_global_val(*self, instance_idx, name); @@ -169,8 +173,8 @@ pub trait Sandbox { fn set_global_val( &mut self, instance_idx: u32, - name: &str, - value: sp_wasm_interface::Value, + name: PassFatPointerAndRead<&str>, + value: PassFatPointerAndDecode, ) -> u32 { #[cfg(feature = "host-api")] return detail::set_global_val(*self, instance_idx, name, value); diff --git a/vara/runtime/interface/src/lib.rs b/vara/runtime/interface/src/lib.rs index 4788666b1a2..8b75653524f 100644 --- a/vara/runtime/interface/src/lib.rs +++ b/vara/runtime/interface/src/lib.rs @@ -16,7 +16,10 @@ use gear_core::{ use gear_lazy_pages_common::{GlobalsAccessConfig, Status}; use parity_scale_codec::{Decode, Encode}; use sp_runtime_interface::{ - pass_by::{Codec, PassBy}, + pass_by::{ + AllocateAndReturnByCodec, PassFatPointerAndDecode, PassFatPointerAndDecodeSlice, + PassFatPointerAndRead, PassFatPointerAndReadWrite, + }, runtime_interface, }; use sp_std::{result::Result, vec::Vec}; @@ -56,10 +59,6 @@ pub struct LazyPagesProgramContext { pub costs: Vec, } -impl PassBy for LazyPagesProgramContext { - type PassBy = Codec; -} - #[derive(Debug, Clone, Encode, Decode)] pub struct LazyPagesInitContext { pub page_sizes: Vec, @@ -99,10 +98,6 @@ impl From for gear_lazy_pages_common::LazyPagesInitContext } } -impl PassBy for LazyPagesInitContext { - type PassBy = Codec; -} - #[cfg(feature = "std")] #[derive(Debug, Default)] struct SpIoProgramStorage; @@ -130,26 +125,34 @@ pub enum ProcessAccessErrorVer1 { #[runtime_interface] pub trait GearRI { #[version(2)] - fn pre_process_memory_accesses(reads: &[u8], writes: &[u8], gas_bytes: &mut [u8; 8]) -> u8 { - let mut gas_counter = u64::from_le_bytes(*gas_bytes); + fn pre_process_memory_accesses( + reads: PassFatPointerAndRead<&[u8]>, + writes: PassFatPointerAndRead<&[u8]>, + gas_bytes: PassFatPointerAndReadWrite<&mut [u8]>, + ) -> u8 { + let mut gas_counter = u64::from_le_bytes( + gas_bytes + .try_into() + .expect("gas counter must be encoded as 8 bytes"), + ); let res = lazy_pages_detail::pre_process_memory_accesses(reads, writes, &mut gas_counter); gas_bytes.copy_from_slice(&gas_counter.to_le_bytes()); res } - fn lazy_pages_status() -> (Status,) { + fn lazy_pages_status() -> AllocateAndReturnByCodec<(Status,)> { lazy_pages_detail::lazy_pages_status() } /// Init lazy-pages. /// Returns whether initialization was successful. - fn init_lazy_pages(ctx: LazyPagesInitContext) -> bool { + fn init_lazy_pages(ctx: PassFatPointerAndDecode) -> bool { lazy_pages_detail::init_lazy_pages(ctx) } /// Init lazy pages context for current program. /// Panic if some goes wrong during initialization. - fn init_lazy_pages_for_program(ctx: LazyPagesProgramContext) { + fn init_lazy_pages_for_program(ctx: PassFatPointerAndDecode) { lazy_pages_detail::init_lazy_pages_for_program(ctx) } @@ -160,20 +163,23 @@ pub trait GearRI { lazy_pages_detail::mprotect_lazy_pages(protect) } - fn change_wasm_memory_addr_and_size(addr: Option, size: Option) { + fn change_wasm_memory_addr_and_size( + addr: PassFatPointerAndDecode>, + size: PassFatPointerAndDecode>, + ) { lazy_pages_detail::change_wasm_memory_addr_and_size(addr, size) } - fn write_accessed_pages() -> Vec { + fn write_accessed_pages() -> AllocateAndReturnByCodec> { lazy_pages_detail::write_accessed_pages() } /* Below goes deprecated runtime interface functions. */ fn pre_process_memory_accesses( - reads: &[MemoryInterval], - writes: &[MemoryInterval], - gas_left: (GasLeft,), - ) -> (GasLeft, Result<(), ProcessAccessErrorVer1>) { + reads: PassFatPointerAndDecodeSlice<&[MemoryInterval]>, + writes: PassFatPointerAndDecodeSlice<&[MemoryInterval]>, + gas_left: PassFatPointerAndDecode<(GasLeft,)>, + ) -> AllocateAndReturnByCodec<(GasLeft, Result<(), ProcessAccessErrorVer1>)> { let mut gas_left = gas_left.0; let gas_before = gas_left.gas; let res = gear_lazy_pages::pre_process_memory_accesses(reads, writes, &mut gas_left.gas); @@ -297,18 +303,18 @@ pub mod lazy_pages_detail { /// this interface allows to do it partially. #[runtime_interface] pub trait GearDebug { - fn println(msg: &[u8]) { + fn println(msg: PassFatPointerAndRead<&[u8]>) { println!("{}", sp_std::str::from_utf8(msg).unwrap()); } - fn file_write(path: &str, data: Vec) { + fn file_write(path: PassFatPointerAndRead<&str>, data: PassFatPointerAndRead>) { use std::{fs::File, io::Write}; let mut file = File::create(path).unwrap(); file.write_all(&data).unwrap(); } - fn file_read(path: &str) -> Vec { + fn file_read(path: PassFatPointerAndRead<&str>) -> AllocateAndReturnByCodec> { use std::{fs::File, io::Read}; let mut file = File::open(path).unwrap(); @@ -317,7 +323,7 @@ pub trait GearDebug { data } - fn time_in_nanos() -> u128 { + fn time_in_nanos() -> AllocateAndReturnByCodec { use std::time::SystemTime; SystemTime::now() @@ -332,13 +338,17 @@ pub trait GearBls12_381 { /// Aggregate provided G1-points. Useful for cases with hundreds or more items. /// Accepts scale-encoded `ArkScale>`. /// Result is scale-encoded `ArkScale`. - fn aggregate_g1(points: Vec) -> Result, u32> { + fn aggregate_g1( + points: PassFatPointerAndRead>, + ) -> AllocateAndReturnByCodec, u32>> { Bls12_381OpsLowLevel::aggregate_g1(points).map_err(|e| e.as_u32()) } /// Map a message to G2Affine-point using the domain separation tag from `milagro_bls`. /// Result is encoded `ArkScale`. - fn map_to_g2affine(message: Vec) -> Result, u32> { + fn map_to_g2affine( + message: PassFatPointerAndRead>, + ) -> AllocateAndReturnByCodec, u32>> { Bls12_381OpsLowLevel::map_to_g2affine(message).map_err(|e| e.as_u32()) } } diff --git a/vara/runtime/vara/Cargo.toml b/vara/runtime/vara/Cargo.toml index dd0f0a48f77..5a49c577645 100644 --- a/vara/runtime/vara/Cargo.toml +++ b/vara/runtime/vara/Cargo.toml @@ -42,6 +42,7 @@ pallet-election-provider-multi-phase.workspace = true pallet-grandpa.workspace = true pallet-identity.workspace = true pallet-im-online.workspace = true +pallet-migrations.workspace = true pallet-nomination-pools.workspace = true pallet-nomination-pools-runtime-api.workspace = true pallet-multisig.workspace = true @@ -172,6 +173,8 @@ std = [ "pallet-grandpa/std", "pallet-identity/std", "pallet-im-online/std", + "pallet-migrations/std", + "pallet-migrations/try-runtime", "pallet-nomination-pools/std", "pallet-nomination-pools-runtime-api/std", "pallet-multisig/std", @@ -235,6 +238,7 @@ runtime-benchmarks = [ "pallet-bags-list/runtime-benchmarks", "pallet-staking/runtime-benchmarks", "pallet-conviction-voting/runtime-benchmarks", + "pallet-migrations/runtime-benchmarks", "pallet-ranked-collective/runtime-benchmarks", "pallet-referenda/runtime-benchmarks", ] @@ -268,6 +272,7 @@ try-runtime = [ "pallet-grandpa/try-runtime", "pallet-identity/try-runtime", "pallet-im-online/try-runtime", + "pallet-migrations/try-runtime", "pallet-nomination-pools/try-runtime", "pallet-multisig/try-runtime", "pallet-offences/try-runtime", diff --git a/vara/runtime/vara/src/genesis_config_presets.rs b/vara/runtime/vara/src/genesis_config_presets.rs index 42117be7af7..23b082228a2 100644 --- a/vara/runtime/vara/src/genesis_config_presets.rs +++ b/vara/runtime/vara/src/genesis_config_presets.rs @@ -3,6 +3,7 @@ use super::{UNITS as TOKEN, *}; use crate::{GearBank, GearBuiltin}; +use alloc::format; use pallet_balances::GenesisConfig; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_staking::{Forcing, StakerStatus}; @@ -11,7 +12,7 @@ use sp_consensus_babe::AuthorityId as BabeId; use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{Pair, Public, sr25519}; use sp_genesis_builder::{DEV_RUNTIME_PRESET, LOCAL_TESTNET_RUNTIME_PRESET, PresetId}; -use sp_runtime::{format, traits::IdentifyAccount}; +use sp_runtime::traits::IdentifyAccount; /// Configure initial storage state for FRAME modules. pub fn testnet_genesis( @@ -52,7 +53,10 @@ pub fn testnet_genesis( ); RuntimeGenesisConfig { - balances: GenesisConfig { balances }, + balances: GenesisConfig { + balances, + dev_accounts: None, + }, session: SessionConfig { keys: initial_authorities .iter() @@ -210,8 +214,7 @@ pub fn local_testnet_genesis() -> RuntimeGenesisConfig { /// Provides the JSON representation of predefined genesis config for given `id`. pub fn get_preset(id: &PresetId) -> Option> { // TODO: remove after Substrate update - let id: &str = id.try_into().ok()?; - let patch = match id { + let patch = match id.as_ref() { DEV_RUNTIME_PRESET => development_genesis(), LOCAL_TESTNET_RUNTIME_PRESET => local_testnet_genesis(), _ => return None, diff --git a/vara/runtime/vara/src/governance/fellowship.rs b/vara/runtime/vara/src/governance/fellowship.rs index df5395a56d5..35626bf9343 100644 --- a/vara/runtime/vara/src/governance/fellowship.rs +++ b/vara/runtime/vara/src/governance/fellowship.rs @@ -13,10 +13,24 @@ use sp_runtime::{ morph_types, traits::{ConstU16, Replace, ReplaceWithDefault, TypedGet}, }; +use sp_std::borrow::Cow; use super::*; use crate::{DAYS, ECONOMIC_UNITS}; +const MAX_TRACK_NAME_LEN: usize = 25; + +const fn track_name(name: &str) -> [u8; MAX_TRACK_NAME_LEN] { + let bytes = name.as_bytes(); + let mut out = [0; MAX_TRACK_NAME_LEN]; + let mut i = 0; + while i < bytes.len() { + out[i] = bytes[i]; + i += 1; + } + out +} + parameter_types! { pub const AlarmInterval: BlockNumber = 1; pub const SubmissionDeposit: Balance = 0; @@ -27,12 +41,14 @@ pub struct TracksInfo; impl pallet_referenda::TracksInfo for TracksInfo { type Id = u16; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { + fn tracks() + -> impl Iterator>> + { static DATA: [(u16, pallet_referenda::TrackInfo); 10] = [ ( 0u16, pallet_referenda::TrackInfo { - name: "candidates", + name: track_name("candidates"), max_deciding: 10, decision_deposit: 100 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -54,7 +70,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { ( 1u16, pallet_referenda::TrackInfo { - name: "members", + name: track_name("members"), max_deciding: 10, decision_deposit: 10 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -76,7 +92,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { ( 2u16, pallet_referenda::TrackInfo { - name: "proficients", + name: track_name("proficients"), max_deciding: 10, decision_deposit: 10 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -98,7 +114,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { ( 3u16, pallet_referenda::TrackInfo { - name: "fellows", + name: track_name("fellows"), max_deciding: 10, decision_deposit: 10 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -120,7 +136,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { ( 4u16, pallet_referenda::TrackInfo { - name: "senior fellows", + name: track_name("senior fellows"), max_deciding: 10, decision_deposit: 10 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -142,7 +158,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { ( 5u16, pallet_referenda::TrackInfo { - name: "experts", + name: track_name("experts"), max_deciding: 10, decision_deposit: 1 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -164,7 +180,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { ( 6u16, pallet_referenda::TrackInfo { - name: "senior experts", + name: track_name("senior experts"), max_deciding: 10, decision_deposit: 1 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -186,7 +202,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { ( 7u16, pallet_referenda::TrackInfo { - name: "masters", + name: track_name("masters"), max_deciding: 10, decision_deposit: 1 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -208,7 +224,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { ( 8u16, pallet_referenda::TrackInfo { - name: "senior masters", + name: track_name("senior masters"), max_deciding: 10, decision_deposit: 1 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -230,7 +246,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { ( 9u16, pallet_referenda::TrackInfo { - name: "grand masters", + name: track_name("grand masters"), max_deciding: 10, decision_deposit: 1 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -250,7 +266,12 @@ impl pallet_referenda::TracksInfo for TracksInfo { }, ), ]; - &DATA[..] + DATA.iter().map(|(id, info)| { + Cow::Owned(pallet_referenda::Track { + id: *id, + info: info.clone(), + }) + }) } fn track_for(id: &Self::RuntimeOrigin) -> Result { @@ -281,7 +302,6 @@ impl pallet_referenda::TracksInfo for TracksInfo { } } } -pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); pub type FellowshipReferendaInstance = pallet_referenda::Instance2; @@ -304,6 +324,7 @@ impl pallet_referenda::Config for Runtime { type AlarmInterval = AlarmInterval; type Tracks = TracksInfo; type Preimages = Preimage; + type BlockNumberProvider = System; } pub type FellowshipCollectiveInstance = pallet_ranked_collective::Instance1; diff --git a/vara/runtime/vara/src/governance/mod.rs b/vara/runtime/vara/src/governance/mod.rs index 042f4b506f7..647022eb95b 100644 --- a/vara/runtime/vara/src/governance/mod.rs +++ b/vara/runtime/vara/src/governance/mod.rs @@ -34,6 +34,8 @@ impl pallet_conviction_voting::Config for Runtime { type MaxTurnout = frame_support::traits::tokens::currency::ActiveIssuanceOf; type Polls = Referenda; + type BlockNumberProvider = System; + type VotingHooks = (); } parameter_types! { @@ -77,4 +79,5 @@ impl pallet_referenda::Config for Runtime { type AlarmInterval = AlarmInterval; type Tracks = TracksInfo; type Preimages = Preimage; + type BlockNumberProvider = System; } diff --git a/vara/runtime/vara/src/governance/origins.rs b/vara/runtime/vara/src/governance/origins.rs index 276e98ddb97..f83439da89d 100644 --- a/vara/runtime/vara/src/governance/origins.rs +++ b/vara/runtime/vara/src/governance/origins.rs @@ -19,7 +19,9 @@ pub mod pallet_custom_origins { #[pallet::pallet] pub struct Pallet(_); - #[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug)] + #[derive( + PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug, + )] #[pallet::origin] pub enum Origin { /// Origin for cancelling slashes and managing election provider. diff --git a/vara/runtime/vara/src/governance/tracks.rs b/vara/runtime/vara/src/governance/tracks.rs index 977aa7cb6a3..d1730f05bb9 100644 --- a/vara/runtime/vara/src/governance/tracks.rs +++ b/vara/runtime/vara/src/governance/tracks.rs @@ -6,11 +6,25 @@ #![allow(clippy::identity_op)] use super::*; +use sp_std::borrow::Cow; const fn percent(x: i32) -> sp_runtime::FixedI64 { sp_runtime::FixedI64::from_rational(x as u128, 100) } +const MAX_TRACK_NAME_LEN: usize = 25; + +const fn track_name(name: &str) -> [u8; MAX_TRACK_NAME_LEN] { + let bytes = name.as_bytes(); + let mut out = [0; MAX_TRACK_NAME_LEN]; + let mut i = 0; + while i < bytes.len() { + out[i] = bytes[i]; + i += 1; + } + out +} + use pallet_referenda::Curve; const APP_ROOT: Curve = Curve::make_reciprocal(4, 28, percent(80), percent(50), percent(100)); @@ -69,7 +83,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 0, pallet_referenda::TrackInfo { - name: "root", + name: track_name("root"), max_deciding: 1, decision_deposit: 100_000 * ECONOMIC_UNITS, prepare_period: 2 * HOURS, @@ -83,7 +97,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 1, pallet_referenda::TrackInfo { - name: "whitelisted_caller", + name: track_name("whitelisted_caller"), max_deciding: 100, decision_deposit: 10_000 * ECONOMIC_UNITS, prepare_period: 30 * MINUTES, @@ -97,7 +111,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 10, pallet_referenda::TrackInfo { - name: "staking_admin", + name: track_name("staking_admin"), max_deciding: 10, decision_deposit: 5_000 * ECONOMIC_UNITS, prepare_period: 2 * HOURS, @@ -111,7 +125,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 11, pallet_referenda::TrackInfo { - name: "treasurer", + name: track_name("treasurer"), max_deciding: 10, decision_deposit: 1_000 * ECONOMIC_UNITS, prepare_period: 2 * HOURS, @@ -125,7 +139,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 12, pallet_referenda::TrackInfo { - name: "fellowship_admin", + name: track_name("fellowship_admin"), max_deciding: 10, decision_deposit: 5_000 * ECONOMIC_UNITS, prepare_period: 2 * HOURS, @@ -139,7 +153,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 13, pallet_referenda::TrackInfo { - name: "general_admin", + name: track_name("general_admin"), max_deciding: 10, decision_deposit: 5_000 * ECONOMIC_UNITS, prepare_period: 2 * HOURS, @@ -153,7 +167,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 20, pallet_referenda::TrackInfo { - name: "referendum_canceller", + name: track_name("referendum_canceller"), max_deciding: 1_000, decision_deposit: 10_000 * ECONOMIC_UNITS, prepare_period: 2 * HOURS, @@ -167,7 +181,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 21, pallet_referenda::TrackInfo { - name: "referendum_killer", + name: track_name("referendum_killer"), max_deciding: 1_000, decision_deposit: 50_000 * ECONOMIC_UNITS, prepare_period: 2 * HOURS, @@ -181,7 +195,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 30, pallet_referenda::TrackInfo { - name: "small_tipper", + name: track_name("small_tipper"), max_deciding: 200, decision_deposit: ECONOMIC_UNITS, prepare_period: MINUTES, @@ -195,7 +209,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 31, pallet_referenda::TrackInfo { - name: "big_tipper", + name: track_name("big_tipper"), max_deciding: 100, decision_deposit: 10 * ECONOMIC_UNITS, prepare_period: 10 * MINUTES, @@ -209,7 +223,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 32, pallet_referenda::TrackInfo { - name: "small_spender", + name: track_name("small_spender"), max_deciding: 50, decision_deposit: 100 * ECONOMIC_UNITS, prepare_period: 4 * HOURS, @@ -223,7 +237,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 33, pallet_referenda::TrackInfo { - name: "medium_spender", + name: track_name("medium_spender"), max_deciding: 50, decision_deposit: 200 * ECONOMIC_UNITS, prepare_period: 4 * HOURS, @@ -237,7 +251,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 34, pallet_referenda::TrackInfo { - name: "big_spender", + name: track_name("big_spender"), max_deciding: 50, decision_deposit: 400 * ECONOMIC_UNITS, prepare_period: 4 * HOURS, @@ -251,7 +265,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 40, pallet_referenda::TrackInfo { - name: "bridge_admin", + name: track_name("bridge_admin"), max_deciding: 3, decision_deposit: 100_000 * ECONOMIC_UNITS, prepare_period: 4 * HOURS, @@ -265,7 +279,7 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 ( 41, pallet_referenda::TrackInfo { - name: "bridge_pauser", + name: track_name("bridge_pauser"), max_deciding: 5, decision_deposit: 25_000 * ECONOMIC_UNITS, prepare_period: 3 * MINUTES, @@ -283,8 +297,15 @@ pub struct TracksInfo; impl pallet_referenda::TracksInfo for TracksInfo { type Id = u16; type RuntimeOrigin = ::PalletsOrigin; - fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { - &TRACKS_DATA[..] + fn tracks() + -> impl Iterator>> + { + TRACKS_DATA.iter().map(|(id, info)| { + Cow::Owned(pallet_referenda::Track { + id: *id, + info: info.clone(), + }) + }) } fn track_for(id: &Self::RuntimeOrigin) -> Result { if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { @@ -327,4 +348,3 @@ impl pallet_referenda::TracksInfo for TracksInfo { } } } -pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); diff --git a/vara/runtime/vara/src/lib.rs b/vara/runtime/vara/src/lib.rs index 8b44903bd34..71996ffa4f0 100644 --- a/vara/runtime/vara/src/lib.rs +++ b/vara/runtime/vara/src/lib.rs @@ -12,6 +12,8 @@ #[macro_use] extern crate frame_benchmarking; +extern crate alloc; + // Make the WASM binary available. #[cfg(all(feature = "std", not(fuzz)))] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); @@ -41,18 +43,19 @@ use pallet_grandpa::{ use pallet_identity::legacy::IdentityInfo; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_session::historical as pallet_session_historical; -use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; use runtime_primitives::{Balance, BlockNumber, Hash, Moment, Nonce}; use scale_info::TypeInfo; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_core::{ConstU8, ConstU64, H256, OpaqueMetadata, crypto::KeyTypeId, ed25519}; use sp_runtime::{ - ApplyExtrinsicResult, FixedU128, Perbill, Percent, Permill, Perquintill, RuntimeDebug, - create_runtime_str, generic, impl_opaque_keys, + ApplyExtrinsicResult, FixedU128, Perbill, Percent, Permill, Perquintill, create_runtime_str, + generic, impl_opaque_keys, traits::{ AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, - DispatchInfoOf, Dispatchable, IdentityLookup, NumberFor, One, SignedExtension, + DispatchInfoOf, Dispatchable, IdentityLookup, Implication, NumberFor, One, + TransactionExtension, }, transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity}, }; @@ -80,12 +83,12 @@ pub use frame_support::{ genesis_builder_helper::{build_state, get_preset}, parameter_types, traits::{ - ConstU16, ConstU32, ConstU128, Contains, Currency, EitherOf, EitherOfDiverse, - EqualPrivilegeOnly, Everything, FindAuthor, InstanceFilter, KeyOwnerProofSystem, - LinearStoragePrice, LockIdentifier, Nothing, OnUnbalanced, Randomness, SortedMembers, - StorageInfo, VariantCountOf, WithdrawReasons, + ConstBool, ConstU16, ConstU32, ConstU128, Contains, Currency, EitherOf, EitherOfDiverse, + EqualPrivilegeOnly, Everything, ExistenceRequirement, FindAuthor, Imbalance, + InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, Nothing, + OnUnbalanced, Randomness, SortedMembers, StorageInfo, VariantCountOf, WithdrawReasons, fungible::HoldConsideration, - tokens::{PayFromAccount, UnityAssetBalanceConversion}, + tokens::{PayFromAccount, UnityAssetBalanceConversion, imbalance::ResolveTo}, }, weights::{ Weight, @@ -163,7 +166,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { apis: RUNTIME_API_VERSIONS, authoring_version: 1, impl_version: 1, - state_version: 1, + system_version: 1, transaction_version: 1, }; @@ -179,7 +182,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { apis: RUNTIME_API_VERSIONS, authoring_version: 1, impl_version: 1, - state_version: 1, + system_version: 1, transaction_version: 1, }; @@ -263,6 +266,8 @@ impl frame_system::Config for Runtime { type SS58Prefix = SS58Prefix; /// The set code logic, just the default since we're not a parachain. type OnSetCode = (); + type MultiBlockMigrator = MultiBlockMigrations; + type SingleBlockMigrations = migrations::Migrations; type MaxConsumers = ConstU32<16>; } @@ -336,6 +341,7 @@ impl pallet_scheduler::Config for Runtime { type WeightInfo = pallet_scheduler::weights::SubstrateWeight; type OriginPrivilegeCmp = EqualPrivilegeOnly; type Preimages = Preimage; + type BlockNumberProvider = System; } parameter_types! { @@ -378,6 +384,7 @@ impl pallet_balances::Config for Runtime { type WeightInfo = weights::pallet_balances::SubstrateWeight; type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = VariantCountOf; + type DoneSlashHandler = (); } parameter_types! { @@ -396,6 +403,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = ConstantMultiplier>; type LengthToFee = ConstantMultiplier>; type FeeMultiplierUpdate = pallet_gear_payment::GearFeeMultiplier; + type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight; } // **IMPORTANT**: update this value with care, GearEthBridge is sensitive to this. @@ -473,17 +481,21 @@ pub type VaraSessionHandler = ( impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = ::AccountId; - type ValidatorIdOf = pallet_staking::StashOf; + type ValidatorIdOf = sp_runtime::traits::ConvertInto; type ShouldEndSession = Babe; type NextSessionRotation = Babe; // **IMPORTANT**: update this value with care, GearEthBridge is sensitive to this. type SessionManager = pallet_session_historical::NoteHistoricalRoot; type SessionHandler = VaraSessionHandler; type Keys = SessionKeys; + type DisablingStrategy = pallet_session::disabling::UpToLimitWithReEnablingDisablingStrategy; type WeightInfo = pallet_session::weights::SubstrateWeight; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session_historical::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type FullIdentification = pallet_staking::Exposure; type FullIdentificationOf = pallet_staking::ExposureOf; } @@ -607,14 +619,16 @@ parameter_types! { pub struct OnChainSeqPhragmen; impl onchain::Config for OnChainSeqPhragmen { + type Sort = ConstBool; type System = Runtime; type Solver = SequentialPhragmen< AccountId, pallet_election_provider_multi_phase::SolutionAccuracyOf, >; + type MaxBackersPerWinner = MaxElectingVoters; + type MaxWinnersPerPage = MaxActiveValidators; type DataProvider = ::DataProvider; type WeightInfo = frame_election_provider_support::weights::SubstrateWeight; - type MaxWinners = ::MaxWinners; type Bounds = ElectionBounds; } @@ -626,6 +640,7 @@ impl pallet_election_provider_multi_phase::MinerConfig for Runtime { type MaxVotesPerVoter = <::DataProvider as ElectionDataProvider>::MaxVotesPerVoter; type MaxWinners = MaxActiveValidators; + type MaxBackersPerWinner = MaxElectingVoters; // The unsigned submissions have to respect the weight of the submit_unsigned call, thus their // weight estimate function is wired to this call's weight. @@ -648,6 +663,33 @@ impl pallet_election_provider_multi_phase::BenchmarkingConfig for ElectionProvid const MAXIMUM_TARGETS: u32 = 300; } +type ElectionRewardImbalance = >::PositiveImbalance; + +pub struct ElectionRewardHandler; +impl OnUnbalanced for ElectionRewardHandler { + fn on_nonzero_unbalanced(minted: ElectionRewardImbalance) { + let amount = minted.peek(); + + if >::settle( + &StakingRewards::account_id(), + minted, + WithdrawReasons::TRANSFER, + ExistenceRequirement::KeepAlive, + ) + .is_ok() + { + System::deposit_event(RuntimeEvent::StakingRewards( + pallet_gear_staking_rewards::Event::Burned { amount }, + )); + } else { + log::warn!( + "Staking rewards pool has insufficient balance to burn election rewards. \ + The currency total supply may grow." + ); + }; + } +} + impl pallet_election_provider_multi_phase::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; @@ -667,13 +709,14 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type SignedDepositWeight = (); type SignedMaxWeight = MinerMaxWeight; type SlashHandler = Treasury; - type RewardHandler = StakingRewards; + type RewardHandler = ElectionRewardHandler; type DataProvider = Staking; type Fallback = onchain::OnChainExecution; type GovernanceFallback = onchain::OnChainExecution; type Solver = SequentialPhragmen, ()>; type ForceOrigin = AdminOrigin; type MaxWinners = MaxActiveValidators; + type MaxBackersPerWinner = MaxElectingVoters; type ElectionBounds = ElectionBounds; type BenchmarkingConfig = ElectionProviderBenchmarkConfig; type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight; @@ -708,17 +751,17 @@ impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig { } impl pallet_staking::Config for Runtime { + type OldCurrency = Balances; type Currency = Balances; type CurrencyBalance = Balance; + type RuntimeHoldReason = RuntimeHoldReason; type UnixTime = Timestamp; type CurrencyToVote = sp_staking::currency_to_vote::U128CurrencyToVote; type ElectionProvider = ElectionProviderMultiPhase; type GenesisElectionProvider = onchain::OnChainExecution; - // Burning the reward remainder for now. - // TODO: set remainder back to `RewardProxy` to stop burning `Treasury` part. type RewardRemainder = (); type RuntimeEvent = RuntimeEvent; - type Slash = Treasury; + type Slash = ResolveTo; type Reward = StakingRewards; type SessionsPerEra = SessionsPerEra; type BondingDuration = BondingDuration; @@ -728,6 +771,7 @@ impl pallet_staking::Config for Runtime { type EraPayout = StakingRewards; type NextNewSession = Session; type MaxExposurePageSize = MaxExposurePageSize; + type MaxValidatorSet = MaxActiveValidators; type VoterList = BagsList; type TargetList = pallet_staking::UseValidatorsMap; type NominationsQuota = pallet_staking::FixedNominationsQuota<{ MaxNominations::get() }>; @@ -735,9 +779,9 @@ impl pallet_staking::Config for Runtime { type MaxControllersInDeprecationBatch = MaxControllersInDeprecationBatch; type HistoryDepth = HistoryDepth; type EventListeners = NominationPools; + type Filter = Nothing; type WeightInfo = pallet_staking::weights::SubstrateWeight; type BenchmarkingConfig = StakingBenchmarkingConfig; - type DisablingStrategy = pallet_staking::UpToLimitDisablingStrategy; } parameter_types! { @@ -750,6 +794,7 @@ impl pallet_bags_list::Config for Runtime { type BagThresholds = BagThresholds; type Score = VoteWeight; type WeightInfo = pallet_bags_list::weights::SubstrateWeight; + type MaxAutoRebagPerBlock = ConstU32<10>; } parameter_types! { @@ -787,6 +832,8 @@ impl pallet_nomination_pools::Config for Runtime { type PalletId = NominationPoolsPalletId; type MaxPointsToBalance = MaxPointsToBalance; type AdminOrigin = EnsureRoot; + type BlockNumberProvider = System; + type Filter = Everything; } impl pallet_offences::Config for Runtime { @@ -830,6 +877,7 @@ impl pallet_treasury::Config for Runtime { type Paymaster = PayFromAccount; type BalanceConverter = UnityAssetBalanceConversion; type PayoutPeriod = PayoutSpendPeriod; + type BlockNumberProvider = System; } parameter_types! { @@ -857,6 +905,7 @@ impl pallet_bounties::Config for Runtime { type WeightInfo = pallet_bounties::weights::SubstrateWeight; type ChildBountyManager = ChildBounties; type OnSlash = Treasury; + type TransferAllAssets = (); } parameter_types! { @@ -898,6 +947,7 @@ impl pallet_authority_discovery::Config for Runtime { parameter_types! { pub const BasicDeposit: Balance = 10 * ECONOMIC_UNITS; // 258 bytes on-chain pub const ByteDeposit: Balance = deposit(0, 1); + pub const UsernameDeposit: Balance = deposit(0, 32); pub const SubAccountDeposit: Balance = 2 * ECONOMIC_UNITS; // 53 bytes on-chain pub const MaxSubAccounts: u32 = 100; pub const MaxAdditionalFields: u32 = 100; @@ -909,6 +959,7 @@ impl pallet_identity::Config for Runtime { type Currency = Balances; type BasicDeposit = BasicDeposit; type ByteDeposit = ByteDeposit; + type UsernameDeposit = UsernameDeposit; type SubAccountDeposit = SubAccountDeposit; type MaxSubAccounts = MaxSubAccounts; type IdentityInformation = IdentityInfo; @@ -920,11 +971,30 @@ impl pallet_identity::Config for Runtime { type SigningPublicKey = ::Signer; type UsernameAuthorityOrigin = EnsureRoot; type PendingUsernameExpiration = ConstU32<{ 7 * DAYS }>; + type UsernameGracePeriod = ConstU32<{ 30 * DAYS }>; type MaxSuffixLength = ConstU32<7>; type MaxUsernameLength = ConstU32<32>; type WeightInfo = pallet_identity::weights::SubstrateWeight; } +parameter_types! { + pub MbmServiceWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_migrations::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + #[cfg(not(feature = "runtime-benchmarks"))] + type Migrations = pallet_identity::migration::v2::LazyMigrationV1ToV2; + #[cfg(feature = "runtime-benchmarks")] + type Migrations = pallet_migrations::mock_helpers::MockedMigrations; + type CursorMaxLen = ConstU32<65_536>; + type IdentifierMaxLen = ConstU32<256>; + type MigrationStatusHandler = (); + type FailedMigrationHandler = frame_support::migrations::FreezeChainOnFailedMigration; + type MaxServiceWeight = MbmServiceWeight; + type WeightInfo = (); +} + #[cfg(feature = "dev")] impl pallet_sudo::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -954,6 +1024,7 @@ impl pallet_multisig::Config for Runtime { type DepositFactor = DepositFactor; type MaxSignatories = ConstU32<100>; type WeightInfo = pallet_multisig::weights::SubstrateWeight; + type BlockNumberProvider = System; } parameter_types! { @@ -976,7 +1047,8 @@ parameter_types! { PartialOrd, Encode, Decode, - RuntimeDebug, + DecodeWithMemTracking, + Debug, MaxEncodedLen, scale_info::TypeInfo, )] @@ -1072,6 +1144,7 @@ impl pallet_proxy::Config for Runtime { type CallHasher = BlakeTwo256; type AnnouncementDepositBase = AnnouncementDepositBase; type AnnouncementDepositFactor = AnnouncementDepositFactor; + type BlockNumberProvider = System; } impl pallet_gear_program::Config for Runtime { @@ -1304,12 +1377,21 @@ impl pallet_gear_voucher::Config for Runtime { type MinDuration = MinVoucherDuration; } -impl frame_system::offchain::SendTransactionTypes for Runtime +impl frame_system::offchain::CreateBare for Runtime +where + RuntimeCall: From, +{ + fn create_bare(call: RuntimeCall) -> UncheckedExtrinsic { + generic::UncheckedExtrinsic::new_bare(call).into() + } +} + +impl frame_system::offchain::CreateTransactionBase for Runtime where RuntimeCall: From, { type Extrinsic = UncheckedExtrinsic; - type OverarchingCall = RuntimeCall; + type RuntimeCall = RuntimeCall; } parameter_types! { @@ -1445,6 +1527,9 @@ mod runtime { #[runtime::pallet_index(31)] pub type NominationPools = pallet_nomination_pools; + #[runtime::pallet_index(32)] + pub type MultiBlockMigrations = pallet_migrations; + // Gear // NOTE (!): if adding new pallet, don't forget to extend non payable proxy filter. @@ -1606,6 +1691,9 @@ mod runtime { #[runtime::pallet_index(31)] pub type NominationPools = pallet_nomination_pools; + #[runtime::pallet_index(32)] + pub type MultiBlockMigrations = pallet_migrations; + // Gear #[runtime::pallet_index(100)] @@ -1818,6 +1906,10 @@ impl_runtime_apis_plus_common! { fn pool_balance(pool_id: pallet_nomination_pools::PoolId) -> Balance { NominationPools::api_pool_balance(pool_id) } + + fn pool_accounts(pool_id: pallet_nomination_pools::PoolId) -> (AccountId, AccountId) { + NominationPools::api_pool_accounts(pool_id) + } } impl pallet_staking_runtime_api::StakingApi for Runtime { @@ -1848,7 +1940,7 @@ impl_runtime_apis_plus_common! { impl pallet_gear_eth_bridge_rpc_runtime_api::GearEthBridgeApi for Runtime { fn merkle_proof(hash: H256) -> Option { - GearEthBridge::merkle_proof(hash) + GearEthBridge::merkle_proof(hash.into()) } } @@ -1973,7 +2065,7 @@ where /// NOTE: Copy-paste from substrate/frame/system/src/extensions/check_nonce.rs, /// but without providers and sufficients checks, so contains revert of changes /// from substrate v1.3.0 . -#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] +#[derive(Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct CustomCheckNonce(#[codec(compact)] pub T::Nonce); @@ -1996,28 +2088,72 @@ impl sp_std::fmt::Debug for CustomCheckNonce { } } -impl SignedExtension for CustomCheckNonce +impl TransactionExtension for CustomCheckNonce where - T::RuntimeCall: Dispatchable, + T: frame_system::Config + Send + Sync, + T::RuntimeOrigin: Clone, + T::RuntimeCall: Dispatchable, { - type AccountId = as SignedExtension>::AccountId; - type Call = as SignedExtension>::Call; - type AdditionalSigned = as SignedExtension>::AdditionalSigned; - type Pre = as SignedExtension>::Pre; - const IDENTIFIER: &'static str = as SignedExtension>::IDENTIFIER; + const IDENTIFIER: &'static str = "CheckNonce"; + type Implicit = (); + type Val = Option; + type Pre = (); - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { - Ok(()) + fn weight(&self, _: &T::RuntimeCall) -> Weight { + ::check_nonce() } - fn pre_dispatch( + fn validate( + &self, + origin: T::RuntimeOrigin, + _call: &T::RuntimeCall, + _info: &DispatchInfoOf, + _len: usize, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Implication, + _source: TransactionSource, + ) -> Result<(ValidTransaction, Self::Val, T::RuntimeOrigin), TransactionValidityError> { + let Ok(who) = frame_system::ensure_signed(origin.clone()) else { + return Ok((Default::default(), None, origin)); + }; + let account = frame_system::Account::::get(&who); + + if self.0 < account.nonce { + return Err(InvalidTransaction::Stale.into()); + } + + let provides = vec![Encode::encode(&(who.clone(), self.0))]; + let requires = if account.nonce < self.0 { + vec![Encode::encode(&(who.clone(), self.0 - One::one()))] + } else { + vec![] + }; + + Ok(( + ValidTransaction { + priority: 0, + requires, + provides, + longevity: TransactionLongevity::max_value(), + propagate: true, + }, + Some(who), + origin, + )) + } + + fn prepare( self, - who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, + val: Self::Val, + _origin: &T::RuntimeOrigin, + _call: &T::RuntimeCall, + _info: &DispatchInfoOf, _len: usize, - ) -> Result<(), TransactionValidityError> { - let mut account = frame_system::Account::::get(who); + ) -> Result { + let Some(who) = val else { + return Ok(()); + }; + let mut account = frame_system::Account::::get(&who); if self.0 != account.nonce { return Err(if self.0 < account.nonce { @@ -2028,36 +2164,7 @@ where .into()); } account.nonce += T::Nonce::one(); - frame_system::Account::::insert(who, account); + frame_system::Account::::insert(&who, account); Ok(()) } - - fn validate( - &self, - who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> TransactionValidity { - let account = frame_system::Account::::get(who); - - if self.0 < account.nonce { - return InvalidTransaction::Stale.into(); - } - - let provides = vec![Encode::encode(&(who, self.0))]; - let requires = if account.nonce < self.0 { - vec![Encode::encode(&(who, self.0 - One::one()))] - } else { - vec![] - }; - - Ok(ValidTransaction { - priority: 0, - requires, - provides, - longevity: TransactionLongevity::max_value(), - propagate: true, - }) - } } diff --git a/vara/runtime/vara/src/migrations.rs b/vara/runtime/vara/src/migrations.rs index 0c9bd640c13..75455e4d002 100644 --- a/vara/runtime/vara/src/migrations.rs +++ b/vara/runtime/vara/src/migrations.rs @@ -2,6 +2,13 @@ // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 use crate::Runtime; +use frame_support::{parameter_types, weights::Weight}; + +parameter_types! { + pub ChildBountiesMigrationTransferWeight: Weight = + <::WeightInfo as pallet_balances::WeightInfo>::transfer_allow_death() + .saturating_add(::DbWeight::get().reads(1)); +} /// All migrations that will run on the next runtime upgrade for dev chain. #[cfg(feature = "dev")] @@ -9,15 +16,17 @@ pub type Migrations = ( pallet_gear_eth_bridge::migrations::set_hash::Migration, // migrate to v3 of the Gear Scheduler with removal of program pause tasks pallet_gear_scheduler::migrations::v3_remove_program_pause_tasks::MigrateRemoveProgramPauseTasks, + pallet_child_bounties::migration::MigrateV0ToV1, ); /// All migrations that will run on the next runtime upgrade for prod chain. #[cfg(not(feature = "dev"))] pub type Migrations = ( pallet_gear_eth_bridge::migrations::set_hash::Migration, - LockEdForBuiltin, - // migrate to v3 of the Gear Scheduler with removal of program pause tasks + LockEdForBuiltin, + // migrate to v3 of the Gear Scheduler with removal of program pause tasks pallet_gear_scheduler::migrations::v3_remove_program_pause_tasks::MigrateRemoveProgramPauseTasks, + pallet_child_bounties::migration::MigrateV0ToV1, ); /// This migration is used to top up the ED for the builtin actor from the treasury, diff --git a/vara/runtime/vara/src/weights/pallet_utility.rs b/vara/runtime/vara/src/weights/pallet_utility.rs index 191c1f393cd..a3d378f89df 100644 --- a/vara/runtime/vara/src/weights/pallet_utility.rs +++ b/vara/runtime/vara/src/weights/pallet_utility.rs @@ -27,6 +27,8 @@ pub trait WeightInfo { fn as_derivative() -> Weight; fn batch_all(c: u32, ) -> Weight; fn dispatch_as() -> Weight; + fn dispatch_as_fallible() -> Weight; + fn if_else() -> Weight; fn force_batch(c: u32, ) -> Weight; } @@ -67,6 +69,12 @@ impl pallet_utility::WeightInfo for SubstrateWeight // Minimum execution time: 4_703_000 picoseconds. Weight::from_parts(5_092_000, 0) } + fn dispatch_as_fallible() -> Weight { + Self::dispatch_as() + } + fn if_else() -> Weight { + Self::dispatch_as() + } /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { // Proof Size summary in bytes: @@ -115,6 +123,12 @@ impl WeightInfo for () { // Minimum execution time: 4_703_000 picoseconds. Weight::from_parts(5_092_000, 0) } + fn dispatch_as_fallible() -> Weight { + Self::dispatch_as() + } + fn if_else() -> Weight { + Self::dispatch_as() + } /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { // Proof Size summary in bytes: diff --git a/vara/sdk/builtins/common/src/eth_bridge.rs b/vara/sdk/builtins/common/src/eth_bridge.rs index 1ea9891cff7..ff384ebe08e 100644 --- a/vara/sdk/builtins/common/src/eth_bridge.rs +++ b/vara/sdk/builtins/common/src/eth_bridge.rs @@ -14,8 +14,7 @@ pub fn bridge_call_hash( payload: &[u8], hashing_fn: impl Fn(&[u8]) -> H256, ) -> H256 { - let mut nonce_bytes = [0; 32]; - nonce.to_big_endian(&mut nonce_bytes); + let nonce_bytes = nonce.to_big_endian(); let bytes = [ nonce_bytes.as_ref(), From 71071ae76ad5e39f57833779b598886c8941a710 Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Tue, 9 Jun 2026 21:17:23 +0400 Subject: [PATCH 02/13] Fix stable2603 review findings --- .config/hakari.toml | 14 ++ Cargo.lock | 15 +- utils/gear-workspace-hack/Cargo.toml | 28 --- vara/common/src/pallet_tests.rs | 7 +- vara/node/authorship/Cargo.toml | 1 + vara/node/authorship/src/authorship.rs | 20 +- vara/node/authorship/src/block_builder.rs | 51 ++++- vara/node/authorship/src/tests.rs | 234 +++++++++++++++------ vara/node/testing/src/genesis.rs | 9 +- vara/node/testing/src/keyring.rs | 43 ++-- vara/pallets/payment/src/mock.rs | 9 +- vara/pallets/payment/src/tests.rs | 244 ++++++++++++---------- vara/pallets/staking-rewards/src/mock.rs | 113 +++++++--- vara/pallets/staking-rewards/src/tests.rs | 175 +++++++--------- 14 files changed, 573 insertions(+), 390 deletions(-) diff --git a/.config/hakari.toml b/.config/hakari.toml index 262b65033f2..f26444feeba 100644 --- a/.config/hakari.toml +++ b/.config/hakari.toml @@ -43,25 +43,32 @@ workspace-members = [ third-party = [ # we have to exclude these deps because of their `try-runtime` and `runtime-benchmarks` features, # because we cannot, for example, run `cargo build --package gear-cli` without `--all-features` flag + { name = "cumulus-pallet-parachain-system", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "cumulus-primitives-core", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "frame-benchmarking", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "frame-benchmarking-cli", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "frame-election-provider-support", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "frame-executive", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "frame-storage-access-test-runtime", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "frame-support", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "frame-system", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "frame-try-runtime", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-asset-conversion", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-authority-discovery", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-authorship", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-babe", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-bags-list", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-balances", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-bounties", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-broker", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-child-bounties", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-conviction-voting", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-election-provider-multi-phase", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-grandpa", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-identity", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-im-online", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-message-queue", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "pallet-migrations", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-multisig", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-nomination-pools", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-offences", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, @@ -79,9 +86,16 @@ third-party = [ { name = "pallet-utility", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-vesting", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "pallet-whitelist", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "polkadot-parachain-primitives", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "polkadot-primitives", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "polkadot-runtime-parachains", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "polkadot-sdk-frame", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "sc-cli", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "sc-client-db", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "sc-service", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "sp-runtime", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, { name = "sp-staking", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, + { name = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" }, ] diff --git a/Cargo.lock b/Cargo.lock index 54a327ce122..632b9a2c47d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6921,6 +6921,7 @@ dependencies = [ "sp-consensus", "sp-consensus-babe", "sp-core", + "sp-externalities", "sp-inherents", "sp-runtime", "sp-state-machine", @@ -7707,8 +7708,6 @@ dependencies = [ "crossbeam-utils", "crunchy", "crypto-common", - "cumulus-pallet-parachain-system", - "cumulus-primitives-core", "curve25519-dalek", "data-encoding", "der", @@ -7738,7 +7737,6 @@ dependencies = [ "frame-executive", "frame-metadata 23.0.1", "frame-metadata-hash-extension", - "frame-storage-access-test-runtime", "frame-support", "frame-support-procedural", "frame-system-rpc-runtime-api", @@ -7815,22 +7813,18 @@ dependencies = [ "num-traits", "numerated", "once_cell", - "pallet-asset-conversion", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-bounties", - "pallet-broker", "pallet-child-bounties", "pallet-conviction-voting", "pallet-election-provider-multi-phase", "pallet-grandpa", "pallet-identity", "pallet-im-online", - "pallet-message-queue", - "pallet-migrations", "pallet-multisig", "pallet-nomination-pools", "pallet-nomination-pools-runtime-api", @@ -7858,10 +7852,6 @@ dependencies = [ "percent-encoding", "petgraph 0.6.5", "pkcs8", - "polkadot-parachain-primitives", - "polkadot-primitives", - "polkadot-runtime-parachains", - "polkadot-sdk-frame", "polkavm-common 0.9.0", "portable-atomic", "ppv-lite86", @@ -7960,9 +7950,6 @@ dependencies = [ "spki", "ss58-registry", "stable_deref_trait", - "staging-xcm", - "staging-xcm-builder", - "staging-xcm-executor", "strum 0.24.1", "strum 0.26.3", "strum 0.27.2", diff --git a/utils/gear-workspace-hack/Cargo.toml b/utils/gear-workspace-hack/Cargo.toml index 260c09dcc70..4aaa2721130 100644 --- a/utils/gear-workspace-hack/Cargo.toml +++ b/utils/gear-workspace-hack/Cargo.toml @@ -269,8 +269,6 @@ crossbeam-queue = { version = "0.3" } crossbeam-utils = { version = "0.8" } crunchy = { version = "0.2", features = ["std"] } crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -cumulus-primitives-core = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } curve25519-dalek = { version = "4", features = ["digest", "legacy_compatibility"] } data-encoding = { version = "2" } der = { version = "0.7", default-features = false, features = ["oid", "std", "zeroize"] } @@ -294,7 +292,6 @@ foldhash-c65f7effa3be6d31 = { package = "foldhash", version = "0.1", default-fea form_urlencoded = { version = "1" } frame-metadata = { version = "23", default-features = false, features = ["std", "unstable"] } frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } -frame-storage-access-test-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } futures = { version = "0.3", features = ["bilock", "thread-pool", "unstable"] } futures-channel = { version = "0.3", features = ["sink", "unstable"] } @@ -357,10 +354,6 @@ num-rational = { version = "0.4", features = ["num-bigint-std"] } num-traits = { version = "0.2", features = ["i128", "libm"] } numerated = { version = "2", default-features = false, features = ["mock"] } once_cell = { version = "1", features = ["critical-section"] } -pallet-asset-conversion = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -pallet-broker = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -pallet-migrations = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std", "try-runtime"] } pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } pallet-staking-reward-fn = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } pallet-staking-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } @@ -370,10 +363,6 @@ parity-wasm = { git = "https://github.com/gear-tech/parity-wasm", branch = "v0.4 pbkdf2 = { version = "0.12", features = ["std"] } percent-encoding = { version = "2" } pkcs8 = { version = "0.10", default-features = false, features = ["std"] } -polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks", "wasm-api"] } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -polkadot-sdk-frame = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime", "runtime-benchmarks", "std", "try-runtime"] } polkavm-common = { version = "0.9", features = ["alloc", "logging"] } portable-atomic = { version = "1", features = ["require-cas"] } ppv-lite86 = { version = "0.2", default-features = false, features = ["simd", "std"] } @@ -463,9 +452,6 @@ sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3 spki = { version = "0.7", default-features = false, features = ["std"] } ss58-registry = { version = "1", default-features = false, features = ["std"] } stable_deref_trait = { version = "1", default-features = false, features = ["std"] } -staging-xcm = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -staging-xcm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -staging-xcm-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } strum-2f80eeee3b1b6c7e = { package = "strum", version = "0.26", features = ["derive"] } strum-754bda37e0fb3874 = { package = "strum", version = "0.27", default-features = false, features = ["derive", "std"] } strum-adf3d7031871b0af = { package = "strum", version = "0.24", features = ["derive"] } @@ -573,8 +559,6 @@ crossbeam-queue = { version = "0.3" } crossbeam-utils = { version = "0.8" } crunchy = { version = "0.2", features = ["std"] } crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -cumulus-primitives-core = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } curve25519-dalek = { version = "4", features = ["digest", "legacy_compatibility"] } data-encoding = { version = "2" } der = { version = "0.7", default-features = false, features = ["oid", "std", "zeroize"] } @@ -600,7 +584,6 @@ foldhash-c65f7effa3be6d31 = { package = "foldhash", version = "0.1", default-fea form_urlencoded = { version = "1" } frame-metadata = { version = "23", default-features = false, features = ["std", "unstable"] } frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } -frame-storage-access-test-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } frame-support-procedural = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["experimental", "std"] } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } futures = { version = "0.3", features = ["bilock", "thread-pool", "unstable"] } @@ -664,10 +647,6 @@ num-rational = { version = "0.4", features = ["num-bigint-std"] } num-traits = { version = "0.2", features = ["i128", "libm"] } numerated = { version = "2", default-features = false, features = ["mock"] } once_cell = { version = "1", features = ["critical-section"] } -pallet-asset-conversion = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -pallet-broker = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -pallet-migrations = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std", "try-runtime"] } pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } pallet-staking-reward-fn = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } pallet-staking-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["std"] } @@ -679,10 +658,6 @@ pbkdf2 = { version = "0.12", features = ["std"] } percent-encoding = { version = "2" } petgraph = { version = "0.6" } pkcs8 = { version = "0.10", default-features = false, features = ["std"] } -polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks", "wasm-api"] } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", features = ["runtime-benchmarks"] } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -polkadot-sdk-frame = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime", "runtime-benchmarks", "std", "try-runtime"] } polkavm-common = { version = "0.9", features = ["alloc", "logging"] } portable-atomic = { version = "1", features = ["require-cas"] } ppv-lite86 = { version = "0.2", default-features = false, features = ["simd", "std"] } @@ -775,9 +750,6 @@ sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3 spki = { version = "0.7", default-features = false, features = ["std"] } ss58-registry = { version = "1", default-features = false, features = ["std"] } stable_deref_trait = { version = "1", default-features = false, features = ["std"] } -staging-xcm = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -staging-xcm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } -staging-xcm-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0", default-features = false, features = ["runtime-benchmarks", "std"] } strum-2f80eeee3b1b6c7e = { package = "strum", version = "0.26", features = ["derive"] } strum-754bda37e0fb3874 = { package = "strum", version = "0.27", default-features = false, features = ["derive", "std"] } strum-adf3d7031871b0af = { package = "strum", version = "0.24", features = ["derive"] } diff --git a/vara/common/src/pallet_tests.rs b/vara/common/src/pallet_tests.rs index c4fba93ee5d..ede154b7660 100644 --- a/vara/common/src/pallet_tests.rs +++ b/vara/common/src/pallet_tests.rs @@ -39,6 +39,7 @@ macro_rules! impl_pallet_balances_inner { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); + type DoneSlashHandler = (); } }; @@ -111,6 +112,7 @@ macro_rules! impl_pallet_system_inner { type PreInherents = (); type PostInherents = (); type PostTransactions = (); + type ExtensionsWeightInfo = (); } }; @@ -250,8 +252,10 @@ macro_rules! impl_pallet_staking_inner { impl pallet_staking::Config for Test { type Currency = Balances; + type OldCurrency = Balances; type UnixTime = Timestamp; type CurrencyBalance = ::Balance; + type RuntimeHoldReason = RuntimeHoldReason; type CurrencyToVote = (); type ElectionProvider = StakingConfigElectionProvider; type GenesisElectionProvider = StakingConfigGenesisElectionProvider; @@ -267,16 +271,17 @@ macro_rules! impl_pallet_staking_inner { type EraPayout = StakingConfigEraPayout; type NextNewSession = StakingConfigNextNewSession; type MaxExposurePageSize = MaxExposurePageSize; + type MaxValidatorSet = ConstU32<100>; type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; type TargetList = pallet_staking::UseValidatorsMap; type NominationsQuota = pallet_staking::FixedNominationsQuota<16>; type MaxUnlockingChunks = ConstU32<32>; type HistoryDepth = HistoryDepth; type EventListeners = (); + type Filter = frame_support::traits::Nothing; type WeightInfo = (); type BenchmarkingConfig = pallet_staking::TestBenchmarkingConfig; type MaxControllersInDeprecationBatch = MaxControllersInDeprecationBatch; - type DisablingStrategy = pallet_staking::UpToLimitDisablingStrategy; } }; diff --git a/vara/node/authorship/Cargo.toml b/vara/node/authorship/Cargo.toml index 00ac95da502..da801922189 100644 --- a/vara/node/authorship/Cargo.toml +++ b/vara/node/authorship/Cargo.toml @@ -33,6 +33,7 @@ sc-service.workspace = true sp-core = { workspace = true, features = ["std"] } sp-api = { workspace = true, features = ["std"] } sp-consensus.workspace = true +sp-externalities = { workspace = true, features = ["std"] } sp-runtime = { workspace = true, features = ["std"] } sp-blockchain.workspace = true sp-inherents = { workspace = true, features = ["std"] } diff --git a/vara/node/authorship/src/authorship.rs b/vara/node/authorship/src/authorship.rs index a9496b54470..0a7bdf5c99b 100644 --- a/vara/node/authorship/src/authorship.rs +++ b/vara/node/authorship/src/authorship.rs @@ -14,10 +14,11 @@ use parity_scale_codec::Encode; use sc_block_builder::BlockBuilderApi; use sc_telemetry::{CONSENSUS_INFO, TelemetryHandle, telemetry}; use sc_transaction_pool_api::{InPoolTransaction, TransactionPool, TxInvalidityReportMap}; -use sp_api::{ApiExt, ApiRef, CallApiAt, ProvideRuntimeApi}; +use sp_api::{ApiExt, ApiRef, CallApiAt, ProofRecorder, ProvideRuntimeApi}; use sp_blockchain::{ApplyExtrinsicFailed::Validity, Error::ApplyExtrinsicFailed, HeaderBackend}; use sp_consensus::{Proposal, ProposeArgs}; use sp_core::traits::SpawnNamed; +use sp_externalities::Extensions; use sp_inherents::InherentData; use sp_runtime::{ Digest, Percent, SaturatedConversion, @@ -340,11 +341,15 @@ where max_duration, block_size_limit, storage_proof_recorder, - extra_extensions: _, + extra_extensions, } = args; let (tx, rx) = oneshot::channel(); let spawn_handle = self.spawn_handle.clone(); - let record_proof = PR::ENABLED || storage_proof_recorder.is_some(); + let proof_recorder = if PR::ENABLED { + storage_proof_recorder.or_else(|| Some(Default::default())) + } else { + storage_proof_recorder + }; spawn_handle.spawn_blocking( "gear-authorship-proposer", @@ -358,7 +363,8 @@ where inherent_digests, deadline, block_size_limit, - record_proof, + proof_recorder, + extra_extensions, ) .await; if tx.send(res).is_err() { @@ -391,14 +397,16 @@ where inherent_digests: Digest, deadline: Instant, block_size_limit: Option, - record_proof: bool, + proof_recorder: Option>, + extra_extensions: Extensions, ) -> Result, sp_blockchain::Error> { let block_timer = Instant::now(); let mut block_builder = BlockBuilderBuilder::new(self.client.as_ref()) .on_parent_block(self.parent_hash) .with_parent_block_number(self.parent_number) - .with_proof_recording(record_proof) + .with_proof_recorder(proof_recorder) .with_inherent_digests(inherent_digests) + .with_extra_extensions(extra_extensions) .build()?; self.apply_inherents(&mut block_builder, inherent_data)?; diff --git a/vara/node/authorship/src/block_builder.rs b/vara/node/authorship/src/block_builder.rs index b7b6e4f5560..61defba0f07 100644 --- a/vara/node/authorship/src/block_builder.rs +++ b/vara/node/authorship/src/block_builder.rs @@ -4,8 +4,12 @@ use pallet_gear_rpc_runtime_api::GearApi as GearRuntimeApi; use parity_scale_codec::Encode; use sc_block_builder::{BlockBuilderApi, BuiltBlock}; -use sp_api::{ApiExt, ApiRef, CallApiAt, Core, ProvideRuntimeApi, TransactionOutcome}; +use sp_api::{ + ApiExt, ApiRef, CallApiAt, Core, ProofRecorder, ProvideRuntimeApi, TransactionOutcome, +}; use sp_blockchain::{ApplyExtrinsicFailed, Error, HeaderBackend}; +use sp_core::traits::CallContext; +use sp_externalities::Extensions; use sp_runtime::{ Digest, ExtrinsicInclusionMode, legacy, traits::{Block as BlockT, Hash, HashingFor, Header as HeaderT, NumberFor, One}, @@ -74,7 +78,8 @@ where Ok(BlockBuilderBuilderStage2 { call_api_at: self.call_api_at, - enable_proof_recording: false, + proof_recorder: None, + extra_extensions: Default::default(), inherent_digests: Default::default(), parent_block: self.parent_block, parent_number, @@ -91,7 +96,8 @@ where ) -> BlockBuilderBuilderStage2<'a, B, C> { BlockBuilderBuilderStage2 { call_api_at: self.call_api_at, - enable_proof_recording: false, + proof_recorder: None, + extra_extensions: Default::default(), inherent_digests: Default::default(), parent_block: self.parent_block, parent_number, @@ -105,7 +111,8 @@ where /// [`BlockBuilderBuilder::new`] needs to be used. pub struct BlockBuilderBuilderStage2<'a, B: BlockT, C> { call_api_at: &'a C, - enable_proof_recording: bool, + proof_recorder: Option>, + extra_extensions: Extensions, inherent_digests: Digest, parent_block: B::Hash, parent_number: NumberFor, @@ -115,13 +122,23 @@ impl<'a, B: BlockT, C> BlockBuilderBuilderStage2<'a, B, C> { /// Enable proof recording for the block builder. #[allow(unused)] pub fn enable_proof_recording(mut self) -> Self { - self.enable_proof_recording = true; + self.proof_recorder = Some(Default::default()); self } /// Enable/disable proof recording for the block builder. + #[allow(unused)] pub fn with_proof_recording(mut self, enable: bool) -> Self { - self.enable_proof_recording = enable; + self.proof_recorder = enable.then(Default::default); + self + } + + /// Use the provided proof recorder for block production. + pub fn with_proof_recorder( + mut self, + proof_recorder: impl Into>>, + ) -> Self { + self.proof_recorder = proof_recorder.into(); self } @@ -131,6 +148,12 @@ impl<'a, B: BlockT, C> BlockBuilderBuilderStage2<'a, B, C> { self } + /// Set the extra extensions to be registered with the runtime API during block building. + pub fn with_extra_extensions(mut self, extra_extensions: impl Into) -> Self { + self.extra_extensions = extra_extensions.into(); + self + } + /// Create the instance of the [`BlockBuilder`]. pub fn build(self) -> Result, Error> where @@ -141,8 +164,9 @@ impl<'a, B: BlockT, C> BlockBuilderBuilderStage2<'a, B, C> { self.call_api_at, self.parent_block, self.parent_number, - self.enable_proof_recording, + self.proof_recorder, self.inherent_digests, + self.extra_extensions, ) } } @@ -174,8 +198,9 @@ where call_api_at: &'a C, parent_hash: Block::Hash, parent_number: NumberFor, - record_proof: bool, + proof_recorder: Option>, inherent_digests: Digest, + extra_extensions: Extensions, ) -> Result { let header = <::Header as HeaderT>::new( parent_number + One::one(), @@ -189,10 +214,16 @@ where let mut api = call_api_at.runtime_api(); - if record_proof { - api.record_proof(); + if let Some(recorder) = proof_recorder { + api.record_proof_with_recorder(recorder); } + extra_extensions.into_extensions().for_each(|extension| { + api.register_extension(extension); + }); + + api.set_call_context(CallContext::Onchain); + let core_version = api .api_version::>(parent_hash)? .ok_or_else(|| Error::VersionInvalid("Core".to_string()))?; diff --git a/vara/node/authorship/src/tests.rs b/vara/node/authorship/src/tests.rs index 22399fcc03a..c411a23f246 100644 --- a/vara/node/authorship/src/tests.rs +++ b/vara/node/authorship/src/tests.rs @@ -23,15 +23,15 @@ use pallet_gear_rpc_runtime_api::GearApi; use parity_scale_codec::{Decode, Encode}; use parking_lot::Mutex; use runtime_primitives::{Block as TestBlock, BlockNumber}; -use sc_client_api::Backend as _; +use sc_client_api::{Backend as _, TrieCacheContext}; use sc_service::client::Client; -use sc_transaction_pool::{BasicPool, FullPool}; +use sc_transaction_pool::{BasicPool, FullChainApi}; use sc_transaction_pool_api::{ ChainEvent, MaintainedTransactionPool, TransactionPool, TransactionSource, }; use sp_api::{ApiExt, Core, ProvideRuntimeApi}; use sp_blockchain::HeaderBackend; -use sp_consensus::{BlockOrigin, Environment, Proposer}; +use sp_consensus::{BlockOrigin, Environment, ProposeArgs, Proposer}; use sp_consensus_babe::{ BABE_ENGINE_ID, Slot, digests::{PreDigest, SecondaryPlainPreDigest}, @@ -39,16 +39,20 @@ use sp_consensus_babe::{ use sp_inherents::InherentDataProvider; use sp_runtime::{ Digest, DigestItem, OpaqueExtrinsic, Perbill, Percent, - generic::BlockId, + generic::{BlockId, ExtrinsicFormat}, traits::{Block as BlockT, Header as HeaderT, NumberFor}, }; use sp_state_machine::Backend; use sp_timestamp::Timestamp; use std::{ + any::{Any, TypeId}, env, fs, ops::Deref, path::PathBuf, - sync::{Arc, OnceLock}, + sync::{ + Arc, OnceLock, + atomic::{AtomicUsize, Ordering}, + }, time::{self, SystemTime, UNIX_EPOCH}, }; use testing::{ @@ -62,11 +66,29 @@ use vara_runtime::{ AccountId, Runtime, RuntimeApi as RA, RuntimeCall, SLOT_DURATION, UncheckedExtrinsic, VERSION, }; -type TestProposal = sp_consensus::Proposal; +type TestPool = BasicPool, TestBlock>; +type TestProposal = sp_consensus::Proposal; const SOURCE: TransactionSource = TransactionSource::External; const DEFAULT_GAS_LIMIT: u64 = 10_000_000_000; +#[derive(Clone)] +struct CountingExtension(Arc); + +impl sp_externalities::Extension for CountingExtension { + fn as_mut_any(&mut self) -> &mut dyn Any { + self + } + + fn type_id(&self) -> TypeId { + TypeId::of::() + } + + fn start_transaction(&mut self, _: sp_externalities::TransactionType) { + self.0.fetch_add(1, Ordering::SeqCst); + } +} + fn cache_base_path() -> PathBuf { static CACHE_DIR: OnceLock = OnceLock::new(); CACHE_DIR @@ -133,13 +155,21 @@ where { let last_nonce = starting_nonce + n; (starting_nonce..last_nonce) - .map(|nonce| CheckedExtrinsic { - signed: Some((signer.clone(), signed_extra(nonce))), - function: f(), - }) + .map(|nonce| signed_checked_extrinsic(f(), signer.clone(), nonce)) .collect() } +fn signed_checked_extrinsic( + function: RuntimeCall, + signer: AccountId, + nonce: u32, +) -> CheckedExtrinsic { + CheckedExtrinsic { + format: ExtrinsicFormat::Signed(signer, signed_extra(nonce)), + function, + } +} + fn sign_extrinsics( extrinsics: Vec, spec_version: u32, @@ -238,7 +268,7 @@ pub(crate) fn init_logger() { pub fn init() -> ( Arc, Arc, - Arc>, + Arc, sp_core::testing::TaskExecutor, [u8; 32], ) { @@ -265,7 +295,7 @@ pub fn init() -> ( let genesis_hash = <[u8; 32]>::try_from(&client.info().best_hash[..]).expect("H256 is a 32 byte type"); - (client, backend, txpool, spawner, genesis_hash) + (client, backend, txpool.into(), spawner, genesis_hash) } pub fn create_proposal( @@ -301,9 +331,13 @@ where let inherent_data = block_on(timestamp_provider.create_inherent_data()).expect("Create inherent data failed"); - let proposal = - block_on(proposer.propose(inherent_data, pre_digest(time_slot, 0), deadline, None)) - .unwrap(); + let proposal = block_on(proposer.propose(ProposeArgs { + inherent_data, + inherent_digests: pre_digest(time_slot, 0), + max_duration: deadline, + ..Default::default() + })) + .unwrap(); // Import last block block_on(client.import(BlockOrigin::Own, proposal.block.clone())).unwrap(); @@ -370,10 +404,11 @@ fn test_queue_remains_intact_if_processing_fails() { let nonce = 5_u32; // Bob's nonce for the future // Disable queue processing in Gear pallet as the root - checked.push(CheckedExtrinsic { - signed: Some((alice(), signed_extra(0))), - function: CallBuilder::toggle_run_queue(false).build(), - }); + checked.push(signed_checked_extrinsic( + CallBuilder::toggle_run_queue(false).build(), + alice(), + 0, + )); let extrinsics = sign_extrinsics( checked, VERSION.spec_version, @@ -415,7 +450,9 @@ fn test_queue_remains_intact_if_processing_fails() { let best_hash = block.hash(); // Ensure message queue still has 5 messages - let state = backend.state_at(best_hash).unwrap(); + let state = backend + .state_at(best_hash, TrieCacheContext::Untrusted) + .unwrap(); let queue_entry_prefix = storage_prefix( pallet_gear_messenger::Pallet::::name().as_bytes(), "Dispatches".as_bytes(), @@ -459,7 +496,9 @@ fn test_queue_remains_intact_if_processing_fails() { let best_hash = block.hash(); - let state = backend.state_at(best_hash).unwrap(); + let state = backend + .state_at(best_hash, TrieCacheContext::Untrusted) + .unwrap(); // Ensure message queue has not been drained again, and now has 8 messages let mut queue_len = 0_u32; let mut queue_entry_args = IterArgs::default(); @@ -551,7 +590,9 @@ fn test_block_max_gas_works() { // All extrinsics have been included in the block: 1 inherent + 5 normal + 1 terminal assert_eq!(block.extrinsics().len(), 7); - let state = backend.state_at(block.hash()).unwrap(); + let state = backend + .state_at(block.hash(), TrieCacheContext::Untrusted) + .unwrap(); // Ensure message queue still has 5 messages as none of the messages fit into the gas allowance let queue_entry_prefix = storage_prefix( pallet_gear_messenger::Pallet::::name().as_bytes(), @@ -595,14 +636,13 @@ fn test_pseudo_inherent_discarded_from_txpool() { // Create Gear::run() extrinsic - both unsigned and signed let unsigned_gear_run_xt = - UncheckedExtrinsic::new_unsigned(RuntimeCall::Gear(pallet_gear::Call::run { - max_gas: None, - })); + UncheckedExtrinsic::new_bare(RuntimeCall::Gear(pallet_gear::Call::run { max_gas: None })); let signed_gear_run_xt = sign( - CheckedExtrinsic { - signed: Some((bob(), signed_extra(0))), - function: RuntimeCall::Gear(pallet_gear::Call::run { max_gas: None }), - }, + signed_checked_extrinsic( + RuntimeCall::Gear(pallet_gear::Call::run { max_gas: None }), + bob(), + 0, + ), VERSION.spec_version, VERSION.transaction_version, genesis_hash, @@ -610,10 +650,7 @@ fn test_pseudo_inherent_discarded_from_txpool() { ); // A `DispatchClass::Normal` extrinsic - supposed to end up in the txpool let legit_xt = sign( - CheckedExtrinsic { - signed: Some((alice(), signed_extra(0))), - function: CallBuilder::noop().build(), - }, + signed_checked_extrinsic(CallBuilder::noop().build(), alice(), 0), VERSION.spec_version, VERSION.transaction_version, genesis_hash, @@ -727,10 +764,11 @@ fn test_proposal_timing_consistent() { let (client, backend, txpool, spawner, genesis_hash) = init(); // Disable queue processing in block #1 - let mut checked = vec![CheckedExtrinsic { - signed: Some((alice(), signed_extra(0))), - function: CallBuilder::toggle_run_queue(false).build(), - }]; + let mut checked = vec![signed_checked_extrinsic( + CallBuilder::toggle_run_queue(false).build(), + alice(), + 0, + )]; // Creating a bunch of extrinsics that will put N time-consuming init messages // to the message queue. The number of extrinsics should better allow all of @@ -766,7 +804,9 @@ fn test_proposal_timing_consistent() { ) .block; - let state = backend.state_at(block.hash()).unwrap(); + let state = backend + .state_at(block.hash(), TrieCacheContext::Untrusted) + .unwrap(); let queue_entry_prefix = storage_prefix( pallet_gear_messenger::Pallet::::name().as_bytes(), @@ -780,10 +820,11 @@ fn test_proposal_timing_consistent() { // Preparing block #2 // Re-enable queue processing in block #2 let extrinsics = sign_extrinsics( - vec![CheckedExtrinsic { - signed: Some((alice(), signed_extra(1))), - function: CallBuilder::toggle_run_queue(true).build(), - }], + vec![signed_checked_extrinsic( + CallBuilder::toggle_run_queue(true).build(), + alice(), + 1, + )], VERSION.spec_version, VERSION.transaction_version, genesis_hash, @@ -825,7 +866,9 @@ fn test_proposal_timing_consistent() { ) .block; - let state = backend.state_at(block.hash()).unwrap(); + let state = backend + .state_at(block.hash(), TrieCacheContext::Untrusted) + .unwrap(); // Check that the message queue has all messages pushed to it let queue_entry_prefix = storage_prefix( @@ -864,7 +907,9 @@ fn test_proposal_timing_consistent() { ) .block; - let state = backend.state_at(block.hash()).unwrap(); + let state = backend + .state_at(block.hash(), TrieCacheContext::Untrusted) + .unwrap(); let mut queue_entry_args = IterArgs::default(); queue_entry_args.prefix = Some(&queue_entry_prefix); @@ -910,10 +955,11 @@ mod basic_tests { E: From + Clone, { sign_extrinsics::( - vec![CheckedExtrinsic { - signed: Some((alice(), signed_extra(nonce))), - function: CallBuilder::toggle_run_queue(false).build(), - }], + vec![signed_checked_extrinsic( + CallBuilder::toggle_run_queue(false).build(), + alice(), + nonce, + )], VERSION.spec_version, VERSION.transaction_version, genesis_hash, @@ -1038,9 +1084,12 @@ mod basic_tests { let api = client.runtime_api(); let genesis_hash = genesis_hash.into(); - api.execute_block(genesis_hash, proposal.block).unwrap(); + api.execute_block(genesis_hash, proposal.block.into()) + .unwrap(); - let state = backend.state_at(genesis_hash).unwrap(); + let state = backend + .state_at(genesis_hash, TrieCacheContext::Untrusted) + .unwrap(); let storage_changes = api.into_storage_changes(&state, genesis_hash).unwrap(); @@ -1175,12 +1224,13 @@ mod basic_tests { let inherent_data = block_on(timestamp_provider.create_inherent_data()) .expect("Create inherent data failed"); - let block = block_on(proposer.propose( - inherent_data.clone(), - pre_digest(time_slot, 0), - deadline, - Some(block_limit), - )) + let block = block_on(proposer.propose(ProposeArgs { + inherent_data: inherent_data.clone(), + inherent_digests: pre_digest(time_slot, 0), + max_duration: deadline, + block_size_limit: Some(block_limit), + ..Default::default() + })) .map(|r| r.block) .unwrap(); @@ -1190,12 +1240,12 @@ mod basic_tests { let proposer = block_on(proposer_factory.init(&genesis_header)).unwrap(); - let block = block_on(proposer.propose( - inherent_data.clone(), - pre_digest(time_slot, 0), - deadline, - None, - )) + let block = block_on(proposer.propose(ProposeArgs { + inherent_data: inherent_data.clone(), + inherent_digests: pre_digest(time_slot, 0), + max_duration: deadline, + ..Default::default() + })) .map(|r| r.block) .unwrap(); @@ -1214,12 +1264,13 @@ mod basic_tests { let proposer = block_on(proposer_factory.init(&genesis_header)).unwrap(); // Give it enough time - let block = block_on(proposer.propose( + let block = block_on(proposer.propose(ProposeArgs { inherent_data, - pre_digest(time_slot, 0), - deadline, - Some(block_limit), - )) + inherent_digests: pre_digest(time_slot, 0), + max_duration: deadline, + block_size_limit: Some(block_limit), + ..Default::default() + })) .map(|r| r.block) .unwrap(); @@ -1229,6 +1280,55 @@ mod basic_tests { assert_eq!(block.extrinsics().len(), extrinsics_num - 2 + 2); } + #[test] + fn test_proposer_forwards_proof_recorder_and_extra_extensions() { + init_logger(); + let (client, _, txpool, spawner, _) = init(); + + let block_id = BlockId::number(0); + let genesis_header = client + .header(client.block_hash_from_id(&block_id).unwrap().unwrap()) + .expect("header get error") + .expect("there should be header"); + + let mut proposer_factory = ProposerFactory::new( + spawner.clone(), + client.clone(), + txpool.clone(), + None, + None, + None, + ); + let proposer = block_on(proposer_factory.init(&genesis_header)).unwrap(); + + let deadline = time::Duration::from_secs(300_000); + let timestamp = Timestamp::current(); + let timestamp_provider = sp_timestamp::InherentDataProvider::new(timestamp); + let time_slot = timestamp.as_millis() / SLOT_DURATION; + let inherent_data = block_on(timestamp_provider.create_inherent_data()) + .expect("Create inherent data failed"); + + let proof_recorder = sp_api::ProofRecorder::::default(); + let extension_transactions = Arc::new(AtomicUsize::new(0)); + let mut extra_extensions = sp_externalities::Extensions::default(); + extra_extensions.register(CountingExtension(extension_transactions.clone())); + + let block = block_on(proposer.propose(ProposeArgs { + inherent_data, + inherent_digests: pre_digest(time_slot, 0), + max_duration: deadline, + storage_proof_recorder: Some(proof_recorder.clone()), + extra_extensions, + ..Default::default() + })) + .map(|r| r.block) + .unwrap(); + + assert!(!block.extrinsics().is_empty()); + assert!(proof_recorder.drain_storage_proof().encoded_size() > 0); + assert!(extension_transactions.load(Ordering::SeqCst) > 0); + } + #[test] fn test_transactions_keep_being_added_after_exhaust_resources_before_soft_deadline() { init_logger(); diff --git a/vara/node/testing/src/genesis.rs b/vara/node/testing/src/genesis.rs index 972f66b63da..83becfe1e65 100644 --- a/vara/node/testing/src/genesis.rs +++ b/vara/node/testing/src/genesis.rs @@ -24,9 +24,9 @@ pub fn config_endowed(extra_endowed: Vec) -> RuntimeGenesisConfig { (alice(), 111 * ECONOMIC_UNITS), (bob(), 100 * ECONOMIC_UNITS), (charlie(), 100_000_000 * ECONOMIC_UNITS), - (dave(), 111 * ECONOMIC_UNITS), + (dave(), 111 * ECONOMIC_UNITS + EXISTENTIAL_DEPOSIT), (eve(), 101 * ECONOMIC_UNITS), - (ferdie(), 100 * ECONOMIC_UNITS), + (ferdie(), 100 * ECONOMIC_UNITS + EXISTENTIAL_DEPOSIT), (GearBank::bank_address(), UNITS), ]; @@ -38,7 +38,10 @@ pub fn config_endowed(extra_endowed: Vec) -> RuntimeGenesisConfig { RuntimeGenesisConfig { system: Default::default(), - balances: BalancesConfig { balances: endowed }, + balances: BalancesConfig { + balances: endowed, + dev_accounts: None, + }, babe: BabeConfig { authorities: vec![], epoch_config: BABE_GENESIS_EPOCH_CONFIG, diff --git a/vara/node/testing/src/keyring.rs b/vara/node/testing/src/keyring.rs index d7de73fe5f3..6ab103cbf6a 100644 --- a/vara/node/testing/src/keyring.rs +++ b/vara/node/testing/src/keyring.rs @@ -5,8 +5,8 @@ use parity_scale_codec::Encode; use runtime_primitives::{AccountId, Nonce}; -use sp_keyring::{AccountKeyring, Ed25519Keyring, Sr25519Keyring}; -use sp_runtime::generic::Era; +use sp_keyring::{Ed25519Keyring, Sr25519Keyring}; +use sp_runtime::generic::{self, Era, ExtrinsicFormat}; use vara_runtime::{ CustomChargeTransactionPayment, CustomCheckNonce, RuntimeCall, SessionKeys, SignedExtra, StakingBlackList, UncheckedExtrinsic, @@ -17,32 +17,32 @@ pub type CheckedExtrinsic = /// Alice's account id. pub fn alice() -> AccountId { - AccountKeyring::Alice.into() + Sr25519Keyring::Alice.into() } /// Bob's account id. pub fn bob() -> AccountId { - AccountKeyring::Bob.into() + Sr25519Keyring::Bob.into() } /// Charlie's account id. pub fn charlie() -> AccountId { - AccountKeyring::Charlie.into() + Sr25519Keyring::Charlie.into() } /// Dave's account id. pub fn dave() -> AccountId { - AccountKeyring::Dave.into() + Sr25519Keyring::Dave.into() } /// Eve's account id. pub fn eve() -> AccountId { - AccountKeyring::Eve.into() + Sr25519Keyring::Eve.into() } /// Ferdie's account id. pub fn ferdie() -> AccountId { - AccountKeyring::Ferdie.into() + Sr25519Keyring::Ferdie.into() } /// Convert keyrings into `SessionKeys`. @@ -82,8 +82,8 @@ pub fn sign( genesis_hash: [u8; 32], metadata_hash: Option<[u8; 32]>, ) -> UncheckedExtrinsic { - match xt.signed { - Some((signed, extra)) => { + match xt.format { + ExtrinsicFormat::Signed(signed, extra) => { let payload = ( xt.function, extra.clone(), @@ -93,7 +93,7 @@ pub fn sign( genesis_hash, metadata_hash, ); - let key = AccountKeyring::from_account_id(&signed).unwrap(); + let key = Sr25519Keyring::from_account_id(&signed).unwrap(); let signature = payload .using_encoded(|b| { if b.len() > 256 { @@ -103,14 +103,19 @@ pub fn sign( } }) .into(); - UncheckedExtrinsic { - signature: Some((sp_runtime::MultiAddress::Id(signed), signature, extra)), - function: payload.0, - } + generic::UncheckedExtrinsic::new_signed( + payload.0, + sp_runtime::MultiAddress::Id(signed), + signature, + extra, + ) + .into() } - None => UncheckedExtrinsic { - signature: None, - function: xt.function, - }, + ExtrinsicFormat::Bare => generic::UncheckedExtrinsic::new_bare(xt.function).into(), + ExtrinsicFormat::General(ext_version, extra) => generic::UncheckedExtrinsic::from_parts( + xt.function, + generic::Preamble::General(ext_version, extra), + ) + .into(), } } diff --git a/vara/pallets/payment/src/mock.rs b/vara/pallets/payment/src/mock.rs index 488ec5b97ba..93e043dfd65 100644 --- a/vara/pallets/payment/src/mock.rs +++ b/vara/pallets/payment/src/mock.rs @@ -19,7 +19,6 @@ use pallet_transaction_payment::CurrencyAdapter; use primitive_types::H256; use sp_runtime::{ BuildStorage, - testing::TestXt, traits::{BlakeTwo256, ConstU64, IdentityLookup}, }; use sp_std::{ @@ -91,6 +90,7 @@ impl pallet_transaction_payment::Config for Test { type WeightToFee = ConstantMultiplier>; type LengthToFee = ConstantMultiplier>; type FeeMultiplierUpdate = pallet_gear_payment::GearFeeMultiplier; + type WeightInfo = (); } parameter_types! { @@ -188,6 +188,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { (FEE_PAYER, 10_000_000u128), (GearBank::bank_address(), ExistentialDeposit::get()), ], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); @@ -210,12 +211,6 @@ pub fn run_to_block(n: u64) { } } -impl common::ExtractCall for TestXt { - fn extract_call(&self) -> RuntimeCall { - self.call.clone() - } -} - pub fn get_last_voucher_id() -> VoucherId { System::events() .iter() diff --git a/vara/pallets/payment/src/tests.rs b/vara/pallets/payment/src/tests.rs index 502de854347..42520278489 100644 --- a/vara/pallets/payment/src/tests.rs +++ b/vara/pallets/payment/src/tests.rs @@ -14,7 +14,13 @@ use gear_core::message::{Dispatch, DispatchKind, Message, StoredDispatch, UserSt use pallet_gear_voucher::{Call as VoucherCall, PrepaidCall}; use pallet_transaction_payment::{FeeDetails, InclusionFee, Multiplier, RuntimeDispatchInfo}; use primitive_types::H256; -use sp_runtime::{FixedPointNumber, codec::Encode, testing::TestXt, traits::SignedExtension}; +use sp_runtime::{ + FixedPointNumber, + codec::Encode, + testing::TestXt, + traits::{TransactionExtension, TxBaseImplication}, + transaction_validity::{TransactionSource, TransactionValidityError}, +}; use utils::*; type WeightToFeeFor = ::WeightToFee; @@ -77,9 +83,7 @@ fn fee_rounding_error_bounded_by_multiplier() { let alice_initial_balance = Balances::free_balance(ALICE); let author_initial_balance = Balances::free_balance(BLOCK_AUTHOR); - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&ALICE, call, &info_from_weight(w), len) - .unwrap(); + let pre = pre_dispatch_payment(&ALICE, call, &info_from_weight(w), len).unwrap(); let fee = WeightToFeeFor::::weight_to_fee(&w); assert_approx_eq!( @@ -88,8 +92,8 @@ fn fee_rounding_error_bounded_by_multiplier() { rounding_error ); - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(w), &default_post_info(), len, @@ -163,9 +167,7 @@ fn mq_size_affecting_fee_works() { let weight = Weight::from_parts(1_000, 0); - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&ALICE, call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&ALICE, call, &info_from_weight(weight), len).unwrap(); let fee_weight = WeightToFeeFor::::weight_to_fee(&weight); // Can use strict equality for calls that do not introduce rounding error @@ -174,8 +176,8 @@ fn mq_size_affecting_fee_works() { alice_initial_balance - fee_weight - fee_length ); - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -199,17 +201,15 @@ fn mq_size_affecting_fee_works() { let author_initial_balance = Balances::free_balance(BLOCK_AUTHOR); // Fee multiplier should have been set to 5 - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&ALICE, call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&ALICE, call, &info_from_weight(weight), len).unwrap(); assert_eq!( Balances::free_balance(ALICE), alice_initial_balance - (fee_weight * 5 + fee_length) ); - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -253,9 +253,7 @@ fn mq_size_not_affecting_fee_works() { let weight = Weight::from_parts(1_000, 0); - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&ALICE, call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&ALICE, call, &info_from_weight(weight), len).unwrap(); let fee_weight = WeightToFeeFor::::weight_to_fee(&weight); assert_approx_eq!( @@ -264,8 +262,8 @@ fn mq_size_not_affecting_fee_works() { 1 ); - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -295,9 +293,7 @@ fn mq_size_not_affecting_fee_works() { let author_initial_balance = Balances::free_balance(BLOCK_AUTHOR); // Fee multiplier should have been set to 16 - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&ALICE, call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&ALICE, call, &info_from_weight(weight), len).unwrap(); let rounding_error = WeightToFeeFor::::weight_to_fee(&Weight::from_parts(16, 0)); // Now we may have some rounding error somewhere at the least significant digits @@ -307,8 +303,8 @@ fn mq_size_not_affecting_fee_works() { rounding_error ); - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -343,27 +339,31 @@ fn query_info_and_fee_details_work() { }); let extra = (); - let xt_affecting_mq = TestXt::new(call_affecting_mq.clone(), Some((ALICE, extra))); + let xt_affecting_mq = TestXt::new_signed(call_affecting_mq.clone(), ALICE, (), extra); let info_affecting_mq = xt_affecting_mq.get_dispatch_info(); let ext_affecting_mq = xt_affecting_mq.encode(); let len_affecting_mq = ext_affecting_mq.len() as u32; - let xt_not_affecting_mq = TestXt::new(call_not_affecting_mq, Some((ALICE, extra))); + let xt_not_affecting_mq = TestXt::new_signed(call_not_affecting_mq, ALICE, (), extra); let info_not_affecting_mq = xt_not_affecting_mq.get_dispatch_info(); let ext_not_affecting_mq = xt_not_affecting_mq.encode(); let len_not_affecting_mq = ext_not_affecting_mq.len() as u32; - let unsigned_xt = TestXt::<_, ()>::new(call_affecting_mq, None); + let unsigned_xt = TestXt::<_, ()>::new_bare(call_affecting_mq); let unsigned_xt_info = unsigned_xt.get_dispatch_info(); new_test_ext().execute_with(|| { // Empty Message queue => extra fee is not applied - let fee_affecting_weight = WeightToFeeFor::::weight_to_fee(&info_affecting_mq.weight); - let fee_affecting_length = LengthToFeeFor::::weight_to_fee(&Weight::from_parts(len_affecting_mq.into(), 0)); + let fee_affecting_weight = + WeightToFeeFor::::weight_to_fee(&info_affecting_mq.total_weight()); + let fee_affecting_length = LengthToFeeFor::::weight_to_fee(&Weight::from_parts( + len_affecting_mq.into(), + 0, + )); assert_eq!( GearPayment::query_info(xt_affecting_mq.clone(), len_affecting_mq), RuntimeDispatchInfo { - weight: info_affecting_mq.weight, + weight: info_affecting_mq.total_weight(), class: info_affecting_mq.class, partial_fee: 0 /* base_fee */ + fee_affecting_length /* len * 1 */ @@ -371,12 +371,16 @@ fn query_info_and_fee_details_work() { }, ); - let fee_weight = WeightToFeeFor::::weight_to_fee(&info_not_affecting_mq.weight); - let fee_length = LengthToFeeFor::::weight_to_fee(&Weight::from_parts(len_not_affecting_mq.into(), 0)); + let fee_weight = + WeightToFeeFor::::weight_to_fee(&info_not_affecting_mq.total_weight()); + let fee_length = LengthToFeeFor::::weight_to_fee(&Weight::from_parts( + len_not_affecting_mq.into(), + 0, + )); assert_eq!( GearPayment::query_info(xt_not_affecting_mq.clone(), len_not_affecting_mq), RuntimeDispatchInfo { - weight: info_not_affecting_mq.weight, + weight: info_not_affecting_mq.total_weight(), class: info_not_affecting_mq.class, partial_fee: 0 /* base_fee */ + fee_length /* len * 1 */ @@ -387,7 +391,7 @@ fn query_info_and_fee_details_work() { assert_eq!( GearPayment::query_info(unsigned_xt.clone(), len_affecting_mq), RuntimeDispatchInfo { - weight: unsigned_xt_info.weight, + weight: unsigned_xt_info.total_weight(), class: unsigned_xt_info.class, partial_fee: 0, }, @@ -433,7 +437,7 @@ fn query_info_and_fee_details_work() { assert_eq!( GearPayment::query_info(xt_affecting_mq.clone(), len_affecting_mq), RuntimeDispatchInfo { - weight: info_affecting_mq.weight, + weight: info_affecting_mq.total_weight(), class: info_affecting_mq.class, partial_fee: 0 /* base_fee */ + fee_affecting_length /* len * 1 */ @@ -447,7 +451,7 @@ fn query_info_and_fee_details_work() { assert_eq!( GearPayment::query_info(xt_not_affecting_mq.clone(), len_not_affecting_mq), RuntimeDispatchInfo { - weight: info_not_affecting_mq.weight, + weight: info_not_affecting_mq.total_weight(), class: info_not_affecting_mq.class, partial_fee: 0 /* base_fee */ + fee_length /* len * 1 */ @@ -458,7 +462,7 @@ fn query_info_and_fee_details_work() { assert_eq!( GearPayment::query_info(unsigned_xt.clone(), len_affecting_mq), RuntimeDispatchInfo { - weight: unsigned_xt_info.weight, + weight: unsigned_xt_info.total_weight(), class: unsigned_xt_info.class, partial_fee: 0, }, @@ -539,9 +543,7 @@ fn fee_payer_replacement_works() { let weight = Weight::from_parts(1_000, 0); - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&BOB, call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&BOB, call, &info_from_weight(weight), len).unwrap(); let fee_weight = WeightToFeeFor::::weight_to_fee(&weight); @@ -554,8 +556,8 @@ fn fee_payer_replacement_works() { synthesized_initial_balance - fee_weight - fee_length ); - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -639,9 +641,7 @@ fn reply_with_voucher_pays_fee_from_voucher_ok() { let voucher_initial_balance = Balances::free_balance(voucher_id.cast::>()); - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&BOB, call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&BOB, call, &info_from_weight(weight), len).unwrap(); let fee_weight = WeightToFeeFor::::weight_to_fee(&weight); @@ -654,8 +654,8 @@ fn reply_with_voucher_pays_fee_from_voucher_ok() { voucher_initial_balance - fee_weight - fee_length ); - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -709,9 +709,7 @@ fn voucher_call_send_payer_ok() { let call_fee = fee_length + fee_weight; // Pre-dispatch of the call. - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&BOB, &call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&BOB, &call, &info_from_weight(weight), len).unwrap(); // Bob hasn't paid fees. assert_eq!(Balances::free_balance(BOB), bob_initial_balance); @@ -729,8 +727,8 @@ fn voucher_call_send_payer_ok() { ); // Post-dispatch of the call. - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -770,14 +768,12 @@ fn voucher_call_send_payer_inexistent_voucher_err() { let call_fee = fee_length + fee_weight; // Pre-dispatch of the call. - assert_ok!( - CustomChargeTransactionPayment::::from(0).pre_dispatch( - &BOB, - &call, - &info_from_weight(weight), - len - ) - ); + assert_ok!(pre_dispatch_payment( + &BOB, + &call, + &info_from_weight(weight), + len + )); // Bob has paid fees. assert_eq!(Balances::free_balance(BOB), bob_initial_balance - call_fee); @@ -823,14 +819,12 @@ fn voucher_call_send_payer_wrong_program_err() { let call_fee = fee_length + fee_weight; // Pre-dispatch of the call. - assert_ok!( - CustomChargeTransactionPayment::::from(0).pre_dispatch( - &BOB, - &call, - &info_from_weight(weight), - len - ) - ); + assert_ok!(pre_dispatch_payment( + &BOB, + &call, + &info_from_weight(weight), + len + )); // Bob has paid fees. assert_eq!(Balances::free_balance(BOB), bob_initial_balance - call_fee); @@ -884,14 +878,12 @@ fn voucher_call_send_payer_expiry_err() { let call_fee = fee_length + fee_weight; // Pre-dispatch of the call. - assert_ok!( - CustomChargeTransactionPayment::::from(0).pre_dispatch( - &BOB, - &call, - &info_from_weight(weight), - len - ) - ); + assert_ok!(pre_dispatch_payment( + &BOB, + &call, + &info_from_weight(weight), + len + )); // Bob has paid fees. assert_eq!(Balances::free_balance(BOB), bob_initial_balance - call_fee); @@ -956,9 +948,7 @@ fn voucher_call_reply_payer_ok() { let call_fee = fee_length + fee_weight; // Pre-dispatch of the call. - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&BOB, &call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&BOB, &call, &info_from_weight(weight), len).unwrap(); // Bob hasn't paid fees. assert_eq!(Balances::free_balance(BOB), bob_initial_balance); @@ -976,8 +966,8 @@ fn voucher_call_reply_payer_ok() { ); // Post-dispatch of the call. - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -1035,9 +1025,7 @@ fn voucher_call_upload_payer_ok() { let call_fee = fee_length + fee_weight; // Pre-dispatch of the call. - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&BOB, &call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&BOB, &call, &info_from_weight(weight), len).unwrap(); // Bob hasn't paid fees. assert_eq!(Balances::free_balance(BOB), bob_initial_balance); @@ -1055,8 +1043,8 @@ fn voucher_call_upload_payer_ok() { ); // Post-dispatch of the call. - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -1113,14 +1101,12 @@ fn voucher_call_upload_payer_forbidden_err() { let call_fee = fee_length + fee_weight; // Pre-dispatch of the call. - assert_ok!( - CustomChargeTransactionPayment::::from(0).pre_dispatch( - &BOB, - &call, - &info_from_weight(weight), - len - ) - ); + assert_ok!(pre_dispatch_payment( + &BOB, + &call, + &info_from_weight(weight), + len + )); // Bob has paid fees. assert_eq!(Balances::free_balance(BOB), bob_initial_balance - call_fee); @@ -1174,9 +1160,7 @@ fn voucher_call_decline_payer_ok() { let call_fee = fee_length + fee_weight; // Pre-dispatch of the call. - let pre = CustomChargeTransactionPayment::::from(0) - .pre_dispatch(&BOB, &call, &info_from_weight(weight), len) - .unwrap(); + let pre = pre_dispatch_payment(&BOB, &call, &info_from_weight(weight), len).unwrap(); // Bob hasn't paid fees. assert_eq!(Balances::free_balance(BOB), bob_initial_balance); @@ -1194,8 +1178,8 @@ fn voucher_call_decline_payer_ok() { ); // Post-dispatch of the call. - assert_ok!(CustomChargeTransactionPayment::::post_dispatch( - Some(pre), + assert_ok!(post_dispatch_payment( + pre, &info_from_weight(weight), &default_post_info(), len, @@ -1257,14 +1241,12 @@ fn voucher_call_decline_payer_expired_err() { let call_fee = fee_length + fee_weight; // Pre-dispatch of the call. - assert_ok!( - CustomChargeTransactionPayment::::from(0).pre_dispatch( - &BOB, - &call, - &info_from_weight(weight), - len - ) - ); + assert_ok!(pre_dispatch_payment( + &BOB, + &call, + &info_from_weight(weight), + len + )); // Bob has paid fees. assert_eq!(Balances::free_balance(BOB), bob_initial_balance - call_fee); @@ -1330,9 +1312,8 @@ mod utils { } pub fn info_from_weight(weight: Weight) -> DispatchInfo { - // DispatchInfo { weight: w, class: DispatchClass::Normal, pays_fee: Pays::Yes } DispatchInfo { - weight, + call_weight: weight, ..Default::default() } } @@ -1344,6 +1325,47 @@ mod utils { } } + pub fn pre_dispatch_payment( + who: &AccountIdOf, + call: &RuntimeCall, + info: &DispatchInfo, + len: usize, + ) -> Result< + as TransactionExtension>::Pre, + TransactionValidityError, + > { + let extension = CustomChargeTransactionPayment::::from(0); + let implicit = extension.implicit()?; + let (_, val, origin) = extension.validate( + RuntimeOrigin::signed(*who), + call, + info, + len, + implicit, + &TxBaseImplication(()), + TransactionSource::External, + )?; + + extension.prepare(val, &origin, call, info, len) + } + + pub fn post_dispatch_payment( + pre: as TransactionExtension>::Pre, + info: &DispatchInfo, + post_info: &PostDispatchInfo, + len: usize, + result: &sp_runtime::DispatchResult, + ) -> Result<(), TransactionValidityError> { + let mut post_info = *post_info; + as TransactionExtension>::post_dispatch( + pre, + info, + &mut post_info, + len, + result, + ) + } + pub fn populate_message_queue(n: u64) where T: Config, diff --git a/vara/pallets/staking-rewards/src/mock.rs b/vara/pallets/staking-rewards/src/mock.rs index 956e211c333..5e3831117ba 100644 --- a/vara/pallets/staking-rewards/src/mock.rs +++ b/vara/pallets/staking-rewards/src/mock.rs @@ -9,7 +9,8 @@ use frame_election_provider_support::{ use frame_support::{ PalletId, construct_runtime, parameter_types, traits::{ - ConstU32, ConstU64, Contains, Currency, FindAuthor, Hooks, NeverEnsureOrigin, + ConstBool, ConstU32, ConstU64, Contains, Currency, ExistenceRequirement, FindAuthor, Hooks, + NeverEnsureOrigin, OnUnbalanced, WithdrawReasons, tokens::{PayFromAccount, UnityAssetBalanceConversion}, }, weights::{Weight, constants::RocksDbWeight}, @@ -21,7 +22,7 @@ use sp_core::{H256, crypto::key_types}; use sp_runtime::{ BuildStorage, KeyTypeId, Perbill, Percent, Permill, Perquintill, testing::{Block as TestBlock, UintAuthorityId}, - traits::{BlakeTwo256, IdentityLookup, One, OpaqueKeys, Scale}, + traits::{BlakeTwo256, ConvertInto, IdentityLookup, One, OpaqueKeys, Scale}, }; use sp_std::convert::{TryFrom, TryInto}; @@ -87,7 +88,6 @@ common::impl_pallet_timestamp!(Test); common::impl_pallet_staking!( Test, EraPayout = StakingRewards, - Slash = Treasury, Reward = StakingRewards, NextNewSession = Session, ElectionProvider = onchain::OnChainExecution>, @@ -181,16 +181,20 @@ parameter_types! { impl pallet_session::Config for Test { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; - type ValidatorIdOf = pallet_staking::StashOf; + type ValidatorIdOf = ConvertInto; type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; type SessionManager = pallet_session_historical::NoteHistoricalRoot; type SessionHandler = TestSessionHandler; type Keys = UintAuthorityId; + type DisablingStrategy = pallet_session::disabling::UpToLimitDisablingStrategy; + type Currency = Balances; + type KeyDeposit = (); type WeightInfo = (); } impl pallet_session_historical::Config for Test { + type RuntimeEvent = RuntimeEvent; type FullIdentification = pallet_staking::Exposure; type FullIdentificationOf = pallet_staking::ExposureOf; } @@ -235,11 +239,13 @@ frame_election_provider_support::generate_solution_type!( pub struct OnChainSeqPhragmen(PhantomData); impl onchain::Config for OnChainSeqPhragmen { + type Sort = ConstBool; type System = T; type Solver = SequentialPhragmen<::AccountId, Perbill>; + type MaxBackersPerWinner = MaxElectingVoters; + type MaxWinnersPerPage = MaxActiveValidators; type DataProvider = pallet_staking::Pallet; type WeightInfo = (); - type MaxWinners = MaxActiveValidators; type Bounds = ElectionBounds; } @@ -271,6 +277,7 @@ impl pallet_treasury::Config for Test { type Paymaster = PayFromAccount; type BalanceConverter = UnityAssetBalanceConversion; type PayoutPeriod = ConstU64<10>; + type BlockNumberProvider = System; } parameter_types! { @@ -303,6 +310,7 @@ impl multi_phase::MinerConfig for Test { type MaxWeight = MinerMaxWeight; type MaxVotesPerVoter = ::MaxVotesPerVoter; type MaxWinners = MaxActiveValidators; + type MaxBackersPerWinner = MaxElectingVoters; type Solution = TestNposSolution; fn solution_weight(v: u32, t: u32, a: u32, d: u32) -> Weight { @@ -323,6 +331,26 @@ impl multi_phase::BenchmarkingConfig for TestBenchmarkingConfig { const MAXIMUM_TARGETS: u32 = 300; } +type ElectionRewardImbalance = as Currency< + ::AccountId, +>>::PositiveImbalance; + +pub struct ElectionRewardHandler(PhantomData); +impl OnUnbalanced> for ElectionRewardHandler +where + T: pallet_balances::Config + pallet_gear_staking_rewards::Config, + pallet_balances::Pallet: Currency<::AccountId>, +{ + fn on_nonzero_unbalanced(minted: ElectionRewardImbalance) { + let _ = as Currency<_>>::settle( + &pallet_gear_staking_rewards::Pallet::::account_id(), + minted, + WithdrawReasons::TRANSFER, + ExistenceRequirement::KeepAlive, + ); + } +} + impl multi_phase::Config for Test { type RuntimeEvent = RuntimeEvent; type Currency = Balances; @@ -341,12 +369,13 @@ impl multi_phase::Config for Test { type SignedMaxSubmissions = SignedMaxSubmissions; type SignedMaxRefunds = SignedMaxRefunds; type SlashHandler = Treasury; - type RewardHandler = StakingRewards; + type RewardHandler = ElectionRewardHandler; type DataProvider = Staking; type Fallback = onchain::OnChainExecution>; type GovernanceFallback = onchain::OnChainExecution>; type ForceOrigin = frame_system::EnsureRoot; type MaxWinners = MaxActiveValidators; + type MaxBackersPerWinner = MaxElectingVoters; type ElectionBounds = ElectionBounds; type WeightInfo = (); type BenchmarkingConfig = TestBenchmarkingConfig; @@ -354,14 +383,23 @@ impl multi_phase::Config for Test { type Solver = SequentialPhragmen, ()>; } -impl frame_system::offchain::SendTransactionTypes for Test +impl frame_system::offchain::CreateTransactionBase for Test where - RuntimeCall: From, + RuntimeCall: From, { - type OverarchingCall = RuntimeCall; + type RuntimeCall = RuntimeCall; type Extrinsic = TestXt; } +impl frame_system::offchain::CreateBare for Test +where + RuntimeCall: From, +{ + fn create_bare(call: Self::RuntimeCall) -> Self::Extrinsic { + TestXt::new_bare(call) + } +} + pub type ValidatorAccountId = ( AccountId, // stash UintAuthorityId, // authority discovery ID @@ -414,6 +452,7 @@ where T: pallet_timestamp::Config, T: pallet_authorship::Config, T: pallet_election_provider_multi_phase::Config, + CurrencyOf: frame_support::traits::fungible::Mutate, { pub fn stash(mut self, s: Balance) -> Self { self.stash = s; @@ -478,13 +517,16 @@ where let balances: Vec<(AccountId, u128)> = self .initial_authorities .iter() - .map(|x| (x.0, self.stash)) + .map(|x| (x.0, self.stash.saturating_add(EXISTENTIAL_DEPOSIT))) .chain(self.endowed_accounts.iter().map(|k| (*k, self.endowment))) .collect(); - pallet_balances::GenesisConfig:: { balances } - .assimilate_storage(&mut storage) - .unwrap(); + pallet_balances::GenesisConfig:: { + balances, + dev_accounts: None, + } + .assimilate_storage(&mut storage) + .unwrap(); pallet_treasury::GenesisConfig::::default() .assimilate_storage(&mut storage) @@ -548,7 +590,9 @@ where if total_supply < self.total_supply { // Mint the difference to SIGNER user let diff = self.total_supply.saturating_sub(total_supply); - let _ = CurrencyOf::::deposit_creating(&SIGNER, diff); + let _ = as frame_support::traits::fungible::Mutate<_>>::mint_into( + &SIGNER, diff, + ); } }); @@ -656,13 +700,13 @@ pub fn default_test_ext() -> sp_io::TestExternalities { pub(crate) fn validators_total_balance() -> u128 { pallet_staking::Validators::::iter() - .map(|(stash_id, _)| Balances::free_balance(stash_id)) + .map(|(stash_id, _)| Balances::total_balance(&stash_id)) .fold(0_u128, |acc, x| acc.saturating_add(x)) } pub(crate) fn nominators_total_balance() -> u128 { pallet_staking::Nominators::::iter() - .map(|(stash_id, _)| Balances::free_balance(stash_id)) + .map(|(stash_id, _)| Balances::total_balance(&stash_id)) .fold(0_u128, |acc, x| acc.saturating_add(x)) } @@ -702,14 +746,6 @@ pub(crate) mod two_block_producers { } ); - impl frame_system::offchain::SendTransactionTypes for Test - where - RuntimeCall: From, - { - type OverarchingCall = RuntimeCall; - type Extrinsic = TestXt; - } - common::impl_pallet_system!(Test, DbWeight = RocksDbWeight, BlockWeights = ()); common::impl_pallet_timestamp!(Test); @@ -730,7 +766,6 @@ pub(crate) mod two_block_producers { common::impl_pallet_staking!( Test, EraPayout = StakingRewards, - Slash = Treasury, Reward = StakingRewards, NextNewSession = Session, ElectionProvider = onchain::OnChainExecution>, @@ -740,16 +775,20 @@ pub(crate) mod two_block_producers { impl pallet_session::Config for Test { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; - type ValidatorIdOf = pallet_staking::StashOf; + type ValidatorIdOf = ConvertInto; type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; type SessionManager = pallet_session_historical::NoteHistoricalRoot; type SessionHandler = TestSessionHandler; type Keys = UintAuthorityId; + type DisablingStrategy = pallet_session::disabling::UpToLimitDisablingStrategy; + type Currency = Balances; + type KeyDeposit = (); type WeightInfo = (); } impl pallet_session_historical::Config for Test { + type RuntimeEvent = RuntimeEvent; type FullIdentification = pallet_staking::Exposure; type FullIdentificationOf = pallet_staking::ExposureOf; } @@ -776,6 +815,7 @@ pub(crate) mod two_block_producers { type Paymaster = PayFromAccount; type BalanceConverter = UnityAssetBalanceConversion; type PayoutPeriod = ConstU64<10>; + type BlockNumberProvider = System; } impl pallet_sudo::Config for Test { @@ -797,6 +837,7 @@ pub(crate) mod two_block_producers { type MaxWeight = MinerMaxWeight; type MaxVotesPerVoter = ::MaxVotesPerVoter; type MaxWinners = MaxActiveValidators; + type MaxBackersPerWinner = MaxElectingVoters; type Solution = TestNposSolution; fn solution_weight(v: u32, t: u32, a: u32, d: u32) -> Weight { @@ -827,12 +868,13 @@ pub(crate) mod two_block_producers { type SignedMaxSubmissions = SignedMaxSubmissions; type SignedMaxRefunds = SignedMaxRefunds; type SlashHandler = Treasury; - type RewardHandler = StakingRewards; + type RewardHandler = ElectionRewardHandler; type DataProvider = Staking; type Fallback = onchain::OnChainExecution>; type GovernanceFallback = onchain::OnChainExecution>; type ForceOrigin = frame_system::EnsureRoot; type MaxWinners = MaxActiveValidators; + type MaxBackersPerWinner = MaxElectingVoters; type ElectionBounds = ElectionBounds; type WeightInfo = (); type BenchmarkingConfig = TestBenchmarkingConfig; @@ -854,6 +896,23 @@ pub(crate) mod two_block_producers { type WeightInfo = (); } + impl frame_system::offchain::CreateTransactionBase for Test + where + RuntimeCall: From, + { + type RuntimeCall = RuntimeCall; + type Extrinsic = TestXt; + } + + impl frame_system::offchain::CreateBare for Test + where + RuntimeCall: From, + { + fn create_bare(call: Self::RuntimeCall) -> Self::Extrinsic { + TestXt::new_bare(call) + } + } + #[allow(unused)] pub(crate) fn run_to_block(n: BlockNumberFor) { run_to_block_impl::(n) diff --git a/vara/pallets/staking-rewards/src/tests.rs b/vara/pallets/staking-rewards/src/tests.rs index abdaaf34f45..9d777c402a1 100644 --- a/vara/pallets/staking-rewards/src/tests.rs +++ b/vara/pallets/staking-rewards/src/tests.rs @@ -4,8 +4,15 @@ //! Staking rewards pallet tests. use crate::{mock::*, *}; -use frame_support::{assert_noop, assert_ok, traits::EstimateNextNewSession}; -use sp_runtime::{PerThing, Perbill, traits::Convert}; +use frame_support::{ + assert_noop, assert_ok, + dispatch::GetDispatchInfo, + traits::{Currency, EstimateNextNewSession}, +}; +use sp_runtime::{ + PerThing, Perbill, + traits::{Convert, TransactionExtension, TxBaseImplication}, +}; macro_rules! assert_approx_eq { ($left:expr, $right:expr, $tol:expr) => {{ @@ -264,13 +271,15 @@ fn validators_rewards_disbursement_works() { // All the rewards should have landed at the VAL_1_STASH account - // the only one who has earned any points for authoring blocks assert_eq!( - Balances::free_balance(VAL_1_STASH), - VALIDATOR_STAKE + expected_payout_0 + expected_payout_1 + >::total_balance(&VAL_1_STASH), + VALIDATOR_STAKE + EXISTENTIAL_DEPOSIT + expected_payout_0 + expected_payout_1 ); // Other validators' balances remained intact assert_eq!( validators_total_balance(), - VALIDATOR_STAKE * num_validators as u128 + expected_payout_0 + expected_payout_1 + (VALIDATOR_STAKE + EXISTENTIAL_DEPOSIT) * num_validators as u128 + + expected_payout_0 + + expected_payout_1 ); }); } @@ -477,85 +486,85 @@ fn nominators_rewards_disbursement_works() { // All the rewards should have landed at the VAL_1_STASH account - // the only one who has earned any points for authoring blocks assert_eq!( - Balances::free_balance(VAL_1_STASH), - VALIDATOR_STAKE + expected_payout_0 + expected_validators_payout + >::total_balance(&VAL_1_STASH), + VALIDATOR_STAKE + EXISTENTIAL_DEPOSIT + expected_payout_0 + expected_validators_payout ); // Other validators' balances remained intact assert_eq!( validators_total_balance(), - VALIDATOR_STAKE * 3_u128 + expected_payout_0 + expected_validators_payout + (VALIDATOR_STAKE + EXISTENTIAL_DEPOSIT) * 3_u128 + + expected_payout_0 + + expected_validators_payout ); }); } #[test] fn staking_blacklist_works() { - use sp_runtime::{testing::TestXt, transaction_validity::InvalidTransaction}; + use sp_runtime::transaction_validity::{InvalidTransaction, TransactionSource}; init_logger(); - let extra: SignedExtra = StakingBlackList::::new(); + fn validate_blacklist( + signer: u64, + call: RuntimeCall, + ) -> sp_runtime::transaction_validity::TransactionValidity { + let info = call.get_dispatch_info(); + StakingBlackList::::new() + .validate( + RuntimeOrigin::signed(signer), + &call, + &info, + 0, + (), + &TxBaseImplication(()), + TransactionSource::External, + ) + .map(|(validity, _, _)| validity) + } + + let invalid_call = RuntimeCall::Staking(pallet_staking::Call::bond { + value: 10_000_u128, + payee: pallet_staking::RewardDestination::Stash, + }); - let invalid_call = TestXt::::new( - RuntimeCall::Staking(pallet_staking::Call::bond { + // Wrapping `bond` call in a batch is also illegal + let invalid_batch = RuntimeCall::Utility(pallet_utility::Call::batch { + calls: vec![RuntimeCall::Staking(pallet_staking::Call::bond { value: 10_000_u128, payee: pallet_staking::RewardDestination::Stash, - }), - Some((NOM_1_STASH, extra.clone())), - ); + })], + }); - // Wrapping `bond` call in a batch is also illegal - let invalid_batch = TestXt::::new( - RuntimeCall::Utility(pallet_utility::Call::batch { - calls: vec![RuntimeCall::Staking(pallet_staking::Call::bond { - value: 10_000_u128, - payee: pallet_staking::RewardDestination::Stash, - })], - }), - Some((NOM_1_STASH, extra.clone())), - ); - - let invalid_batch_all = TestXt::::new( - RuntimeCall::Utility(pallet_utility::Call::batch_all { - calls: vec![RuntimeCall::Staking(pallet_staking::Call::bond { - value: 10_000_u128, - payee: pallet_staking::RewardDestination::Stash, - })], - }), - Some((NOM_1_STASH, extra.clone())), - ); + let invalid_batch_all = RuntimeCall::Utility(pallet_utility::Call::batch_all { + calls: vec![RuntimeCall::Staking(pallet_staking::Call::bond { + value: 10_000_u128, + payee: pallet_staking::RewardDestination::Stash, + })], + }); // Nested batches and/or other `Utility` calls shouldn't work, as well - let nested_batches = TestXt::::new( - RuntimeCall::Utility(pallet_utility::Call::batch { - calls: vec![RuntimeCall::Utility(pallet_utility::Call::batch_all { - calls: vec![RuntimeCall::Utility(pallet_utility::Call::as_derivative { - index: 0, - call: Box::new(RuntimeCall::Staking(pallet_staking::Call::bond { - value: 10_000_u128, - payee: pallet_staking::RewardDestination::Stash, - })), - })], + let nested_batches = RuntimeCall::Utility(pallet_utility::Call::batch { + calls: vec![RuntimeCall::Utility(pallet_utility::Call::batch_all { + calls: vec![RuntimeCall::Utility(pallet_utility::Call::as_derivative { + index: 0, + call: Box::new(RuntimeCall::Staking(pallet_staking::Call::bond { + value: 10_000_u128, + payee: pallet_staking::RewardDestination::Stash, + })), })], - }), - Some((NOM_1_STASH, extra.clone())), - ); + })], + }); - let valid_call = TestXt::::new( - RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { - dest: NOM_1_STASH, - value: 10_000_u128, - }), - Some((NOM_1_STASH, extra.clone())), - ); + let valid_call = RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { + dest: NOM_1_STASH, + value: 10_000_u128, + }); - let valid_signer = TestXt::::new( - RuntimeCall::Staking(pallet_staking::Call::bond { - value: 10_000_u128, - payee: pallet_staking::RewardDestination::Stash, - }), - Some((SIGNER, extra)), - ); + let valid_signer = RuntimeCall::Staking(pallet_staking::Call::bond { + value: 10_000_u128, + payee: pallet_staking::RewardDestination::Stash, + }); ExtBuilder::::default() .initial_authorities(vec![ @@ -570,56 +579,28 @@ fn staking_blacklist_works() { .build() .execute_with(|| { assert_eq!( - Executive::validate_transaction( - sp_runtime::transaction_validity::TransactionSource::External, - invalid_call, - Default::default(), - ) - .unwrap_err(), + validate_blacklist(NOM_1_STASH, invalid_call).unwrap_err(), InvalidTransaction::Call.into() ); assert_eq!( - Executive::validate_transaction( - sp_runtime::transaction_validity::TransactionSource::External, - invalid_batch, - Default::default(), - ) - .unwrap_err(), + validate_blacklist(NOM_1_STASH, invalid_batch).unwrap_err(), InvalidTransaction::Call.into() ); assert_eq!( - Executive::validate_transaction( - sp_runtime::transaction_validity::TransactionSource::External, - invalid_batch_all, - Default::default(), - ) - .unwrap_err(), + validate_blacklist(NOM_1_STASH, invalid_batch_all).unwrap_err(), InvalidTransaction::Call.into() ); assert_eq!( - Executive::validate_transaction( - sp_runtime::transaction_validity::TransactionSource::External, - nested_batches, - Default::default(), - ) - .unwrap_err(), + validate_blacklist(NOM_1_STASH, nested_batches).unwrap_err(), InvalidTransaction::Call.into() ); - assert_ok!(Executive::validate_transaction( - sp_runtime::transaction_validity::TransactionSource::External, - valid_call, - Default::default(), - )); + assert_ok!(validate_blacklist(NOM_1_STASH, valid_call)); - assert_ok!(Executive::validate_transaction( - sp_runtime::transaction_validity::TransactionSource::External, - valid_signer, - Default::default(), - )); + assert_ok!(validate_blacklist(SIGNER, valid_signer)); }); } @@ -1379,7 +1360,7 @@ fn rent_pool_disbursments_work() { // imitate rent charging let rent = u128::from(1 + (blocks_1 + blocks_2) * reward_points); - let imbalance = CurrencyOf::::issue(rent); + let imbalance = as Currency>::issue(rent); let result = CurrencyOf::::resolve_into_existing( &StakingRewards::rent_pool_account_id(), imbalance, From 9cf598aafb39a9f3cf41fec3bd00ecae84d5de72 Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Tue, 9 Jun 2026 22:15:06 +0400 Subject: [PATCH 03/13] Restore ethexe Malachite on stable2603 --- Cargo.lock | 853 +++++++++++++++++++- Cargo.toml | 19 + TODOS.md | 8 +- docs/polkadot-sdk-stable2603-3-migration.md | 13 +- ethexe/cli/Cargo.toml | 1 + ethexe/service/Cargo.toml | 1 + utils/gear-workspace-hack/Cargo.toml | 70 +- 7 files changed, 906 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 632b9a2c47d..ff8b9084a78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,16 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "advisory-lock" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6caee7d48f930f9ad3fc9546f8cbf843365da0c5b0ca4eee1d1ac3dd12d8f93" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "aead" version = "0.5.2" @@ -999,6 +1009,355 @@ dependencies = [ "derive_arbitrary", ] +[[package]] +name = "arc-malachitebft-app" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-codec", + "arc-malachitebft-config", + "arc-malachitebft-core-consensus", + "arc-malachitebft-core-types", + "arc-malachitebft-engine", + "arc-malachitebft-metrics", + "arc-malachitebft-network", + "arc-malachitebft-peer", + "arc-malachitebft-signing", + "arc-malachitebft-sync", + "arc-malachitebft-wal", + "async-trait", + "derive-where", + "eyre", + "libp2p", + "libp2p-identity", + "ractor", + "rand 0.8.5", + "serde", + "tokio", + "tracing", +] + +[[package]] +name = "arc-malachitebft-app-channel" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-app", + "arc-malachitebft-config", + "arc-malachitebft-engine", + "arc-malachitebft-signing", + "bytes", + "derive-where", + "eyre", + "ractor", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "arc-malachitebft-codec" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "bytes", +] + +[[package]] +name = "arc-malachitebft-config" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-types", + "bytesize", + "config", + "humantime-serde", + "multiaddr 0.18.2", + "serde", + "tracing", +] + +[[package]] +name = "arc-malachitebft-core-consensus" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-driver", + "arc-malachitebft-core-types", + "arc-malachitebft-core-votekeeper", + "arc-malachitebft-metrics", + "arc-malachitebft-peer", + "async-recursion", + "derive-where", + "futures", + "genawaiter", + "multiaddr 0.18.2", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "arc-malachitebft-core-driver" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-state-machine", + "arc-malachitebft-core-types", + "arc-malachitebft-core-votekeeper", + "derive-where", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "arc-malachitebft-core-state-machine" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-types", + "derive-where", + "displaydoc", +] + +[[package]] +name = "arc-malachitebft-core-types" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-peer", + "async-trait", + "bytes", + "derive-where", + "serde", + "thiserror 2.0.17", +] + +[[package]] +name = "arc-malachitebft-core-votekeeper" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-types", + "derive-where", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "arc-malachitebft-discovery" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-metrics", + "either", + "eyre", + "libp2p", + "rand 0.8.5", + "serde", + "tokio", + "tracing", +] + +[[package]] +name = "arc-malachitebft-engine" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-codec", + "arc-malachitebft-config", + "arc-malachitebft-core-consensus", + "arc-malachitebft-core-driver", + "arc-malachitebft-core-state-machine", + "arc-malachitebft-core-types", + "arc-malachitebft-core-votekeeper", + "arc-malachitebft-metrics", + "arc-malachitebft-network", + "arc-malachitebft-signing", + "arc-malachitebft-sync", + "arc-malachitebft-wal", + "async-recursion", + "async-trait", + "byteorder", + "bytes", + "bytesize", + "derive-where", + "eyre", + "hex", + "libp2p", + "ractor", + "rand 0.8.5", + "tokio", + "tracing", +] + +[[package]] +name = "arc-malachitebft-metrics" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-state-machine", + "prometheus-client", +] + +[[package]] +name = "arc-malachitebft-network" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-discovery", + "arc-malachitebft-metrics", + "arc-malachitebft-peer", + "arc-malachitebft-sync", + "async-trait", + "asynchronous-codec 0.7.0", + "bytes", + "either", + "eyre", + "futures", + "hex", + "itertools 0.14.0", + "libp2p", + "libp2p-gossipsub", + "libp2p-scatter", + "libp2p-stream", + "seahash", + "serde", + "thiserror 2.0.17", + "tokio", + "tracing", + "unsigned-varint 0.8.0", + "void", +] + +[[package]] +name = "arc-malachitebft-peer" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "bs58", + "multihash 0.19.5", + "rand 0.8.5", + "serde", + "thiserror 2.0.17", +] + +[[package]] +name = "arc-malachitebft-proto" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "prost 0.13.5", + "prost-types 0.13.5", + "thiserror 2.0.17", +] + +[[package]] +name = "arc-malachitebft-signing" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-types", + "async-trait", + "signature", +] + +[[package]] +name = "arc-malachitebft-signing-ecdsa" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-types", + "base64 0.22.1", + "k256", + "rand 0.8.5", + "serde", + "signature", +] + +[[package]] +name = "arc-malachitebft-signing-ed25519" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-types", + "base64 0.22.1", + "ed25519-consensus", + "rand 0.8.5", + "serde", + "signature", +] + +[[package]] +name = "arc-malachitebft-sync" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-core-types", + "arc-malachitebft-metrics", + "arc-malachitebft-peer", + "async-trait", + "bytes", + "dashmap 6.1.0", + "derive-where", + "displaydoc", + "eyre", + "genawaiter", + "libp2p", + "rand 0.8.5", + "serde", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "arc-malachitebft-test" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "arc-malachitebft-app", + "arc-malachitebft-codec", + "arc-malachitebft-config", + "arc-malachitebft-core-consensus", + "arc-malachitebft-core-types", + "arc-malachitebft-engine", + "arc-malachitebft-peer", + "arc-malachitebft-proto", + "arc-malachitebft-signing", + "arc-malachitebft-signing-ed25519", + "arc-malachitebft-sync", + "async-trait", + "base64 0.22.1", + "bytes", + "ed25519-consensus", + "eyre", + "futures", + "hex", + "libp2p-identity", + "prost 0.13.5", + "prost-build 0.13.5", + "prost-types 0.13.5", + "protox", + "rand 0.8.5", + "serde", + "serde_json", + "sha3", + "signature", + "tokio", + "tracing", +] + +[[package]] +name = "arc-malachitebft-wal" +version = "0.7.0-pre" +source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +dependencies = [ + "advisory-lock", + "bytes", + "cfg-if", + "crc32fast", +] + [[package]] name = "ark-bls12-377" version = "0.4.0" @@ -2093,6 +2452,12 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + [[package]] name = "bimap" version = "0.6.3" @@ -2332,6 +2697,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bon" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97493a391b4b18ee918675fb8663e53646fd09321c58b46afa04e8ce2499c869" +dependencies = [ + "bon-macros", + "rustversion", +] + +[[package]] +name = "bon-macros" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2af3eac944c12cdf4423eab70d310da0a8e5851a18ffb192c0a5e3f7ae1663" +dependencies = [ + "darling 0.20.11", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "borsh" version = "1.6.0" @@ -2526,6 +2914,15 @@ dependencies = [ "serde", ] +[[package]] +name = "bytesize" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" +dependencies = [ + "serde", +] + [[package]] name = "bzip2-sys" version = "0.1.13+1.0.8" @@ -2677,6 +3074,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cbor4ii" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "472931dd4dfcc785075b09be910147f9c6258883fc4591d0dac6116392b2daa6" +dependencies = [ + "serde", +] + [[package]] name = "cc" version = "1.2.52" @@ -2979,7 +3385,7 @@ checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ "serde", "termcolor", - "unicode-width 0.1.14", + "unicode-width 0.2.2", ] [[package]] @@ -3084,6 +3490,18 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "config" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" +dependencies = [ + "nom 7.1.3", + "pathdiff", + "serde", + "toml 0.8.23", +] + [[package]] name = "console" version = "0.15.11" @@ -3819,6 +4237,19 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.6.4", + "subtle-ng", + "zeroize", +] + [[package]] name = "cxx" version = "1.0.192" @@ -5138,6 +5569,21 @@ dependencies = [ "signature", ] +[[package]] +name = "ed25519-consensus" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" +dependencies = [ + "curve25519-dalek-ng", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "thiserror 1.0.69", + "zeroize", +] + [[package]] name = "ed25519-dalek" version = "2.2.0" @@ -5202,6 +5648,7 @@ dependencies = [ "ff", "generic-array 0.14.7", "group", + "pem-rfc7468", "pkcs8", "rand_core 0.6.4", "sec1", @@ -5413,6 +5860,7 @@ dependencies = [ "ethexe-compute", "ethexe-db", "ethexe-ethereum", + "ethexe-malachite", "ethexe-network", "ethexe-processor", "ethexe-prometheus", @@ -5516,60 +5964,120 @@ dependencies = [ ] [[package]] -name = "ethexe-db" +name = "ethexe-db" +version = "2.0.0" +dependencies = [ + "alloy", + "anyhow", + "auto_impl", + "dashmap 5.5.3", + "delegate", + "derive_more 2.1.1", + "ethexe-common", + "ethexe-ethereum", + "ethexe-runtime-common", + "flate2", + "futures", + "gear-core", + "gear-workspace-hack", + "gprimitives", + "gsigner", + "hex", + "indoc", + "log", + "parity-scale-codec", + "paste", + "rocksdb", + "scale-info", + "scopeguard", + "serde", + "serde_json", + "sha3", + "tempfile", + "tracing", +] + +[[package]] +name = "ethexe-ethereum" +version = "2.0.0" +dependencies = [ + "alloy", + "anyhow", + "async-trait", + "ethexe-common", + "futures", + "gear-core", + "gear-core-errors", + "gear-utils", + "gear-workspace-hack", + "gprimitives", + "gsigner", + "log", + "nonempty 0.12.0", + "rand 0.8.5", + "serde", + "tokio", + "tracing", +] + +[[package]] +name = "ethexe-malachite" version = "2.0.0" dependencies = [ "alloy", "anyhow", - "auto_impl", - "dashmap 5.5.3", - "delegate", + "async-trait", "derive_more 2.1.1", "ethexe-common", - "ethexe-ethereum", + "ethexe-db", + "ethexe-malachite-core", "ethexe-runtime-common", - "flate2", "futures", - "gear-core", "gear-workspace-hack", "gprimitives", "gsigner", - "hex", - "indoc", - "log", "parity-scale-codec", - "paste", - "rocksdb", - "scale-info", - "scopeguard", - "serde", - "serde_json", - "sha3", + "proptest", "tempfile", + "tokio", "tracing", + "tracing-subscriber", ] [[package]] -name = "ethexe-ethereum" +name = "ethexe-malachite-core" version = "2.0.0" dependencies = [ - "alloy", + "advisory-lock", "anyhow", + "arc-malachitebft-app", + "arc-malachitebft-app-channel", + "arc-malachitebft-codec", + "arc-malachitebft-core-consensus", + "arc-malachitebft-core-types", + "arc-malachitebft-engine", + "arc-malachitebft-signing", + "arc-malachitebft-signing-ecdsa", + "arc-malachitebft-sync", + "arc-malachitebft-test", "async-trait", - "ethexe-common", + "bytes", "futures", "gear-core", - "gear-core-errors", - "gear-utils", "gear-workspace-hack", "gprimitives", "gsigner", - "log", - "nonempty 0.12.0", - "rand 0.8.5", + "hex", + "libp2p-identity", + "parity-scale-codec", + "proptest", + "rocksdb", "serde", + "sha3", + "tempfile", "tokio", "tracing", + "tracing-subscriber", ] [[package]] @@ -5839,6 +6347,7 @@ dependencies = [ "ethexe-consensus", "ethexe-db", "ethexe-ethereum", + "ethexe-malachite", "ethexe-network", "ethexe-observer", "ethexe-processor", @@ -5924,6 +6433,16 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "fail" version = "0.5.1" @@ -7764,6 +8283,7 @@ dependencies = [ "hashbrown 0.16.1", "hashbrown 0.17.1", "hex", + "hickory-proto 0.24.4", "hkdf", "hmac 0.12.1", "http-body-util", @@ -7788,7 +8308,11 @@ dependencies = [ "keccak", "libc", "libp2p", + "libp2p-core", + "libp2p-gossipsub", "libp2p-identity", + "libp2p-kad", + "libp2p-request-response", "libp2p-swarm", "libp2p-tcp", "librocksdb-sys", @@ -7802,6 +8326,7 @@ dependencies = [ "merlin", "miniz_oxide", "mio", + "multihash 0.19.5", "names", "netlink-proto", "netlink-sys", @@ -7860,6 +8385,7 @@ dependencies = [ "proc-macro2", "proptest", "prost 0.13.5", + "prost-types 0.13.5", "pulley-interpreter", "quanta", "quote", @@ -7992,11 +8518,27 @@ dependencies = [ "wasmparser 0.230.0 (registry+https://github.com/rust-lang/crates.io-index)", "wasmtime-internal-core", "winnow", + "x25519-dalek", "yasna", "zerocopy", "zeroize", ] +[[package]] +name = "genawaiter" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" +dependencies = [ + "genawaiter-macro", +] + +[[package]] +name = "genawaiter-macro" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" + [[package]] name = "generate-bags" version = "46.0.0" @@ -8650,6 +9192,9 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hex-conservative" @@ -8879,6 +9424,22 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" + +[[package]] +name = "humantime-serde" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c" +dependencies = [ + "humantime", + "serde", +] + [[package]] name = "hyper" version = "0.14.32" @@ -9247,6 +9808,12 @@ dependencies = [ "quote", ] +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + [[package]] name = "indexmap" version = "1.9.3" @@ -10029,6 +10596,7 @@ dependencies = [ "quick-protobuf", "rand 0.8.5", "rw-stream-sink", + "serde", "smallvec", "thiserror 1.0.69", "tracing", @@ -10077,6 +10645,7 @@ dependencies = [ "quick-protobuf-codec", "rand 0.8.5", "regex", + "serde", "sha2 0.10.9", "smallvec", "tracing", @@ -10119,8 +10688,10 @@ dependencies = [ "hkdf", "k256", "multihash 0.19.5", + "p256", "quick-protobuf", "rand 0.8.5", + "sec1", "serde", "sha2 0.10.9", "thiserror 2.0.17", @@ -10148,6 +10719,7 @@ dependencies = [ "quick-protobuf", "quick-protobuf-codec", "rand 0.8.5", + "serde", "sha2 0.10.9", "smallvec", "thiserror 1.0.69", @@ -10288,6 +10860,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1356c9e376a94a75ae830c42cdaea3d4fe1290ba409a22c809033d1b7dcab0a6" dependencies = [ "async-trait", + "cbor4ii", "futures", "futures-bounded", "futures-timer", @@ -10295,12 +10868,43 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "rand 0.8.5", + "serde", "smallvec", "tracing", "void", "web-time", ] +[[package]] +name = "libp2p-scatter" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14fe352c950cea000ecc697e2e71ce22a3586b607d74104ec6aaf22deaef1883" +dependencies = [ + "bytes", + "fnv", + "futures", + "libp2p", + "prometheus-client", + "tracing", + "unsigned-varint 0.8.0", +] + +[[package]] +name = "libp2p-stream" +version = "0.2.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d454f6647bc9054e7fede2dc86e625786c4d1304bff7afc995285f53ef9091f0" +dependencies = [ + "futures", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "rand 0.8.5", + "tracing", + "void", +] + [[package]] name = "libp2p-swarm" version = "0.45.1" @@ -10682,6 +11286,40 @@ dependencies = [ "value-bag", ] +[[package]] +name = "logos" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "192a3a2b90b0c05b27a0b2c43eecdb7c415e29243acc3f89cc8247a5b693045c" +dependencies = [ + "beef", + "fnv", + "lazy_static", + "proc-macro2", + "quote", + "regex-syntax 0.8.8", + "rustc_version 0.4.1", + "syn 2.0.114", +] + +[[package]] +name = "logos-derive" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470" +dependencies = [ + "logos-codegen", +] + [[package]] name = "loom" version = "0.7.2" @@ -11008,6 +11646,28 @@ dependencies = [ "sketches-ddsketch", ] +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "cfg-if", + "miette-derive", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "mimalloc" version = "0.1.48" @@ -11206,6 +11866,7 @@ version = "0.19.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "577c63b00ad74d57e8c9aa870b5fccebf2fd64a308a5aee9f1bb88e4aea19447" dependencies = [ + "serde", "unsigned-varint 0.8.0", ] @@ -11841,6 +12502,18 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.9", +] + [[package]] name = "page_size" version = "0.6.0" @@ -13909,6 +14582,15 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "primitive-types" version = "0.12.2" @@ -14213,6 +14895,18 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "prost-reflect" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37587d5a8a1b3dc9863403d084fc2254b91ab75a702207098837950767e2260b" +dependencies = [ + "logos", + "miette", + "prost 0.13.5", + "prost-types 0.13.5", +] + [[package]] name = "prost-types" version = "0.13.5" @@ -14231,6 +14925,33 @@ dependencies = [ "prost 0.14.4", ] +[[package]] +name = "protox" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "424c2bd294b69c49b949f3619362bc3c5d28298cd1163b6d1a62df37c16461aa" +dependencies = [ + "bytes", + "miette", + "prost 0.13.5", + "prost-reflect", + "prost-types 0.13.5", + "protox-parse", + "thiserror 2.0.17", +] + +[[package]] +name = "protox-parse" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57927f9dbeeffcce7192404deee6157a640cbb3fe8ac11eabbe571565949ab75" +dependencies = [ + "logos", + "miette", + "prost-types 0.13.5", + "thiserror 2.0.17", +] + [[package]] name = "pulley-interpreter" version = "44.0.2" @@ -14379,6 +15100,27 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "ractor" +version = "0.15.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12c86deb2af198b10a04c4fb3fba73baf3bb300df765a29272f0e5583da7510" +dependencies = [ + "async-trait", + "bon", + "dashmap 6.1.0", + "futures", + "js-sys", + "once_cell", + "strum 0.28.0", + "tokio", + "tokio_with_wasm", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-time", +] + [[package]] name = "radium" version = "0.7.0" @@ -16606,6 +17348,12 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "sec1" version = "0.7.3" @@ -18340,6 +19088,15 @@ dependencies = [ "strum_macros 0.27.2", ] +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros 0.28.0", +] + [[package]] name = "strum_macros" version = "0.24.3" @@ -18378,6 +19135,18 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "substrate-bip39" version = "0.6.1" @@ -18524,6 +19293,12 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + [[package]] name = "subxt" version = "0.44.2" @@ -19109,6 +19884,7 @@ dependencies = [ "signal-hook-registry", "socket2 0.6.1", "tokio-macros", + "tracing", "windows-sys 0.61.2", ] @@ -19201,6 +19977,30 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio_with_wasm" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34e40fbbbd95441133fe9483f522db15dbfd26dc636164ebd8f2dd28759a6aa6" +dependencies = [ + "js-sys", + "tokio", + "tokio_with_wasm_proc", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "tokio_with_wasm_proc" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d01145a2c788d6aae4cd653afec1e8332534d7d783d01897cefcafe4428de992" +dependencies = [ + "quote", + "syn 2.0.114", +] + [[package]] name = "toml" version = "0.5.11" @@ -19741,6 +20541,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" dependencies = [ + "asynchronous-codec 0.7.0", "bytes", "tokio-util", ] diff --git a/Cargo.toml b/Cargo.toml index 7d741b9105e..cb0051edea2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,8 @@ members = [ "vara/tools/regression-analysis/junit-common", # ethexe "ethexe/*", + "ethexe/malachite/core", + "ethexe/malachite/service", "ethexe/runtime/common", "ethexe/service/utils", # sdk @@ -381,11 +383,28 @@ ethexe-compute = { path = "ethexe/compute", default-features = false } ethexe-blob-loader = { path = "ethexe/blob-loader", default-features = false } ethexe-db-init = { path = "ethexe/db/init", default-features = false } ethexe-node-wrapper = {path = "ethexe/node-wrapper", default-features = false} +ethexe-malachite = { path = "ethexe/malachite/service", default-features = false } +ethexe-malachite-core = { path = "ethexe/malachite/core", default-features = false } libp2p-identity = { version = "0.2", default-features = false, features = ["secp256k1"] } # Pinned at the version `ethexe-db`'s librocksdb-sys uses — only one # `links = "rocksdb"` crate may live in the dependency graph. rocksdb = { version = "0.24", default-features = false, features = ["snappy"] } +# Malachite BFT engine — Gear compatibility fork pinned so all sub-crates share +# the stable2603-compatible libp2p snapshot. +malachitebft-app-channel = { package = "arc-malachitebft-app-channel", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-app = { package = "arc-malachitebft-app", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-codec = { package = "arc-malachitebft-codec", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-core-consensus = { package = "arc-malachitebft-core-consensus", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-core-types = { package = "arc-malachitebft-core-types", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-engine = { package = "arc-malachitebft-engine", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-proto = { package = "arc-malachitebft-proto", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-signing = { package = "arc-malachitebft-signing", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-signing-ed25519 = { package = "arc-malachitebft-signing-ed25519", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-signing-ecdsa = { package = "arc-malachitebft-signing-ecdsa", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3", default-features = false, features = ["k256", "rand", "serde", "std"] } +malachitebft-sync = { package = "arc-malachitebft-sync", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +malachitebft-test = { package = "arc-malachitebft-test", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } + # Common executor between `sandbox-host` and `lazy-pages-fuzzer` wasmi = { version = "0.38" } diff --git a/TODOS.md b/TODOS.md index 8a56d48c474..ae89150a665 100644 --- a/TODOS.md +++ b/TODOS.md @@ -8,7 +8,7 @@ - Run try-runtime against production and development snapshots for the wired identity lazy migration and child-bounties v0-to-v1 migration, confirming storage versions, cardinality, and weight bounds. -- Revisit ethexe Malachite once its `libp2p` dependency can coexist with the - stable2603 Polkadot SDK graph. The current blocker is the exact - `libp2p-swarm-derive` conflict between stable2603 `sc-network` and - Malachite's `libp2p` stack. +- Port the prior ethexe Malachite hardening items on top of the stable2603 + dependency graph: validator identity/peer gating, bounded stream cleanup, + injected transaction caps and duplicate checks, quarantine liveness, and + typed-hash audit items. diff --git a/docs/polkadot-sdk-stable2603-3-migration.md b/docs/polkadot-sdk-stable2603-3-migration.md index 21cdeffb532..64f7d54b14b 100644 --- a/docs/polkadot-sdk-stable2603-3-migration.md +++ b/docs/polkadot-sdk-stable2603-3-migration.md @@ -89,10 +89,13 @@ In this branch: ## Deferred Items - Evaluate `system_version >= 3` pending-code runtime-upgrade semantics. -- Re-enable or realign ethexe Malachite integration after resolving the - stable2603 `libp2p` version conflict. The concrete resolver blocker is - stable2603 `sc-network` pulling `libp2p` 0.54 / `libp2p-swarm` 0.45 while - Malachite pulls `libp2p` 0.56 / `libp2p-swarm` 0.47, whose exact - `libp2p-swarm-derive` requirements cannot coexist in the same workspace. +- ethexe Malachite is re-enabled through the Gear compatibility fork at + `gear-tech/malachite` commit + `c53a7a2b424b5d951de8284529c2e7d36901f3b3`. The fork keeps Malachite on + the stable2603 `libp2p` 0.54 / `libp2p-swarm` 0.45 line so the workspace has + one `libp2p-swarm-derive` identity. +- Port prior Malachite hardening work after the stable2603 dependency update: + validator identity/peer gating, bounded stream cleanup, injected transaction + caps and duplicate checks, quarantine liveness, and typed-hash audit items. - Run try-runtime against production and development snapshots before shipping the wired identity and child-bounties runtime migrations. diff --git a/ethexe/cli/Cargo.toml b/ethexe/cli/Cargo.toml index 9db483eef03..185e256c3b6 100644 --- a/ethexe/cli/Cargo.toml +++ b/ethexe/cli/Cargo.toml @@ -18,6 +18,7 @@ path = "src/main.rs" [dependencies] ethexe-compute.workspace = true ethexe-network.workspace = true +ethexe-malachite.workspace = true ethexe-prometheus.workspace = true ethexe-rpc = { workspace = true, features = ["client"] } ethexe-service.workspace = true diff --git a/ethexe/service/Cargo.toml b/ethexe/service/Cargo.toml index 6ccddddd216..00eb0b3c584 100644 --- a/ethexe/service/Cargo.toml +++ b/ethexe/service/Cargo.toml @@ -19,6 +19,7 @@ ethexe-observer.workspace = true ethexe-blob-loader.workspace = true ethexe-processor.workspace = true ethexe-consensus.workspace = true +ethexe-malachite.workspace = true ethexe-ethereum.workspace = true ethexe-common = { workspace = true, features = ["std", "mock"] } ethexe-runtime-common.workspace = true diff --git a/utils/gear-workspace-hack/Cargo.toml b/utils/gear-workspace-hack/Cargo.toml index 4aaa2721130..aaa6dc26ec2 100644 --- a/utils/gear-workspace-hack/Cargo.toml +++ b/utils/gear-workspace-hack/Cargo.toml @@ -255,7 +255,7 @@ bs58 = { version = "0.5", features = ["check"] } bumpalo = { version = "3", features = ["allocator-api2"] } byte-slice-cast = { version = "1", default-features = false, features = ["std"] } bytemuck = { version = "1", default-features = false, features = ["const_zeroed", "derive", "min_const_generics", "must_cast"] } -byteorder = { version = "1" } +byteorder = { version = "1", features = ["i128"] } bytes = { version = "1", features = ["serde"] } clap = { version = "4", features = ["derive", "env", "string", "wrap_help"] } clap_builder = { version = "4", default-features = false, features = ["color", "env", "std", "string", "suggestions", "usage", "wrap_help"] } @@ -271,16 +271,16 @@ crunchy = { version = "0.2", features = ["std"] } crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } curve25519-dalek = { version = "4", features = ["digest", "legacy_compatibility"] } data-encoding = { version = "2" } -der = { version = "0.7", default-features = false, features = ["oid", "std", "zeroize"] } +der = { version = "0.7", default-features = false, features = ["oid", "pem", "std"] } derive_more-f595c2ba2a3f28df = { package = "derive_more", version = "2", default-features = false, features = ["full", "std"] } digest-274715c4dabd11b0 = { package = "digest", version = "0.9", default-features = false, features = ["std"] } digest-93f6ce9d446188ac = { package = "digest", version = "0.10", features = ["mac", "oid", "std"] } -ecdsa = { version = "0.16", default-features = false, features = ["pkcs8", "serde", "signing", "std", "verifying"] } +ecdsa = { version = "0.16", default-features = false, features = ["pem", "serde", "signing", "std", "verifying"] } ed25519 = { version = "2", default-features = false, features = ["alloc", "std"] } ed25519-dalek = { version = "2", features = ["rand_core"] } ed25519-zebra = { version = "4", default-features = false, features = ["std"] } either = { version = "1", features = ["serde", "use_std"] } -elliptic-curve = { version = "0.13", default-features = false, features = ["arithmetic", "digest", "hazmat", "serde", "std"] } +elliptic-curve = { version = "0.13", default-features = false, features = ["digest", "hazmat", "pem", "serde", "std"] } enumflags2 = { version = "0.7", default-features = false, features = ["std"] } env_filter = { version = "0.1" } environmental = { version = "1" } @@ -314,7 +314,7 @@ hashbrown-594e8ee84c453af0 = { package = "hashbrown", version = "0.13", features hashbrown-5ef9efb8ec2df382 = { package = "hashbrown", version = "0.12", features = ["raw"] } hashbrown-9067fe90e8c1f593 = { package = "hashbrown", version = "0.17", default-features = false, features = ["default-hasher"] } hashbrown-986da7b5efc2b80e = { package = "hashbrown", version = "0.16", features = ["serde"] } -hex = { version = "0.4" } +hex = { version = "0.4", features = ["serde"] } hkdf = { version = "0.12", default-features = false, features = ["std"] } hmac = { version = "0.12", default-features = false, features = ["reset", "std"] } http-body-util = { version = "0.1" } @@ -322,6 +322,7 @@ hyper-582f2526e08bb6a0 = { package = "hyper", version = "0.14", features = ["cli hyper-dff4ba8e3ae991db = { package = "hyper", version = "1", features = ["client", "http1", "http2", "server"] } hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "rustls-native-certs", "tls12"] } hyper-util = { version = "0.1", features = ["client-legacy", "server-auto", "server-graceful", "service"] } +idna = { version = "1", default-features = false, features = ["compiled_data", "std"] } impl-codec = { version = "0.7", default-features = false, features = ["std"] } impl-serde = { version = "0.5", default-features = false, features = ["std"] } indexmap = { version = "2", features = ["serde"] } @@ -336,8 +337,12 @@ jsonrpsee-core = { version = "0.24", features = ["async-client", "async-wasm-cli k256 = { version = "0.13", features = ["serde"] } keccak = { version = "0.1", default-features = false, features = ["asm"] } libc = { version = "0.2" } -libp2p = { version = "0.54", default-features = false, features = ["dns", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "tcp", "tls", "tokio", "websocket", "yamux"] } -libp2p-identity = { version = "0.2", default-features = false, features = ["ed25519", "peerid", "rand", "secp256k1", "serde"] } +libp2p = { version = "0.54", default-features = false, features = ["cbor", "dns", "ecdsa", "ed25519", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "serde", "tcp", "tls", "tokio", "websocket", "yamux"] } +libp2p-core = { version = "0.42", default-features = false, features = ["serde"] } +libp2p-gossipsub = { version = "0.47", default-features = false, features = ["serde"] } +libp2p-identity = { version = "0.2", default-features = false, features = ["ecdsa", "ed25519", "peerid", "rand", "secp256k1", "serde"] } +libp2p-kad = { version = "0.46", default-features = false, features = ["serde"] } +libp2p-request-response = { version = "0.27", default-features = false, features = ["cbor"] } libp2p-swarm = { version = "0.45", default-features = false, features = ["async-std", "macros", "tokio"] } libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context", "std"] } libsecp256k1-core = { version = "0.3" } @@ -346,6 +351,7 @@ macro_magic = { version = "0.5", features = ["proc_support"] } memchr = { version = "2" } memory-db = { version = "0.34", default-features = false, features = ["std"] } merlin = { version = "3", default-features = false, features = ["std"] } +multihash = { version = "0.19", features = ["serde-codec"] } names = { version = "0.14" } nom = { version = "7" } num-bigint = { version = "0.4" } @@ -362,7 +368,7 @@ parity-scale-codec = { version = "3", features = ["bit-vec", "bytes", "derive", parity-wasm = { git = "https://github.com/gear-tech/parity-wasm", branch = "v0.45.0-sign-ext" } pbkdf2 = { version = "0.12", features = ["std"] } percent-encoding = { version = "2" } -pkcs8 = { version = "0.10", default-features = false, features = ["std"] } +pkcs8 = { version = "0.10", default-features = false, features = ["pem", "std"] } polkavm-common = { version = "0.9", features = ["alloc", "logging"] } portable-atomic = { version = "1", features = ["require-cas"] } ppv-lite86 = { version = "0.2", default-features = false, features = ["simd", "std"] } @@ -371,6 +377,7 @@ primitive-types = { version = "0.13", default-features = false, features = ["byt proc-macro2 = { version = "1", features = ["span-locations"] } proptest = { version = "1", features = ["alloc", "no_std"] } prost = { version = "0.13", features = ["prost-derive"] } +prost-types = { version = "0.13" } pulley-interpreter = { version = "44", default-features = false, features = ["disas", "interp", "std"] } quanta = { version = "0.12" } quote = { version = "1" } @@ -400,7 +407,7 @@ scale-encode = { version = "0.10" } scale-info = { version = "2", features = ["bit-vec", "decode", "derive", "docs", "serde"] } scale-type-resolver = { version = "0.2" } schnorrkel = { version = "0.11", features = ["preaudit_deprecated"] } -sec1 = { version = "0.7", features = ["serde", "std", "subtle"] } +sec1 = { version = "0.7", features = ["pem", "serde", "std", "subtle"] } secp256k1 = { version = "0.28", features = ["global-context", "recovery"] } secrecy = { version = "0.8" } semver = { version = "1", features = ["serde"] } @@ -449,7 +456,7 @@ sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", sp-trie = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } -spki = { version = "0.7", default-features = false, features = ["std"] } +spki = { version = "0.7", default-features = false, features = ["pem", "std"] } ss58-registry = { version = "1", default-features = false, features = ["std"] } stable_deref_trait = { version = "1", default-features = false, features = ["std"] } strum-2f80eeee3b1b6c7e = { package = "strum", version = "0.26", features = ["derive"] } @@ -464,7 +471,7 @@ syn-f595c2ba2a3f28df = { package = "syn", version = "2", features = ["extra-trai thiserror = { version = "2" } time = { version = "0.3", features = ["formatting", "macros", "parsing"] } tiny-keccak = { version = "2", features = ["keccak", "shake"] } -tokio = { version = "1", features = ["full", "test-util"] } +tokio = { version = "1", features = ["full", "test-util", "tracing"] } tokio-rustls = { version = "0.26", default-features = false, features = ["logging", "ring", "tls12"] } tokio-stream = { version = "0.1", features = ["sync"] } tokio-util = { version = "0.7", features = ["codec", "compat", "io"] } @@ -482,7 +489,7 @@ tuplex = { version = "0.1", default-features = false, features = ["std"] } twox-hash = { version = "1", default-features = false, features = ["digest_0_10", "std"] } uint = { version = "0.10" } unicode-normalization = { version = "0.1", default-features = false, features = ["std"] } -unsigned-varint-c38e5c1d305a1b54 = { package = "unsigned-varint", version = "0.8", default-features = false, features = ["codec"] } +unsigned-varint-c38e5c1d305a1b54 = { package = "unsigned-varint", version = "0.8", default-features = false, features = ["asynchronous_codec", "codec"] } unsigned-varint-ca01ad9e24f5d932 = { package = "unsigned-varint", version = "0.7", default-features = false, features = ["asynchronous_codec", "futures"] } url = { version = "2", features = ["serde"] } uuid = { version = "1", features = ["v4"] } @@ -492,6 +499,7 @@ wasmi = { version = "0.38", features = ["extra-checks"] } wasmparser = { version = "0.230", default-features = false, features = ["component-model", "features", "simd", "std", "validate"] } wasmtime-internal-core = { version = "44", default-features = false, features = ["anyhow", "serde", "std"] } winnow = { version = "0.7" } +x25519-dalek = { version = "2", features = ["static_secrets"] } zeroize = { version = "1", features = ["derive", "std"] } [target.'cfg(not(any(target_arch = "wasm32", loom)))'.build-dependencies] @@ -544,7 +552,7 @@ bs58 = { version = "0.5", features = ["check"] } bumpalo = { version = "3", features = ["allocator-api2"] } byte-slice-cast = { version = "1", default-features = false, features = ["std"] } bytemuck = { version = "1", default-features = false, features = ["const_zeroed", "derive", "min_const_generics", "must_cast"] } -byteorder = { version = "1" } +byteorder = { version = "1", features = ["i128"] } bytes = { version = "1", features = ["serde"] } cc = { version = "1", default-features = false, features = ["parallel"] } clap = { version = "4", features = ["derive", "env", "string", "wrap_help"] } @@ -561,18 +569,18 @@ crunchy = { version = "0.2", features = ["std"] } crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } curve25519-dalek = { version = "4", features = ["digest", "legacy_compatibility"] } data-encoding = { version = "2" } -der = { version = "0.7", default-features = false, features = ["oid", "std", "zeroize"] } +der = { version = "0.7", default-features = false, features = ["oid", "pem", "std"] } derive_more-2247a326473123a6 = { package = "derive_more", version = "0.99" } derive_more-f595c2ba2a3f28df = { package = "derive_more", version = "2", default-features = false, features = ["full", "std"] } digest-274715c4dabd11b0 = { package = "digest", version = "0.9", default-features = false, features = ["std"] } digest-93f6ce9d446188ac = { package = "digest", version = "0.10", features = ["mac", "oid", "std"] } displaydoc = { version = "0.2" } -ecdsa = { version = "0.16", default-features = false, features = ["pkcs8", "serde", "signing", "std", "verifying"] } +ecdsa = { version = "0.16", default-features = false, features = ["pem", "serde", "signing", "std", "verifying"] } ed25519 = { version = "2", default-features = false, features = ["alloc", "std"] } ed25519-dalek = { version = "2", features = ["rand_core"] } ed25519-zebra = { version = "4", default-features = false, features = ["std"] } either = { version = "1", features = ["serde", "use_std"] } -elliptic-curve = { version = "0.13", default-features = false, features = ["arithmetic", "digest", "hazmat", "serde", "std"] } +elliptic-curve = { version = "0.13", default-features = false, features = ["digest", "hazmat", "pem", "serde", "std"] } enumflags2 = { version = "0.7", default-features = false, features = ["std"] } env_filter = { version = "0.1" } environmental = { version = "1" } @@ -607,7 +615,7 @@ hashbrown-594e8ee84c453af0 = { package = "hashbrown", version = "0.13", features hashbrown-5ef9efb8ec2df382 = { package = "hashbrown", version = "0.12", features = ["raw"] } hashbrown-9067fe90e8c1f593 = { package = "hashbrown", version = "0.17", default-features = false, features = ["default-hasher"] } hashbrown-986da7b5efc2b80e = { package = "hashbrown", version = "0.16", features = ["serde"] } -hex = { version = "0.4" } +hex = { version = "0.4", features = ["serde"] } hkdf = { version = "0.12", default-features = false, features = ["std"] } hmac = { version = "0.12", default-features = false, features = ["reset", "std"] } http-body-util = { version = "0.1" } @@ -615,6 +623,7 @@ hyper-582f2526e08bb6a0 = { package = "hyper", version = "0.14", features = ["cli hyper-dff4ba8e3ae991db = { package = "hyper", version = "1", features = ["client", "http1", "http2", "server"] } hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "ring", "rustls-native-certs", "tls12"] } hyper-util = { version = "0.1", features = ["client-legacy", "server-auto", "server-graceful", "service"] } +idna = { version = "1", default-features = false, features = ["compiled_data", "std"] } impl-codec = { version = "0.7", default-features = false, features = ["std"] } impl-serde = { version = "0.5", default-features = false, features = ["std"] } indexmap = { version = "2", features = ["serde"] } @@ -629,8 +638,12 @@ jsonrpsee-core = { version = "0.24", features = ["async-client", "async-wasm-cli k256 = { version = "0.13", features = ["serde"] } keccak = { version = "0.1", default-features = false, features = ["asm"] } libc = { version = "0.2" } -libp2p = { version = "0.54", default-features = false, features = ["dns", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "tcp", "tls", "tokio", "websocket", "yamux"] } -libp2p-identity = { version = "0.2", default-features = false, features = ["ed25519", "peerid", "rand", "secp256k1", "serde"] } +libp2p = { version = "0.54", default-features = false, features = ["cbor", "dns", "ecdsa", "ed25519", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "serde", "tcp", "tls", "tokio", "websocket", "yamux"] } +libp2p-core = { version = "0.42", default-features = false, features = ["serde"] } +libp2p-gossipsub = { version = "0.47", default-features = false, features = ["serde"] } +libp2p-identity = { version = "0.2", default-features = false, features = ["ecdsa", "ed25519", "peerid", "rand", "secp256k1", "serde"] } +libp2p-kad = { version = "0.46", default-features = false, features = ["serde"] } +libp2p-request-response = { version = "0.27", default-features = false, features = ["cbor"] } libp2p-swarm = { version = "0.45", default-features = false, features = ["async-std", "macros", "tokio"] } libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context", "std"] } libsecp256k1-core = { version = "0.3" } @@ -639,6 +652,7 @@ macro_magic = { version = "0.5", features = ["proc_support"] } memchr = { version = "2" } memory-db = { version = "0.34", default-features = false, features = ["std"] } merlin = { version = "3", default-features = false, features = ["std"] } +multihash = { version = "0.19", features = ["serde-codec"] } names = { version = "0.14" } nom = { version = "7" } num-bigint = { version = "0.4" } @@ -657,7 +671,7 @@ parity-wasm = { git = "https://github.com/gear-tech/parity-wasm", branch = "v0.4 pbkdf2 = { version = "0.12", features = ["std"] } percent-encoding = { version = "2" } petgraph = { version = "0.6" } -pkcs8 = { version = "0.10", default-features = false, features = ["std"] } +pkcs8 = { version = "0.10", default-features = false, features = ["pem", "std"] } polkavm-common = { version = "0.9", features = ["alloc", "logging"] } portable-atomic = { version = "1", features = ["require-cas"] } ppv-lite86 = { version = "0.2", default-features = false, features = ["simd", "std"] } @@ -666,6 +680,7 @@ primitive-types = { version = "0.13", default-features = false, features = ["byt proc-macro2 = { version = "1", features = ["span-locations"] } proptest = { version = "1", features = ["alloc", "no_std"] } prost = { version = "0.13", features = ["prost-derive"] } +prost-types = { version = "0.13" } pulley-interpreter = { version = "44", default-features = false, features = ["disas", "interp", "std"] } quanta = { version = "0.12" } quote = { version = "1" } @@ -696,7 +711,7 @@ scale-info = { version = "2", features = ["bit-vec", "decode", "derive", "docs", scale-info-derive = { version = "2", default-features = false, features = ["docs"] } scale-type-resolver = { version = "0.2" } schnorrkel = { version = "0.11", features = ["preaudit_deprecated"] } -sec1 = { version = "0.7", features = ["serde", "std", "subtle"] } +sec1 = { version = "0.7", features = ["pem", "serde", "std", "subtle"] } secp256k1 = { version = "0.28", features = ["global-context", "recovery"] } secrecy = { version = "0.8" } semver = { version = "1", features = ["serde"] } @@ -747,7 +762,7 @@ sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", sp-trie = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", rev = "e3737178ec726cffe506c907263aaaa417893fd0" } -spki = { version = "0.7", default-features = false, features = ["std"] } +spki = { version = "0.7", default-features = false, features = ["pem", "std"] } ss58-registry = { version = "1", default-features = false, features = ["std"] } stable_deref_trait = { version = "1", default-features = false, features = ["std"] } strum-2f80eeee3b1b6c7e = { package = "strum", version = "0.26", features = ["derive"] } @@ -763,7 +778,7 @@ syn-f595c2ba2a3f28df = { package = "syn", version = "2", features = ["extra-trai thiserror = { version = "2" } time = { version = "0.3", features = ["formatting", "macros", "parsing"] } tiny-keccak = { version = "2", features = ["keccak", "shake"] } -tokio = { version = "1", features = ["full", "test-util"] } +tokio = { version = "1", features = ["full", "test-util", "tracing"] } tokio-rustls = { version = "0.26", default-features = false, features = ["logging", "ring", "tls12"] } tokio-stream = { version = "0.1", features = ["sync"] } tokio-util = { version = "0.7", features = ["codec", "compat", "io"] } @@ -781,7 +796,7 @@ tuplex = { version = "0.1", default-features = false, features = ["std"] } twox-hash = { version = "1", default-features = false, features = ["digest_0_10", "std"] } uint = { version = "0.10" } unicode-normalization = { version = "0.1", default-features = false, features = ["std"] } -unsigned-varint-c38e5c1d305a1b54 = { package = "unsigned-varint", version = "0.8", default-features = false, features = ["codec"] } +unsigned-varint-c38e5c1d305a1b54 = { package = "unsigned-varint", version = "0.8", default-features = false, features = ["asynchronous_codec", "codec"] } unsigned-varint-ca01ad9e24f5d932 = { package = "unsigned-varint", version = "0.7", default-features = false, features = ["asynchronous_codec", "futures"] } url = { version = "2", features = ["serde"] } uuid = { version = "1", features = ["v4"] } @@ -791,6 +806,7 @@ wasmi = { version = "0.38", features = ["extra-checks"] } wasmparser = { version = "0.230", default-features = false, features = ["component-model", "features", "simd", "std", "validate"] } wasmtime-internal-core = { version = "44", default-features = false, features = ["anyhow", "serde", "std"] } winnow = { version = "0.7" } +x25519-dalek = { version = "2", features = ["static_secrets"] } zeroize = { version = "1", features = ["derive", "std"] } [target.'cfg(all(target_arch = "x86_64", target_vendor = "unknown", target_os = "linux", target_env = "gnu", not(any(target_arch = "wasm32", loom))))'.dependencies] @@ -798,6 +814,7 @@ errno = { version = "0.3" } event-listener = { version = "5" } event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } @@ -829,6 +846,7 @@ errno = { version = "0.3" } event-listener = { version = "5" } event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } @@ -860,6 +878,7 @@ errno = { version = "0.3" } event-listener = { version = "5" } event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } @@ -891,6 +910,7 @@ errno = { version = "0.3" } event-listener = { version = "5" } event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } @@ -921,6 +941,7 @@ zerocopy = { version = "0.8", default-features = false, features = ["derive", "s errno = { version = "0.3" } event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } @@ -946,6 +967,7 @@ zerocopy = { version = "0.8", default-features = false, features = ["derive", "s errno = { version = "0.3" } event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } +hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } From 527de49bc94f5bc5a2ca7607b23d3aeba41c29eb Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Wed, 10 Jun 2026 13:00:25 +0400 Subject: [PATCH 04/13] Fix stable2603 fork compatibility --- THIRD_PARTY_NOTICES.md | 13 ++++++------- docs/polkadot-sdk-stable2603-3-migration.md | 12 ++++++++++++ ethexe/ethereum/src/router/mod.rs | 2 +- ethexe/processor/src/host/api/lazy_pages.rs | 13 +++++++++---- ethexe/processor/src/host/context.rs | 5 +++++ substrate/README.md | 2 +- 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index bbd9dc04c29..06f21e75426 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -2,20 +2,19 @@ ## Polkadot SDK Copied Sources -Some local crates contain copied or modified source files from `paritytech/polkadot-sdk`: +Some local crates contain copied or modified source files from `paritytech/polkadot-sdk` +at : -- `substrate/sp-allocator` (`sp-allocator`, published by Gear as `gsp-allocator`; derived from upstream `sc-allocator` through the Gear Polkadot SDK fork) +- `substrate/sp-allocator` (`sp-allocator`, published by Gear as `gsp-allocator`; derived from upstream `sc-allocator`) - `substrate/runtime-executor/common` (`sc-executor-common`, published by Gear as `gsc-executor-common`) - `substrate/runtime-executor/polkavm` (`sc-executor-polkavm`, published by Gear as `gsc-executor-polkavm`) - `substrate/runtime-executor/wasmtime` (`sc-executor-wasmtime`, published by Gear as `gsc-executor-wasmtime`) - `substrate/runtime-executor` (`sc-executor`, not published by Gear) - `substrate/substrate-wasm-builder` (`substrate-wasm-builder`, published by Gear as `gsubstrate-wasm-builder`) -Source reference: - -Current migration source reference: - -`substrate/sp-allocator` was sourced from the Gear Polkadot SDK fork `gear-polkadot-stable2409-wasm32v1-none` at `1d1b394647eb26c094cf50c759b900dc5faa3b80`, derived from Parity Polkadot SDK `sc-allocator`. +`substrate/sp-allocator` keeps the historical local package name for dependency +compatibility, while its source is refreshed from upstream +`substrate/client/allocator`. These copied source files retain the upstream copyright notices and their original SPDX headers. See [`substrate/README.md`](substrate/README.md) for the shared fork, provenance, and publishing notice. diff --git a/docs/polkadot-sdk-stable2603-3-migration.md b/docs/polkadot-sdk-stable2603-3-migration.md index 64f7d54b14b..ae3e978f9f3 100644 --- a/docs/polkadot-sdk-stable2603-3-migration.md +++ b/docs/polkadot-sdk-stable2603-3-migration.md @@ -77,6 +77,7 @@ In this branch: | Local path | Upstream package | stable2603 action | | --- | --- | --- | | `substrate/sc-mixnet` | `sc-mixnet` | Deleted; use upstream stable2603-3 | +| `substrate/sp-allocator` | `sc-allocator` | Refreshed for stable2603 compatibility; keep `sp-allocator` package name locally | | `substrate/runtime-executor` | `sc-executor` | Keep Gear fork for sandbox/lazy-pages compatibility | | `substrate/runtime-executor/common` | `sc-executor-common` | Refreshed for stable2603 compatibility | | `substrate/runtime-executor/polkavm` | `sc-executor-polkavm` | Refreshed for stable2603 compatibility | @@ -86,6 +87,17 @@ In this branch: | `substrate/sp-wasm-interface-common` | local compatibility crate | Keep compatibility-only fork | | `substrate/substrate-wasm-builder` | `substrate-wasm-builder` | Refreshed for stable2603 compatibility | +The local diff against `e3737178ec726cffe506c907263aaaa417893fd0` was +re-audited after the ethexe Malachite restore. The remaining `substrate/` +source deltas are intentional Gear compatibility changes: allocator package +renaming and shared wasm-interface types, static Wasmtime host-function +registration for the current `wasmtime` API, Gear executor host-state and +memory-wrapper plumbing, `get_global_const` support, wasm32v1/RISC-V builder +handling, and omission of upstream-only benches/runtime-test fixtures. The +manual ethexe host registration for +`ext_gear_ri_pre_process_memory_accesses_version_2` was updated separately to +match stable2603's `PassFatPointerAndReadWrite<&mut [u8]>` FFI shape. + ## Deferred Items - Evaluate `system_version >= 3` pending-code runtime-upgrade semantics. diff --git a/ethexe/ethereum/src/router/mod.rs b/ethexe/ethereum/src/router/mod.rs index 045ffad48f6..f612adea9e9 100644 --- a/ethexe/ethereum/src/router/mod.rs +++ b/ethexe/ethereum/src/router/mod.rs @@ -165,7 +165,7 @@ impl Router { self.instance .requestCodeValidation(code_id.into_bytes().into(), deadline, v, r, s); let builder = - builder.sidecar_7594(SidecarBuilder::::from_slice(code).build_7594()?); + builder.sidecar(SidecarBuilder::::from_slice(code).build_4844()?); let receipt = builder .send() diff --git a/ethexe/processor/src/host/api/lazy_pages.rs b/ethexe/processor/src/host/api/lazy_pages.rs index 4b57384dbae..9506dda068d 100644 --- a/ethexe/processor/src/host/api/lazy_pages.rs +++ b/ethexe/processor/src/host/api/lazy_pages.rs @@ -98,7 +98,7 @@ fn pre_process_memory_accesses( mut caller: Caller<'_, StoreData>, reads: i64, writes: i64, - gas_bytes: u32, + gas_bytes: i64, ) -> i32 { log::trace!(target: "host_call", "pre_process_memory_accesses(reads={reads:?}, writes={writes:?}, gas_bytes={gas_bytes:?})"); @@ -108,14 +108,19 @@ fn pre_process_memory_accesses( // read gas_bytes into `mut` variable because `pre_process_memory_accesses` updates // it, then write updated slice to memory. - let mut gas_counter: u64 = memory.decode_by_max_len(gas_bytes); + let mut gas_counter = u64::from_le_bytes( + memory + .slice_by_val(gas_bytes) + .try_into() + .expect("gas counter must be encoded as 8 bytes"), + ); let res = lazy_pages_detail::pre_process_memory_accesses(reads, writes, &mut gas_counter) as i32; memory - .slice_mut(gas_bytes, 8) - .unwrap() + .slice_mut_by_val(gas_bytes) + .expect("gas counter must be encoded as 8 bytes") .copy_from_slice(&gas_counter.to_le_bytes()); log::trace!(target: "host_call", "pre_process_memory_accesses(..) -> {res:?}"); diff --git a/ethexe/processor/src/host/context.rs b/ethexe/processor/src/host/context.rs index d690f96d6b5..58291778af8 100644 --- a/ethexe/processor/src/host/context.rs +++ b/ethexe/processor/src/host/context.rs @@ -84,6 +84,11 @@ where .get_mut(ptr as usize..) .and_then(|s| s.get_mut(..len as usize)) } + + pub fn slice_mut_by_val(&mut self, ptr_len: i64) -> Option<&mut [u8]> { + let (ptr, len) = unpack_i64_to_u32(ptr_len); + self.slice_mut(ptr, len) + } } impl sp_allocator::Memory for MemoryWrapper { diff --git a/substrate/README.md b/substrate/README.md index 2c5226852b4..a4e85b50f32 100644 --- a/substrate/README.md +++ b/substrate/README.md @@ -10,7 +10,7 @@ Local Cargo package names intentionally stay compatible with upstream package na | Local path | Upstream package | Gear publish name | License | | --- | --- | --- | --- | -| `substrate/sp-allocator` | `sp-allocator`; derived from upstream `sc-allocator` | `gsp-allocator` | Apache-2.0 | +| `substrate/sp-allocator` | local `sp-allocator` package name; derived from upstream `sc-allocator` | `gsp-allocator` | Apache-2.0 | | `substrate/sp-wasm-interface` | `sp-wasm-interface` | `gsp-wasm-interface` | Apache-2.0 | | `substrate/runtime-executor/common` | `sc-executor-common` | `gsc-executor-common` | GPL-3.0-or-later WITH Classpath-exception-2.0 | | `substrate/runtime-executor/polkavm` | `sc-executor-polkavm` | `gsc-executor-polkavm` | GPL-3.0-or-later WITH Classpath-exception-2.0 | From 5a16386a4dd8faec99d7879be51f1fb2879cc55f Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Wed, 10 Jun 2026 13:47:27 +0400 Subject: [PATCH 05/13] Avoid duplicate runtime migration registration --- vara/runtime/vara/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/vara/runtime/vara/src/lib.rs b/vara/runtime/vara/src/lib.rs index 71996ffa4f0..add459adff3 100644 --- a/vara/runtime/vara/src/lib.rs +++ b/vara/runtime/vara/src/lib.rs @@ -1768,7 +1768,6 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - migrations::Migrations, >; #[cfg(test)] From 81f5afdc0cdb5840ca036bfdfce998ae63979f02 Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Wed, 10 Jun 2026 15:36:07 +0400 Subject: [PATCH 06/13] Restore upstream Malachite libp2p line --- Cargo.lock | 770 ++++-- Cargo.toml | 36 +- THIRD_PARTY_NOTICES.md | 10 + docs/polkadot-sdk-stable2603-3-migration.md | 10 +- ethexe/network/Cargo.toml | 8 +- ethexe/network/src/db_sync/mod.rs | 4 + ethexe/network/src/gossipsub.rs | 28 +- ethexe/network/src/injected.rs | 4 + .../libp2p-swarm-0.45.1/.cargo_vcs_info.json | 6 + third-party/libp2p-swarm-0.45.1/CHANGELOG.md | 1003 +++++++ third-party/libp2p-swarm-0.45.1/Cargo.toml | 189 ++ .../libp2p-swarm-0.45.1/Cargo.toml.orig | 76 + .../benches/connection_handler.rs | 360 +++ .../libp2p-swarm-0.45.1/src/behaviour.rs | 585 ++++ .../src/behaviour/either.rs | 168 ++ .../src/behaviour/external_addresses.rs | 182 ++ .../src/behaviour/listen_addresses.rs | 78 + .../src/behaviour/peer_addresses.rs | 338 +++ .../src/behaviour/toggle.rs | 377 +++ .../libp2p-swarm-0.45.1/src/connection.rs | 1387 ++++++++++ .../src/connection/error.rs | 147 ++ .../src/connection/pool.rs | 1044 ++++++++ .../src/connection/pool/concurrent_dial.rs | 103 + .../src/connection/pool/task.rs | 265 ++ .../src/connection/supported_protocols.rs | 92 + .../libp2p-swarm-0.45.1/src/dial_opts.rs | 348 +++ third-party/libp2p-swarm-0.45.1/src/dummy.rs | 120 + .../libp2p-swarm-0.45.1/src/executor.rs | 70 + .../libp2p-swarm-0.45.1/src/handler.rs | 896 +++++++ .../libp2p-swarm-0.45.1/src/handler/either.rs | 230 ++ .../libp2p-swarm-0.45.1/src/handler/map_in.rs | 98 + .../src/handler/map_out.rs | 106 + .../libp2p-swarm-0.45.1/src/handler/multi.rs | 456 ++++ .../src/handler/one_shot.rs | 237 ++ .../src/handler/pending.rs | 97 + .../libp2p-swarm-0.45.1/src/handler/select.rs | 350 +++ third-party/libp2p-swarm-0.45.1/src/lib.rs | 2346 +++++++++++++++++ .../libp2p-swarm-0.45.1/src/listen_opts.rs | 33 + third-party/libp2p-swarm-0.45.1/src/stream.rs | 98 + .../src/stream_protocol.rs | 132 + third-party/libp2p-swarm-0.45.1/src/test.rs | 522 ++++ .../libp2p-swarm-0.45.1/src/translation.rs | 115 + .../libp2p-swarm-0.45.1/src/upgrade.rs | 158 ++ .../tests/connection_close.rs | 148 ++ .../libp2p-swarm-0.45.1/tests/listener.rs | 144 + .../libp2p-swarm-0.45.1/tests/swarm_derive.rs | 618 +++++ .../tests/ui/fail/prelude_not_string.rs | 11 + .../tests/ui/fail/prelude_not_string.stderr | 5 + .../tests/ui/fail/to_swarm_not_string.rs | 19 + .../tests/ui/fail/to_swarm_not_string.stderr | 5 + utils/gear-workspace-hack/Cargo.toml | 124 +- 51 files changed, 14424 insertions(+), 332 deletions(-) create mode 100644 third-party/libp2p-swarm-0.45.1/.cargo_vcs_info.json create mode 100644 third-party/libp2p-swarm-0.45.1/CHANGELOG.md create mode 100644 third-party/libp2p-swarm-0.45.1/Cargo.toml create mode 100644 third-party/libp2p-swarm-0.45.1/Cargo.toml.orig create mode 100644 third-party/libp2p-swarm-0.45.1/benches/connection_handler.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/either.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/external_addresses.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/listen_addresses.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/peer_addresses.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/toggle.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/connection.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/error.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/pool.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/pool/concurrent_dial.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/pool/task.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/supported_protocols.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/dial_opts.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/dummy.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/executor.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/handler.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/either.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/map_in.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/map_out.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/multi.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/one_shot.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/pending.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/select.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/lib.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/listen_opts.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/stream.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/stream_protocol.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/test.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/translation.rs create mode 100644 third-party/libp2p-swarm-0.45.1/src/upgrade.rs create mode 100644 third-party/libp2p-swarm-0.45.1/tests/connection_close.rs create mode 100644 third-party/libp2p-swarm-0.45.1/tests/listener.rs create mode 100644 third-party/libp2p-swarm-0.45.1/tests/swarm_derive.rs create mode 100644 third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.rs create mode 100644 third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.stderr create mode 100644 third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.rs create mode 100644 third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.stderr diff --git a/Cargo.lock b/Cargo.lock index ff8b9084a78..965006d8e06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1012,7 +1012,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-app" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-codec", "arc-malachitebft-config", @@ -1028,7 +1028,7 @@ dependencies = [ "async-trait", "derive-where", "eyre", - "libp2p", + "libp2p 0.56.0", "libp2p-identity", "ractor", "rand 0.8.5", @@ -1040,7 +1040,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-app-channel" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-app", "arc-malachitebft-config", @@ -1058,7 +1058,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-codec" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "bytes", ] @@ -1066,7 +1066,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-config" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-types", "bytesize", @@ -1080,7 +1080,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-core-consensus" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-driver", "arc-malachitebft-core-types", @@ -1100,7 +1100,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-core-driver" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-state-machine", "arc-malachitebft-core-types", @@ -1113,7 +1113,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-core-state-machine" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-types", "derive-where", @@ -1123,7 +1123,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-core-types" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-peer", "async-trait", @@ -1136,7 +1136,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-core-votekeeper" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-types", "derive-where", @@ -1147,12 +1147,12 @@ dependencies = [ [[package]] name = "arc-malachitebft-discovery" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-metrics", "either", "eyre", - "libp2p", + "libp2p 0.56.0", "rand 0.8.5", "serde", "tokio", @@ -1162,7 +1162,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-engine" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-codec", "arc-malachitebft-config", @@ -1184,7 +1184,7 @@ dependencies = [ "derive-where", "eyre", "hex", - "libp2p", + "libp2p 0.56.0", "ractor", "rand 0.8.5", "tokio", @@ -1194,16 +1194,16 @@ dependencies = [ [[package]] name = "arc-malachitebft-metrics" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-state-machine", - "prometheus-client", + "prometheus-client 0.23.1", ] [[package]] name = "arc-malachitebft-network" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-discovery", "arc-malachitebft-metrics", @@ -1217,7 +1217,7 @@ dependencies = [ "futures", "hex", "itertools 0.14.0", - "libp2p", + "libp2p 0.56.0", "libp2p-gossipsub", "libp2p-scatter", "libp2p-stream", @@ -1227,13 +1227,12 @@ dependencies = [ "tokio", "tracing", "unsigned-varint 0.8.0", - "void", ] [[package]] name = "arc-malachitebft-peer" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "bs58", "multihash 0.19.5", @@ -1245,7 +1244,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-proto" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "prost 0.13.5", "prost-types 0.13.5", @@ -1255,7 +1254,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-signing" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-types", "async-trait", @@ -1265,7 +1264,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-signing-ecdsa" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-types", "base64 0.22.1", @@ -1278,7 +1277,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-signing-ed25519" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-types", "base64 0.22.1", @@ -1291,7 +1290,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-sync" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-core-types", "arc-malachitebft-metrics", @@ -1303,7 +1302,7 @@ dependencies = [ "displaydoc", "eyre", "genawaiter", - "libp2p", + "libp2p 0.56.0", "rand 0.8.5", "serde", "thiserror 2.0.17", @@ -1313,7 +1312,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-test" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "arc-malachitebft-app", "arc-malachitebft-codec", @@ -1350,7 +1349,7 @@ dependencies = [ [[package]] name = "arc-malachitebft-wal" version = "0.7.0-pre" -source = "git+https://github.com/gear-tech/malachite?rev=c53a7a2b424b5d951de8284529c2e7d36901f3b3#c53a7a2b424b5d951de8284529c2e7d36901f3b3" +source = "git+https://github.com/circlefin/malachite?rev=1fe7961aca933cefad8e4d9a52f50eda565288e7#1fe7961aca933cefad8e4d9a52f50eda565288e7" dependencies = [ "advisory-lock", "bytes", @@ -2097,21 +2096,6 @@ dependencies = [ "futures-lite", ] -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.5.0", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - [[package]] name = "async-io" version = "2.6.0" @@ -2199,32 +2183,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "async-std" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" -dependencies = [ - "async-channel 1.9.0", - "async-global-executor", - "async-io", - "async-lock", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers 0.3.0", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - [[package]] name = "async-stream" version = "0.3.6" @@ -2335,6 +2293,18 @@ dependencies = [ "url", ] +[[package]] +name = "attohttpc" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e2cdb6d5ed835199484bb92bb8b3edd526effe995c61732580439c1a67e2e9" +dependencies = [ + "base64 0.22.1", + "http 1.4.0", + "log", + "url", +] + [[package]] name = "atty" version = "0.2.14" @@ -6099,7 +6069,7 @@ dependencies = [ "indexmap 2.14.0", "ip_network", "itertools 0.13.0", - "libp2p", + "libp2p 0.56.0", "libp2p-gossipsub", "libp2p-swarm-test", "log", @@ -6108,7 +6078,7 @@ dependencies = [ "metrics-derive", "nonempty 0.12.0", "parity-scale-codec", - "prometheus-client", + "prometheus-client 0.23.1", "proptest", "rand 0.8.5", "tokio", @@ -7249,24 +7219,13 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" -[[package]] -name = "futures-ticker" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9763058047f713632a52e916cc7f6a4b3fc6e9fc1ff8c5b1dc49e5a89041682e" -dependencies = [ - "futures", - "futures-timer", - "instant", -] - [[package]] name = "futures-timer" version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" dependencies = [ - "gloo-timers 0.2.6", + "gloo-timers", "send_wrapper 0.4.0", ] @@ -8283,7 +8242,8 @@ dependencies = [ "hashbrown 0.16.1", "hashbrown 0.17.1", "hex", - "hickory-proto 0.24.4", + "hickory-proto 0.25.2", + "hickory-resolver 0.25.2", "hkdf", "hmac 0.12.1", "http-body-util", @@ -8292,7 +8252,6 @@ dependencies = [ "hyper-rustls", "hyper-util", "idna", - "if-watch", "impl-codec 0.7.1", "impl-serde 0.5.0", "indexmap 2.14.0", @@ -8307,14 +8266,12 @@ dependencies = [ "k256", "keccak", "libc", - "libp2p", - "libp2p-core", + "libp2p 0.56.0", + "libp2p-core 0.43.2", "libp2p-gossipsub", "libp2p-identity", - "libp2p-kad", - "libp2p-request-response", - "libp2p-swarm", - "libp2p-tcp", + "libp2p-kad 0.48.0", + "libp2p-request-response 0.29.0", "librocksdb-sys", "libsecp256k1", "libsecp256k1-core", @@ -8328,8 +8285,6 @@ dependencies = [ "mio", "multihash 0.19.5", "names", - "netlink-proto", - "netlink-sys", "nix", "nom 7.1.3", "num-bigint", @@ -8402,7 +8357,6 @@ dependencies = [ "ring 0.17.14", "ripemd", "rocksdb", - "rtnetlink", "ruint", "rustc-demangle", "rustc-hash 1.1.0", @@ -8436,6 +8390,7 @@ dependencies = [ "sha3", "signature", "smallvec", + "socket2 0.5.10", "soketto", "sp-api", "sp-api-proc-macro", @@ -8727,18 +8682,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "gloo-utils" version = "0.2.0" @@ -9127,6 +9070,24 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + [[package]] name = "headers" version = "0.3.9" @@ -9260,6 +9221,7 @@ dependencies = [ "once_cell", "rand 0.9.2", "ring 0.17.14", + "socket2 0.5.10", "thiserror 2.0.17", "tinyvec", "tokio", @@ -9706,7 +9668,6 @@ dependencies = [ "netlink-proto", "netlink-sys", "rtnetlink", - "smol", "system-configuration", "tokio", "windows 0.53.0", @@ -9719,7 +9680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064d90fec10d541084e7b39ead8875a5a80d9114a2b18791565253bae25f49e4" dependencies = [ "async-trait", - "attohttpc", + "attohttpc 0.24.1", "bytes", "futures", "http 0.2.12", @@ -9731,6 +9692,27 @@ dependencies = [ "xmltree", ] +[[package]] +name = "igd-next" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516893339c97f6011282d5825ac94fc1c7aad5cad26bdc2d0cee068c0bf97f97" +dependencies = [ + "async-trait", + "attohttpc 0.30.1", + "bytes", + "futures", + "http 1.4.0", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "log", + "rand 0.9.2", + "tokio", + "url", + "xmltree", +] + [[package]] name = "impl-codec" version = "0.6.0" @@ -10369,15 +10351,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28" -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "kvdb" version = "0.13.0" @@ -10525,57 +10498,113 @@ dependencies = [ "futures", "futures-timer", "getrandom 0.2.16", - "libp2p-allow-block-list", - "libp2p-connection-limits", - "libp2p-core", - "libp2p-dns", - "libp2p-gossipsub", - "libp2p-identify", + "libp2p-allow-block-list 0.4.0", + "libp2p-connection-limits 0.4.0", + "libp2p-core 0.42.0", + "libp2p-dns 0.42.0", + "libp2p-identify 0.45.0", "libp2p-identity", - "libp2p-kad", - "libp2p-mdns", - "libp2p-metrics", - "libp2p-noise", - "libp2p-ping", - "libp2p-plaintext", - "libp2p-quic", - "libp2p-request-response", - "libp2p-swarm", - "libp2p-tcp", - "libp2p-tls", - "libp2p-upnp", + "libp2p-kad 0.46.2", + "libp2p-mdns 0.46.0", + "libp2p-metrics 0.15.0", + "libp2p-noise 0.45.0", + "libp2p-ping 0.45.0", + "libp2p-quic 0.11.1", + "libp2p-request-response 0.27.0", + "libp2p-swarm 0.45.1", + "libp2p-tcp 0.42.0", + "libp2p-upnp 0.3.0", "libp2p-websocket", - "libp2p-yamux", + "libp2p-yamux 0.46.0", "multiaddr 0.18.2", "pin-project", "rw-stream-sink", "thiserror 1.0.69", ] +[[package]] +name = "libp2p" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce71348bf5838e46449ae240631117b487073d5f347c06d434caddcb91dceb5a" +dependencies = [ + "bytes", + "either", + "futures", + "futures-timer", + "getrandom 0.2.16", + "libp2p-allow-block-list 0.6.0", + "libp2p-connection-limits 0.6.0", + "libp2p-core 0.43.2", + "libp2p-dns 0.44.0", + "libp2p-gossipsub", + "libp2p-identify 0.47.0", + "libp2p-identity", + "libp2p-kad 0.48.0", + "libp2p-mdns 0.48.0", + "libp2p-metrics 0.17.0", + "libp2p-noise 0.46.1", + "libp2p-ping 0.47.0", + "libp2p-plaintext", + "libp2p-quic 0.13.0", + "libp2p-request-response 0.29.0", + "libp2p-swarm 0.47.1", + "libp2p-tcp 0.44.1", + "libp2p-tls 0.6.2", + "libp2p-upnp 0.5.0", + "libp2p-yamux 0.47.0", + "multiaddr 0.18.2", + "pin-project", + "rw-stream-sink", + "thiserror 2.0.17", +] + [[package]] name = "libp2p-allow-block-list" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1027ccf8d70320ed77e984f273bc8ce952f623762cb9bf2d126df73caef8041" dependencies = [ - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", - "libp2p-swarm", + "libp2p-swarm 0.45.1", "void", ] +[[package]] +name = "libp2p-allow-block-list" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16ccf824ee859ca83df301e1c0205270206223fd4b1f2e512a693e1912a8f4a" +dependencies = [ + "libp2p-core 0.43.2", + "libp2p-identity", + "libp2p-swarm 0.47.1", +] + [[package]] name = "libp2p-connection-limits" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d003540ee8baef0d254f7b6bfd79bac3ddf774662ca0abf69186d517ef82ad8" dependencies = [ - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", - "libp2p-swarm", + "libp2p-swarm 0.45.1", "void", ] +[[package]] +name = "libp2p-connection-limits" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18b8b607cf3bfa2f8c57db9c7d8569a315d5cc0a282e6bfd5ebfc0a9840b2a0" +dependencies = [ + "libp2p-core 0.43.2", + "libp2p-identity", + "libp2p-swarm 0.47.1", +] + [[package]] name = "libp2p-core" version = "0.42.0" @@ -10596,7 +10625,6 @@ dependencies = [ "quick-protobuf", "rand 0.8.5", "rw-stream-sink", - "serde", "smallvec", "thiserror 1.0.69", "tracing", @@ -10605,6 +10633,31 @@ dependencies = [ "web-time", ] +[[package]] +name = "libp2p-core" +version = "0.43.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "249128cd37a2199aff30a7675dffa51caf073b51aa612d2f544b19932b9aebca" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "libp2p-identity", + "multiaddr 0.18.2", + "multihash 0.19.5", + "multistream-select", + "parking_lot 0.12.5", + "pin-project", + "quick-protobuf", + "rand 0.8.5", + "rw-stream-sink", + "thiserror 2.0.17", + "tracing", + "unsigned-varint 0.8.0", + "web-time", +] + [[package]] name = "libp2p-dns" version = "0.42.0" @@ -10614,7 +10667,23 @@ dependencies = [ "async-trait", "futures", "hickory-resolver 0.24.4", - "libp2p-core", + "libp2p-core 0.42.0", + "libp2p-identity", + "parking_lot 0.12.5", + "smallvec", + "tracing", +] + +[[package]] +name = "libp2p-dns" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b770c1c8476736ca98c578cba4b505104ff8e842c2876b528925f9766379f9a" +dependencies = [ + "async-trait", + "futures", + "hickory-resolver 0.25.2", + "libp2p-core 0.43.2", "libp2p-identity", "parking_lot 0.12.5", "smallvec", @@ -10623,10 +10692,11 @@ dependencies = [ [[package]] name = "libp2p-gossipsub" -version = "0.47.0" +version = "0.49.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4e830fdf24ac8c444c12415903174d506e1e077fbe3875c404a78c5935a8543" +checksum = "a538e571cd38f504f761c61b8f79127489ea7a7d6f05c41ca15d31ffb5726326" dependencies = [ + "async-channel 2.5.0", "asynchronous-codec 0.7.0", "base64 0.22.1", "byteorder", @@ -10634,22 +10704,21 @@ dependencies = [ "either", "fnv", "futures", - "futures-ticker", + "futures-timer", "getrandom 0.2.16", + "hashlink 0.9.1", "hex_fmt", - "libp2p-core", + "libp2p-core 0.43.2", "libp2p-identity", - "libp2p-swarm", - "prometheus-client", + "libp2p-swarm 0.47.1", + "prometheus-client 0.23.1", "quick-protobuf", "quick-protobuf-codec", "rand 0.8.5", "regex", "serde", "sha2 0.10.9", - "smallvec", "tracing", - "void", "web-time", ] @@ -10664,9 +10733,9 @@ dependencies = [ "futures", "futures-bounded", "futures-timer", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", - "libp2p-swarm", + "libp2p-swarm 0.45.1", "lru 0.12.5", "quick-protobuf", "quick-protobuf-codec", @@ -10676,6 +10745,27 @@ dependencies = [ "void", ] +[[package]] +name = "libp2p-identify" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ab792a8b68fdef443a62155b01970c81c3aadab5e659621b063ef252a8e65e8" +dependencies = [ + "asynchronous-codec 0.7.0", + "either", + "futures", + "futures-bounded", + "futures-timer", + "libp2p-core 0.43.2", + "libp2p-identity", + "libp2p-swarm 0.47.1", + "quick-protobuf", + "quick-protobuf-codec", + "smallvec", + "thiserror 2.0.17", + "tracing", +] + [[package]] name = "libp2p-identity" version = "0.2.13" @@ -10713,13 +10803,12 @@ dependencies = [ "futures", "futures-bounded", "futures-timer", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", - "libp2p-swarm", + "libp2p-swarm 0.45.1", "quick-protobuf", "quick-protobuf-codec", "rand 0.8.5", - "serde", "sha2 0.10.9", "smallvec", "thiserror 1.0.69", @@ -10729,6 +10818,34 @@ dependencies = [ "web-time", ] +[[package]] +name = "libp2p-kad" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d3fd632a5872ec804d37e7413ceea20588f69d027a0fa3c46f82574f4dee60" +dependencies = [ + "asynchronous-codec 0.7.0", + "bytes", + "either", + "fnv", + "futures", + "futures-bounded", + "futures-timer", + "libp2p-core 0.43.2", + "libp2p-identity", + "libp2p-swarm 0.47.1", + "quick-protobuf", + "quick-protobuf-codec", + "rand 0.8.5", + "serde", + "sha2 0.10.9", + "smallvec", + "thiserror 2.0.17", + "tracing", + "uint 0.10.0", + "web-time", +] + [[package]] name = "libp2p-mdns" version = "0.46.0" @@ -10739,9 +10856,9 @@ dependencies = [ "futures", "hickory-proto 0.24.4", "if-watch", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", - "libp2p-swarm", + "libp2p-swarm 0.45.1", "rand 0.8.5", "smallvec", "socket2 0.5.10", @@ -10750,6 +10867,25 @@ dependencies = [ "void", ] +[[package]] +name = "libp2p-mdns" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66872d0f1ffcded2788683f76931be1c52e27f343edb93bc6d0bcd8887be443" +dependencies = [ + "futures", + "hickory-proto 0.25.2", + "if-watch", + "libp2p-core 0.43.2", + "libp2p-identity", + "libp2p-swarm 0.47.1", + "rand 0.8.5", + "smallvec", + "socket2 0.5.10", + "tokio", + "tracing", +] + [[package]] name = "libp2p-metrics" version = "0.15.0" @@ -10757,15 +10893,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ebafa94a717c8442d8db8d3ae5d1c6a15e30f2d347e0cd31d057ca72e42566" dependencies = [ "futures", - "libp2p-core", + "libp2p-core 0.42.0", + "libp2p-identify 0.45.0", + "libp2p-identity", + "libp2p-kad 0.46.2", + "libp2p-ping 0.45.0", + "libp2p-swarm 0.45.1", + "pin-project", + "prometheus-client 0.22.3", + "web-time", +] + +[[package]] +name = "libp2p-metrics" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "805a555148522cb3414493a5153451910cb1a146c53ffbf4385708349baf62b7" +dependencies = [ + "futures", + "libp2p-core 0.43.2", "libp2p-gossipsub", - "libp2p-identify", + "libp2p-identify 0.47.0", "libp2p-identity", - "libp2p-kad", - "libp2p-ping", - "libp2p-swarm", + "libp2p-kad 0.48.0", + "libp2p-ping 0.47.0", + "libp2p-swarm 0.47.1", "pin-project", - "prometheus-client", + "prometheus-client 0.23.1", "web-time", ] @@ -10779,7 +10933,7 @@ dependencies = [ "bytes", "curve25519-dalek", "futures", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", "multiaddr 0.18.2", "multihash 0.19.5", @@ -10795,6 +10949,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "libp2p-noise" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc73eacbe6462a0eb92a6527cac6e63f02026e5407f8831bde8293f19217bfbf" +dependencies = [ + "asynchronous-codec 0.7.0", + "bytes", + "futures", + "libp2p-core 0.43.2", + "libp2p-identity", + "multiaddr 0.18.2", + "multihash 0.19.5", + "quick-protobuf", + "rand 0.8.5", + "snow", + "static_assertions", + "thiserror 2.0.17", + "tracing", + "x25519-dalek", + "zeroize", +] + [[package]] name = "libp2p-ping" version = "0.45.0" @@ -10804,25 +10981,41 @@ dependencies = [ "either", "futures", "futures-timer", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", - "libp2p-swarm", + "libp2p-swarm 0.45.1", "rand 0.8.5", "tracing", "void", "web-time", ] +[[package]] +name = "libp2p-ping" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74bb7fcdfd9fead4144a3859da0b49576f171a8c8c7c0bfc7c541921d25e60d3" +dependencies = [ + "futures", + "futures-timer", + "libp2p-core 0.43.2", + "libp2p-identity", + "libp2p-swarm 0.47.1", + "rand 0.8.5", + "tracing", + "web-time", +] + [[package]] name = "libp2p-plaintext" -version = "0.42.0" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63d926c6be56a2489e0e7316b17fe95a70bc5c4f3e85740bb3e67c0f3c6a44" +checksum = "7e659439578fc6d305da8303834beb9d62f155f40e7f5b9d81c9f2b2c69d1926" dependencies = [ "asynchronous-codec 0.7.0", "bytes", "futures", - "libp2p-core", + "libp2p-core 0.43.2", "libp2p-identity", "quick-protobuf", "quick-protobuf-codec", @@ -10839,9 +11032,9 @@ dependencies = [ "futures", "futures-timer", "if-watch", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", - "libp2p-tls", + "libp2p-tls 0.5.0", "parking_lot 0.12.5", "quinn", "rand 0.8.5", @@ -10853,6 +11046,28 @@ dependencies = [ "tracing", ] +[[package]] +name = "libp2p-quic" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dc448b2de9f4745784e3751fe8bc6c473d01b8317edd5ababcb0dec803d843f" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libp2p-core 0.43.2", + "libp2p-identity", + "libp2p-tls 0.6.2", + "quinn", + "rand 0.8.5", + "ring 0.17.14", + "rustls", + "socket2 0.5.10", + "thiserror 2.0.17", + "tokio", + "tracing", +] + [[package]] name = "libp2p-request-response" version = "0.27.0" @@ -10860,63 +11075,76 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1356c9e376a94a75ae830c42cdaea3d4fe1290ba409a22c809033d1b7dcab0a6" dependencies = [ "async-trait", - "cbor4ii", "futures", "futures-bounded", "futures-timer", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", - "libp2p-swarm", + "libp2p-swarm 0.45.1", "rand 0.8.5", - "serde", "smallvec", "tracing", "void", "web-time", ] +[[package]] +name = "libp2p-request-response" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9f1cca83488b90102abac7b67d5c36fc65bc02ed47620228af7ed002e6a1478" +dependencies = [ + "async-trait", + "cbor4ii", + "futures", + "futures-bounded", + "libp2p-core 0.43.2", + "libp2p-identity", + "libp2p-swarm 0.47.1", + "rand 0.8.5", + "serde", + "smallvec", + "tracing", +] + [[package]] name = "libp2p-scatter" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14fe352c950cea000ecc697e2e71ce22a3586b607d74104ec6aaf22deaef1883" +checksum = "ea402c419f99e6013d5b12f97c5a1a1abe4aca285844b01b0ed96deab11f0b6e" dependencies = [ "bytes", "fnv", "futures", - "libp2p", - "prometheus-client", + "libp2p 0.56.0", + "prometheus-client 0.23.1", "tracing", "unsigned-varint 0.8.0", ] [[package]] name = "libp2p-stream" -version = "0.2.0-alpha" +version = "0.4.0-alpha" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d454f6647bc9054e7fede2dc86e625786c4d1304bff7afc995285f53ef9091f0" +checksum = "1d6bd8025c80205ec2810cfb28b02f362ab48a01bee32c50ab5f12761e033464" dependencies = [ "futures", - "libp2p-core", + "libp2p-core 0.43.2", "libp2p-identity", - "libp2p-swarm", + "libp2p-swarm 0.47.1", "rand 0.8.5", "tracing", - "void", ] [[package]] name = "libp2p-swarm" version = "0.45.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7dd6741793d2c1fb2088f67f82cf07261f25272ebe3c0b0c311e0c6b50e851a" dependencies = [ - "async-std", "either", "fnv", "futures", "futures-timer", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", "libp2p-swarm-derive", "lru 0.12.5", @@ -10930,34 +11158,54 @@ dependencies = [ "web-time", ] +[[package]] +name = "libp2p-swarm" +version = "0.47.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce88c6c4bf746c8482480345ea3edfd08301f49e026889d1cbccfa1808a9ed9e" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "hashlink 0.10.0", + "libp2p-core 0.43.2", + "libp2p-identity", + "libp2p-swarm-derive", + "multistream-select", + "rand 0.8.5", + "smallvec", + "tokio", + "tracing", + "web-time", +] + [[package]] name = "libp2p-swarm-derive" -version = "0.35.0" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206e0aa0ebe004d778d79fb0966aa0de996c19894e2c0605ba2f8524dd4443d8" +checksum = "dd297cf53f0cb3dee4d2620bb319ae47ef27c702684309f682bdb7e55a18ae9c" dependencies = [ "heck 0.5.0", - "proc-macro2", "quote", "syn 2.0.114", ] [[package]] name = "libp2p-swarm-test" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4e1d1d92421dc4c90cad42e3cd24f50fd210191c9f126d41bd483a09567f67" +checksum = "7b149112570d507efe305838c7130835955a0b1147aa8051c1c3867a83175cf6" dependencies = [ "async-trait", "futures", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.2", "libp2p-identity", "libp2p-plaintext", - "libp2p-swarm", - "libp2p-tcp", - "libp2p-yamux", - "rand 0.8.5", + "libp2p-swarm 0.47.1", + "libp2p-tcp 0.44.1", + "libp2p-yamux 0.47.0", "tracing", ] @@ -10967,18 +11215,33 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad964f312c59dcfcac840acd8c555de8403e295d39edf96f5240048b5fcaa314" dependencies = [ - "async-io", "futures", "futures-timer", "if-watch", "libc", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", "socket2 0.5.10", "tokio", "tracing", ] +[[package]] +name = "libp2p-tcp" +version = "0.44.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb6585b9309699f58704ec9ab0bb102eca7a3777170fa91a8678d73ca9cafa93" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libc", + "libp2p-core 0.43.2", + "socket2 0.6.1", + "tokio", + "tracing", +] + [[package]] name = "libp2p-tls" version = "0.5.0" @@ -10987,9 +11250,9 @@ checksum = "47b23dddc2b9c355f73c1e36eb0c3ae86f7dc964a3715f0731cfad352db4d847" dependencies = [ "futures", "futures-rustls", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", - "rcgen", + "rcgen 0.11.3", "ring 0.17.14", "rustls", "rustls-webpki 0.101.7", @@ -10998,6 +11261,25 @@ dependencies = [ "yasna", ] +[[package]] +name = "libp2p-tls" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ff65a82e35375cbc31ebb99cacbbf28cb6c4fefe26bf13756ddcf708d40080" +dependencies = [ + "futures", + "futures-rustls", + "libp2p-core 0.43.2", + "libp2p-identity", + "rcgen 0.13.2", + "ring 0.17.14", + "rustls", + "rustls-webpki 0.103.8", + "thiserror 2.0.17", + "x509-parser 0.17.0", + "yasna", +] + [[package]] name = "libp2p-upnp" version = "0.3.0" @@ -11006,14 +11288,29 @@ checksum = "01bf2d1b772bd3abca049214a3304615e6a36fa6ffc742bdd1ba774486200b8f" dependencies = [ "futures", "futures-timer", - "igd-next", - "libp2p-core", - "libp2p-swarm", + "igd-next 0.14.3", + "libp2p-core 0.42.0", + "libp2p-swarm 0.45.1", "tokio", "tracing", "void", ] +[[package]] +name = "libp2p-upnp" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4757e65fe69399c1a243bbb90ec1ae5a2114b907467bf09f3575e899815bb8d3" +dependencies = [ + "futures", + "futures-timer", + "igd-next 0.16.2", + "libp2p-core 0.43.2", + "libp2p-swarm 0.47.1", + "tokio", + "tracing", +] + [[package]] name = "libp2p-websocket" version = "0.44.0" @@ -11023,7 +11320,7 @@ dependencies = [ "either", "futures", "futures-rustls", - "libp2p-core", + "libp2p-core 0.42.0", "libp2p-identity", "parking_lot 0.12.5", "pin-project-lite", @@ -11043,13 +11340,28 @@ checksum = "788b61c80789dba9760d8c669a5bedb642c8267555c803fabd8396e4ca5c5882" dependencies = [ "either", "futures", - "libp2p-core", + "libp2p-core 0.42.0", "thiserror 1.0.69", "tracing", "yamux 0.12.1", "yamux 0.13.10", ] +[[package]] +name = "libp2p-yamux" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f15df094914eb4af272acf9adaa9e287baa269943f32ea348ba29cfb9bfc60d8" +dependencies = [ + "either", + "futures", + "libp2p-core 0.43.2", + "thiserror 2.0.17", + "tracing", + "yamux 0.12.1", + "yamux 0.13.10", +] + [[package]] name = "libredox" version = "0.1.12" @@ -11282,9 +11594,6 @@ name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -dependencies = [ - "value-bag", -] [[package]] name = "logos" @@ -11734,7 +12043,7 @@ dependencies = [ "c2-chacha", "curve25519-dalek", "either", - "hashlink", + "hashlink 0.8.4", "lioness", "log", "parking_lot 0.12.5", @@ -12015,7 +12324,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23" dependencies = [ - "async-io", "bytes", "futures", "libc", @@ -14757,6 +15065,18 @@ dependencies = [ "prometheus-client-derive-encode", ] +[[package]] +name = "prometheus-client" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf41c1a7c32ed72abe5082fb19505b969095c12da9f5732a4bc9878757fd087c" +dependencies = [ + "dtoa", + "itoa", + "parking_lot 0.12.5", + "prometheus-client-derive-encode", +] + [[package]] name = "prometheus-client-derive-encode" version = "0.4.2" @@ -15282,6 +15602,19 @@ dependencies = [ "yasna", ] +[[package]] +name = "rcgen" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +dependencies = [ + "pem", + "ring 0.17.14", + "rustls-pki-types", + "time", + "yasna", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -15615,7 +15948,6 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" dependencies = [ - "async-global-executor", "futures", "log", "netlink-packet-core", @@ -16473,7 +16805,7 @@ dependencies = [ "futures", "futures-timer", "ip_network", - "libp2p", + "libp2p 0.54.1", "linked_hash_set", "litep2p", "log", @@ -16642,7 +16974,7 @@ dependencies = [ "bytes", "ed25519-dalek", "libp2p-identity", - "libp2p-kad", + "libp2p-kad 0.46.2", "litep2p", "log", "multiaddr 0.18.2", @@ -16982,7 +17314,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?rev=e3737178ec726cf dependencies = [ "chrono", "futures", - "libp2p", + "libp2p 0.54.1", "log", "parking_lot 0.12.5", "pin-project", @@ -20606,12 +20938,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "value-bag" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" - [[package]] name = "vara-runtime" version = "2.0.0" diff --git a/Cargo.toml b/Cargo.toml index cb0051edea2..59247dde79e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,13 @@ resolver = "3" default-members = ["vara/node/cli"] -exclude = ["ethexe/contracts", "ethexe/docker", "ethexe/malachite", "ethexe/scripts"] +exclude = [ + "ethexe/contracts", + "ethexe/docker", + "ethexe/malachite", + "ethexe/scripts", + "third-party/libp2p-swarm-0.45.1", +] members = [ # substrate @@ -390,20 +396,19 @@ libp2p-identity = { version = "0.2", default-features = false, features = ["secp # `links = "rocksdb"` crate may live in the dependency graph. rocksdb = { version = "0.24", default-features = false, features = ["snappy"] } -# Malachite BFT engine — Gear compatibility fork pinned so all sub-crates share -# the stable2603-compatible libp2p snapshot. -malachitebft-app-channel = { package = "arc-malachitebft-app-channel", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-app = { package = "arc-malachitebft-app", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-codec = { package = "arc-malachitebft-codec", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-core-consensus = { package = "arc-malachitebft-core-consensus", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-core-types = { package = "arc-malachitebft-core-types", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-engine = { package = "arc-malachitebft-engine", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-proto = { package = "arc-malachitebft-proto", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-signing = { package = "arc-malachitebft-signing", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-signing-ed25519 = { package = "arc-malachitebft-signing-ed25519", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-signing-ecdsa = { package = "arc-malachitebft-signing-ecdsa", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3", default-features = false, features = ["k256", "rand", "serde", "std"] } -malachitebft-sync = { package = "arc-malachitebft-sync", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } -malachitebft-test = { package = "arc-malachitebft-test", git = "https://github.com/gear-tech/malachite", rev = "c53a7a2b424b5d951de8284529c2e7d36901f3b3" } +# Malachite BFT engine. +malachitebft-app-channel = { package = "arc-malachitebft-app-channel", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-app = { package = "arc-malachitebft-app", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-codec = { package = "arc-malachitebft-codec", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-core-consensus = { package = "arc-malachitebft-core-consensus", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-core-types = { package = "arc-malachitebft-core-types", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-engine = { package = "arc-malachitebft-engine", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-proto = { package = "arc-malachitebft-proto", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-signing = { package = "arc-malachitebft-signing", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-signing-ed25519 = { package = "arc-malachitebft-signing-ed25519", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-signing-ecdsa = { package = "arc-malachitebft-signing-ecdsa", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7", default-features = false, features = ["k256", "rand", "serde", "std"] } +malachitebft-sync = { package = "arc-malachitebft-sync", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } +malachitebft-test = { package = "arc-malachitebft-test", git = "https://github.com/circlefin/malachite", rev = "1fe7961aca933cefad8e4d9a52f50eda565288e7" } # Common executor between `sandbox-host` and `lazy-pages-fuzzer` wasmi = { version = "0.38" } @@ -718,6 +723,7 @@ debug = true [patch.crates-io] gear-workspace-hack = { path = "utils/gear-workspace-hack" } +libp2p-swarm = { path = "third-party/libp2p-swarm-0.45.1" } # core2 0.4.0 was yanked on crates.io; pin upstream git so cargo metadata doesn't fail on yanked lookup. # Needed by cid -> sc-network transitive; triggers during wasm-builder sub-project resolve. core2 = { git = "https://github.com/bbqsrc/core2", rev = "545e84bcb0f235b12e21351e0c69767958efe2a7" } diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 06f21e75426..d02995e0509 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -25,5 +25,15 @@ uses upstream `sc-mixnet` from the Polkadot SDK source reference above. Additional third-party file: `substrate/runtime-executor/wasmtime/src/test-guard-page-skip.wat` is a modified WebAssembly testsuite fixture from , licensed under Apache-2.0. +## libp2p Copied Source + +`third-party/libp2p-swarm-0.45.1` is copied from the crates.io +`libp2p-swarm` 0.45.1 package, originally published from +. Gear patches only its +`libp2p-swarm-derive` dependency to `=0.35.1` so the stable2603 Substrate +networking stack can coexist with ethexe's upstream libp2p 0.56 dependency +line. `libp2p-swarm` declares the MIT license in its package manifest. + Apache-2.0 license text: +MIT license text: GPL-3.0-or-later WITH Classpath-exception-2.0 license text: [`LICENSE`](LICENSE) diff --git a/docs/polkadot-sdk-stable2603-3-migration.md b/docs/polkadot-sdk-stable2603-3-migration.md index ae3e978f9f3..3a052ef5031 100644 --- a/docs/polkadot-sdk-stable2603-3-migration.md +++ b/docs/polkadot-sdk-stable2603-3-migration.md @@ -101,11 +101,11 @@ match stable2603's `PassFatPointerAndReadWrite<&mut [u8]>` FFI shape. ## Deferred Items - Evaluate `system_version >= 3` pending-code runtime-upgrade semantics. -- ethexe Malachite is re-enabled through the Gear compatibility fork at - `gear-tech/malachite` commit - `c53a7a2b424b5d951de8284529c2e7d36901f3b3`. The fork keeps Malachite on - the stable2603 `libp2p` 0.54 / `libp2p-swarm` 0.45 line so the workspace has - one `libp2p-swarm-derive` identity. +- ethexe Malachite uses upstream Circle Malachite at + `circlefin/malachite` commit + `1fe7961aca933cefad8e4d9a52f50eda565288e7`. Substrate stable2603 may keep + its own libp2p line, while ethexe networking and Malachite stay aligned with + upstream Malachite on libp2p 0.56. - Port prior Malachite hardening work after the stable2603 dependency update: validator identity/peer gating, bounded stream cleanup, injected transaction caps and duplicate checks, quarantine liveness, and typed-hash audit items. diff --git a/ethexe/network/Cargo.toml b/ethexe/network/Cargo.toml index a27c653f352..9d2e8786651 100644 --- a/ethexe/network/Cargo.toml +++ b/ethexe/network/Cargo.toml @@ -23,8 +23,8 @@ ethexe-common.workspace = true gprimitives = { workspace = true, features = ["std", "codec"] } # libp2p -libp2p = { version = "0.54.1", features = ["mdns", "gossipsub", "kad", "identify", "ping", "secp256k1", "request-response", "quic", "tcp", "dns", "tls", "tokio", "macros", "plaintext", "yamux", "metrics"] } -libp2p-gossipsub = "0.47.0" +libp2p = { version = "0.56.0", features = ["mdns", "gossipsub", "kad", "identify", "ping", "secp256k1", "request-response", "quic", "tcp", "dns", "tls", "tokio", "macros", "plaintext", "yamux", "metrics"] } +libp2p-gossipsub = { version = "0.49.4", features = ["metrics"] } # other deps tokio = { workspace = true, features = ["macros", "sync"] } @@ -41,7 +41,7 @@ auto_impl.workspace = true lru.workspace = true indexmap.workspace = true ip_network.workspace = true -prometheus-client = "0.22.3" # specific version that libp2p uses +prometheus-client = "0.23.1" # specific version that libp2p uses metrics.workspace = true metrics-derive.workspace = true assert_matches.workspace = true @@ -50,7 +50,7 @@ assert_matches.workspace = true gear-workspace-hack.workspace = true [dev-dependencies] -libp2p-swarm-test = { version = "0.4.0", default-features = false } +libp2p-swarm-test = { version = "0.6.0", default-features = false, features = ["tokio"] } tokio = { workspace = true, features = ["full", "test-util"] } tracing-subscriber.workspace = true proptest = { workspace = true } diff --git a/ethexe/network/src/db_sync/mod.rs b/ethexe/network/src/db_sync/mod.rs index af31732fee8..b0fd9efda3f 100644 --- a/ethexe/network/src/db_sync/mod.rs +++ b/ethexe/network/src/db_sync/mod.rs @@ -414,6 +414,7 @@ impl Behaviour { request, channel, }, + .. } => { let response_id = self .ongoing_responses @@ -438,6 +439,7 @@ impl Behaviour { request_id, response, }, + .. } => { self.ongoing_requests.on_peer_response(request_id, response); } @@ -445,6 +447,7 @@ impl Behaviour { peer, request_id, error, + .. } => { log::trace!("outbound failure for request {request_id} to {peer}: {error}"); @@ -460,6 +463,7 @@ impl Behaviour { peer, request_id: _, error: InboundFailure::UnsupportedProtocols, + .. } => { log::debug!( "request from {peer} failed because it doesn't support {STREAM_PROTOCOL} protocol" diff --git a/ethexe/network/src/gossipsub.rs b/ethexe/network/src/gossipsub.rs index 580a5ea8483..6b77b00b67f 100644 --- a/ethexe/network/src/gossipsub.rs +++ b/ethexe/network/src/gossipsub.rs @@ -73,7 +73,7 @@ impl MessageValidator { &propagation_source, acceptance, ); - debug_assert!(validated.unwrap_or(false)); + debug_assert!(validated); message } } @@ -123,13 +123,12 @@ impl Behaviour { .validate_messages() .build() .map_err(|e| anyhow!("`gossipsub::ConfigBuilder::build()` error: {e}"))?; - let mut inner = gossipsub::Behaviour::new_with_metrics( - MessageAuthenticity::Signed(keypair), - inner, - registry.sub_registry_with_prefix("libp2p_gossipsub"), - MetricsConfig::default(), - ) - .map_err(|e| anyhow!("`gossipsub::Behaviour` error: {e}"))?; + let mut inner = gossipsub::Behaviour::new(MessageAuthenticity::Signed(keypair), inner) + .map_err(|e| anyhow!("`gossipsub::Behaviour` error: {e}"))? + .with_metrics( + registry.sub_registry_with_prefix("libp2p_gossipsub"), + MetricsConfig::default(), + ); inner .with_peer_score(PeerScoreParams::default(), PeerScoreThresholds::default()) .map_err(|e| anyhow!("`gossipsub` scoring parameters error: {e}"))?; @@ -190,7 +189,7 @@ impl Behaviour { &propagation_source, MessageAcceptance::Reject, ); - debug_assert!(validated.unwrap_or(false)); + debug_assert!(validated); self.peer_score.invalid_data(source); return Poll::Pending; } @@ -216,6 +215,13 @@ impl Behaviour { log::trace!("peer doesn't support gossipsub: {peer_id}"); Poll::Pending } + gossipsub::Event::SlowPeer { + peer_id, + failed_messages, + } => { + log::trace!("peer is too slow: {peer_id}, failed messages: {failed_messages:?}"); + Poll::Pending + } } } } @@ -303,7 +309,9 @@ impl NetworkBehaviour for Behaviour { Ok(_msg_id) => { let _ = self.message_queue.pop_front().expect("checked above"); } - Err(PublishError::InsufficientPeers) => break, + Err(PublishError::NoPeersSubscribedToTopic | PublishError::AllQueuesFull(_)) => { + break; + } Err(error) => { let message = self.message_queue.pop_front().expect("checked above"); return Poll::Ready(ToSwarm::GenerateEvent(Event::PublishFailure { diff --git a/ethexe/network/src/injected.rs b/ethexe/network/src/injected.rs index b8d1eda150a..c755edd38ff 100644 --- a/ethexe/network/src/injected.rs +++ b/ethexe/network/src/injected.rs @@ -219,6 +219,7 @@ impl Behaviour { request, channel, }, + .. } => { let InnerRequest(transaction) = request; let (tx, rx) = oneshot::channel(); @@ -242,6 +243,7 @@ impl Behaviour { request_id, response, }, + .. } => { let transaction_hash = self .pending_requests @@ -258,6 +260,7 @@ impl Behaviour { peer, request_id, error, + .. } => { let transaction_hash = self .pending_requests @@ -280,6 +283,7 @@ impl Behaviour { peer, request_id: _, error: InboundFailure::UnsupportedProtocols, + .. } => { log::debug!( "request from {peer} failed because it doesn't support {STREAM_PROTOCOL} protocol" diff --git a/third-party/libp2p-swarm-0.45.1/.cargo_vcs_info.json b/third-party/libp2p-swarm-0.45.1/.cargo_vcs_info.json new file mode 100644 index 00000000000..4929f430a48 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "87101870709aaf64e141e07624855155ed4faaac" + }, + "path_in_vcs": "swarm" +} \ No newline at end of file diff --git a/third-party/libp2p-swarm-0.45.1/CHANGELOG.md b/third-party/libp2p-swarm-0.45.1/CHANGELOG.md new file mode 100644 index 00000000000..b5fb72d68ac --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/CHANGELOG.md @@ -0,0 +1,1003 @@ +## 0.45.1 + +- Update `libp2p-swarm-derive` to version `0.35.0`, see [PR XXXX] + +[PR XXXX]: https://github.com/libp2p/rust-libp2p/pull/XXXX + +## 0.45.0 + +- Implement refactored `Transport`. + See [PR 4568] +- Move `address_translation` into swarm and into `libp2p-identify`. + See [PR 4568] + +[PR 4568]: https://github.com/libp2p/rust-libp2p/pull/4568 + +## 0.44.3 +- Optimize internal connection `fn poll`. New implementation now scales much better with number of listen protocols active. + No changes to public API introduced. + See [PR 5026](https://github.com/libp2p/rust-libp2p/pull/5026) +- Add peer_id to `FromSwarm::ListenFailure`. + See [PR 4818](https://github.com/libp2p/rust-libp2p/pull/4818). +- Use `web-time` instead of `instant`. + See [PR 5347](https://github.com/libp2p/rust-libp2p/pull/5347). +- Add `#[track_caller]` on all `spawn` wrappers. + See [PR 5465](https://github.com/libp2p/rust-libp2p/pull/5465). +- Add ConnectionError to FromSwarm::ConnectionClosed. + See [PR 5485](https://github.com/libp2p/rust-libp2p/pull/5485). + +## 0.44.2 + +- Allow `NetworkBehaviour`s to share addresses of peers. + This is enabled via the new `ToSwarm::NewExternalAddrOfPeer` event. + The address is broadcast to all behaviours via `FromSwarm::NewExternalAddrOfPeer`. + Protocols that want to collect these addresses can use the new `PeerAddresses` utility. + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371). + +## 0.44.1 + +- Implement `Clone` & `Copy` for `FromSwarm. + This makes it easier to forward these events when wrapping other behaviours. + See [PR 4825](https://github.com/libp2p/rust-libp2p/pull/4825). + +## 0.44.0 + +- Add `#[non_exhaustive]` to `FromSwarm`, `ToSwarm`, `SwarmEvent`, `ConnectionHandlerEvent`, `ConnectionEvent`. + See [PR 4581](https://github.com/libp2p/rust-libp2p/pull/4581). +- Remove `handler` field from `ConnectionClosed`. + If you need to transfer state from a `ConnectionHandler` to its `NetworkBehaviour` when a connection closes, use `ConnectionHandler::poll_close`. + See [PR 4076](https://github.com/libp2p/rust-libp2p/pull/4076). +- Remove deprecated `PollParameters` from `NetworkBehaviour::poll` function. + See [PR 4490](https://github.com/libp2p/rust-libp2p/pull/4490). +- Remove deprecated `ConnectionHandlerEvent::Close` and `ConnectionHandler::Error`. + `ConnectionHandler`s should not close connections directly as the connection might still be in use by other handlers. + See [PR 4755](https://github.com/libp2p/rust-libp2p/pull/4755). +- Add `PeerCondition::DisconnectedAndNotDialing` variant, combining pre-existing conditions. + This is the new default. + A new dialing attempt is iniated _only if_ the peer is both considered disconnected and there is currently no ongoing dialing attempt. + See [PR 4225](https://github.com/libp2p/rust-libp2p/pull/4225). +- Remove deprecated `keep_alive_timeout` in `OneShotHandlerConfig`. + See [PR 4677](https://github.com/libp2p/rust-libp2p/pull/4677). +- Don't close entire connection upon `DialUpgradeError`s within `OneShotHandler`. + Instead, the error is reported as `Err(e)` via `ConnectionHandler::ToBehaviour`. + See [PR 4715](https://github.com/libp2p/rust-libp2p/pull/4715). +- Log `PeerId` of `Swarm` even when constructed with new `SwarmBuilder`. + See [PR 4671](https://github.com/libp2p/rust-libp2p/pull/4671). +- Add `SwarmEvent::{NewExternalAddrCandidate,ExternalAddrConfirmed,ExternalAddrExpired}` variants. + See [PR 4721](https://github.com/libp2p/rust-libp2p/pull/4721). +- Remove deprecated symbols. + See [PR 4737](https://github.com/libp2p/rust-libp2p/pull/4737). + +## 0.43.7 + +- Deprecate `ConnectionHandlerEvent::Close`. + See [issue 3591](https://github.com/libp2p/rust-libp2p/issues/3591) for details. + See [PR 4714](https://github.com/libp2p/rust-libp2p/pull/4714). + +## 0.43.6 + +- Deprecate `libp2p::swarm::SwarmBuilder`. + Most users should use `libp2p::SwarmBuilder`. + In some special cases, users may need to use `Swarm::new` and `Config` instead of the new `libp2p::SwarmBuilder`. + See [PR 4120]. +- Make the `Debug` implementation of `StreamProtocol` more concise. + See [PR 4631](https://github.com/libp2p/rust-libp2p/pull/4631). +- Fix overflow in `KeepAlive` computation that could occur panic at `Delay::new` if `SwarmBuilder::idle_connection_timeout` is configured too large. + See [PR 4644](https://github.com/libp2p/rust-libp2p/pull/4644). +- Deprecate `KeepAlive::Until`. + Individual protocols should not keep connections alive for longer than necessary. + Users should use `swarm::Config::idle_connection_timeout` instead. + See [PR 4656](https://github.com/libp2p/rust-libp2p/pull/4656). +- Deprecate `keep_alive_timeout` in `OneShotHandlerConfig`. + See [PR 4680](https://github.com/libp2p/rust-libp2p/pull/4680). + +[PR 4120]: https://github.com/libp2p/rust-libp2p/pull/4120 + +## 0.43.5 + +- Fix overflow in `KeepAlive` computation that could occur if `SwarmBuilder::idle_connection_timeout` is configured with `u64::MAX`. + See [PR 4559](https://github.com/libp2p/rust-libp2p/pull/4559). + +## 0.43.4 + +- Implement `Debug` for event structs. + See [PR 4426]. + +- Improve error message when `DialPeerCondition` prevents a dial. + See [PR 4409]. + +- Introduce `SwarmBuilder::idle_conncetion_timeout` and deprecate `keep_alive::Behaviour` as a result. + See [PR 4161]. + +[PR 4426]: https://github.com/libp2p/rust-libp2p/pull/4426 +[PR 4409]: https://github.com/libp2p/rust-libp2p/pull/4409 +[PR 4161]: https://github.com/libp2p/rust-libp2p/pull/4161 + +## 0.43.3 + +- Implement `Display` for `ConnectionId`. + See [PR 4278]. + +[PR 4278]: https://github.com/libp2p/rust-libp2p/pull/4278 + +## 0.43.2 +- Display the cause of a `ListenError::Denied`. + See [PR 4232] + +[PR 4232]: https://github.com/libp2p/rust-libp2p/pull/4158 + +## 0.43.1 + +- Do not announce external address candidate before address translation, unless translation does not apply. + This will prevent ephemeral TCP addresses being announced as external address candidates. + See [PR 4158]. + +[PR 4158]: https://github.com/libp2p/rust-libp2p/pull/4158 + +## 0.43.0 + +- Allow `NetworkBehaviours` to create and remove listeners. + See [PR 3292]. + +- Raise MSRV to 1.65. + See [PR 3715]. + +- Introduce `StreamProtocol` type. + This type enforces invariants on protocol names, such as leading forward slashes and correct UTF8 encoding. + See [PR 3746]. + +- Return a bool from `ExternalAddresses::on_swarm_event` and `ListenAddresses::on_swarm_event` indicating whether any state was changed. + See [PR 3865]. + +- Remove deprecated banning API from `Swarm`. + Users should migrate to `libp2p::allow_block_list`. + See [PR 3886]. + +- Remove `ConnectionHandlerUpgrErr::Timer` variant. + This variant was never constructed and thus dead code. + See [PR 3605]. + +- Remove deprecated `IntoConnectionHandler` and all its implementations. + This also removes the `NetworkBehaviour::new_handler` and `NetworkBehaviour::addresses_of_peer` methods. + See changelog for `0.42` on how to migrate. + See [PR 3884]. + +- Remove `ConnectionHandlerUpgrErr::Timer` variant. + This variant was never constructed and thus dead code. + See [PR 3605]. + +- Flatten `ConnectionHandlerUpgrErr` and rename to `StreamUpgradeError`. + See [PR 3882]. + +- Remove deprecated `ConnectionLimits`. + Users should migrate to `libp2p::connection_limits::Behaviour`. + See [PR 3885]. + +- Allow `ConnectionHandler`s to report and learn about the supported protocols on a connection. + The newly introduced API elements are: + - `ConnectionHandlerEvent::ReportRemoteProtocols` + - `ConnectionEvent::LocalProtocolsChange` + - `ConnectionEvent::RemoteProtocolsChange` + + See [PR 3651]. + +- Deprecate the `NegotiatedSubstream` type and replace it with `Stream`. + See [PR 3912]. + +- Rename `NetworkBehaviour::OutEvent` to `NetworkBehaviour::ToSwarm`, `ConnectionHandler::InEvent` to `ConnectionHandler::FromBehaviour`, `ConnectionHandler::OutEvent` to `ConnectionHandler::ToBehaviour`. See [PR 3848]. + +- Remove deprecated `NetworkBehaviourAction` type. + See [PR 3919]. + +- Expose `ConnectionId` on `SwarmEvent::{ConnectionEstablished,ConnectionClosed,IncomingConnection,IncomingConnectionError,OutgoingConnectionError,Dialing}`. + Also emit `SwarmEvent::Dialing` for dials with unknown `PeerId`. + See [PR 3927]. + +- Rename `ConnectionHandlerEvent::Custom` to `ConnectionHandlerEvent::NotifyBehaviour`. See [PR 3955]. + +- Remove `DialError::InvalidPeerId` variant. With the move to `multiaddr` `v0.18.0` peer IDs in `/p2p` are type safe and thus usage of the contained peer ID can not result in a parsing error. + See [PR 4037]. + +- Remove deprecated items. See [PR 3956]. + +- Add ability to `downcast_ref` ConnectionDenied errors. See [PR 4020]. + +[PR 3292]: https://github.com/libp2p/rust-libp2p/pull/3292 +[PR 3605]: https://github.com/libp2p/rust-libp2p/pull/3605 +[PR 3651]: https://github.com/libp2p/rust-libp2p/pull/3651 +[PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 +[PR 3746]: https://github.com/libp2p/rust-libp2p/pull/3746 +[PR 3848]: https://github.com/libp2p/rust-libp2p/pull/3848 +[PR 3865]: https://github.com/libp2p/rust-libp2p/pull/3865 +[PR 3882]: https://github.com/libp2p/rust-libp2p/pull/3882 +[PR 3884]: https://github.com/libp2p/rust-libp2p/pull/3884 +[PR 3885]: https://github.com/libp2p/rust-libp2p/pull/3885 +[PR 3886]: https://github.com/libp2p/rust-libp2p/pull/3886 +[PR 3912]: https://github.com/libp2p/rust-libp2p/pull/3912 +[PR 3919]: https://github.com/libp2p/rust-libp2p/pull/3919 +[PR 3927]: https://github.com/libp2p/rust-libp2p/pull/3927 +[PR 3955]: https://github.com/libp2p/rust-libp2p/pull/3955 +[PR 3956]: https://github.com/libp2p/rust-libp2p/pull/3956 +[PR 4020]: https://github.com/libp2p/rust-libp2p/pull/4020 +[PR 4037]: https://github.com/libp2p/rust-libp2p/pull/4037 + +## 0.42.2 + +- Add `ConnectionEvent::{is_outbound,is_inbound}`. See [PR 3625]. + +[PR 3625]: https://github.com/libp2p/rust-libp2p/pull/3625 + +## 0.42.1 + +- Deprecate `ConnectionLimits` in favor of `libp2p::connection_limits`. + See [PR 3386]. + +- Introduce `ConnectionId::new_unchecked` to allow for more sophisticated, manual tests of `NetworkBehaviour`. + See [PR 3652]. + +- Deprecate `Swarm::ban_peer_id` in favor of the new `libp2p::allow_block_list` module. + See [PR 3590]. + +- Rename `NetworkBehaviourAction` to `ToSwarm`. + A deprecated type-alias is provided to ease the transition. + The new name is meant to better indicate the message-passing relationship between `Swarm` and `NetworkBehaviour`. + See [PR 3658]. + +[PR 3386]: https://github.com/libp2p/rust-libp2p/pull/3386 +[PR 3652]: https://github.com/libp2p/rust-libp2p/pull/3652 +[PR 3590]: https://github.com/libp2p/rust-libp2p/pull/3590 +[PR 3658]: https://github.com/libp2p/rust-libp2p/pull/3658 + +## 0.42.0 + +- Allow `NetworkBehaviour`s to manage connections. + We deprecate `NetworkBehaviour::new_handler` and `NetworkBehaviour::addresses_of_peer` in favor of four new callbacks: + + - `NetworkBehaviour::handle_pending_inbound_connection` + - `NetworkBehaviour::handle_pending_outbound_connection` + - `NetworkBehaviour::handle_established_inbound_connection` + - `NetworkBehaviour::handle_established_outbound_connection` + + Please note that due to [limitations](https://github.com/rust-lang/rust/issues/98990) in the Rust compiler, _implementations_ of `new_handler` and `addresses_of_peer` are not flagged as deprecated. + Nevertheless, they will be removed in the future. + + All four are fallible and returning an error from any of them will abort the given connection. + This allows you to create dedicated `NetworkBehaviour`s that only concern themselves with managing connections. + For example: + - checking the `PeerId` of a newly established connection against an allow/block list + - only allowing X connection upgrades at any one time + - denying incoming or outgoing connections from a certain IP range + - only allowing N connections to or from the same peer + + See [PR 3254]. + +- Remove `handler` field from `NetworkBehaviourAction::Dial`. + Instead of constructing the handler early, you can now access the `ConnectionId` of the future connection on `DialOpts`. + `ConnectionId`s are `Copy` and will be used throughout the entire lifetime of the connection to report events. + This allows you to send events to a very specific connection, much like you previously could directly set state in the handler. + + Removing the `handler` field also reduces the type parameters of `NetworkBehaviourAction` from three to two. + The third one used to be defaulted to the `InEvent` of the `ConnectionHandler`. + You now have to manually specify that where you previously had to specify the `ConnectionHandler`. + This very likely will trigger **convoluted compile errors** about traits not being implemented. + + Within `NetworkBehaviourAction::poll`, the easiest way to migrate is to do this (in the example of `libp2p-floodsub`): + ```diff + --- a/protocols/floodsub/src/layer.rs + +++ b/protocols/floodsub/src/layer.rs + @@ -472,7 +465,7 @@ impl NetworkBehaviour for Floodsub { + &mut self, + _: &mut Context<'_>, + _: &mut impl PollParameters, + - ) -> Poll> { + + ) -> Poll>> { + ``` + + In other words: + + |Search|Replace| + |---|---| + |`NetworkBehaviourAction`|`NetworkBehaviourAction>`| + + If you reference `NetworkBehaviourAction` somewhere else as well, + you may have to fill in the type of `ConnectionHandler::InEvent` manually as the 2nd parameter. + + See [PR 3328]. + +- Update to `libp2p-core` `v0.39.0`. + +- Removed deprecated Swarm constructors. For transition notes see [0.41.0](#0.41.0). See [PR 3170]. + +- Deprecate functions on `PollParameters` in preparation for `PollParameters` to be removed entirely eventually. See [PR 3153]. + +- Add `estblished_in` to `SwarmEvent::ConnectionEstablished`. See [PR 3134]. + +- Remove deprecated `inject_*` methods from `NetworkBehaviour` and `ConnectionHandler`. + Make the implementation of `on_swarm_event` and `on_connection_handler_event` + both mandatory. See [PR 3264] and [PR 3364]. + +- Update to `libp2p-swarm-derive` `v0.32.0`. + +- Replace `SwarmBuilder::connection_event_buffer_size` with `SwarmBuilder::per_connection_event_buffer_size` . + The configured value now applies _per_ connection. + The default values remains 7. + If you have previously set `connection_event_buffer_size` you should re-evaluate what a good size for a _per connection_ buffer is. + See [PR 3188]. + +- Remove `DialError::ConnectionIo` variant. + This was never constructed. + See [PR 3374]. + +- Introduce `ListenError` and use it within `SwarmEvent::IncomingConnectionError`. + See [PR 3375]. + +- Remove `PendingConnectionError`, `PendingInboundConnectionError` and `PendingOutboundConnectionError` from the public API. + They are no longer referenced anywhere with the addition of `ListenError`. + See [PR 3497]. + +- Remove `ConnectionId::new`. Manually creating `ConnectionId`s is now unsupported. See [PR 3327]. + +- Deprecate methods `Swarm::with_executor`, `Swarm::with_*_executor`, `Swarm::without_executor`. + Introduce similar methods in `SwarmBuilder`. See [PR 3588]. + +- Gracefully disable oneshot handler on dial upgrade errors. See [PR 3577]. + +[PR 3364]: https://github.com/libp2p/rust-libp2p/pull/3364 +[PR 3170]: https://github.com/libp2p/rust-libp2p/pull/3170 +[PR 3134]: https://github.com/libp2p/rust-libp2p/pull/3134 +[PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153 +[PR 3264]: https://github.com/libp2p/rust-libp2p/pull/3264 +[PR 3272]: https://github.com/libp2p/rust-libp2p/pull/3272 +[PR 3327]: https://github.com/libp2p/rust-libp2p/pull/3327 +[PR 3328]: https://github.com/libp2p/rust-libp2p/pull/3328 +[PR 3188]: https://github.com/libp2p/rust-libp2p/pull/3188 +[PR 3377]: https://github.com/libp2p/rust-libp2p/pull/3377 +[PR 3373]: https://github.com/libp2p/rust-libp2p/pull/3373 +[PR 3374]: https://github.com/libp2p/rust-libp2p/pull/3374 +[PR 3375]: https://github.com/libp2p/rust-libp2p/pull/3375 +[PR 3254]: https://github.com/libp2p/rust-libp2p/pull/3254 +[PR 3497]: https://github.com/libp2p/rust-libp2p/pull/3497 +[PR 3588]: https://github.com/libp2p/rust-libp2p/pull/3588 +[PR 3577]: https://github.com/libp2p/rust-libp2p/pull/3577 + +## 0.41.1 + +- Update to `libp2p-swarm-derive` `v0.31.0`. + +## 0.41.0 + +- Update to `libp2p-core` `v0.38.0`. + +- Add new `on_connection_event` method to `ConnectionHandler` that accepts a `ConnectionEvent` enum and update + `inject_*` methods to call `on_connection_event` with the respective `ConnectionEvent` variant and deprecate + `inject_*`. + To migrate, users should replace the `ConnectionHandler::inject_*` calls with a single + implementation of `ConnectionHandler::on_connection_event` treating each `ConnectionEvent` variant in + the same way its corresponding `inject_*` call was treated. + See [PR 3085]. + +- Add new `on_behaviour_event` method with the same signature as `inject_event`, make the + default implementation of `inject_event` call `on_behaviour_event` and deprecate it. + To migrate, users should replace the `ConnectionHandler::inject_event` call + with `ConnectionHandler::on_behaviour_event`. + See [PR 3085]. + +- Add new `on_swarm_event` method to `NetworkBehaviour` that accepts a `FromSwarm` enum and update + `inject_*` methods to call `on_swarm_event` with the respective `FromSwarm` variant and deprecate + `inject_*`. + To migrate, users should replace the `NetworkBehaviour::inject_*` calls with a single + implementation of `NetworkBehaviour::on_swarm_event` treating each `FromSwarm` variant in + the same way its corresponding `inject_*` call was treated. + See [PR 3011]. + +- Add new `on_connection_handler_event` method with the same signature as `inject_event`, make the + default implementation of `inject_event` call `on_connection_handler_event` and deprecate it. + To migrate, users should replace the `NetworkBehaviour::inject_event` call + with `NetworkBehaviour::on_connection_handler_event`. + See [PR 3011]. + +- Export `NetworkBehaviour` derive as `libp2p_swarm::NetworkBehaviour`. + This follows the convention of other popular libraries. `serde` for example exports the `Serialize` trait and macro as + `serde::Serialize`. See [PR 3055]. + +- Feature-gate `NetworkBehaviour` macro behind `macros` feature flag. See [PR 3055]. + +- Make executor in Swarm constructor explicit. See [PR 3097]. + + Supported executors: + - Tokio + + Previously + ```rust + let swarm = SwarmBuilder::new(transport, behaviour, peer_id) + .executor(Box::new(|fut| { + tokio::spawn(fut); + })) + .build(); + ``` + Now + ```rust + let swarm = Swarm::with_tokio_executor(transport, behaviour, peer_id); + ``` + - Async Std + + Previously + ```rust + let swarm = SwarmBuilder::new(transport, behaviour, peer_id) + .executor(Box::new(|fut| { + async_std::task::spawn(fut); + })) + .build(); + ``` + Now + ```rust + let swarm = Swarm::with_async_std_executor(transport, behaviour, peer_id); + ``` + - ThreadPool (see [Issue 3107]) + + In most cases ThreadPool can be replaced by executors or spawning on the local task. + + Previously + ```rust + let swarm = Swarm::new(transport, behaviour, peer_id); + ``` + + Now + ```rust + let swarm = Swarm::with_threadpool_executor(transport, behaviour, peer_id); + ``` + - Without + + Spawns the tasks on the current task, this may result in bad performance so try to use an executor where possible. Previously this was just a fallback when no executor was specified and constructing a `ThreadPool` failed. + + New + ```rust + let swarm = Swarm::without_executor(transport, behaviour, peer_id); + ``` + + Deprecated APIs: + - `Swarm::new` + - `SwarmBuilder::new` + - `SwarmBuilder::executor` + +- Update `rust-version` to reflect the actual MSRV: 1.62.0. See [PR 3090]. + +[PR 3085]: https://github.com/libp2p/rust-libp2p/pull/3085 +[PR 3011]: https://github.com/libp2p/rust-libp2p/pull/3011 +[PR 3055]: https://github.com/libp2p/rust-libp2p/pull/3055 +[PR 3097]: https://github.com/libp2p/rust-libp2p/pull/3097 +[Issue 3107]: https://github.com/libp2p/rust-libp2p/issues/3107 +[PR 3090]: https://github.com/libp2p/rust-libp2p/pull/3090 + +## 0.40.1 + +- Bump rand to 0.8 and quickcheck to 1. See [PR 2857]. + +- Update to `libp2p-core` `v0.37.0`. + +- Introduce `libp2p_swarm::keep_alive::ConnectionHandler` in favor of removing `keep_alive` from + `libp2p_swarm::dummy::ConnectionHandler`. `dummy::ConnectionHandler` now literally does not do anything. In the same + spirit, introduce `libp2p_swarm::keep_alive::Behaviour` and `libp2p_swarm::dummy::Behaviour`. See [PR 2859]. + +[PR 2857]: https://github.com/libp2p/rust-libp2p/pull/2857 +[PR 2859]: https://github.com/libp2p/rust-libp2p/pull/2859/ + +- Pass actual `PeerId` of dial to `NetworkBehaviour::inject_dial_failure` on `DialError::ConnectionLimit`. See [PR 2928]. + +[PR 2928]: https://github.com/libp2p/rust-libp2p/pull/2928 + + +## 0.39.0 + +- Remove deprecated `NetworkBehaviourEventProcess`. See [libp2p-swarm v0.38.0 changelog entry] for + migration path. + +- Update to `libp2p-core` `v0.36.0`. + +- Enforce backpressure on incoming streams via `StreamMuxer` interface. In case we hit the configured limit of maximum + number of inbound streams, we will stop polling the `StreamMuxer` for new inbound streams. Depending on the muxer + implementation in use, this may lead to instant dropping of inbound streams. See [PR 2861]. + +[libp2p-swarm v0.38.0 changelog entry]: https://github.com/libp2p/rust-libp2p/blob/master/swarm/CHANGELOG.md#0380 +[PR 2861]: https://github.com/libp2p/rust-libp2p/pull/2861/ + +## 0.38.0 + +- Deprecate `NetworkBehaviourEventProcess`. When deriving `NetworkBehaviour` on a custom `struct` users + should either bring their own `OutEvent` via `#[behaviour(out_event = "MyBehaviourEvent")]` or, + when not specified, have the derive macro generate one for the user. + + See [`NetworkBehaviour` + documentation](https://docs.rs/libp2p/latest/libp2p/swarm/trait.NetworkBehaviour.html) and [PR + 2784] for details. + + Previously + + ``` rust + #[derive(NetworkBehaviour)] + #[behaviour(event_process = true)] + struct MyBehaviour { + gossipsub: Gossipsub, + mdns: Mdns, + } + + impl NetworkBehaviourEventProcess for MyBehaviour { + fn inject_event(&mut self, message: GossipsubEvent) { + todo!("Handle event") + } + } + + impl NetworkBehaviourEventProcess for MyBehaviour { + fn inject_event(&mut self, message: MdnsEvent) { + todo!("Handle event") + } + } + ``` + + Now + + ``` rust + #[derive(NetworkBehaviour)] + #[behaviour(out_event = "MyBehaviourEvent")] + struct MyBehaviour { + gossipsub: Gossipsub, + mdns: Mdns, + } + + enum MyBehaviourEvent { + Gossipsub(GossipsubEvent), + Mdns(MdnsEvent), + } + + impl From for MyBehaviourEvent { + fn from(event: GossipsubEvent) -> Self { + MyBehaviourEvent::Gossipsub(event) + } + } + + impl From for MyBehaviourEvent { + fn from(event: MdnsEvent) -> Self { + MyBehaviourEvent::Mdns(event) + } + } + + match swarm.next().await.unwrap() { + SwarmEvent::Behaviour(MyBehaviourEvent::Gossipsub(event)) => { + todo!("Handle event") + } + SwarmEvent::Behaviour(MyBehaviourEvent::Mdns(event)) => { + todo!("Handle event") + } + } + ``` + +- When deriving `NetworkBehaviour` on a custom `struct` where the user does not specify their own + `OutEvent` via `#[behaviour(out_event = "MyBehaviourEvent")]` and where the user does not enable + `#[behaviour(event_process = true)]`, then the derive macro generates an `OutEvent` definition for + the user. + + See [`NetworkBehaviour` + documentation](https://docs.rs/libp2p/latest/libp2p/swarm/trait.NetworkBehaviour.html) and [PR + 2792] for details. + +- Update dial address concurrency factor to `8`, thus dialing up to 8 addresses concurrently for a single connection attempt. See `Swarm::dial_concurrency_factor` and [PR 2741]. + +- Update to `libp2p-core` `v0.35.0`. + +[PR 2741]: https://github.com/libp2p/rust-libp2p/pull/2741/ +[PR 2784]: https://github.com/libp2p/rust-libp2p/pull/2784 +[PR 2792]: https://github.com/libp2p/rust-libp2p/pull/2792 + +## 0.37.0 + +- Update to `libp2p-core` `v0.34.0`. + +- Extend log message when exceeding inbound negotiating streams with peer ID and limit. See [PR 2716]. + +- Remove `connection::ListenersStream` and poll the `Transport` directly. See [PR 2652]. + +[PR 2716]: https://github.com/libp2p/rust-libp2p/pull/2716/ +[PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 + +## 0.36.1 + +- Limit negotiating inbound substreams per connection. See [PR 2697]. + +[PR 2697]: https://github.com/libp2p/rust-libp2p/pull/2697 + +## 0.36.0 + +- Don't require `Transport` to be `Clone`. See [PR 2529]. + +- Update to `libp2p-core` `v0.33.0`. + +- Make `behaviour::either` module private. See [PR 2610] + +- Rename `IncomingInfo::to_connected_point` to `IncomingInfo::create_connected_point`. See [PR 2620]. + +- Rename `TProtoHandler` to `TConnectionHandler`, `ToggleProtoHandler` to `ToggleConnectionHandler`, `ToggleIntoProtoHandler` to `ToggleIntoConnectionHandler`. See [PR 2640]. + +[PR 2529]: https://github.com/libp2p/rust-libp2p/pull/2529 +[PR 2610]: https://github.com/libp2p/rust-libp2p/pull/2610 +[PR 2620]: https://github.com/libp2p/rust-libp2p/pull/2620 +[PR 2640]: https://github.com/libp2p/rust-libp2p/pull/2640 + +## 0.35.0 + +- Add impl `IntoIterator` for `MultiHandler`. See [PR 2572]. +- Remove `Send` bound from `NetworkBehaviour`. See [PR 2535]. + +[PR 2572]: https://github.com/libp2p/rust-libp2p/pull/2572/ +[PR 2535]: https://github.com/libp2p/rust-libp2p/pull/2535/ + +## 0.34.0 [2022-02-22] + +- Rename `ProtocolsHandler` to `ConnectionHandler`. Upgrade should be as simple as renaming all + occurrences of `ProtocolsHandler` to `ConnectionHandler` with your favorite text manipulation tool + across your codebase. See [PR 2527]. + +- Fold `libp2p-core`'s `Network` into `Swarm`. See [PR 2492]. + +- Update to `libp2p-core` `v0.32.0`. + +- Disconnect pending connections with `Swarm::disconnect`. See [PR 2517]. + +- Report aborted connections via `SwarmEvent::OutgoingConnectionError`. See [PR 2517]. + +[PR 2492]: https://github.com/libp2p/rust-libp2p/pull/2492 +[PR 2517]: https://github.com/libp2p/rust-libp2p/pull/2517 +[PR 2527]: https://github.com/libp2p/rust-libp2p/pull/2527 + +## 0.33.0 [2022-01-27] + +- Patch reporting on banned peers and their non-banned and banned connections (see [PR 2350]). + +- Update dependencies. + +- Migrate to Rust edition 2021 (see [PR 2339]). + +- Update `Connection::address` on `inject_address_change` (see [PR 2362]). + +- Move `swarm::Toggle` to `swarm::behaviour::Toggle` (see [PR 2375]). + +- Add `Swarm::connected_peers` (see [PR 2378]). + +- Implement `swarm::NetworkBehaviour` on `either::Either` (see [PR 2370]). + +- Allow overriding _dial concurrency factor_ per dial via + `DialOpts::override_dial_concurrency_factor`. See [PR 2404]. + +- Report negotiated and expected `PeerId` as well as remote address in + `DialError::WrongPeerId` (see [PR 2428]). + +- Allow overriding role when dialing through `override_role` option on + `DialOpts`. This option is needed for NAT and firewall hole punching. See [PR + 2363]. + +- Merge NetworkBehaviour's inject_\* paired methods (see PR 2445). + +[PR 2339]: https://github.com/libp2p/rust-libp2p/pull/2339 +[PR 2350]: https://github.com/libp2p/rust-libp2p/pull/2350 +[PR 2362]: https://github.com/libp2p/rust-libp2p/pull/2362 +[PR 2370]: https://github.com/libp2p/rust-libp2p/pull/2370 +[PR 2375]: https://github.com/libp2p/rust-libp2p/pull/2375 +[PR 2378]: https://github.com/libp2p/rust-libp2p/pull/2378 +[PR 2404]: https://github.com/libp2p/rust-libp2p/pull/2404 +[PR 2428]: https://github.com/libp2p/rust-libp2p/pull/2428 +[PR 2363]: https://github.com/libp2p/rust-libp2p/pull/2363 +[PR 2445]: https://github.com/libp2p/rust-libp2p/pull/2445 + +## 0.32.0 [2021-11-16] + +- Use `instant` and `futures-timer` instead of `wasm-timer` (see [PR 2245]). + +- Enable advanced dialing requests both on `Swarm::dial` and via + `NetworkBehaviourAction::Dial`. Users can now trigger a dial with a specific + set of addresses, optionally extended via + `NetworkBehaviour::addresses_of_peer`. + + Changes required to maintain status quo: + + - Previously `swarm.dial(peer_id)` + now `swarm.dial(DialOpts::peer_id(peer_id).build())` + or `swarm.dial(peer_id)` given that `DialOpts` implements `From`. + + - Previously `swarm.dial_addr(addr)` + now `swarm.dial(DialOpts::unknown_peer_id().address(addr).build())` + or `swarm.dial(addr)` given that `DialOpts` implements `From`. + + - Previously `NetworkBehaviourAction::DialPeer { peer_id, condition, handler }` + now + + ```rust + NetworkBehaviourAction::Dial { + opts: DialOpts::peer_id(peer_id) + .condition(condition) + .build(), + handler, + } + ``` + + - Previously `NetworkBehaviourAction::DialAddress { address, handler }` + now + + ```rust + NetworkBehaviourAction::Dial { + opts: DialOpts::unknown_peer_id() + .address(address) + .build(), + handler, + } + ``` + + See [PR 2317]. + +[PR 2245]: https://github.com/libp2p/rust-libp2p/pull/2245 +[PR 2317]: https://github.com/libp2p/rust-libp2p/pull/2317 + +## 0.31.0 [2021-11-01] + +- Make default features of `libp2p-core` optional. + [PR 2181](https://github.com/libp2p/rust-libp2p/pull/2181) + +- Update dependencies. + +- Provide default implementations for all functions of `NetworkBehaviour`, + except for `new_handler`, `inject_event` and `poll`. + This should make it easier to create new implementations. See [PR 2150]. + +- Remove `Swarm` type alias and rename `ExpandedSwarm` to `Swarm`. Reduce direct + trait parameters on `Swarm` (previously `ExpandedSwarm`), deriving parameters + through associated types on `TBehaviour`. See [PR 2182]. + +- Require `ProtocolsHandler::{InEvent,OutEvent,Error}` to implement `Debug` (see + [PR 2183]). + +- Implement `ProtocolsHandler` on `either::Either`representing either of two + `ProtocolsHandler` implementations (see [PR 2192]). + +- Require implementation to provide handler in + `NetworkBehaviourAction::DialPeer` and `NetworkBehaviourAction::DialAddress`. + Note that the handler is returned to the `NetworkBehaviour` on connection + failure and connection closing. Thus it can be used to carry state, which + otherwise would have to be tracked in the `NetworkBehaviour` itself. E.g. a + message destined to an unconnected peer can be included in the handler, and + thus directly send on connection success or extracted by the + `NetworkBehaviour` on connection failure (see [PR 2191]). + +- Include handler in `NetworkBehaviour::inject_dial_failure`, + `NetworkBehaviour::inject_connection_closed`, + `NetworkBehaviour::inject_listen_failure` (see [PR 2191]). + +- Include error in `NetworkBehaviour::inject_dial_failure` and call + `NetworkBehaviour::inject_dial_failure` on `DialPeerCondition` evaluating to + false. To emulate the previous behaviour, return early within + `inject_dial_failure` on `DialError::DialPeerConditionFalse`. See [PR 2191]. + +- Make `NetworkBehaviourAction` generic over `NetworkBehaviour::OutEvent` and + `NetworkBehaviour::ProtocolsHandler`. In most cases, change your generic type + parameters to `NetworkBehaviourAction`. See [PR 2191]. + +- Return `bool` instead of `Result<(), ()>` for `Swarm::remove_listener`(see + [PR 2261]). + +- Concurrently dial address candidates within a single dial attempt (see [PR 2248]) configured via + `Swarm::dial_concurrency_factor`. + + - On success of a single address, report errors of the thus far failed dials via + `SwarmEvent::ConnectionEstablished::outgoing`. + + - On failure of all addresses, report errors via the new `SwarmEvent::OutgoingConnectionError`. + + - Remove `SwarmEvent::UnreachableAddr` and `SwarmEvent::UnknownPeerUnreachableAddr` event. + + - In `NetworkBehaviour::inject_connection_established` provide errors of all thus far failed addresses. + + - On unknown peer dial failures, call `NetworkBehaviour::inject_dial_failure` with a peer ID of `None`. + + - Remove `NetworkBehaviour::inject_addr_reach_failure`. Information is now provided via + `NetworkBehaviour::inject_connection_established` and `NetworkBehaviour::inject_dial_failure`. + +[PR 2150]: https://github.com/libp2p/rust-libp2p/pull/2150 +[PR 2182]: https://github.com/libp2p/rust-libp2p/pull/2182 +[PR 2183]: https://github.com/libp2p/rust-libp2p/pull/2183 +[PR 2192]: https://github.com/libp2p/rust-libp2p/pull/2192 +[PR 2191]: https://github.com/libp2p/rust-libp2p/pull/2191 +[PR 2248]: https://github.com/libp2p/rust-libp2p/pull/2248 +[PR 2261]: https://github.com/libp2p/rust-libp2p/pull/2261 + +## 0.30.0 [2021-07-12] + +- Update dependencies. + +- Drive `ExpandedSwarm` via `Stream` trait only. + + - Change `Stream` implementation of `ExpandedSwarm` to return all + `SwarmEvents` instead of only the `NetworkBehaviour`'s events. + + - Remove `ExpandedSwarm::next_event`. Users can use `::next` instead. + + - Remove `ExpandedSwarm::next`. Users can use `::filter_map` instead. + + See [PR 2100] for details. + +- Add `ExpandedSwarm::disconnect_peer_id` and + `NetworkBehaviourAction::CloseConnection` to close connections to a specific + peer via an `ExpandedSwarm` or `NetworkBehaviour`. See [PR 2110] for details. + +- Expose the `ListenerId` in `SwarmEvent`s that are associated with a listener. + + See [PR 2123] for details. + +[PR 2100]: https://github.com/libp2p/rust-libp2p/pull/2100 +[PR 2110]: https://github.com/libp2p/rust-libp2p/pull/2110/ +[PR 2123]: https://github.com/libp2p/rust-libp2p/pull/2123 + +## 0.29.0 [2021-04-13] + +- Remove `Deref` and `DerefMut` implementations previously dereferencing to the + `NetworkBehaviour` on `Swarm`. Instead one can access the `NetworkBehaviour` + via `Swarm::behaviour` and `Swarm::behaviour_mut`. Methods on `Swarm` can now + be accessed directly, e.g. via `my_swarm.local_peer_id()`. You may use the + command below to transform fully qualified method calls on `Swarm` to simple + method calls [PR 1995](https://github.com/libp2p/rust-libp2p/pull/1995). + + ``` bash + # Go from e.g. `Swarm::local_peer_id(&my_swarm)` to `my_swarm.local_peer_id()`. + grep -RiIl --include \*.rs --exclude-dir target . --exclude-dir .git | xargs sed -i "s/\(libp2p::\)*Swarm::\([a-z_]*\)(&mut \([a-z_0-9]*\), /\3.\2(/g" + ``` + +- Extend `NetworkBehaviour` callbacks, more concretely introducing new `fn + inject_new_listener` and `fn inject_expired_external_addr` and have `fn + inject_{new,expired}_listen_addr` provide a `ListenerId` [PR + 2011](https://github.com/libp2p/rust-libp2p/pull/2011). + +## 0.28.0 [2021-03-17] + +- New error variant `DialError::InvalidAddress` + +- `Swarm::dial_addr()` now returns a `DialError` on error. + +- Remove the option for a substream-specific multistream select protocol override. + The override at this granularity is no longer deemed useful, in particular because + it can usually not be configured for existing protocols like `libp2p-kad` and others. + There is a `Swarm`-scoped configuration for this version available since + [1858](https://github.com/libp2p/rust-libp2p/pull/1858). + +## 0.27.2 [2021-02-04] + +- Have `ToggleProtoHandler` ignore listen upgrade errors when disabled. + [PR 1945](https://github.com/libp2p/rust-libp2p/pull/1945/files). + +## 0.27.1 [2021-01-27] + +- Make `OneShotHandler`s `max_dial_negotiate` limit configurable. + [PR 1936](https://github.com/libp2p/rust-libp2p/pull/1936). + +- Fix handling of DialPeerCondition::Always. + [PR 1937](https://github.com/libp2p/rust-libp2p/pull/1937). + +## 0.27.0 [2021-01-12] + +- Update dependencies. + +## 0.26.0 [2020-12-17] + +- Update `libp2p-core`. + +- Remove `NotifyHandler::All` thus removing the requirement for events send from + a `NetworkBehaviour` to a `ProtocolsHandler` to be `Clone`. + [PR 1880](https://github.com/libp2p/rust-libp2p/pull/1880). + +## 0.25.1 [2020-11-26] + +- Add `ExpandedSwarm::is_connected`. + [PR 1862](https://github.com/libp2p/rust-libp2p/pull/1862). + +## 0.25.0 [2020-11-25] + +- Permit a configuration override for the substream upgrade protocol + to use for all (outbound) substreams. + [PR 1858](https://github.com/libp2p/rust-libp2p/pull/1858). + +- Changed parameters for connection limits from `usize` to `u32`. + Connection limits are now configured via `SwarmBuilder::connection_limits()`. + +- Update `libp2p-core`. + +- Expose configurable scores for external addresses, as well as + the ability to remove them and to add addresses that are + retained "forever" (or until explicitly removed). + [PR 1842](https://github.com/libp2p/rust-libp2p/pull/1842). + +## 0.24.0 [2020-11-09] + +- Update dependencies. + +## 0.23.0 [2020-10-16] + +- Require a `Boxed` transport to be given to the `Swarm` + or `SwarmBuilder` to avoid unnecessary double-boxing of + transports and simplify API bounds. + [PR 1794](https://github.com/libp2p/rust-libp2p/pull/1794) + +- Respect inbound timeouts and upgrade versions in the `MultiHandler`. + [PR 1786](https://github.com/libp2p/rust-libp2p/pull/1786). + +- Instead of iterating each inbound and outbound substream upgrade looking for + one to make progress, use a `FuturesUnordered` for both pending inbound and + pending outbound upgrades. As a result only those upgrades are polled that are + ready to progress. + + Implementors of `InboundUpgrade` and `OutboundUpgrade` need to ensure to wake + up the underlying task once they are ready to make progress as they won't be + polled otherwise. + + [PR 1775](https://github.com/libp2p/rust-libp2p/pull/1775) + +## 0.22.0 [2020-09-09] + +- Bump `libp2p-core` dependency. + +- Adds `ProtocolsHandler::InboundOpenInfo` type which mirrors the existing + `OutboundOpenInfo` type. A value of this type is passed as an extra argument + to `ProtocolsHandler::inject_fully_negotiated_inbound` and + `ProtocolsHandler::inject_listen_upgrade_error`. + +- `SubstreamProtocol` now has a second type parameter corresponding to + inbound or outbound information, a value of which is part of `SubstreamProtocol` + now. Consequently `ProtocolsHandlerEvent::OutboundSubstreamRequest` no longer + has a separate `info` field. + +## 0.21.0 [2020-08-18] + +- Add missing delegation calls in some `ProtocolsHandler` wrappers. +See [PR 1710](https://github.com/libp2p/rust-libp2p/pull/1710). + +- Add as_ref and as_mut functions to Toggle +[PR 1684](https://github.com/libp2p/rust-libp2p/pull/1684). + +- The `cause` of `SwarmEvent::ConnectionClosed` is now an `Option`, +and `None` indicates an active connection close not caused by an +error. + +- `DialError::Banned` has been added and is returned from `Swarm::dial` +if the peer is banned, thereby also invoking the `NetworkBehaviour::inject_dial_failure` +callback. + +- Update the `libp2p-core` dependency to `0.21`, fixing [1584](https://github.com/libp2p/rust-libp2p/issues/1584). + +- Fix connections being kept alive by `OneShotHandler` when not handling any + requests [PR 1698](https://github.com/libp2p/rust-libp2p/pull/1698). + +## 0.20.1 [2020-07-08] + +- Documentation updates. + +- Ignore addresses returned by `NetworkBehaviour::addresses_of_peer` +that the `Swarm` considers to be listening addresses of the local node. This +avoids futile dialing attempts of a node to itself, which can otherwise +even happen in genuine situations, e.g. after the local node changed +its network identity and a behaviour makes a dialing attempt to a +former identity using the same addresses. + +## 0.20.0 [2020-07-01] + +- Updated the `libp2p-core` dependency. + +- Add `ProtocolsHandler::inject_listen_upgrade_error`, the inbound +analogue of `ProtocolsHandler::inject_dial_upgrade_error`, with an +empty default implementation. No implementation is required to +retain existing behaviour. + +- Add `ProtocolsHandler::inject_address_change` and +`NetworkBehaviour::inject_address_change` to notify of a change in +the address of an existing connection. + +## 0.19.1 [2020-06-18] + +- Bugfix: Fix MultiHandler panicking when empty + ([PR 1598](https://github.com/libp2p/rust-libp2p/pull/1598)). diff --git a/third-party/libp2p-swarm-0.45.1/Cargo.toml b/third-party/libp2p-swarm-0.45.1/Cargo.toml new file mode 100644 index 00000000000..158d5d8a721 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/Cargo.toml @@ -0,0 +1,189 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.75.0" +name = "libp2p-swarm" +version = "0.45.1" +authors = ["Parity Technologies "] +build = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "The libp2p swarm" +readme = false +keywords = [ + "peer-to-peer", + "libp2p", + "networking", +] +categories = [ + "network-programming", + "asynchronous", +] +license = "MIT" +repository = "https://github.com/libp2p/rust-libp2p" + +[package.metadata.docs.rs] +all-features = true + +[lib] +name = "libp2p_swarm" +path = "src/lib.rs" + +[[test]] +name = "connection_close" +path = "tests/connection_close.rs" + +[[test]] +name = "listener" +path = "tests/listener.rs" + +[[test]] +name = "swarm_derive" +path = "tests/swarm_derive.rs" +required-features = ["macros"] + +[[bench]] +name = "connection_handler" +path = "benches/connection_handler.rs" +harness = false + +[dependencies.either] +version = "1.11.0" + +[dependencies.fnv] +version = "1.0" + +[dependencies.futures] +version = "0.3.30" + +[dependencies.futures-timer] +version = "3.0.3" + +[dependencies.getrandom] +version = "0.2.15" +features = ["js"] +optional = true + +[dependencies.libp2p-core] +version = "0.42.0" + +[dependencies.libp2p-identity] +version = "0.2.9" + +[dependencies.libp2p-swarm-derive] +version = "=0.35.1" +optional = true + +[dependencies.lru] +version = "0.12.3" + +[dependencies.multistream-select] +version = "0.13.0" + +[dependencies.once_cell] +version = "1.19.0" + +[dependencies.rand] +version = "0.8" + +[dependencies.smallvec] +version = "1.13.2" + +[dependencies.tracing] +version = "0.1.37" + +[dependencies.void] +version = "1" + +[dependencies.wasm-bindgen-futures] +version = "0.4.42" +optional = true + +[dependencies.web-time] +version = "1.1.0" + +[dev-dependencies.async-std] +version = "1.6.2" +features = ["attributes"] + +[dev-dependencies.criterion] +version = "0.5" +features = ["async_tokio"] + +[dev-dependencies.either] +version = "1.11.0" + +[dev-dependencies.futures] +version = "0.3.30" + +[dev-dependencies.libp2p-identity] +version = "0.2.9" +features = ["ed25519"] + +[dev-dependencies.once_cell] +version = "1.19.0" + +[dev-dependencies.tokio] +version = "1.38" +features = [ + "time", + "rt", + "macros", + "rt-multi-thread", +] +default-features = false + +[dev-dependencies.tracing-subscriber] +version = "0.3" +features = ["env-filter"] + +[dev-dependencies.trybuild] +version = "1.0.95" + +[dev-dependencies.void] +version = "1" + +[features] +async-std = ["dep:async-std"] +macros = ["dep:libp2p-swarm-derive"] +tokio = ["dep:tokio"] +wasm-bindgen = [ + "dep:wasm-bindgen-futures", + "dep:getrandom", +] + +[target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies.async-std] +version = "1.6.2" +optional = true + +[target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies.tokio] +version = "1.38" +features = ["rt"] +optional = true +default-features = false + +[lints.clippy] +dbg_macro = "warn" +manual_let_else = "warn" +type_complexity = "allow" +unnecessary_wraps = "warn" +used_underscore_binding = "warn" + +[lints.clippy.pedantic] +level = "allow" +priority = -1 + +[lints.rust] +unreachable_pub = "warn" diff --git a/third-party/libp2p-swarm-0.45.1/Cargo.toml.orig b/third-party/libp2p-swarm-0.45.1/Cargo.toml.orig new file mode 100644 index 00000000000..3d0b1a84eee --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/Cargo.toml.orig @@ -0,0 +1,76 @@ +[package] +name = "libp2p-swarm" +edition = "2021" +rust-version = { workspace = true } +description = "The libp2p swarm" +version = "0.45.1" +authors = ["Parity Technologies "] +license = "MIT" +repository = "https://github.com/libp2p/rust-libp2p" +keywords = ["peer-to-peer", "libp2p", "networking"] +categories = ["network-programming", "asynchronous"] + +[dependencies] +either = "1.11.0" +fnv = "1.0" +futures = { workspace = true } +futures-timer = "3.0.3" +getrandom = { version = "0.2.15", features = ["js"], optional = true } # Explicit dependency to be used in `wasm-bindgen` feature +web-time = { workspace = true } +libp2p-core = { workspace = true } +libp2p-identity = { workspace = true } +libp2p-swarm-derive = { workspace = true, optional = true } +lru = "0.12.3" +multistream-select = { workspace = true } +once_cell = "1.19.0" +rand = "0.8" +smallvec = "1.13.2" +tracing = { workspace = true } +void = "1" +wasm-bindgen-futures = { version = "0.4.42", optional = true } + +[target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies] +async-std = { version = "1.6.2", optional = true } +tokio = { workspace = true, features = ["rt"], optional = true } + +[features] +macros = ["dep:libp2p-swarm-derive"] +tokio = ["dep:tokio"] +async-std = ["dep:async-std"] +wasm-bindgen = ["dep:wasm-bindgen-futures", "dep:getrandom"] + +[dev-dependencies] +async-std = { version = "1.6.2", features = ["attributes"] } +either = "1.11.0" +futures = { workspace = true } +libp2p-identify = { path = "../protocols/identify" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. +libp2p-identity = { workspace = true, features = ["ed25519"] } +libp2p-kad = { path = "../protocols/kad" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. +libp2p-ping = { path = "../protocols/ping" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. +libp2p-plaintext = { path = "../transports/plaintext" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. +libp2p-swarm-derive = { path = "../swarm-derive" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. +libp2p-swarm-test = { path = "../swarm-test" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. +libp2p-yamux = { path = "../muxers/yamux" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. +quickcheck = { workspace = true } +criterion = { version = "0.5", features = ["async_tokio"] } +void = "1" +once_cell = "1.19.0" +trybuild = "1.0.95" +tokio = { workspace = true, features = ["time", "rt", "macros", "rt-multi-thread"] } +tracing-subscriber = { workspace = true, features = ["env-filter"] } + +[[test]] +name = "swarm_derive" +required-features = ["macros"] + +# Passing arguments to the docsrs builder in order to properly document cfg's. +# More information: https://docs.rs/about/builds#cross-compiling +[package.metadata.docs.rs] +all-features = true + +[[bench]] +name = "connection_handler" +harness = false + +[lints] +workspace = true diff --git a/third-party/libp2p-swarm-0.45.1/benches/connection_handler.rs b/third-party/libp2p-swarm-0.45.1/benches/connection_handler.rs new file mode 100644 index 00000000000..09340421f83 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/benches/connection_handler.rs @@ -0,0 +1,360 @@ +use async_std::stream::StreamExt; +use criterion::{criterion_group, criterion_main, Criterion}; +use libp2p_core::{ + transport::MemoryTransport, InboundUpgrade, Multiaddr, OutboundUpgrade, Transport, UpgradeInfo, +}; +use libp2p_identity::PeerId; +use libp2p_swarm::{ConnectionHandler, NetworkBehaviour, StreamProtocol}; +use std::{convert::Infallible, sync::atomic::AtomicUsize}; +use web_time::Duration; + +macro_rules! gen_behaviour { + ($($name:ident {$($field:ident),*};)*) => {$( + #[derive(libp2p_swarm::NetworkBehaviour, Default)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct $name { + $($field: SpinningBehaviour,)* + } + + impl BigBehaviour for $name { + fn behaviours(&mut self) -> &mut [SpinningBehaviour] { + unsafe { + std::slice::from_raw_parts_mut( + self as *mut Self as *mut SpinningBehaviour, + std::mem::size_of::() / std::mem::size_of::(), + ) + } + } + } + )*}; +} + +macro_rules! benchmarks { + ($( + $group:ident::[$( + $beh:ident::bench() + .name($name:ident) + .poll_count($count:expr) + .protocols_per_behaviour($protocols:expr), + )+]; + )*) => { + + $( + $( + fn $name(c: &mut Criterion) { + <$beh>::run_bench(c, $protocols, $count, true); + } + )+ + + criterion_group!($group, $($name),*); + )* + + criterion_main!($($group),*); + }; +} + +// fans go brrr +gen_behaviour! { + SpinningBehaviour5 { a, b, c, d, e }; + SpinningBehaviour10 { a, b, c, d, e, f, g, h, i, j }; + SpinningBehaviour20 { a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u }; +} + +benchmarks! { + singles::[ + SpinningBehaviour::bench().name(b).poll_count(1000).protocols_per_behaviour(10), + SpinningBehaviour::bench().name(c).poll_count(1000).protocols_per_behaviour(100), + SpinningBehaviour::bench().name(d).poll_count(1000).protocols_per_behaviour(1000), + ]; + big_5::[ + SpinningBehaviour5::bench().name(e).poll_count(1000).protocols_per_behaviour(2), + SpinningBehaviour5::bench().name(f).poll_count(1000).protocols_per_behaviour(20), + SpinningBehaviour5::bench().name(g).poll_count(1000).protocols_per_behaviour(200), + ]; + top_10::[ + SpinningBehaviour10::bench().name(h).poll_count(1000).protocols_per_behaviour(1), + SpinningBehaviour10::bench().name(i).poll_count(1000).protocols_per_behaviour(10), + SpinningBehaviour10::bench().name(j).poll_count(1000).protocols_per_behaviour(100), + ]; + lucky_20::[ + SpinningBehaviour20::bench().name(k).poll_count(500).protocols_per_behaviour(1), + SpinningBehaviour20::bench().name(l).poll_count(500).protocols_per_behaviour(10), + SpinningBehaviour20::bench().name(m).poll_count(500).protocols_per_behaviour(100), + ]; +} +//fn main() {} + +trait BigBehaviour: Sized { + fn behaviours(&mut self) -> &mut [SpinningBehaviour]; + + fn for_each_beh(&mut self, f: impl FnMut(&mut SpinningBehaviour)) { + self.behaviours().iter_mut().for_each(f); + } + + fn any_beh(&mut self, f: impl FnMut(&mut SpinningBehaviour) -> bool) -> bool { + self.behaviours().iter_mut().any(f) + } + + fn run_bench( + c: &mut Criterion, + protocols_per_behaviour: usize, + spam_count: usize, + static_protocols: bool, + ) where + Self: Default + NetworkBehaviour, + { + let name = format!( + "{}::bench().poll_count({}).protocols_per_behaviour({})", + std::any::type_name::(), + spam_count, + protocols_per_behaviour + ); + + let init = || { + let mut swarm_a = new_swarm(Self::default()); + let mut swarm_b = new_swarm(Self::default()); + + let behaviour_count = swarm_a.behaviours().len(); + let protocol_count = behaviour_count * protocols_per_behaviour; + let protocols = (0..protocol_count) + .map(|i| { + if static_protocols { + StreamProtocol::new(format!("/protocol/{i}").leak()) + } else { + StreamProtocol::try_from_owned(format!("/protocol/{i}")).unwrap() + } + }) + .collect::>() + .leak(); + + let mut protocol_chunks = protocols.chunks(protocols_per_behaviour); + swarm_a.for_each_beh(|b| b.protocols = protocol_chunks.next().unwrap()); + let mut protocol_chunks = protocols.chunks(protocols_per_behaviour); + swarm_b.for_each_beh(|b| b.protocols = protocol_chunks.next().unwrap()); + + swarm_a.for_each_beh(|b| b.iter_count = spam_count); + swarm_b.for_each_beh(|b| b.iter_count = 0); + + swarm_a.for_each_beh(|b| b.other_peer = Some(*swarm_b.local_peer_id())); + swarm_b.for_each_beh(|b| b.other_peer = Some(*swarm_a.local_peer_id())); + + static OFFSET: AtomicUsize = AtomicUsize::new(8000); + let offset = OFFSET.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + + swarm_a + .listen_on(format!("/memory/{offset}").parse().unwrap()) + .unwrap(); + swarm_b + .dial(format!("/memory/{offset}").parse::().unwrap()) + .unwrap(); + + (swarm_a, swarm_b) + }; + + c.bench_function(&name, |b| { + b.to_async(tokio::runtime::Builder::new_multi_thread().build().unwrap()) + .iter_batched( + init, + |(mut swarm_a, mut swarm_b)| async move { + while swarm_a.any_beh(|b| !b.finished) || swarm_b.any_beh(|b| !b.finished) { + futures::future::select(swarm_b.next(), swarm_a.next()).await; + } + }, + criterion::BatchSize::LargeInput, + ); + }); + } +} + +impl BigBehaviour for libp2p_swarm::Swarm { + fn behaviours(&mut self) -> &mut [SpinningBehaviour] { + self.behaviour_mut().behaviours() + } +} + +fn new_swarm(beh: T) -> libp2p_swarm::Swarm { + let keypair = libp2p_identity::Keypair::generate_ed25519(); + libp2p_swarm::Swarm::new( + MemoryTransport::default() + .upgrade(multistream_select::Version::V1) + .authenticate(libp2p_plaintext::Config::new(&keypair)) + .multiplex(libp2p_yamux::Config::default()) + .boxed(), + beh, + keypair.public().to_peer_id(), + libp2p_swarm::Config::without_executor().with_idle_connection_timeout(Duration::MAX), + ) +} + +/// Whole purpose of the behaviour is to rapidly call `poll` on the handler +/// configured amount of times and then emit event when finished. +#[derive(Default)] +struct SpinningBehaviour { + iter_count: usize, + protocols: &'static [StreamProtocol], + finished: bool, + emitted: bool, + other_peer: Option, +} + +#[derive(Debug)] +struct FinishedSpinning; + +impl NetworkBehaviour for SpinningBehaviour { + type ConnectionHandler = SpinningHandler; + type ToSwarm = FinishedSpinning; + + fn handle_established_inbound_connection( + &mut self, + _connection_id: libp2p_swarm::ConnectionId, + _peer: libp2p_identity::PeerId, + _local_addr: &libp2p_core::Multiaddr, + _remote_addr: &libp2p_core::Multiaddr, + ) -> Result, libp2p_swarm::ConnectionDenied> { + Ok(SpinningHandler { + iter_count: 0, + protocols: self.protocols, + }) + } + + fn handle_established_outbound_connection( + &mut self, + _connection_id: libp2p_swarm::ConnectionId, + _peer: libp2p_identity::PeerId, + _addr: &libp2p_core::Multiaddr, + _role_override: libp2p_core::Endpoint, + _port_use: libp2p_core::transport::PortUse, + ) -> Result, libp2p_swarm::ConnectionDenied> { + Ok(SpinningHandler { + iter_count: self.iter_count, + protocols: self.protocols, + }) + } + + fn on_swarm_event(&mut self, _: libp2p_swarm::FromSwarm) {} + + fn on_connection_handler_event( + &mut self, + _peer_id: libp2p_identity::PeerId, + _connection_id: libp2p_swarm::ConnectionId, + _event: libp2p_swarm::THandlerOutEvent, + ) { + self.finished = true; + } + + fn poll( + &mut self, + _: &mut std::task::Context<'_>, + ) -> std::task::Poll>> + { + if self.finished && !self.emitted { + self.emitted = true; + std::task::Poll::Ready(libp2p_swarm::ToSwarm::GenerateEvent(FinishedSpinning)) + } else { + std::task::Poll::Pending + } + } +} + +impl BigBehaviour for SpinningBehaviour { + fn behaviours(&mut self) -> &mut [SpinningBehaviour] { + std::slice::from_mut(self) + } +} + +struct SpinningHandler { + iter_count: usize, + protocols: &'static [StreamProtocol], +} + +impl ConnectionHandler for SpinningHandler { + type FromBehaviour = Infallible; + + type ToBehaviour = FinishedSpinning; + + type InboundProtocol = Upgrade; + + type OutboundProtocol = Upgrade; + + type InboundOpenInfo = (); + + type OutboundOpenInfo = (); + + fn listen_protocol( + &self, + ) -> libp2p_swarm::SubstreamProtocol { + libp2p_swarm::SubstreamProtocol::new(Upgrade(self.protocols), ()) + } + + fn poll( + &mut self, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll< + libp2p_swarm::ConnectionHandlerEvent< + Self::OutboundProtocol, + Self::OutboundOpenInfo, + Self::ToBehaviour, + >, + > { + if self.iter_count == usize::MAX { + return std::task::Poll::Pending; + } + + if self.iter_count != 0 { + self.iter_count -= 1; + cx.waker().wake_by_ref(); + return std::task::Poll::Pending; + } + + self.iter_count = usize::MAX; + std::task::Poll::Ready(libp2p_swarm::ConnectionHandlerEvent::NotifyBehaviour( + FinishedSpinning, + )) + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + match event {} + } + + fn on_connection_event( + &mut self, + _event: libp2p_swarm::handler::ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + } +} + +pub struct Upgrade(&'static [StreamProtocol]); + +impl UpgradeInfo for Upgrade { + type Info = &'static StreamProtocol; + type InfoIter = std::slice::Iter<'static, StreamProtocol>; + + fn protocol_info(&self) -> Self::InfoIter { + self.0.iter() + } +} + +impl OutboundUpgrade for Upgrade { + type Output = libp2p_swarm::Stream; + type Error = Infallible; + type Future = futures::future::Ready>; + + fn upgrade_outbound(self, s: libp2p_swarm::Stream, _: Self::Info) -> Self::Future { + futures::future::ready(Ok(s)) + } +} + +impl InboundUpgrade for Upgrade { + type Output = libp2p_swarm::Stream; + type Error = Infallible; + type Future = futures::future::Ready>; + + fn upgrade_inbound(self, s: libp2p_swarm::Stream, _: Self::Info) -> Self::Future { + futures::future::ready(Ok(s)) + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour.rs new file mode 100644 index 00000000000..35aed12fba5 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/behaviour.rs @@ -0,0 +1,585 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +mod either; +mod external_addresses; +mod listen_addresses; +mod peer_addresses; +pub mod toggle; + +pub use external_addresses::ExternalAddresses; +pub use listen_addresses::ListenAddresses; +pub use peer_addresses::PeerAddresses; + +use crate::connection::ConnectionId; +use crate::dial_opts::DialOpts; +use crate::listen_opts::ListenOpts; +use crate::{ + ConnectionDenied, ConnectionError, ConnectionHandler, DialError, ListenError, THandler, + THandlerInEvent, THandlerOutEvent, +}; +use libp2p_core::{ + transport::{ListenerId, PortUse}, + ConnectedPoint, Endpoint, Multiaddr, +}; +use libp2p_identity::PeerId; +use std::{task::Context, task::Poll}; + +/// A [`NetworkBehaviour`] defines the behaviour of the local node on the network. +/// +/// In contrast to [`Transport`](libp2p_core::Transport) which defines **how** to send bytes on the +/// network, [`NetworkBehaviour`] defines **what** bytes to send and **to whom**. +/// +/// Each protocol (e.g. `libp2p-ping`, `libp2p-identify` or `libp2p-kad`) implements +/// [`NetworkBehaviour`]. Multiple implementations of [`NetworkBehaviour`] can be composed into a +/// hierarchy of [`NetworkBehaviour`]s where parent implementations delegate to child +/// implementations. Finally the root of the [`NetworkBehaviour`] hierarchy is passed to +/// [`Swarm`](crate::Swarm) where it can then control the behaviour of the local node on a libp2p +/// network. +/// +/// # Hierarchy of [`NetworkBehaviour`] +/// +/// To compose multiple [`NetworkBehaviour`] implementations into a single [`NetworkBehaviour`] +/// implementation, potentially building a multi-level hierarchy of [`NetworkBehaviour`]s, one can +/// use one of the [`NetworkBehaviour`] combinators, and/or use the [`NetworkBehaviour`] derive +/// macro. +/// +/// ## Combinators +/// +/// [`NetworkBehaviour`] combinators wrap one or more [`NetworkBehaviour`] implementations and +/// implement [`NetworkBehaviour`] themselves. Example is the +/// [`Toggle`](crate::behaviour::toggle::Toggle) [`NetworkBehaviour`]. +/// +/// ``` rust +/// # use libp2p_swarm::dummy; +/// # use libp2p_swarm::behaviour::toggle::Toggle; +/// let my_behaviour = dummy::Behaviour; +/// let my_toggled_behaviour = Toggle::from(Some(my_behaviour)); +/// ``` +/// +/// ## Custom [`NetworkBehaviour`] with the Derive Macro +/// +/// One can derive [`NetworkBehaviour`] for a custom `struct` via the `#[derive(NetworkBehaviour)]` +/// proc macro re-exported by the `libp2p` crate. The macro generates a delegating `trait` +/// implementation for the custom `struct`. Each [`NetworkBehaviour`] trait method is simply +/// delegated to each `struct` member in the order the `struct` is defined. For example for +/// [`NetworkBehaviour::poll`] it will first poll the first `struct` member until it returns +/// [`Poll::Pending`] before moving on to later members. +/// +/// Events ([`NetworkBehaviour::ToSwarm`]) returned by each `struct` member are wrapped in a new +/// `enum` event, with an `enum` variant for each `struct` member. Users can define this event +/// `enum` themselves and provide the name to the derive macro via `#[behaviour(to_swarm = +/// "MyCustomOutEvent")]`. If the user does not specify an `to_swarm`, the derive macro generates +/// the event definition itself, naming it `Event`. +/// +/// The aforementioned conversion of each of the event types generated by the struct members to the +/// custom `to_swarm` is handled by [`From`] implementations which the user needs to define in +/// addition to the event `enum` itself. +/// +/// ``` rust +/// # use libp2p_identify as identify; +/// # use libp2p_ping as ping; +/// # use libp2p_swarm_derive::NetworkBehaviour; +/// #[derive(NetworkBehaviour)] +/// #[behaviour(to_swarm = "Event")] +/// # #[behaviour(prelude = "libp2p_swarm::derive_prelude")] +/// struct MyBehaviour { +/// identify: identify::Behaviour, +/// ping: ping::Behaviour, +/// } +/// +/// enum Event { +/// Identify(identify::Event), +/// Ping(ping::Event), +/// } +/// +/// impl From for Event { +/// fn from(event: identify::Event) -> Self { +/// Self::Identify(event) +/// } +/// } +/// +/// impl From for Event { +/// fn from(event: ping::Event) -> Self { +/// Self::Ping(event) +/// } +/// } +/// ``` +pub trait NetworkBehaviour: 'static { + /// Handler for all the protocols the network behaviour supports. + type ConnectionHandler: ConnectionHandler; + + /// Event generated by the `NetworkBehaviour` and that the swarm will report back. + type ToSwarm: Send + 'static; + + /// Callback that is invoked for every new inbound connection. + /// + /// At this point in the connection lifecycle, only the remote's and our local address are known. + /// We have also already allocated a [`ConnectionId`]. + /// + /// Any error returned from this function will immediately abort the dial attempt. + fn handle_pending_inbound_connection( + &mut self, + _connection_id: ConnectionId, + _local_addr: &Multiaddr, + _remote_addr: &Multiaddr, + ) -> Result<(), ConnectionDenied> { + Ok(()) + } + + /// Callback that is invoked for every established inbound connection. + /// + /// This is invoked once another peer has successfully dialed us. + /// + /// At this point, we have verified their [`PeerId`] and we know, which particular [`Multiaddr`] succeeded in the dial. + /// In order to actually use this connection, this function must return a [`ConnectionHandler`]. + /// Returning an error will immediately close the connection. + /// + /// Note when any composed behaviour returns an error the connection will be closed and a + /// [`FromSwarm::ListenFailure`] event will be emitted. + fn handle_established_inbound_connection( + &mut self, + _connection_id: ConnectionId, + peer: PeerId, + local_addr: &Multiaddr, + remote_addr: &Multiaddr, + ) -> Result, ConnectionDenied>; + + /// Callback that is invoked for every outbound connection attempt. + /// + /// We have access to: + /// + /// - The [`PeerId`], if known. Remember that we can dial without a [`PeerId`]. + /// - All addresses passed to [`DialOpts`] are passed in here too. + /// - The effective [`Role`](Endpoint) of this peer in the dial attempt. Typically, this is set to [`Endpoint::Dialer`] except if we are attempting a hole-punch. + /// - The [`ConnectionId`] identifying the future connection resulting from this dial, if successful. + /// + /// Note that the addresses returned from this function are only used for dialing if [`WithPeerIdWithAddresses::extend_addresses_through_behaviour`](crate::dial_opts::WithPeerIdWithAddresses::extend_addresses_through_behaviour) is set. + /// + /// Any error returned from this function will immediately abort the dial attempt. + fn handle_pending_outbound_connection( + &mut self, + _connection_id: ConnectionId, + _maybe_peer: Option, + _addresses: &[Multiaddr], + _effective_role: Endpoint, + ) -> Result, ConnectionDenied> { + Ok(vec![]) + } + + /// Callback that is invoked for every established outbound connection. + /// + /// This is invoked once we have successfully dialed a peer. + /// At this point, we have verified their [`PeerId`] and we know, which particular [`Multiaddr`] succeeded in the dial. + /// In order to actually use this connection, this function must return a [`ConnectionHandler`]. + /// Returning an error will immediately close the connection. + /// + /// Note when any composed behaviour returns an error the connection will be closed and a + /// [`FromSwarm::DialFailure`] event will be emitted. + fn handle_established_outbound_connection( + &mut self, + _connection_id: ConnectionId, + peer: PeerId, + addr: &Multiaddr, + role_override: Endpoint, + port_use: PortUse, + ) -> Result, ConnectionDenied>; + + /// Informs the behaviour about an event from the [`Swarm`](crate::Swarm). + fn on_swarm_event(&mut self, event: FromSwarm); + + /// Informs the behaviour about an event generated by the [`ConnectionHandler`] + /// dedicated to the peer identified by `peer_id`. for the behaviour. + /// + /// The [`PeerId`] is guaranteed to be in a connected state. In other words, + /// [`FromSwarm::ConnectionEstablished`] has previously been received with this [`PeerId`]. + fn on_connection_handler_event( + &mut self, + _peer_id: PeerId, + _connection_id: ConnectionId, + _event: THandlerOutEvent, + ); + + /// Polls for things that swarm should do. + /// + /// This API mimics the API of the `Stream` trait. The method may register the current task in + /// order to wake it up at a later point in time. + fn poll(&mut self, cx: &mut Context<'_>) + -> Poll>>; +} + +/// A command issued from a [`NetworkBehaviour`] for the [`Swarm`]. +/// +/// [`Swarm`]: super::Swarm +#[derive(Debug)] +#[non_exhaustive] +pub enum ToSwarm { + /// Instructs the `Swarm` to return an event when it is being polled. + GenerateEvent(TOutEvent), + + /// Instructs the swarm to start a dial. + /// + /// On success, [`NetworkBehaviour::on_swarm_event`] with `ConnectionEstablished` is invoked. + /// On failure, [`NetworkBehaviour::on_swarm_event`] with `DialFailure` is invoked. + /// + /// [`DialOpts`] provides access to the [`ConnectionId`] via [`DialOpts::connection_id`]. + /// This [`ConnectionId`] will be used throughout the connection's lifecycle to associate events with it. + /// This allows a [`NetworkBehaviour`] to identify a connection that resulted out of its own dial request. + Dial { opts: DialOpts }, + + /// Instructs the [`Swarm`](crate::Swarm) to listen on the provided address. + ListenOn { opts: ListenOpts }, + + /// Instructs the [`Swarm`](crate::Swarm) to remove the listener. + RemoveListener { id: ListenerId }, + + /// Instructs the `Swarm` to send an event to the handler dedicated to a + /// connection with a peer. + /// + /// If the `Swarm` is connected to the peer, the message is delivered to the [`ConnectionHandler`] + /// instance identified by the peer ID and connection ID. + /// + /// If the specified connection no longer exists, the event is silently dropped. + /// + /// Typically the connection ID given is the same as the one passed to + /// [`NetworkBehaviour::on_connection_handler_event`], i.e. whenever the behaviour wishes to + /// respond to a request on the same connection (and possibly the same + /// substream, as per the implementation of [`ConnectionHandler`]). + /// + /// Note that even if the peer is currently connected, connections can get closed + /// at any time and thus the event may not reach a handler. + NotifyHandler { + /// The peer for whom a [`ConnectionHandler`] should be notified. + peer_id: PeerId, + /// The options w.r.t. which connection handler to notify of the event. + handler: NotifyHandler, + /// The event to send. + event: TInEvent, + }, + + /// Reports a **new** candidate for an external address to the [`Swarm`](crate::Swarm). + /// + /// The emphasis on a **new** candidate is important. + /// Protocols MUST take care to only emit a candidate once per "source". + /// For example, the observed address of a TCP connection does not change throughout its lifetime. + /// Thus, only one candidate should be emitted per connection. + /// + /// This makes the report frequency of an address a meaningful data-point for consumers of this event. + /// This address will be shared with all [`NetworkBehaviour`]s via [`FromSwarm::NewExternalAddrCandidate`]. + /// + /// This address could come from a variety of sources: + /// - A protocol such as identify obtained it from a remote. + /// - The user provided it based on configuration. + /// - We made an educated guess based on one of our listen addresses. + NewExternalAddrCandidate(Multiaddr), + + /// Indicates to the [`Swarm`](crate::Swarm) that the provided address is confirmed to be externally reachable. + /// + /// This is intended to be issued in response to a [`FromSwarm::NewExternalAddrCandidate`] if we are indeed externally reachable on this address. + /// This address will be shared with all [`NetworkBehaviour`]s via [`FromSwarm::ExternalAddrConfirmed`]. + ExternalAddrConfirmed(Multiaddr), + + /// Indicates to the [`Swarm`](crate::Swarm) that we are no longer externally reachable under the provided address. + /// + /// This expires an address that was earlier confirmed via [`ToSwarm::ExternalAddrConfirmed`]. + /// This address will be shared with all [`NetworkBehaviour`]s via [`FromSwarm::ExternalAddrExpired`]. + ExternalAddrExpired(Multiaddr), + + /// Instructs the `Swarm` to initiate a graceful close of one or all connections with the given peer. + /// + /// Closing a connection via [`ToSwarm::CloseConnection`] will poll [`ConnectionHandler::poll_close`] to completion. + /// In most cases, stopping to "use" a connection is enough to have it closed. + /// The keep-alive algorithm will close a connection automatically once all [`ConnectionHandler`]s are idle. + /// + /// Use this command if you want to close a connection _despite_ it still being in use by one or more handlers. + CloseConnection { + /// The peer to disconnect. + peer_id: PeerId, + /// Whether to close a specific or all connections to the given peer. + connection: CloseConnection, + }, + + /// Reports external address of a remote peer to the [`Swarm`](crate::Swarm) and through that to other [`NetworkBehaviour`]s. + NewExternalAddrOfPeer { peer_id: PeerId, address: Multiaddr }, +} + +impl ToSwarm { + /// Map the handler event. + pub fn map_in( + self, + f: impl FnOnce(TInEventOld) -> TInEventNew, + ) -> ToSwarm { + match self { + ToSwarm::GenerateEvent(e) => ToSwarm::GenerateEvent(e), + ToSwarm::Dial { opts } => ToSwarm::Dial { opts }, + ToSwarm::ListenOn { opts } => ToSwarm::ListenOn { opts }, + ToSwarm::RemoveListener { id } => ToSwarm::RemoveListener { id }, + ToSwarm::NotifyHandler { + peer_id, + handler, + event, + } => ToSwarm::NotifyHandler { + peer_id, + handler, + event: f(event), + }, + ToSwarm::CloseConnection { + peer_id, + connection, + } => ToSwarm::CloseConnection { + peer_id, + connection, + }, + ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), + ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), + ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), + ToSwarm::NewExternalAddrOfPeer { + address: addr, + peer_id, + } => ToSwarm::NewExternalAddrOfPeer { + address: addr, + peer_id, + }, + } + } +} + +impl ToSwarm { + /// Map the event the swarm will return. + pub fn map_out(self, f: impl FnOnce(TOutEvent) -> E) -> ToSwarm { + match self { + ToSwarm::GenerateEvent(e) => ToSwarm::GenerateEvent(f(e)), + ToSwarm::Dial { opts } => ToSwarm::Dial { opts }, + ToSwarm::ListenOn { opts } => ToSwarm::ListenOn { opts }, + ToSwarm::RemoveListener { id } => ToSwarm::RemoveListener { id }, + ToSwarm::NotifyHandler { + peer_id, + handler, + event, + } => ToSwarm::NotifyHandler { + peer_id, + handler, + event, + }, + ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), + ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), + ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), + ToSwarm::CloseConnection { + peer_id, + connection, + } => ToSwarm::CloseConnection { + peer_id, + connection, + }, + ToSwarm::NewExternalAddrOfPeer { + address: addr, + peer_id, + } => ToSwarm::NewExternalAddrOfPeer { + address: addr, + peer_id, + }, + } + } +} + +/// The options w.r.t. which connection handler to notify of an event. +#[derive(Debug, Clone)] +pub enum NotifyHandler { + /// Notify a particular connection handler. + One(ConnectionId), + /// Notify an arbitrary connection handler. + Any, +} + +/// The options which connections to close. +#[derive(Debug, Clone, Default)] +pub enum CloseConnection { + /// Disconnect a particular connection. + One(ConnectionId), + /// Disconnect all connections. + #[default] + All, +} + +/// Enumeration with the list of the possible events +/// to pass to [`on_swarm_event`](NetworkBehaviour::on_swarm_event). +#[derive(Debug, Clone, Copy)] +#[non_exhaustive] +pub enum FromSwarm<'a> { + /// Informs the behaviour about a newly established connection to a peer. + ConnectionEstablished(ConnectionEstablished<'a>), + /// Informs the behaviour about a closed connection to a peer. + /// + /// This event is always paired with an earlier + /// [`FromSwarm::ConnectionEstablished`] with the same peer ID, connection ID + /// and endpoint. + ConnectionClosed(ConnectionClosed<'a>), + /// Informs the behaviour that the [`ConnectedPoint`] of an existing + /// connection has changed. + AddressChange(AddressChange<'a>), + /// Informs the behaviour that the dial to a known + /// or unknown node failed. + DialFailure(DialFailure<'a>), + /// Informs the behaviour that an error + /// happened on an incoming connection during its initial handshake. + /// + /// This can include, for example, an error during the handshake of the encryption layer, or the + /// connection unexpectedly closed. + ListenFailure(ListenFailure<'a>), + /// Informs the behaviour that a new listener was created. + NewListener(NewListener), + /// Informs the behaviour that we have started listening on a new multiaddr. + NewListenAddr(NewListenAddr<'a>), + /// Informs the behaviour that a multiaddr + /// we were listening on has expired, + /// which means that we are no longer listening on it. + ExpiredListenAddr(ExpiredListenAddr<'a>), + /// Informs the behaviour that a listener experienced an error. + ListenerError(ListenerError<'a>), + /// Informs the behaviour that a listener closed. + ListenerClosed(ListenerClosed<'a>), + /// Informs the behaviour that we have discovered a new candidate for an external address for us. + NewExternalAddrCandidate(NewExternalAddrCandidate<'a>), + /// Informs the behaviour that an external address of the local node was confirmed. + ExternalAddrConfirmed(ExternalAddrConfirmed<'a>), + /// Informs the behaviour that an external address of the local node expired, i.e. is no-longer confirmed. + ExternalAddrExpired(ExternalAddrExpired<'a>), + /// Informs the behaviour that we have discovered a new external address for a remote peer. + NewExternalAddrOfPeer(NewExternalAddrOfPeer<'a>), +} + +/// [`FromSwarm`] variant that informs the behaviour about a newly established connection to a peer. +#[derive(Debug, Clone, Copy)] +pub struct ConnectionEstablished<'a> { + pub peer_id: PeerId, + pub connection_id: ConnectionId, + pub endpoint: &'a ConnectedPoint, + pub failed_addresses: &'a [Multiaddr], + pub other_established: usize, +} + +/// [`FromSwarm`] variant that informs the behaviour about a closed connection to a peer. +/// +/// This event is always paired with an earlier +/// [`FromSwarm::ConnectionEstablished`] with the same peer ID, connection ID +/// and endpoint. +#[derive(Debug, Clone, Copy)] +pub struct ConnectionClosed<'a> { + pub peer_id: PeerId, + pub connection_id: ConnectionId, + pub endpoint: &'a ConnectedPoint, + pub cause: Option<&'a ConnectionError>, + pub remaining_established: usize, +} + +/// [`FromSwarm`] variant that informs the behaviour that the [`ConnectedPoint`] of an existing +/// connection has changed. +#[derive(Debug, Clone, Copy)] +pub struct AddressChange<'a> { + pub peer_id: PeerId, + pub connection_id: ConnectionId, + pub old: &'a ConnectedPoint, + pub new: &'a ConnectedPoint, +} + +/// [`FromSwarm`] variant that informs the behaviour that the dial to a known +/// or unknown node failed. +#[derive(Debug, Clone, Copy)] +pub struct DialFailure<'a> { + pub peer_id: Option, + pub error: &'a DialError, + pub connection_id: ConnectionId, +} + +/// [`FromSwarm`] variant that informs the behaviour that an error +/// happened on an incoming connection during its initial handshake. +/// +/// This can include, for example, an error during the handshake of the encryption layer, or the +/// connection unexpectedly closed. +#[derive(Debug, Clone, Copy)] +pub struct ListenFailure<'a> { + pub local_addr: &'a Multiaddr, + pub send_back_addr: &'a Multiaddr, + pub error: &'a ListenError, + pub connection_id: ConnectionId, + pub peer_id: Option, +} + +/// [`FromSwarm`] variant that informs the behaviour that a new listener was created. +#[derive(Debug, Clone, Copy)] +pub struct NewListener { + pub listener_id: ListenerId, +} + +/// [`FromSwarm`] variant that informs the behaviour +/// that we have started listening on a new multiaddr. +#[derive(Debug, Clone, Copy)] +pub struct NewListenAddr<'a> { + pub listener_id: ListenerId, + pub addr: &'a Multiaddr, +} + +/// [`FromSwarm`] variant that informs the behaviour that a multiaddr +/// we were listening on has expired, +/// which means that we are no longer listening on it. +#[derive(Debug, Clone, Copy)] +pub struct ExpiredListenAddr<'a> { + pub listener_id: ListenerId, + pub addr: &'a Multiaddr, +} + +/// [`FromSwarm`] variant that informs the behaviour that a listener experienced an error. +#[derive(Debug, Clone, Copy)] +pub struct ListenerError<'a> { + pub listener_id: ListenerId, + pub err: &'a (dyn std::error::Error + 'static), +} + +/// [`FromSwarm`] variant that informs the behaviour that a listener closed. +#[derive(Debug, Clone, Copy)] +pub struct ListenerClosed<'a> { + pub listener_id: ListenerId, + pub reason: Result<(), &'a std::io::Error>, +} + +/// [`FromSwarm`] variant that informs the behaviour about a new candidate for an external address for us. +#[derive(Debug, Clone, Copy)] +pub struct NewExternalAddrCandidate<'a> { + pub addr: &'a Multiaddr, +} + +/// [`FromSwarm`] variant that informs the behaviour that an external address was confirmed. +#[derive(Debug, Clone, Copy)] +pub struct ExternalAddrConfirmed<'a> { + pub addr: &'a Multiaddr, +} + +/// [`FromSwarm`] variant that informs the behaviour that an external address was removed. +#[derive(Debug, Clone, Copy)] +pub struct ExternalAddrExpired<'a> { + pub addr: &'a Multiaddr, +} + +/// [`FromSwarm`] variant that informs the behaviour that a new external address for a remote peer was detected. +#[derive(Clone, Copy, Debug)] +pub struct NewExternalAddrOfPeer<'a> { + pub peer_id: PeerId, + pub addr: &'a Multiaddr, +} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/either.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/either.rs new file mode 100644 index 00000000000..7a51303e74d --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/behaviour/either.rs @@ -0,0 +1,168 @@ +// Copyright 2021 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::behaviour::{self, NetworkBehaviour, ToSwarm}; +use crate::connection::ConnectionId; +use crate::{ConnectionDenied, THandler, THandlerInEvent, THandlerOutEvent}; +use either::Either; +use libp2p_core::transport::PortUse; +use libp2p_core::{Endpoint, Multiaddr}; +use libp2p_identity::PeerId; +use std::{task::Context, task::Poll}; + +/// Implementation of [`NetworkBehaviour`] that can be either of two implementations. +impl NetworkBehaviour for Either +where + L: NetworkBehaviour, + R: NetworkBehaviour, +{ + type ConnectionHandler = Either, THandler>; + type ToSwarm = Either; + + fn handle_pending_inbound_connection( + &mut self, + id: ConnectionId, + local_addr: &Multiaddr, + remote_addr: &Multiaddr, + ) -> Result<(), ConnectionDenied> { + match self { + Either::Left(a) => a.handle_pending_inbound_connection(id, local_addr, remote_addr), + Either::Right(b) => b.handle_pending_inbound_connection(id, local_addr, remote_addr), + } + } + + fn handle_established_inbound_connection( + &mut self, + connection_id: ConnectionId, + peer: PeerId, + local_addr: &Multiaddr, + remote_addr: &Multiaddr, + ) -> Result, ConnectionDenied> { + let handler = match self { + Either::Left(inner) => Either::Left(inner.handle_established_inbound_connection( + connection_id, + peer, + local_addr, + remote_addr, + )?), + Either::Right(inner) => Either::Right(inner.handle_established_inbound_connection( + connection_id, + peer, + local_addr, + remote_addr, + )?), + }; + + Ok(handler) + } + + fn handle_pending_outbound_connection( + &mut self, + connection_id: ConnectionId, + maybe_peer: Option, + addresses: &[Multiaddr], + effective_role: Endpoint, + ) -> Result, ConnectionDenied> { + let addresses = match self { + Either::Left(inner) => inner.handle_pending_outbound_connection( + connection_id, + maybe_peer, + addresses, + effective_role, + )?, + Either::Right(inner) => inner.handle_pending_outbound_connection( + connection_id, + maybe_peer, + addresses, + effective_role, + )?, + }; + + Ok(addresses) + } + + fn handle_established_outbound_connection( + &mut self, + connection_id: ConnectionId, + peer: PeerId, + addr: &Multiaddr, + role_override: Endpoint, + port_use: PortUse, + ) -> Result, ConnectionDenied> { + let handler = match self { + Either::Left(inner) => Either::Left(inner.handle_established_outbound_connection( + connection_id, + peer, + addr, + role_override, + port_use, + )?), + Either::Right(inner) => Either::Right(inner.handle_established_outbound_connection( + connection_id, + peer, + addr, + role_override, + port_use, + )?), + }; + + Ok(handler) + } + + fn on_swarm_event(&mut self, event: behaviour::FromSwarm) { + match self { + Either::Left(b) => b.on_swarm_event(event), + Either::Right(b) => b.on_swarm_event(event), + } + } + + fn on_connection_handler_event( + &mut self, + peer_id: PeerId, + connection_id: ConnectionId, + event: THandlerOutEvent, + ) { + match (self, event) { + (Either::Left(left), Either::Left(event)) => { + left.on_connection_handler_event(peer_id, connection_id, event); + } + (Either::Right(right), Either::Right(event)) => { + right.on_connection_handler_event(peer_id, connection_id, event); + } + _ => unreachable!(), + } + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll>> { + let event = match self { + Either::Left(behaviour) => futures::ready!(behaviour.poll(cx)) + .map_out(Either::Left) + .map_in(Either::Left), + Either::Right(behaviour) => futures::ready!(behaviour.poll(cx)) + .map_out(Either::Right) + .map_in(Either::Right), + }; + + Poll::Ready(event) + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/external_addresses.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/external_addresses.rs new file mode 100644 index 00000000000..579f46fe486 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/behaviour/external_addresses.rs @@ -0,0 +1,182 @@ +use crate::behaviour::{ExternalAddrConfirmed, ExternalAddrExpired, FromSwarm}; +use libp2p_core::Multiaddr; + +/// The maximum number of local external addresses. When reached any +/// further externally reported addresses are ignored. The behaviour always +/// tracks all its listen addresses. +const MAX_LOCAL_EXTERNAL_ADDRS: usize = 20; + +/// Utility struct for tracking the external addresses of a [`Swarm`](crate::Swarm). +#[derive(Debug, Clone, Default)] +pub struct ExternalAddresses { + addresses: Vec, +} + +impl ExternalAddresses { + /// Returns an [`Iterator`] over all external addresses. + pub fn iter(&self) -> impl ExactSizeIterator { + self.addresses.iter() + } + + pub fn as_slice(&self) -> &[Multiaddr] { + self.addresses.as_slice() + } + + /// Feed a [`FromSwarm`] event to this struct. + /// + /// Returns whether the event changed our set of external addresses. + pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { + match event { + FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { addr }) => { + if let Some(pos) = self + .addresses + .iter() + .position(|candidate| candidate == *addr) + { + // Refresh the existing confirmed address. + self.addresses.remove(pos); + self.push_front(addr); + + tracing::debug!(address=%addr, "Refreshed external address"); + + return false; // No changes to our external addresses. + } + + self.push_front(addr); + + if self.addresses.len() > MAX_LOCAL_EXTERNAL_ADDRS { + let expired = self.addresses.pop().expect("list to be not empty"); + + tracing::debug!( + external_address=%expired, + address_limit=%MAX_LOCAL_EXTERNAL_ADDRS, + "Removing previously confirmed external address because we reached the address limit" + ); + } + + return true; + } + FromSwarm::ExternalAddrExpired(ExternalAddrExpired { + addr: expired_addr, .. + }) => { + let pos = match self + .addresses + .iter() + .position(|candidate| candidate == *expired_addr) + { + None => return false, + Some(p) => p, + }; + + self.addresses.remove(pos); + return true; + } + _ => {} + } + + false + } + + fn push_front(&mut self, addr: &Multiaddr) { + self.addresses.insert(0, addr.clone()); // We have at most `MAX_LOCAL_EXTERNAL_ADDRS` so this isn't very expensive. + } +} + +#[cfg(test)] +mod tests { + use super::*; + use libp2p_core::multiaddr::Protocol; + use once_cell::sync::Lazy; + use rand::Rng; + + #[test] + fn new_external_addr_returns_correct_changed_value() { + let mut addresses = ExternalAddresses::default(); + + let changed = addresses.on_swarm_event(&new_external_addr1()); + assert!(changed); + + let changed = addresses.on_swarm_event(&new_external_addr1()); + assert!(!changed) + } + + #[test] + fn expired_external_addr_returns_correct_changed_value() { + let mut addresses = ExternalAddresses::default(); + addresses.on_swarm_event(&new_external_addr1()); + + let changed = addresses.on_swarm_event(&expired_external_addr1()); + assert!(changed); + + let changed = addresses.on_swarm_event(&expired_external_addr1()); + assert!(!changed) + } + + #[test] + fn more_recent_external_addresses_are_prioritized() { + let mut addresses = ExternalAddresses::default(); + + addresses.on_swarm_event(&new_external_addr1()); + addresses.on_swarm_event(&new_external_addr2()); + + assert_eq!( + addresses.as_slice(), + &[(*MEMORY_ADDR_2000).clone(), (*MEMORY_ADDR_1000).clone()] + ); + } + + #[test] + fn when_pushing_more_than_max_addresses_oldest_is_evicted() { + let mut addresses = ExternalAddresses::default(); + + while addresses.as_slice().len() < MAX_LOCAL_EXTERNAL_ADDRS { + let random_address = + Multiaddr::empty().with(Protocol::Memory(rand::thread_rng().gen_range(0..1000))); + addresses.on_swarm_event(&FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { + addr: &random_address, + })); + } + + addresses.on_swarm_event(&new_external_addr2()); + + assert_eq!(addresses.as_slice().len(), 20); + assert_eq!(addresses.as_slice()[0], (*MEMORY_ADDR_2000).clone()); + } + + #[test] + fn reporting_existing_external_address_moves_it_to_the_front() { + let mut addresses = ExternalAddresses::default(); + + addresses.on_swarm_event(&new_external_addr1()); + addresses.on_swarm_event(&new_external_addr2()); + addresses.on_swarm_event(&new_external_addr1()); + + assert_eq!( + addresses.as_slice(), + &[(*MEMORY_ADDR_1000).clone(), (*MEMORY_ADDR_2000).clone()] + ); + } + + fn new_external_addr1() -> FromSwarm<'static> { + FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { + addr: &MEMORY_ADDR_1000, + }) + } + + fn new_external_addr2() -> FromSwarm<'static> { + FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { + addr: &MEMORY_ADDR_2000, + }) + } + + fn expired_external_addr1() -> FromSwarm<'static> { + FromSwarm::ExternalAddrExpired(ExternalAddrExpired { + addr: &MEMORY_ADDR_1000, + }) + } + + static MEMORY_ADDR_1000: Lazy = + Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000))); + static MEMORY_ADDR_2000: Lazy = + Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(2000))); +} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/listen_addresses.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/listen_addresses.rs new file mode 100644 index 00000000000..6076f5e7923 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/behaviour/listen_addresses.rs @@ -0,0 +1,78 @@ +use crate::behaviour::{ExpiredListenAddr, FromSwarm, NewListenAddr}; +use libp2p_core::Multiaddr; +use std::collections::HashSet; + +/// Utility struct for tracking the addresses a [`Swarm`](crate::Swarm) is listening on. +#[derive(Debug, Default, Clone)] +pub struct ListenAddresses { + addresses: HashSet, +} + +impl ListenAddresses { + /// Returns an [`Iterator`] over all listen addresses. + pub fn iter(&self) -> impl ExactSizeIterator { + self.addresses.iter() + } + + /// Feed a [`FromSwarm`] event to this struct. + /// + /// Returns whether the event changed our set of listen addresses. + pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { + match event { + FromSwarm::NewListenAddr(NewListenAddr { addr, .. }) => { + self.addresses.insert((*addr).clone()) + } + FromSwarm::ExpiredListenAddr(ExpiredListenAddr { addr, .. }) => { + self.addresses.remove(addr) + } + _ => false, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use libp2p_core::{multiaddr::Protocol, transport::ListenerId}; + use once_cell::sync::Lazy; + + #[test] + fn new_listen_addr_returns_correct_changed_value() { + let mut addresses = ListenAddresses::default(); + + let changed = addresses.on_swarm_event(&new_listen_addr()); + assert!(changed); + + let changed = addresses.on_swarm_event(&new_listen_addr()); + assert!(!changed) + } + + #[test] + fn expired_listen_addr_returns_correct_changed_value() { + let mut addresses = ListenAddresses::default(); + addresses.on_swarm_event(&new_listen_addr()); + + let changed = addresses.on_swarm_event(&expired_listen_addr()); + assert!(changed); + + let changed = addresses.on_swarm_event(&expired_listen_addr()); + assert!(!changed) + } + + fn new_listen_addr() -> FromSwarm<'static> { + FromSwarm::NewListenAddr(NewListenAddr { + listener_id: ListenerId::next(), + addr: &MEMORY_ADDR, + }) + } + + fn expired_listen_addr() -> FromSwarm<'static> { + FromSwarm::ExpiredListenAddr(ExpiredListenAddr { + listener_id: ListenerId::next(), + addr: &MEMORY_ADDR, + }) + } + + static MEMORY_ADDR: Lazy = + Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000))); +} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/peer_addresses.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/peer_addresses.rs new file mode 100644 index 00000000000..1eeead56ca1 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/behaviour/peer_addresses.rs @@ -0,0 +1,338 @@ +use crate::behaviour::FromSwarm; +use crate::{DialError, DialFailure, NewExternalAddrOfPeer}; + +use libp2p_core::Multiaddr; +use libp2p_identity::PeerId; + +use lru::LruCache; + +use std::num::NonZeroUsize; + +/// Struct for tracking peers' external addresses of the [`Swarm`](crate::Swarm). +#[derive(Debug)] +pub struct PeerAddresses(LruCache>); + +impl PeerAddresses { + /// Creates a [`PeerAddresses`] cache with capacity for the given number of peers. + /// + /// For each peer, we will at most store 10 addresses. + pub fn new(number_of_peers: NonZeroUsize) -> Self { + Self(LruCache::new(number_of_peers)) + } + + /// Feed a [`FromSwarm`] event to this struct. + /// + /// Returns whether the event changed peer's known external addresses. + pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { + match event { + FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, addr }) => { + self.add(*peer_id, (*addr).clone()) + } + FromSwarm::DialFailure(DialFailure { + peer_id: Some(peer_id), + error: DialError::Transport(errors), + .. + }) => { + for (addr, _error) in errors { + self.remove(peer_id, addr); + } + true + } + _ => false, + } + } + + /// Adds address to cache. + /// Appends address to the existing set if peer addresses already exist. + /// Creates a new cache entry for peer_id if no addresses are present. + /// Returns true if the newly added address was not previously in the cache. + /// + pub fn add(&mut self, peer: PeerId, address: Multiaddr) -> bool { + match prepare_addr(&peer, &address) { + Ok(address) => { + if let Some(cached) = self.0.get_mut(&peer) { + cached.put(address, ()).is_none() + } else { + let mut set = LruCache::new(NonZeroUsize::new(10).expect("10 > 0")); + set.put(address, ()); + self.0.put(peer, set); + + true + } + } + Err(_) => false, + } + } + + /// Returns peer's external addresses. + pub fn get(&mut self, peer: &PeerId) -> impl Iterator + '_ { + self.0 + .get(peer) + .into_iter() + .flat_map(|c| c.iter().map(|(m, ())| m)) + .cloned() + } + + /// Removes address from peer addresses cache. + /// Returns true if the address was removed. + pub fn remove(&mut self, peer: &PeerId, address: &Multiaddr) -> bool { + match self.0.get_mut(peer) { + Some(addrs) => match prepare_addr(peer, address) { + Ok(address) => addrs.pop(&address).is_some(), + Err(_) => false, + }, + None => false, + } + } +} + +fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Result { + addr.clone().with_p2p(*peer) +} + +impl Default for PeerAddresses { + fn default() -> Self { + Self(LruCache::new(NonZeroUsize::new(100).unwrap())) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::io; + + use crate::ConnectionId; + use libp2p_core::{ + multiaddr::Protocol, + transport::{memory::MemoryTransportError, TransportError}, + }; + + use once_cell::sync::Lazy; + + #[test] + fn new_peer_addr_returns_correct_changed_value() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + + let event = new_external_addr_of_peer1(peer_id); + + let changed = cache.on_swarm_event(&event); + assert!(changed); + + let changed = cache.on_swarm_event(&event); + assert!(!changed); + } + + #[test] + fn new_peer_addr_saves_peer_addrs() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let event = new_external_addr_of_peer1(peer_id); + + let changed = cache.on_swarm_event(&event); + assert!(changed); + + let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); + let expected = cache.get(&peer_id).collect::>(); + assert_eq!(expected, vec![addr1]); + + let event = new_external_addr_of_peer2(peer_id); + let changed = cache.on_swarm_event(&event); + + let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); + let addr2 = MEMORY_ADDR_2000.clone().with_p2p(peer_id).unwrap(); + + let expected_addrs = cache.get(&peer_id).collect::>(); + assert!(expected_addrs.contains(&addr1)); + assert!(expected_addrs.contains(&addr2)); + + let expected = cache.get(&peer_id).collect::>().len(); + assert_eq!(expected, 2); + + assert!(changed); + } + + #[test] + fn existing_addr_is_not_added_to_cache() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + + let event = new_external_addr_of_peer1(peer_id); + + let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); + let changed = cache.on_swarm_event(&event); + let expected = cache.get(&peer_id).collect::>(); + assert!(changed); + assert_eq!(expected, vec![addr1]); + + let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); + let changed = cache.on_swarm_event(&event); + let expected = cache.get(&peer_id).collect::>(); + assert!(!changed); + assert_eq!(expected, [addr1]); + } + + #[test] + fn addresses_of_peer_are_removed_when_received_dial_failure() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); + let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); + + cache.add(peer_id, addr.clone()); + cache.add(peer_id, addr2.clone()); + cache.add(peer_id, addr3.clone()); + + let error = DialError::Transport(prepare_errors(vec![addr, addr3])); + + let event = FromSwarm::DialFailure(DialFailure { + peer_id: Some(peer_id), + error: &error, + connection_id: ConnectionId::new_unchecked(8), + }); + + let changed = cache.on_swarm_event(&event); + + assert!(changed); + + let cached = cache.get(&peer_id).collect::>(); + let expected = prepare_expected_addrs(peer_id, [addr2].into_iter()); + + assert_eq!(cached, expected); + } + + #[test] + fn remove_removes_address_if_present() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + + cache.add(peer_id, addr.clone()); + + assert!(cache.remove(&peer_id, &addr)); + } + + #[test] + fn remove_returns_false_if_address_not_present() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + + assert!(!cache.remove(&peer_id, &addr)); + } + + #[test] + fn remove_returns_false_if_peer_not_present() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + + assert!(!cache.remove(&peer_id, &addr)); + } + + #[test] + fn remove_removes_address_provided_in_param() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); + let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); + + cache.add(peer_id, addr.clone()); + cache.add(peer_id, addr2.clone()); + cache.add(peer_id, addr3.clone()); + + assert!(cache.remove(&peer_id, &addr2)); + + let mut cached = cache.get(&peer_id).collect::>(); + cached.sort(); + + let expected = prepare_expected_addrs(peer_id, [addr, addr3].into_iter()); + + assert_eq!(cached, expected); + } + + #[test] + fn add_adds_new_address_to_cache() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + + assert!(cache.add(peer_id, addr.clone())); + + let mut cached = cache.get(&peer_id).collect::>(); + cached.sort(); + let expected = prepare_expected_addrs(peer_id, [addr].into_iter()); + + assert_eq!(cached, expected); + } + + #[test] + fn add_adds_address_to_cache_to_existing_key() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); + let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); + + assert!(cache.add(peer_id, addr.clone())); + + cache.add(peer_id, addr2.clone()); + cache.add(peer_id, addr3.clone()); + + let expected = prepare_expected_addrs(peer_id, [addr, addr2, addr3].into_iter()); + + let mut cached = cache.get(&peer_id).collect::>(); + cached.sort(); + + assert_eq!(cached, expected); + } + + fn prepare_expected_addrs( + peer_id: PeerId, + addrs: impl Iterator, + ) -> Vec { + let mut addrs = addrs + .filter_map(|a| a.with_p2p(peer_id).ok()) + .collect::>(); + addrs.sort(); + addrs + } + + fn new_external_addr_of_peer1(peer_id: PeerId) -> FromSwarm<'static> { + FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { + peer_id, + addr: &MEMORY_ADDR_1000, + }) + } + + fn new_external_addr_of_peer2(peer_id: PeerId) -> FromSwarm<'static> { + FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { + peer_id, + addr: &MEMORY_ADDR_2000, + }) + } + + fn prepare_errors(addrs: Vec) -> Vec<(Multiaddr, TransportError)> { + let errors: Vec<(Multiaddr, TransportError)> = addrs + .iter() + .map(|addr| { + ( + addr.clone(), + TransportError::Other(io::Error::new( + io::ErrorKind::Other, + MemoryTransportError::Unreachable, + )), + ) + }) + .collect(); + errors + } + + static MEMORY_ADDR_1000: Lazy = + Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000))); + static MEMORY_ADDR_2000: Lazy = + Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(2000))); +} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/toggle.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/toggle.rs new file mode 100644 index 00000000000..398c919ae86 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/behaviour/toggle.rs @@ -0,0 +1,377 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::behaviour::FromSwarm; +use crate::connection::ConnectionId; +use crate::handler::{ + AddressChange, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError, + FullyNegotiatedInbound, FullyNegotiatedOutbound, ListenUpgradeError, SubstreamProtocol, +}; +use crate::upgrade::SendWrapper; +use crate::{ + ConnectionDenied, NetworkBehaviour, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, +}; +use either::Either; +use futures::future; +use libp2p_core::transport::PortUse; +use libp2p_core::{upgrade::DeniedUpgrade, Endpoint, Multiaddr}; +use libp2p_identity::PeerId; +use std::{task::Context, task::Poll}; + +/// Implementation of `NetworkBehaviour` that can be either in the disabled or enabled state. +/// +/// The state can only be chosen at initialization. +pub struct Toggle { + inner: Option, +} + +impl Toggle { + /// Returns `true` if `Toggle` is enabled and `false` if it's disabled. + pub fn is_enabled(&self) -> bool { + self.inner.is_some() + } + + /// Returns a reference to the inner `NetworkBehaviour`. + pub fn as_ref(&self) -> Option<&TBehaviour> { + self.inner.as_ref() + } + + /// Returns a mutable reference to the inner `NetworkBehaviour`. + pub fn as_mut(&mut self) -> Option<&mut TBehaviour> { + self.inner.as_mut() + } +} + +impl From> for Toggle { + fn from(inner: Option) -> Self { + Toggle { inner } + } +} + +impl NetworkBehaviour for Toggle +where + TBehaviour: NetworkBehaviour, +{ + type ConnectionHandler = ToggleConnectionHandler>; + type ToSwarm = TBehaviour::ToSwarm; + + fn handle_pending_inbound_connection( + &mut self, + connection_id: ConnectionId, + local_addr: &Multiaddr, + remote_addr: &Multiaddr, + ) -> Result<(), ConnectionDenied> { + let inner = match self.inner.as_mut() { + None => return Ok(()), + Some(inner) => inner, + }; + + inner.handle_pending_inbound_connection(connection_id, local_addr, remote_addr)?; + + Ok(()) + } + + fn handle_established_inbound_connection( + &mut self, + connection_id: ConnectionId, + peer: PeerId, + local_addr: &Multiaddr, + remote_addr: &Multiaddr, + ) -> Result, ConnectionDenied> { + let inner = match self.inner.as_mut() { + None => return Ok(ToggleConnectionHandler { inner: None }), + Some(inner) => inner, + }; + + let handler = inner.handle_established_inbound_connection( + connection_id, + peer, + local_addr, + remote_addr, + )?; + + Ok(ToggleConnectionHandler { + inner: Some(handler), + }) + } + + fn handle_pending_outbound_connection( + &mut self, + connection_id: ConnectionId, + maybe_peer: Option, + addresses: &[Multiaddr], + effective_role: Endpoint, + ) -> Result, ConnectionDenied> { + let inner = match self.inner.as_mut() { + None => return Ok(vec![]), + Some(inner) => inner, + }; + + let addresses = inner.handle_pending_outbound_connection( + connection_id, + maybe_peer, + addresses, + effective_role, + )?; + + Ok(addresses) + } + + fn handle_established_outbound_connection( + &mut self, + connection_id: ConnectionId, + peer: PeerId, + addr: &Multiaddr, + role_override: Endpoint, + port_use: PortUse, + ) -> Result, ConnectionDenied> { + let inner = match self.inner.as_mut() { + None => return Ok(ToggleConnectionHandler { inner: None }), + Some(inner) => inner, + }; + + let handler = inner.handle_established_outbound_connection( + connection_id, + peer, + addr, + role_override, + port_use, + )?; + + Ok(ToggleConnectionHandler { + inner: Some(handler), + }) + } + + fn on_swarm_event(&mut self, event: FromSwarm) { + if let Some(behaviour) = &mut self.inner { + behaviour.on_swarm_event(event); + } + } + + fn on_connection_handler_event( + &mut self, + peer_id: PeerId, + connection_id: ConnectionId, + event: THandlerOutEvent, + ) { + if let Some(behaviour) = &mut self.inner { + behaviour.on_connection_handler_event(peer_id, connection_id, event) + } + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll>> { + if let Some(inner) = self.inner.as_mut() { + inner.poll(cx) + } else { + Poll::Pending + } + } +} + +/// Implementation of [`ConnectionHandler`] that can be in the disabled state. +pub struct ToggleConnectionHandler { + inner: Option, +} + +impl ToggleConnectionHandler +where + TInner: ConnectionHandler, +{ + fn on_fully_negotiated_inbound( + &mut self, + FullyNegotiatedInbound { + protocol: out, + info, + }: FullyNegotiatedInbound< + ::InboundProtocol, + ::InboundOpenInfo, + >, + ) { + let out = match out { + future::Either::Left(out) => out, + future::Either::Right(v) => void::unreachable(v), + }; + + if let Either::Left(info) = info { + self.inner + .as_mut() + .expect("Can't receive an inbound substream if disabled; QED") + .on_connection_event(ConnectionEvent::FullyNegotiatedInbound( + FullyNegotiatedInbound { + protocol: out, + info, + }, + )); + } else { + panic!("Unexpected Either::Right in enabled `on_fully_negotiated_inbound`.") + } + } + + fn on_listen_upgrade_error( + &mut self, + ListenUpgradeError { info, error: err }: ListenUpgradeError< + ::InboundOpenInfo, + ::InboundProtocol, + >, + ) { + let (inner, info) = match (self.inner.as_mut(), info) { + (Some(inner), Either::Left(info)) => (inner, info), + // Ignore listen upgrade errors in disabled state. + (None, Either::Right(())) => return, + (Some(_), Either::Right(())) => panic!( + "Unexpected `Either::Right` inbound info through \ + `on_listen_upgrade_error` in enabled state.", + ), + (None, Either::Left(_)) => panic!( + "Unexpected `Either::Left` inbound info through \ + `on_listen_upgrade_error` in disabled state.", + ), + }; + + let err = match err { + Either::Left(e) => e, + Either::Right(v) => void::unreachable(v), + }; + + inner.on_connection_event(ConnectionEvent::ListenUpgradeError(ListenUpgradeError { + info, + error: err, + })); + } +} + +impl ConnectionHandler for ToggleConnectionHandler +where + TInner: ConnectionHandler, +{ + type FromBehaviour = TInner::FromBehaviour; + type ToBehaviour = TInner::ToBehaviour; + type InboundProtocol = Either, SendWrapper>; + type OutboundProtocol = TInner::OutboundProtocol; + type OutboundOpenInfo = TInner::OutboundOpenInfo; + type InboundOpenInfo = Either; + + fn listen_protocol(&self) -> SubstreamProtocol { + if let Some(inner) = self.inner.as_ref() { + inner + .listen_protocol() + .map_upgrade(|u| Either::Left(SendWrapper(u))) + .map_info(Either::Left) + } else { + SubstreamProtocol::new(Either::Right(SendWrapper(DeniedUpgrade)), Either::Right(())) + } + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + self.inner + .as_mut() + .expect("Can't receive events if disabled; QED") + .on_behaviour_event(event) + } + + fn connection_keep_alive(&self) -> bool { + self.inner + .as_ref() + .map(|h| h.connection_keep_alive()) + .unwrap_or(false) + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + if let Some(inner) = self.inner.as_mut() { + inner.poll(cx) + } else { + Poll::Pending + } + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedInbound(fully_negotiated_inbound) => { + self.on_fully_negotiated_inbound(fully_negotiated_inbound) + } + ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { + protocol: out, + info, + }) => self + .inner + .as_mut() + .expect("Can't receive an outbound substream if disabled; QED") + .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( + FullyNegotiatedOutbound { + protocol: out, + info, + }, + )), + ConnectionEvent::AddressChange(address_change) => { + if let Some(inner) = self.inner.as_mut() { + inner.on_connection_event(ConnectionEvent::AddressChange(AddressChange { + new_address: address_change.new_address, + })); + } + } + ConnectionEvent::DialUpgradeError(DialUpgradeError { info, error: err }) => self + .inner + .as_mut() + .expect("Can't receive an outbound substream if disabled; QED") + .on_connection_event(ConnectionEvent::DialUpgradeError(DialUpgradeError { + info, + error: err, + })), + ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => { + self.on_listen_upgrade_error(listen_upgrade_error) + } + ConnectionEvent::LocalProtocolsChange(change) => { + if let Some(inner) = self.inner.as_mut() { + inner.on_connection_event(ConnectionEvent::LocalProtocolsChange(change)); + } + } + ConnectionEvent::RemoteProtocolsChange(change) => { + if let Some(inner) = self.inner.as_mut() { + inner.on_connection_event(ConnectionEvent::RemoteProtocolsChange(change)); + } + } + } + } + + fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { + let Some(inner) = self.inner.as_mut() else { + return Poll::Ready(None); + }; + + inner.poll_close(cx) + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection.rs b/third-party/libp2p-swarm-0.45.1/src/connection.rs new file mode 100644 index 00000000000..603a5b0d7c4 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/connection.rs @@ -0,0 +1,1387 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +mod error; + +pub(crate) mod pool; +mod supported_protocols; + +pub use error::ConnectionError; +pub(crate) use error::{ + PendingConnectionError, PendingInboundConnectionError, PendingOutboundConnectionError, +}; +use libp2p_core::transport::PortUse; +pub use supported_protocols::SupportedProtocols; + +use crate::handler::{ + AddressChange, ConnectionEvent, ConnectionHandler, DialUpgradeError, FullyNegotiatedInbound, + FullyNegotiatedOutbound, ListenUpgradeError, ProtocolSupport, ProtocolsChange, UpgradeInfoSend, +}; +use crate::stream::ActiveStreamCounter; +use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend}; +use crate::{ + ConnectionHandlerEvent, Stream, StreamProtocol, StreamUpgradeError, SubstreamProtocol, +}; +use futures::future::BoxFuture; +use futures::stream::FuturesUnordered; +use futures::StreamExt; +use futures::{stream, FutureExt}; +use futures_timer::Delay; +use libp2p_core::connection::ConnectedPoint; +use libp2p_core::multiaddr::Multiaddr; +use libp2p_core::muxing::{StreamMuxerBox, StreamMuxerEvent, StreamMuxerExt, SubstreamBox}; +use libp2p_core::upgrade; +use libp2p_core::upgrade::{NegotiationError, ProtocolError}; +use libp2p_core::Endpoint; +use libp2p_identity::PeerId; +use std::collections::{HashMap, HashSet}; +use std::fmt::{Display, Formatter}; +use std::future::Future; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::task::Waker; +use std::time::Duration; +use std::{fmt, io, mem, pin::Pin, task::Context, task::Poll}; +use web_time::Instant; + +static NEXT_CONNECTION_ID: AtomicUsize = AtomicUsize::new(1); + +/// Connection identifier. +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct ConnectionId(usize); + +impl ConnectionId { + /// Creates an _unchecked_ [`ConnectionId`]. + /// + /// [`Swarm`](crate::Swarm) enforces that [`ConnectionId`]s are unique and not reused. + /// This constructor does not, hence the _unchecked_. + /// + /// It is primarily meant for allowing manual tests of [`NetworkBehaviour`](crate::NetworkBehaviour)s. + pub fn new_unchecked(id: usize) -> Self { + Self(id) + } + + /// Returns the next available [`ConnectionId`]. + pub(crate) fn next() -> Self { + Self(NEXT_CONNECTION_ID.fetch_add(1, Ordering::SeqCst)) + } +} + +impl Display for ConnectionId { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// Information about a successfully established connection. +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct Connected { + /// The connected endpoint, including network address information. + pub(crate) endpoint: ConnectedPoint, + /// Information obtained from the transport. + pub(crate) peer_id: PeerId, +} + +/// Event generated by a [`Connection`]. +#[derive(Debug, Clone)] +pub(crate) enum Event { + /// Event generated by the [`ConnectionHandler`]. + Handler(T), + /// Address of the remote has changed. + AddressChange(Multiaddr), +} + +/// A multiplexed connection to a peer with an associated [`ConnectionHandler`]. +pub(crate) struct Connection +where + THandler: ConnectionHandler, +{ + /// Node that handles the muxing. + muxing: StreamMuxerBox, + /// The underlying handler. + handler: THandler, + /// Futures that upgrade incoming substreams. + negotiating_in: FuturesUnordered< + StreamUpgrade< + THandler::InboundOpenInfo, + ::Output, + ::Error, + >, + >, + /// Futures that upgrade outgoing substreams. + negotiating_out: FuturesUnordered< + StreamUpgrade< + THandler::OutboundOpenInfo, + ::Output, + ::Error, + >, + >, + /// The currently planned connection & handler shutdown. + shutdown: Shutdown, + /// The substream upgrade protocol override, if any. + substream_upgrade_protocol_override: Option, + /// The maximum number of inbound streams concurrently negotiating on a + /// connection. New inbound streams exceeding the limit are dropped and thus + /// reset. + /// + /// Note: This only enforces a limit on the number of concurrently + /// negotiating inbound streams. The total number of inbound streams on a + /// connection is the sum of negotiating and negotiated streams. A limit on + /// the total number of streams can be enforced at the [`StreamMuxerBox`] level. + max_negotiating_inbound_streams: usize, + /// Contains all upgrades that are waiting for a new outbound substream. + /// + /// The upgrade timeout is already ticking here so this may fail in case the remote is not quick + /// enough in providing us with a new stream. + requested_substreams: FuturesUnordered< + SubstreamRequested, + >, + + local_supported_protocols: + HashMap::Info>, bool>, + remote_supported_protocols: HashSet, + protocol_buffer: Vec, + + idle_timeout: Duration, + stream_counter: ActiveStreamCounter, +} + +impl fmt::Debug for Connection +where + THandler: ConnectionHandler + fmt::Debug, + THandler::OutboundOpenInfo: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Connection") + .field("handler", &self.handler) + .finish() + } +} + +impl Unpin for Connection where THandler: ConnectionHandler {} + +impl Connection +where + THandler: ConnectionHandler, +{ + /// Builds a new `Connection` from the given substream multiplexer + /// and connection handler. + pub(crate) fn new( + muxer: StreamMuxerBox, + mut handler: THandler, + substream_upgrade_protocol_override: Option, + max_negotiating_inbound_streams: usize, + idle_timeout: Duration, + ) -> Self { + let initial_protocols = gather_supported_protocols(&handler); + let mut buffer = Vec::new(); + + if !initial_protocols.is_empty() { + handler.on_connection_event(ConnectionEvent::LocalProtocolsChange( + ProtocolsChange::from_initial_protocols( + initial_protocols.keys().map(|e| &e.0), + &mut buffer, + ), + )); + } + + Connection { + muxing: muxer, + handler, + negotiating_in: Default::default(), + negotiating_out: Default::default(), + shutdown: Shutdown::None, + substream_upgrade_protocol_override, + max_negotiating_inbound_streams, + requested_substreams: Default::default(), + local_supported_protocols: initial_protocols, + remote_supported_protocols: Default::default(), + protocol_buffer: buffer, + idle_timeout, + stream_counter: ActiveStreamCounter::default(), + } + } + + /// Notifies the connection handler of an event. + pub(crate) fn on_behaviour_event(&mut self, event: THandler::FromBehaviour) { + self.handler.on_behaviour_event(event); + } + + /// Begins an orderly shutdown of the connection, returning a stream of final events and a `Future` that resolves when connection shutdown is complete. + pub(crate) fn close( + self, + ) -> ( + impl futures::Stream, + impl Future>, + ) { + let Connection { + mut handler, + muxing, + .. + } = self; + + ( + stream::poll_fn(move |cx| handler.poll_close(cx)), + muxing.close(), + ) + } + + /// Polls the handler and the substream, forwarding events from the former to the latter and + /// vice versa. + #[tracing::instrument(level = "debug", name = "Connection::poll", skip(self, cx))] + pub(crate) fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll, ConnectionError>> { + let Self { + requested_substreams, + muxing, + handler, + negotiating_out, + negotiating_in, + shutdown, + max_negotiating_inbound_streams, + substream_upgrade_protocol_override, + local_supported_protocols: supported_protocols, + remote_supported_protocols, + protocol_buffer, + idle_timeout, + stream_counter, + .. + } = self.get_mut(); + + loop { + match requested_substreams.poll_next_unpin(cx) { + Poll::Ready(Some(Ok(()))) => continue, + Poll::Ready(Some(Err(info))) => { + handler.on_connection_event(ConnectionEvent::DialUpgradeError( + DialUpgradeError { + info, + error: StreamUpgradeError::Timeout, + }, + )); + continue; + } + Poll::Ready(None) | Poll::Pending => {} + } + + // Poll the [`ConnectionHandler`]. + match handler.poll(cx) { + Poll::Pending => {} + Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { protocol }) => { + let timeout = *protocol.timeout(); + let (upgrade, user_data) = protocol.into_upgrade(); + + requested_substreams.push(SubstreamRequested::new(user_data, timeout, upgrade)); + continue; // Poll handler until exhausted. + } + Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(event)) => { + return Poll::Ready(Ok(Event::Handler(event))); + } + Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols( + ProtocolSupport::Added(protocols), + )) => { + if let Some(added) = + ProtocolsChange::add(remote_supported_protocols, protocols, protocol_buffer) + { + handler.on_connection_event(ConnectionEvent::RemoteProtocolsChange(added)); + remote_supported_protocols.extend(protocol_buffer.drain(..)); + } + continue; + } + Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols( + ProtocolSupport::Removed(protocols), + )) => { + if let Some(removed) = ProtocolsChange::remove( + remote_supported_protocols, + protocols, + protocol_buffer, + ) { + handler + .on_connection_event(ConnectionEvent::RemoteProtocolsChange(removed)); + } + continue; + } + } + + // In case the [`ConnectionHandler`] can not make any more progress, poll the negotiating outbound streams. + match negotiating_out.poll_next_unpin(cx) { + Poll::Pending | Poll::Ready(None) => {} + Poll::Ready(Some((info, Ok(protocol)))) => { + handler.on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( + FullyNegotiatedOutbound { protocol, info }, + )); + continue; + } + Poll::Ready(Some((info, Err(error)))) => { + handler.on_connection_event(ConnectionEvent::DialUpgradeError( + DialUpgradeError { info, error }, + )); + continue; + } + } + + // In case both the [`ConnectionHandler`] and the negotiating outbound streams can not + // make any more progress, poll the negotiating inbound streams. + match negotiating_in.poll_next_unpin(cx) { + Poll::Pending | Poll::Ready(None) => {} + Poll::Ready(Some((info, Ok(protocol)))) => { + handler.on_connection_event(ConnectionEvent::FullyNegotiatedInbound( + FullyNegotiatedInbound { protocol, info }, + )); + continue; + } + Poll::Ready(Some((info, Err(StreamUpgradeError::Apply(error))))) => { + handler.on_connection_event(ConnectionEvent::ListenUpgradeError( + ListenUpgradeError { info, error }, + )); + continue; + } + Poll::Ready(Some((_, Err(StreamUpgradeError::Io(e))))) => { + tracing::debug!("failed to upgrade inbound stream: {e}"); + continue; + } + Poll::Ready(Some((_, Err(StreamUpgradeError::NegotiationFailed)))) => { + tracing::debug!("no protocol could be agreed upon for inbound stream"); + continue; + } + Poll::Ready(Some((_, Err(StreamUpgradeError::Timeout)))) => { + tracing::debug!("inbound stream upgrade timed out"); + continue; + } + } + + // Check if the connection (and handler) should be shut down. + // As long as we're still negotiating substreams or have any active streams shutdown is always postponed. + if negotiating_in.is_empty() + && negotiating_out.is_empty() + && requested_substreams.is_empty() + && stream_counter.has_no_active_streams() + { + if let Some(new_timeout) = + compute_new_shutdown(handler.connection_keep_alive(), shutdown, *idle_timeout) + { + *shutdown = new_timeout; + } + + match shutdown { + Shutdown::None => {} + Shutdown::Asap => return Poll::Ready(Err(ConnectionError::KeepAliveTimeout)), + Shutdown::Later(delay) => match Future::poll(Pin::new(delay), cx) { + Poll::Ready(_) => { + return Poll::Ready(Err(ConnectionError::KeepAliveTimeout)) + } + Poll::Pending => {} + }, + } + } else { + *shutdown = Shutdown::None; + } + + match muxing.poll_unpin(cx)? { + Poll::Pending => {} + Poll::Ready(StreamMuxerEvent::AddressChange(address)) => { + handler.on_connection_event(ConnectionEvent::AddressChange(AddressChange { + new_address: &address, + })); + return Poll::Ready(Ok(Event::AddressChange(address))); + } + } + + if let Some(requested_substream) = requested_substreams.iter_mut().next() { + match muxing.poll_outbound_unpin(cx)? { + Poll::Pending => {} + Poll::Ready(substream) => { + let (user_data, timeout, upgrade) = requested_substream.extract(); + + negotiating_out.push(StreamUpgrade::new_outbound( + substream, + user_data, + timeout, + upgrade, + *substream_upgrade_protocol_override, + stream_counter.clone(), + )); + + continue; // Go back to the top, handler can potentially make progress again. + } + } + } + + if negotiating_in.len() < *max_negotiating_inbound_streams { + match muxing.poll_inbound_unpin(cx)? { + Poll::Pending => {} + Poll::Ready(substream) => { + let protocol = handler.listen_protocol(); + + negotiating_in.push(StreamUpgrade::new_inbound( + substream, + protocol, + stream_counter.clone(), + )); + + continue; // Go back to the top, handler can potentially make progress again. + } + } + } + + let changes = ProtocolsChange::from_full_sets( + supported_protocols, + handler.listen_protocol().upgrade().protocol_info(), + protocol_buffer, + ); + + if !changes.is_empty() { + for change in changes { + handler.on_connection_event(ConnectionEvent::LocalProtocolsChange(change)); + } + continue; // Go back to the top, handler can potentially make progress again. + } + + return Poll::Pending; // Nothing can make progress, return `Pending`. + } + } + + #[cfg(test)] + fn poll_noop_waker(&mut self) -> Poll, ConnectionError>> { + Pin::new(self).poll(&mut Context::from_waker(futures::task::noop_waker_ref())) + } +} + +fn gather_supported_protocols( + handler: &C, +) -> HashMap::Info>, bool> { + handler + .listen_protocol() + .upgrade() + .protocol_info() + .map(|info| (AsStrHashEq(info), true)) + .collect() +} + +fn compute_new_shutdown( + handler_keep_alive: bool, + current_shutdown: &Shutdown, + idle_timeout: Duration, +) -> Option { + match (current_shutdown, handler_keep_alive) { + (_, false) if idle_timeout == Duration::ZERO => Some(Shutdown::Asap), + (Shutdown::Later(_), false) => None, // Do nothing, i.e. let the shutdown timer continue to tick. + (_, false) => { + let now = Instant::now(); + let safe_keep_alive = checked_add_fraction(now, idle_timeout); + + Some(Shutdown::Later(Delay::new(safe_keep_alive))) + } + (_, true) => Some(Shutdown::None), + } +} + +/// Repeatedly halves and adds the [`Duration`] to the [`Instant`] until [`Instant::checked_add`] succeeds. +/// +/// [`Instant`] depends on the underlying platform and has a limit of which points in time it can represent. +/// The [`Duration`] computed by the this function may not be the longest possible that we can add to `now` but it will work. +fn checked_add_fraction(start: Instant, mut duration: Duration) -> Duration { + while start.checked_add(duration).is_none() { + tracing::debug!(start=?start, duration=?duration, "start + duration cannot be presented, halving duration"); + + duration /= 2; + } + + duration +} + +/// Borrowed information about an incoming connection currently being negotiated. +#[derive(Debug, Copy, Clone)] +pub(crate) struct IncomingInfo<'a> { + /// Local connection address. + pub(crate) local_addr: &'a Multiaddr, + /// Address used to send back data to the remote. + pub(crate) send_back_addr: &'a Multiaddr, +} + +impl<'a> IncomingInfo<'a> { + /// Builds the [`ConnectedPoint`] corresponding to the incoming connection. + pub(crate) fn create_connected_point(&self) -> ConnectedPoint { + ConnectedPoint::Listener { + local_addr: self.local_addr.clone(), + send_back_addr: self.send_back_addr.clone(), + } + } +} + +struct StreamUpgrade { + user_data: Option, + timeout: Delay, + upgrade: BoxFuture<'static, Result>>, +} + +impl StreamUpgrade { + fn new_outbound( + substream: SubstreamBox, + user_data: UserData, + timeout: Delay, + upgrade: Upgrade, + version_override: Option, + counter: ActiveStreamCounter, + ) -> Self + where + Upgrade: OutboundUpgradeSend, + { + let effective_version = match version_override { + Some(version_override) if version_override != upgrade::Version::default() => { + tracing::debug!( + "Substream upgrade protocol override: {:?} -> {:?}", + upgrade::Version::default(), + version_override + ); + + version_override + } + _ => upgrade::Version::default(), + }; + let protocols = upgrade.protocol_info(); + + Self { + user_data: Some(user_data), + timeout, + upgrade: Box::pin(async move { + let (info, stream) = multistream_select::dialer_select_proto( + substream, + protocols, + effective_version, + ) + .await + .map_err(to_stream_upgrade_error)?; + + let output = upgrade + .upgrade_outbound(Stream::new(stream, counter), info) + .await + .map_err(StreamUpgradeError::Apply)?; + + Ok(output) + }), + } + } +} + +impl StreamUpgrade { + fn new_inbound( + substream: SubstreamBox, + protocol: SubstreamProtocol, + counter: ActiveStreamCounter, + ) -> Self + where + Upgrade: InboundUpgradeSend, + { + let timeout = *protocol.timeout(); + let (upgrade, open_info) = protocol.into_upgrade(); + let protocols = upgrade.protocol_info(); + + Self { + user_data: Some(open_info), + timeout: Delay::new(timeout), + upgrade: Box::pin(async move { + let (info, stream) = + multistream_select::listener_select_proto(substream, protocols) + .await + .map_err(to_stream_upgrade_error)?; + + let output = upgrade + .upgrade_inbound(Stream::new(stream, counter), info) + .await + .map_err(StreamUpgradeError::Apply)?; + + Ok(output) + }), + } + } +} + +fn to_stream_upgrade_error(e: NegotiationError) -> StreamUpgradeError { + match e { + NegotiationError::Failed => StreamUpgradeError::NegotiationFailed, + NegotiationError::ProtocolError(ProtocolError::IoError(e)) => StreamUpgradeError::Io(e), + NegotiationError::ProtocolError(other) => { + StreamUpgradeError::Io(io::Error::new(io::ErrorKind::Other, other)) + } + } +} + +impl Unpin for StreamUpgrade {} + +impl Future for StreamUpgrade { + type Output = (UserData, Result>); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + match self.timeout.poll_unpin(cx) { + Poll::Ready(()) => { + return Poll::Ready(( + self.user_data + .take() + .expect("Future not to be polled again once ready."), + Err(StreamUpgradeError::Timeout), + )) + } + + Poll::Pending => {} + } + + let result = futures::ready!(self.upgrade.poll_unpin(cx)); + let user_data = self + .user_data + .take() + .expect("Future not to be polled again once ready."); + + Poll::Ready((user_data, result)) + } +} + +enum SubstreamRequested { + Waiting { + user_data: UserData, + timeout: Delay, + upgrade: Upgrade, + /// A waker to notify our [`FuturesUnordered`] that we have extracted the data. + /// + /// This will ensure that we will get polled again in the next iteration which allows us to + /// resolve with `Ok(())` and be removed from the [`FuturesUnordered`]. + extracted_waker: Option, + }, + Done, +} + +impl SubstreamRequested { + fn new(user_data: UserData, timeout: Duration, upgrade: Upgrade) -> Self { + Self::Waiting { + user_data, + timeout: Delay::new(timeout), + upgrade, + extracted_waker: None, + } + } + + fn extract(&mut self) -> (UserData, Delay, Upgrade) { + match mem::replace(self, Self::Done) { + SubstreamRequested::Waiting { + user_data, + timeout, + upgrade, + extracted_waker: waker, + } => { + if let Some(waker) = waker { + waker.wake(); + } + + (user_data, timeout, upgrade) + } + SubstreamRequested::Done => panic!("cannot extract twice"), + } + } +} + +impl Unpin for SubstreamRequested {} + +impl Future for SubstreamRequested { + type Output = Result<(), UserData>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.get_mut(); + + match mem::replace(this, Self::Done) { + SubstreamRequested::Waiting { + user_data, + upgrade, + mut timeout, + .. + } => match timeout.poll_unpin(cx) { + Poll::Ready(()) => Poll::Ready(Err(user_data)), + Poll::Pending => { + *this = Self::Waiting { + user_data, + upgrade, + timeout, + extracted_waker: Some(cx.waker().clone()), + }; + Poll::Pending + } + }, + SubstreamRequested::Done => Poll::Ready(Ok(())), + } + } +} + +/// The options for a planned connection & handler shutdown. +/// +/// A shutdown is planned anew based on the return value of +/// [`ConnectionHandler::connection_keep_alive`] of the underlying handler +/// after every invocation of [`ConnectionHandler::poll`]. +/// +/// A planned shutdown is always postponed for as long as there are ingoing +/// or outgoing substreams being negotiated, i.e. it is a graceful, "idle" +/// shutdown. +#[derive(Debug)] +enum Shutdown { + /// No shutdown is planned. + None, + /// A shut down is planned as soon as possible. + Asap, + /// A shut down is planned for when a `Delay` has elapsed. + Later(Delay), +} + +// Structure used to avoid allocations when storing the protocols in the `HashMap. +// Instead of allocating a new `String` for the key, +// we use `T::as_ref()` in `Hash`, `Eq` and `PartialEq` requirements. +pub(crate) struct AsStrHashEq(pub(crate) T); + +impl> Eq for AsStrHashEq {} + +impl> PartialEq for AsStrHashEq { + fn eq(&self, other: &Self) -> bool { + self.0.as_ref() == other.0.as_ref() + } +} + +impl> std::hash::Hash for AsStrHashEq { + fn hash(&self, state: &mut H) { + self.0.as_ref().hash(state) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::dummy; + use futures::future; + use futures::AsyncRead; + use futures::AsyncWrite; + use libp2p_core::upgrade::{DeniedUpgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo}; + use libp2p_core::StreamMuxer; + use quickcheck::*; + use std::sync::{Arc, Weak}; + use std::time::Instant; + use tracing_subscriber::EnvFilter; + use void::Void; + + #[test] + fn max_negotiating_inbound_streams() { + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + + fn prop(max_negotiating_inbound_streams: u8) { + let max_negotiating_inbound_streams: usize = max_negotiating_inbound_streams.into(); + + let alive_substream_counter = Arc::new(()); + let mut connection = Connection::new( + StreamMuxerBox::new(DummyStreamMuxer { + counter: alive_substream_counter.clone(), + }), + MockConnectionHandler::new(Duration::from_secs(10)), + None, + max_negotiating_inbound_streams, + Duration::ZERO, + ); + + let result = connection.poll_noop_waker(); + + assert!(result.is_pending()); + assert_eq!( + Arc::weak_count(&alive_substream_counter), + max_negotiating_inbound_streams, + "Expect no more than the maximum number of allowed streams" + ); + } + + QuickCheck::new().quickcheck(prop as fn(_)); + } + + #[test] + fn outbound_stream_timeout_starts_on_request() { + let upgrade_timeout = Duration::from_secs(1); + let mut connection = Connection::new( + StreamMuxerBox::new(PendingStreamMuxer), + MockConnectionHandler::new(upgrade_timeout), + None, + 2, + Duration::ZERO, + ); + + connection.handler.open_new_outbound(); + let _ = connection.poll_noop_waker(); + + std::thread::sleep(upgrade_timeout + Duration::from_secs(1)); + + let _ = connection.poll_noop_waker(); + + assert!(matches!( + connection.handler.error.unwrap(), + StreamUpgradeError::Timeout + )) + } + + #[test] + fn propagates_changes_to_supported_inbound_protocols() { + let mut connection = Connection::new( + StreamMuxerBox::new(PendingStreamMuxer), + ConfigurableProtocolConnectionHandler::default(), + None, + 0, + Duration::ZERO, + ); + + // First, start listening on a single protocol. + connection.handler.listen_on(&["/foo"]); + let _ = connection.poll_noop_waker(); + + assert_eq!(connection.handler.local_added, vec![vec!["/foo"]]); + assert!(connection.handler.local_removed.is_empty()); + + // Second, listen on two protocols. + connection.handler.listen_on(&["/foo", "/bar"]); + let _ = connection.poll_noop_waker(); + + assert_eq!( + connection.handler.local_added, + vec![vec!["/foo"], vec!["/bar"]], + "expect to only receive an event for the newly added protocols" + ); + assert!(connection.handler.local_removed.is_empty()); + + // Third, stop listening on the first protocol. + connection.handler.listen_on(&["/bar"]); + let _ = connection.poll_noop_waker(); + + assert_eq!( + connection.handler.local_added, + vec![vec!["/foo"], vec!["/bar"]] + ); + assert_eq!(connection.handler.local_removed, vec![vec!["/foo"]]); + } + + #[test] + fn only_propagtes_actual_changes_to_remote_protocols_to_handler() { + let mut connection = Connection::new( + StreamMuxerBox::new(PendingStreamMuxer), + ConfigurableProtocolConnectionHandler::default(), + None, + 0, + Duration::ZERO, + ); + + // First, remote supports a single protocol. + connection.handler.remote_adds_support_for(&["/foo"]); + let _ = connection.poll_noop_waker(); + + assert_eq!(connection.handler.remote_added, vec![vec!["/foo"]]); + assert!(connection.handler.remote_removed.is_empty()); + + // Second, it adds a protocol but also still includes the first one. + connection + .handler + .remote_adds_support_for(&["/foo", "/bar"]); + let _ = connection.poll_noop_waker(); + + assert_eq!( + connection.handler.remote_added, + vec![vec!["/foo"], vec!["/bar"]], + "expect to only receive an event for the newly added protocol" + ); + assert!(connection.handler.remote_removed.is_empty()); + + // Third, stop listening on a protocol it never advertised (we can't control what handlers do so this needs to be handled gracefully). + connection.handler.remote_removes_support_for(&["/baz"]); + let _ = connection.poll_noop_waker(); + + assert_eq!( + connection.handler.remote_added, + vec![vec!["/foo"], vec!["/bar"]] + ); + assert!(&connection.handler.remote_removed.is_empty()); + + // Fourth, stop listening on a protocol that was previously supported + connection.handler.remote_removes_support_for(&["/bar"]); + let _ = connection.poll_noop_waker(); + + assert_eq!( + connection.handler.remote_added, + vec![vec!["/foo"], vec!["/bar"]] + ); + assert_eq!(connection.handler.remote_removed, vec![vec!["/bar"]]); + } + + #[tokio::test] + async fn idle_timeout_with_keep_alive_no() { + let idle_timeout = Duration::from_millis(100); + + let mut connection = Connection::new( + StreamMuxerBox::new(PendingStreamMuxer), + dummy::ConnectionHandler, + None, + 0, + idle_timeout, + ); + + assert!(connection.poll_noop_waker().is_pending()); + + tokio::time::sleep(idle_timeout).await; + + assert!(matches!( + connection.poll_noop_waker(), + Poll::Ready(Err(ConnectionError::KeepAliveTimeout)) + )); + } + + #[test] + fn checked_add_fraction_can_add_u64_max() { + let _ = tracing_subscriber::fmt() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .try_init(); + let start = Instant::now(); + + let duration = checked_add_fraction(start, Duration::from_secs(u64::MAX)); + + assert!(start.checked_add(duration).is_some()) + } + + #[test] + fn compute_new_shutdown_does_not_panic() { + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + + #[derive(Debug)] + struct ArbitraryShutdown(Shutdown); + + impl Clone for ArbitraryShutdown { + fn clone(&self) -> Self { + let shutdown = match self.0 { + Shutdown::None => Shutdown::None, + Shutdown::Asap => Shutdown::Asap, + Shutdown::Later(_) => Shutdown::Later( + // compute_new_shutdown does not touch the delay. Delay does not + // implement Clone. Thus use a placeholder delay. + Delay::new(Duration::from_secs(1)), + ), + }; + + ArbitraryShutdown(shutdown) + } + } + + impl Arbitrary for ArbitraryShutdown { + fn arbitrary(g: &mut Gen) -> Self { + let shutdown = match g.gen_range(1u8..4) { + 1 => Shutdown::None, + 2 => Shutdown::Asap, + 3 => Shutdown::Later(Delay::new(Duration::from_secs(u32::arbitrary(g) as u64))), + _ => unreachable!(), + }; + + Self(shutdown) + } + } + + fn prop( + handler_keep_alive: bool, + current_shutdown: ArbitraryShutdown, + idle_timeout: Duration, + ) { + compute_new_shutdown(handler_keep_alive, ¤t_shutdown.0, idle_timeout); + } + + QuickCheck::new().quickcheck(prop as fn(_, _, _)); + } + + struct DummyStreamMuxer { + counter: Arc<()>, + } + + impl StreamMuxer for DummyStreamMuxer { + type Substream = PendingSubstream; + type Error = Void; + + fn poll_inbound( + self: Pin<&mut Self>, + _: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(PendingSubstream { + _weak: Arc::downgrade(&self.counter), + })) + } + + fn poll_outbound( + self: Pin<&mut Self>, + _: &mut Context<'_>, + ) -> Poll> { + Poll::Pending + } + + fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn poll( + self: Pin<&mut Self>, + _: &mut Context<'_>, + ) -> Poll> { + Poll::Pending + } + } + + /// A [`StreamMuxer`] which never returns a stream. + struct PendingStreamMuxer; + + impl StreamMuxer for PendingStreamMuxer { + type Substream = PendingSubstream; + type Error = Void; + + fn poll_inbound( + self: Pin<&mut Self>, + _: &mut Context<'_>, + ) -> Poll> { + Poll::Pending + } + + fn poll_outbound( + self: Pin<&mut Self>, + _: &mut Context<'_>, + ) -> Poll> { + Poll::Pending + } + + fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Pending + } + + fn poll( + self: Pin<&mut Self>, + _: &mut Context<'_>, + ) -> Poll> { + Poll::Pending + } + } + + struct PendingSubstream { + _weak: Weak<()>, + } + + impl AsyncRead for PendingSubstream { + fn poll_read( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + _buf: &mut [u8], + ) -> Poll> { + Poll::Pending + } + } + + impl AsyncWrite for PendingSubstream { + fn poll_write( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + _buf: &[u8], + ) -> Poll> { + Poll::Pending + } + + fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Pending + } + + fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Pending + } + } + + struct MockConnectionHandler { + outbound_requested: bool, + error: Option>, + upgrade_timeout: Duration, + } + + impl MockConnectionHandler { + fn new(upgrade_timeout: Duration) -> Self { + Self { + outbound_requested: false, + error: None, + upgrade_timeout, + } + } + + fn open_new_outbound(&mut self) { + self.outbound_requested = true; + } + } + + #[derive(Default)] + struct ConfigurableProtocolConnectionHandler { + events: Vec>, + active_protocols: HashSet, + local_added: Vec>, + local_removed: Vec>, + remote_added: Vec>, + remote_removed: Vec>, + } + + impl ConfigurableProtocolConnectionHandler { + fn listen_on(&mut self, protocols: &[&'static str]) { + self.active_protocols = protocols.iter().copied().map(StreamProtocol::new).collect(); + } + + fn remote_adds_support_for(&mut self, protocols: &[&'static str]) { + self.events + .push(ConnectionHandlerEvent::ReportRemoteProtocols( + ProtocolSupport::Added( + protocols.iter().copied().map(StreamProtocol::new).collect(), + ), + )); + } + + fn remote_removes_support_for(&mut self, protocols: &[&'static str]) { + self.events + .push(ConnectionHandlerEvent::ReportRemoteProtocols( + ProtocolSupport::Removed( + protocols.iter().copied().map(StreamProtocol::new).collect(), + ), + )); + } + } + + impl ConnectionHandler for MockConnectionHandler { + type FromBehaviour = Void; + type ToBehaviour = Void; + type InboundProtocol = DeniedUpgrade; + type OutboundProtocol = DeniedUpgrade; + type InboundOpenInfo = (); + type OutboundOpenInfo = (); + + fn listen_protocol( + &self, + ) -> SubstreamProtocol { + SubstreamProtocol::new(DeniedUpgrade, ()).with_timeout(self.upgrade_timeout) + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { + protocol, + .. + }) => void::unreachable(protocol), + ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { + protocol, + .. + }) => void::unreachable(protocol), + ConnectionEvent::DialUpgradeError(DialUpgradeError { error, .. }) => { + self.error = Some(error) + } + ConnectionEvent::AddressChange(_) + | ConnectionEvent::ListenUpgradeError(_) + | ConnectionEvent::LocalProtocolsChange(_) + | ConnectionEvent::RemoteProtocolsChange(_) => {} + } + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + void::unreachable(event) + } + + fn connection_keep_alive(&self) -> bool { + true + } + + fn poll( + &mut self, + _: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent< + Self::OutboundProtocol, + Self::OutboundOpenInfo, + Self::ToBehaviour, + >, + > { + if self.outbound_requested { + self.outbound_requested = false; + return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: SubstreamProtocol::new(DeniedUpgrade, ()) + .with_timeout(self.upgrade_timeout), + }); + } + + Poll::Pending + } + } + + impl ConnectionHandler for ConfigurableProtocolConnectionHandler { + type FromBehaviour = Void; + type ToBehaviour = Void; + type InboundProtocol = ManyProtocolsUpgrade; + type OutboundProtocol = DeniedUpgrade; + type InboundOpenInfo = (); + type OutboundOpenInfo = (); + + fn listen_protocol( + &self, + ) -> SubstreamProtocol { + SubstreamProtocol::new( + ManyProtocolsUpgrade { + protocols: Vec::from_iter(self.active_protocols.clone()), + }, + (), + ) + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::LocalProtocolsChange(ProtocolsChange::Added(added)) => { + self.local_added.push(added.cloned().collect()) + } + ConnectionEvent::LocalProtocolsChange(ProtocolsChange::Removed(removed)) => { + self.local_removed.push(removed.cloned().collect()) + } + ConnectionEvent::RemoteProtocolsChange(ProtocolsChange::Added(added)) => { + self.remote_added.push(added.cloned().collect()) + } + ConnectionEvent::RemoteProtocolsChange(ProtocolsChange::Removed(removed)) => { + self.remote_removed.push(removed.cloned().collect()) + } + _ => {} + } + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + void::unreachable(event) + } + + fn connection_keep_alive(&self) -> bool { + true + } + + fn poll( + &mut self, + _: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent< + Self::OutboundProtocol, + Self::OutboundOpenInfo, + Self::ToBehaviour, + >, + > { + if let Some(event) = self.events.pop() { + return Poll::Ready(event); + } + + Poll::Pending + } + } + + struct ManyProtocolsUpgrade { + protocols: Vec, + } + + impl UpgradeInfo for ManyProtocolsUpgrade { + type Info = StreamProtocol; + type InfoIter = std::vec::IntoIter; + + fn protocol_info(&self) -> Self::InfoIter { + self.protocols.clone().into_iter() + } + } + + impl InboundUpgrade for ManyProtocolsUpgrade { + type Output = C; + type Error = Void; + type Future = future::Ready>; + + fn upgrade_inbound(self, stream: C, _: Self::Info) -> Self::Future { + future::ready(Ok(stream)) + } + } + + impl OutboundUpgrade for ManyProtocolsUpgrade { + type Output = C; + type Error = Void; + type Future = future::Ready>; + + fn upgrade_outbound(self, stream: C, _: Self::Info) -> Self::Future { + future::ready(Ok(stream)) + } + } +} + +/// The endpoint roles associated with a pending peer-to-peer connection. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +enum PendingPoint { + /// The socket comes from a dialer. + /// + /// There is no single address associated with the Dialer of a pending + /// connection. Addresses are dialed in parallel. Only once the first dial + /// is successful is the address of the connection known. + Dialer { + /// Same as [`ConnectedPoint::Dialer`] `role_override`. + role_override: Endpoint, + port_use: PortUse, + }, + /// The socket comes from a listener. + Listener { + /// Local connection address. + local_addr: Multiaddr, + /// Address used to send back data to the remote. + send_back_addr: Multiaddr, + }, +} + +impl From for PendingPoint { + fn from(endpoint: ConnectedPoint) -> Self { + match endpoint { + ConnectedPoint::Dialer { + role_override, + port_use, + .. + } => PendingPoint::Dialer { + role_override, + port_use, + }, + ConnectedPoint::Listener { + local_addr, + send_back_addr, + } => PendingPoint::Listener { + local_addr, + send_back_addr, + }, + } + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/error.rs b/third-party/libp2p-swarm-0.45.1/src/connection/error.rs new file mode 100644 index 00000000000..33aa81c19a9 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/connection/error.rs @@ -0,0 +1,147 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::transport::TransportError; +use crate::Multiaddr; +use crate::{ConnectedPoint, PeerId}; +use std::{fmt, io}; + +/// Errors that can occur in the context of an established `Connection`. +#[derive(Debug)] +pub enum ConnectionError { + /// An I/O error occurred on the connection. + // TODO: Eventually this should also be a custom error? + IO(io::Error), + + /// The connection keep-alive timeout expired. + KeepAliveTimeout, +} + +impl fmt::Display for ConnectionError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ConnectionError::IO(err) => write!(f, "Connection error: I/O error: {err}"), + ConnectionError::KeepAliveTimeout => { + write!(f, "Connection closed due to expired keep-alive timeout.") + } + } + } +} + +impl std::error::Error for ConnectionError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + ConnectionError::IO(err) => Some(err), + ConnectionError::KeepAliveTimeout => None, + } + } +} + +impl From for ConnectionError { + fn from(error: io::Error) -> Self { + ConnectionError::IO(error) + } +} + +/// Errors that can occur in the context of a pending outgoing `Connection`. +/// +/// Note: Addresses for an outbound connection are dialed in parallel. Thus, compared to +/// [`PendingInboundConnectionError`], one or more [`TransportError`]s can occur for a single +/// connection. +pub(crate) type PendingOutboundConnectionError = + PendingConnectionError)>>; + +/// Errors that can occur in the context of a pending incoming `Connection`. +pub(crate) type PendingInboundConnectionError = PendingConnectionError>; + +/// Errors that can occur in the context of a pending `Connection`. +#[derive(Debug)] +pub enum PendingConnectionError { + /// An error occurred while negotiating the transport protocol(s) on a connection. + Transport(TTransErr), + + /// Pending connection attempt has been aborted. + Aborted, + + /// The peer identity obtained on the connection did not + /// match the one that was expected. + WrongPeerId { + obtained: PeerId, + endpoint: ConnectedPoint, + }, + + /// The connection was dropped because it resolved to our own [`PeerId`]. + LocalPeerId { endpoint: ConnectedPoint }, +} + +impl PendingConnectionError { + pub fn map(self, f: impl FnOnce(T) -> U) -> PendingConnectionError { + match self { + PendingConnectionError::Transport(t) => PendingConnectionError::Transport(f(t)), + PendingConnectionError::Aborted => PendingConnectionError::Aborted, + PendingConnectionError::WrongPeerId { obtained, endpoint } => { + PendingConnectionError::WrongPeerId { obtained, endpoint } + } + PendingConnectionError::LocalPeerId { endpoint } => { + PendingConnectionError::LocalPeerId { endpoint } + } + } + } +} + +impl fmt::Display for PendingConnectionError +where + TTransErr: fmt::Display + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + PendingConnectionError::Aborted => write!(f, "Pending connection: Aborted."), + PendingConnectionError::Transport(err) => { + write!( + f, + "Pending connection: Transport error on connection: {err}" + ) + } + PendingConnectionError::WrongPeerId { obtained, endpoint } => { + write!( + f, + "Pending connection: Unexpected peer ID {obtained} at {endpoint:?}." + ) + } + PendingConnectionError::LocalPeerId { endpoint } => { + write!(f, "Pending connection: Local peer ID at {endpoint:?}.") + } + } + } +} + +impl std::error::Error for PendingConnectionError +where + TTransErr: std::error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + PendingConnectionError::Transport(_) => None, + PendingConnectionError::WrongPeerId { .. } => None, + PendingConnectionError::LocalPeerId { .. } => None, + PendingConnectionError::Aborted => None, + } + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/pool.rs b/third-party/libp2p-swarm-0.45.1/src/connection/pool.rs new file mode 100644 index 00000000000..07f6968dec9 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/connection/pool.rs @@ -0,0 +1,1044 @@ +// Copyright 2021 Protocol Labs. +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +use crate::connection::{Connection, ConnectionId, PendingPoint}; +use crate::{ + connection::{ + Connected, ConnectionError, IncomingInfo, PendingConnectionError, + PendingInboundConnectionError, PendingOutboundConnectionError, + }, + transport::TransportError, + ConnectedPoint, ConnectionHandler, Executor, Multiaddr, PeerId, +}; +use concurrent_dial::ConcurrentDial; +use fnv::FnvHashMap; +use futures::prelude::*; +use futures::stream::SelectAll; +use futures::{ + channel::{mpsc, oneshot}, + future::{poll_fn, BoxFuture, Either}, + ready, + stream::FuturesUnordered, +}; +use libp2p_core::connection::Endpoint; +use libp2p_core::muxing::{StreamMuxerBox, StreamMuxerExt}; +use libp2p_core::transport::PortUse; +use std::task::Waker; +use std::{ + collections::HashMap, + fmt, + num::{NonZeroU8, NonZeroUsize}, + pin::Pin, + task::Context, + task::Poll, +}; +use tracing::Instrument; +use void::Void; +use web_time::{Duration, Instant}; + +mod concurrent_dial; +mod task; + +enum ExecSwitch { + Executor(Box), + LocalSpawn(FuturesUnordered + Send>>>), +} + +impl ExecSwitch { + fn advance_local(&mut self, cx: &mut Context) { + match self { + ExecSwitch::Executor(_) => {} + ExecSwitch::LocalSpawn(local) => { + while let Poll::Ready(Some(())) = local.poll_next_unpin(cx) {} + } + } + } + + #[track_caller] + fn spawn(&mut self, task: impl Future + Send + 'static) { + let task = task.boxed(); + + match self { + Self::Executor(executor) => executor.exec(task), + Self::LocalSpawn(local) => local.push(task), + } + } +} + +/// A connection `Pool` manages a set of connections for each peer. +pub(crate) struct Pool +where + THandler: ConnectionHandler, +{ + local_id: PeerId, + + /// The connection counter(s). + counters: ConnectionCounters, + + /// The managed connections of each peer that are currently considered established. + established: FnvHashMap< + PeerId, + FnvHashMap>, + >, + + /// The pending connections that are currently being negotiated. + pending: HashMap, + + /// Size of the task command buffer (per task). + task_command_buffer_size: usize, + + /// Number of addresses concurrently dialed for a single outbound connection attempt. + dial_concurrency_factor: NonZeroU8, + + /// The configured override for substream protocol upgrades, if any. + substream_upgrade_protocol_override: Option, + + /// The maximum number of inbound streams concurrently negotiating on a connection. + /// + /// See [`Connection::max_negotiating_inbound_streams`]. + max_negotiating_inbound_streams: usize, + + /// How many [`task::EstablishedConnectionEvent`]s can be buffered before the connection is back-pressured. + per_connection_event_buffer_size: usize, + + /// The executor to use for running connection tasks. Can either be a global executor + /// or a local queue. + executor: ExecSwitch, + + /// Sender distributed to pending tasks for reporting events back + /// to the pool. + pending_connection_events_tx: mpsc::Sender, + + /// Receiver for events reported from pending tasks. + pending_connection_events_rx: mpsc::Receiver, + + /// Waker in case we haven't established any connections yet. + no_established_connections_waker: Option, + + /// Receivers for events reported from established connections. + established_connection_events: + SelectAll>>, + + /// Receivers for [`NewConnection`] objects that are dropped. + new_connection_dropped_listeners: FuturesUnordered>, + + /// How long a connection should be kept alive once it starts idling. + idle_connection_timeout: Duration, +} + +#[derive(Debug)] +pub(crate) struct EstablishedConnection { + endpoint: ConnectedPoint, + /// Channel endpoint to send commands to the task. + sender: mpsc::Sender>, +} + +impl EstablishedConnection { + /// (Asynchronously) sends an event to the connection handler. + /// + /// If the handler is not ready to receive the event, either because + /// it is busy or the connection is about to close, the given event + /// is returned with an `Err`. + /// + /// If execution of this method is preceded by successful execution of + /// `poll_ready_notify_handler` without another intervening execution + /// of `notify_handler`, it only fails if the connection is now about + /// to close. + pub(crate) fn notify_handler(&mut self, event: TInEvent) -> Result<(), TInEvent> { + let cmd = task::Command::NotifyHandler(event); + self.sender.try_send(cmd).map_err(|e| match e.into_inner() { + task::Command::NotifyHandler(event) => event, + _ => unreachable!("Expect failed send to return initial event."), + }) + } + + /// Checks if `notify_handler` is ready to accept an event. + /// + /// Returns `Ok(())` if the handler is ready to receive an event via `notify_handler`. + /// + /// Returns `Err(())` if the background task associated with the connection + /// is terminating and the connection is about to close. + pub(crate) fn poll_ready_notify_handler( + &mut self, + cx: &mut Context<'_>, + ) -> Poll> { + self.sender.poll_ready(cx).map_err(|_| ()) + } + + /// Initiates a graceful close of the connection. + /// + /// Has no effect if the connection is already closing. + pub(crate) fn start_close(&mut self) { + // Clone the sender so that we are guaranteed to have + // capacity for the close command (every sender gets a slot). + match self.sender.clone().try_send(task::Command::Close) { + Ok(()) => {} + Err(e) => assert!(e.is_disconnected(), "No capacity for close command."), + }; + } +} + +struct PendingConnection { + /// [`PeerId`] of the remote peer. + peer_id: Option, + endpoint: PendingPoint, + /// When dropped, notifies the task which then knows to terminate. + abort_notifier: Option>, + /// The moment we became aware of this possible connection, useful for timing metrics. + accepted_at: Instant, +} + +impl PendingConnection { + fn is_for_same_remote_as(&self, other: PeerId) -> bool { + self.peer_id.map_or(false, |peer| peer == other) + } + + /// Aborts the connection attempt, closing the connection. + fn abort(&mut self) { + if let Some(notifier) = self.abort_notifier.take() { + drop(notifier); + } + } +} + +impl fmt::Debug for Pool { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.debug_struct("Pool") + .field("counters", &self.counters) + .finish() + } +} + +/// Event that can happen on the `Pool`. +#[derive(Debug)] +pub(crate) enum PoolEvent { + /// A new connection has been established. + ConnectionEstablished { + id: ConnectionId, + peer_id: PeerId, + endpoint: ConnectedPoint, + connection: NewConnection, + /// [`Some`] when the new connection is an outgoing connection. + /// Addresses are dialed in parallel. Contains the addresses and errors + /// of dial attempts that failed before the one successful dial. + concurrent_dial_errors: Option)>>, + /// How long it took to establish this connection. + established_in: std::time::Duration, + }, + + /// An established connection was closed. + /// + /// A connection may close if + /// + /// * it encounters an error, which includes the connection being + /// closed by the remote. In this case `error` is `Some`. + /// * it was actively closed by [`EstablishedConnection::start_close`], + /// i.e. a successful, orderly close. + /// * it was actively closed by [`Pool::disconnect`], i.e. + /// dropped without an orderly close. + /// + ConnectionClosed { + id: ConnectionId, + /// Information about the connection that errored. + connected: Connected, + /// The error that occurred, if any. If `None`, the connection + /// was closed by the local peer. + error: Option, + /// The remaining established connections to the same peer. + remaining_established_connection_ids: Vec, + }, + + /// An outbound connection attempt failed. + PendingOutboundConnectionError { + /// The ID of the failed connection. + id: ConnectionId, + /// The error that occurred. + error: PendingOutboundConnectionError, + /// The (expected) peer of the failed connection. + peer: Option, + }, + + /// An inbound connection attempt failed. + PendingInboundConnectionError { + /// The ID of the failed connection. + id: ConnectionId, + /// Address used to send back data to the remote. + send_back_addr: Multiaddr, + /// Local connection address. + local_addr: Multiaddr, + /// The error that occurred. + error: PendingInboundConnectionError, + }, + + /// A node has produced an event. + ConnectionEvent { + id: ConnectionId, + peer_id: PeerId, + /// The produced event. + event: ToBehaviour, + }, + + /// The connection to a node has changed its address. + AddressChange { + id: ConnectionId, + peer_id: PeerId, + /// The new endpoint. + new_endpoint: ConnectedPoint, + /// The old endpoint. + old_endpoint: ConnectedPoint, + }, +} + +impl Pool +where + THandler: ConnectionHandler, +{ + /// Creates a new empty `Pool`. + pub(crate) fn new(local_id: PeerId, config: PoolConfig) -> Self { + let (pending_connection_events_tx, pending_connection_events_rx) = mpsc::channel(0); + let executor = match config.executor { + Some(exec) => ExecSwitch::Executor(exec), + None => ExecSwitch::LocalSpawn(Default::default()), + }; + Pool { + local_id, + counters: ConnectionCounters::new(), + established: Default::default(), + pending: Default::default(), + task_command_buffer_size: config.task_command_buffer_size, + dial_concurrency_factor: config.dial_concurrency_factor, + substream_upgrade_protocol_override: config.substream_upgrade_protocol_override, + max_negotiating_inbound_streams: config.max_negotiating_inbound_streams, + per_connection_event_buffer_size: config.per_connection_event_buffer_size, + idle_connection_timeout: config.idle_connection_timeout, + executor, + pending_connection_events_tx, + pending_connection_events_rx, + no_established_connections_waker: None, + established_connection_events: Default::default(), + new_connection_dropped_listeners: Default::default(), + } + } + + /// Gets the dedicated connection counters. + pub(crate) fn counters(&self) -> &ConnectionCounters { + &self.counters + } + + /// Gets an established connection from the pool by ID. + pub(crate) fn get_established( + &mut self, + id: ConnectionId, + ) -> Option<&mut EstablishedConnection> { + self.established + .values_mut() + .find_map(|connections| connections.get_mut(&id)) + } + + /// Returns true if we are connected to the given peer. + /// + /// This will return true only after a `NodeReached` event has been produced by `poll()`. + pub(crate) fn is_connected(&self, id: PeerId) -> bool { + self.established.contains_key(&id) + } + + /// Returns the number of connected peers, i.e. those with at least one + /// established connection in the pool. + pub(crate) fn num_peers(&self) -> usize { + self.established.len() + } + + /// (Forcefully) close all connections to the given peer. + /// + /// All connections to the peer, whether pending or established are + /// closed asap and no more events from these connections are emitted + /// by the pool effective immediately. + pub(crate) fn disconnect(&mut self, peer: PeerId) { + if let Some(conns) = self.established.get_mut(&peer) { + for (_, conn) in conns.iter_mut() { + conn.start_close(); + } + } + + for connection in self + .pending + .iter_mut() + .filter_map(|(_, info)| info.is_for_same_remote_as(peer).then_some(info)) + { + connection.abort() + } + } + + /// Returns an iterator over all established connections of `peer`. + pub(crate) fn iter_established_connections_of_peer( + &mut self, + peer: &PeerId, + ) -> impl Iterator + '_ { + match self.established.get(peer) { + Some(conns) => either::Either::Left(conns.iter().map(|(id, _)| *id)), + None => either::Either::Right(std::iter::empty()), + } + } + + /// Checks whether we are currently dialing the given peer. + pub(crate) fn is_dialing(&self, peer: PeerId) -> bool { + self.pending.iter().any(|(_, info)| { + matches!(info.endpoint, PendingPoint::Dialer { .. }) && info.is_for_same_remote_as(peer) + }) + } + + /// Returns an iterator over all connected peers, i.e. those that have + /// at least one established connection in the pool. + pub(crate) fn iter_connected(&self) -> impl Iterator { + self.established.keys() + } + + /// Adds a pending outgoing connection to the pool in the form of a `Future` + /// that establishes and negotiates the connection. + pub(crate) fn add_outgoing( + &mut self, + dials: Vec< + BoxFuture< + 'static, + ( + Multiaddr, + Result<(PeerId, StreamMuxerBox), TransportError>, + ), + >, + >, + peer: Option, + role_override: Endpoint, + port_use: PortUse, + dial_concurrency_factor_override: Option, + connection_id: ConnectionId, + ) { + let concurrency_factor = + dial_concurrency_factor_override.unwrap_or(self.dial_concurrency_factor); + let span = tracing::debug_span!(parent: tracing::Span::none(), "new_outgoing_connection", %concurrency_factor, num_dials=%dials.len(), id = %connection_id); + span.follows_from(tracing::Span::current()); + + let (abort_notifier, abort_receiver) = oneshot::channel(); + + self.executor.spawn( + task::new_for_pending_outgoing_connection( + connection_id, + ConcurrentDial::new(dials, concurrency_factor), + abort_receiver, + self.pending_connection_events_tx.clone(), + ) + .instrument(span), + ); + + let endpoint = PendingPoint::Dialer { + role_override, + port_use, + }; + + self.counters.inc_pending(&endpoint); + self.pending.insert( + connection_id, + PendingConnection { + peer_id: peer, + endpoint, + abort_notifier: Some(abort_notifier), + accepted_at: Instant::now(), + }, + ); + } + + /// Adds a pending incoming connection to the pool in the form of a + /// `Future` that establishes and negotiates the connection. + pub(crate) fn add_incoming( + &mut self, + future: TFut, + info: IncomingInfo<'_>, + connection_id: ConnectionId, + ) where + TFut: Future> + Send + 'static, + { + let endpoint = info.create_connected_point(); + + let (abort_notifier, abort_receiver) = oneshot::channel(); + + let span = tracing::debug_span!(parent: tracing::Span::none(), "new_incoming_connection", remote_addr = %info.send_back_addr, id = %connection_id); + span.follows_from(tracing::Span::current()); + + self.executor.spawn( + task::new_for_pending_incoming_connection( + connection_id, + future, + abort_receiver, + self.pending_connection_events_tx.clone(), + ) + .instrument(span), + ); + + self.counters.inc_pending_incoming(); + self.pending.insert( + connection_id, + PendingConnection { + peer_id: None, + endpoint: endpoint.into(), + abort_notifier: Some(abort_notifier), + accepted_at: Instant::now(), + }, + ); + } + + pub(crate) fn spawn_connection( + &mut self, + id: ConnectionId, + obtained_peer_id: PeerId, + endpoint: &ConnectedPoint, + connection: NewConnection, + handler: THandler, + ) { + let connection = connection.extract(); + let conns = self.established.entry(obtained_peer_id).or_default(); + self.counters.inc_established(endpoint); + + let (command_sender, command_receiver) = mpsc::channel(self.task_command_buffer_size); + let (event_sender, event_receiver) = mpsc::channel(self.per_connection_event_buffer_size); + + conns.insert( + id, + EstablishedConnection { + endpoint: endpoint.clone(), + sender: command_sender, + }, + ); + self.established_connection_events.push(event_receiver); + if let Some(waker) = self.no_established_connections_waker.take() { + waker.wake(); + } + + let connection = Connection::new( + connection, + handler, + self.substream_upgrade_protocol_override, + self.max_negotiating_inbound_streams, + self.idle_connection_timeout, + ); + + let span = tracing::debug_span!(parent: tracing::Span::none(), "new_established_connection", remote_addr = %endpoint.get_remote_address(), %id, peer = %obtained_peer_id); + span.follows_from(tracing::Span::current()); + + self.executor.spawn( + task::new_for_established_connection( + id, + obtained_peer_id, + connection, + command_receiver, + event_sender, + ) + .instrument(span), + ) + } + + /// Polls the connection pool for events. + #[tracing::instrument(level = "debug", name = "Pool::poll", skip(self, cx))] + pub(crate) fn poll(&mut self, cx: &mut Context<'_>) -> Poll> + where + THandler: ConnectionHandler + 'static, + ::OutboundOpenInfo: Send, + { + // Poll for events of established connections. + // + // Note that established connections are polled before pending connections, thus + // prioritizing established connections over pending connections. + match self.established_connection_events.poll_next_unpin(cx) { + Poll::Pending => {} + Poll::Ready(None) => { + self.no_established_connections_waker = Some(cx.waker().clone()); + } + + Poll::Ready(Some(task::EstablishedConnectionEvent::Notify { id, peer_id, event })) => { + return Poll::Ready(PoolEvent::ConnectionEvent { peer_id, id, event }); + } + Poll::Ready(Some(task::EstablishedConnectionEvent::AddressChange { + id, + peer_id, + new_address, + })) => { + let connection = self + .established + .get_mut(&peer_id) + .expect("Receive `AddressChange` event for established peer.") + .get_mut(&id) + .expect("Receive `AddressChange` event from established connection"); + let mut new_endpoint = connection.endpoint.clone(); + new_endpoint.set_remote_address(new_address); + let old_endpoint = + std::mem::replace(&mut connection.endpoint, new_endpoint.clone()); + + return Poll::Ready(PoolEvent::AddressChange { + peer_id, + id, + new_endpoint, + old_endpoint, + }); + } + Poll::Ready(Some(task::EstablishedConnectionEvent::Closed { id, peer_id, error })) => { + let connections = self + .established + .get_mut(&peer_id) + .expect("`Closed` event for established connection"); + let EstablishedConnection { endpoint, .. } = + connections.remove(&id).expect("Connection to be present"); + self.counters.dec_established(&endpoint); + let remaining_established_connection_ids: Vec = + connections.keys().cloned().collect(); + if remaining_established_connection_ids.is_empty() { + self.established.remove(&peer_id); + } + return Poll::Ready(PoolEvent::ConnectionClosed { + id, + connected: Connected { endpoint, peer_id }, + error, + remaining_established_connection_ids, + }); + } + } + + // Poll for events of pending connections. + loop { + if let Poll::Ready(Some(result)) = + self.new_connection_dropped_listeners.poll_next_unpin(cx) + { + if let Ok(dropped_connection) = result { + self.executor.spawn(async move { + let _ = dropped_connection.close().await; + }); + } + continue; + } + + let event = match self.pending_connection_events_rx.poll_next_unpin(cx) { + Poll::Ready(Some(event)) => event, + Poll::Pending => break, + Poll::Ready(None) => unreachable!("Pool holds both sender and receiver."), + }; + + match event { + task::PendingConnectionEvent::ConnectionEstablished { + id, + output: (obtained_peer_id, mut muxer), + outgoing, + } => { + let PendingConnection { + peer_id: expected_peer_id, + endpoint, + abort_notifier: _, + accepted_at, + } = self + .pending + .remove(&id) + .expect("Entry in `self.pending` for previously pending connection."); + + self.counters.dec_pending(&endpoint); + + let (endpoint, concurrent_dial_errors) = match (endpoint, outgoing) { + ( + PendingPoint::Dialer { + role_override, + port_use, + }, + Some((address, errors)), + ) => ( + ConnectedPoint::Dialer { + address, + role_override, + port_use, + }, + Some(errors), + ), + ( + PendingPoint::Listener { + local_addr, + send_back_addr, + }, + None, + ) => ( + ConnectedPoint::Listener { + local_addr, + send_back_addr, + }, + None, + ), + (PendingPoint::Dialer { .. }, None) => unreachable!( + "Established incoming connection via pending outgoing connection." + ), + (PendingPoint::Listener { .. }, Some(_)) => unreachable!( + "Established outgoing connection via pending incoming connection." + ), + }; + + let check_peer_id = || { + if let Some(peer) = expected_peer_id { + if peer != obtained_peer_id { + return Err(PendingConnectionError::WrongPeerId { + obtained: obtained_peer_id, + endpoint: endpoint.clone(), + }); + } + } + + if self.local_id == obtained_peer_id { + return Err(PendingConnectionError::LocalPeerId { + endpoint: endpoint.clone(), + }); + } + + Ok(()) + }; + + if let Err(error) = check_peer_id() { + self.executor.spawn(poll_fn(move |cx| { + if let Err(e) = ready!(muxer.poll_close_unpin(cx)) { + tracing::debug!( + peer=%obtained_peer_id, + connection=%id, + "Failed to close connection to peer: {:?}", + e + ); + } + Poll::Ready(()) + })); + + match endpoint { + ConnectedPoint::Dialer { .. } => { + return Poll::Ready(PoolEvent::PendingOutboundConnectionError { + id, + error: error + .map(|t| vec![(endpoint.get_remote_address().clone(), t)]), + peer: expected_peer_id.or(Some(obtained_peer_id)), + }) + } + ConnectedPoint::Listener { + send_back_addr, + local_addr, + } => { + return Poll::Ready(PoolEvent::PendingInboundConnectionError { + id, + error, + send_back_addr, + local_addr, + }) + } + }; + } + + let established_in = accepted_at.elapsed(); + + let (connection, drop_listener) = NewConnection::new(muxer); + self.new_connection_dropped_listeners.push(drop_listener); + + return Poll::Ready(PoolEvent::ConnectionEstablished { + peer_id: obtained_peer_id, + endpoint, + id, + connection, + concurrent_dial_errors, + established_in, + }); + } + task::PendingConnectionEvent::PendingFailed { id, error } => { + if let Some(PendingConnection { + peer_id, + endpoint, + abort_notifier: _, + accepted_at: _, // Ignoring the time it took for the connection to fail. + }) = self.pending.remove(&id) + { + self.counters.dec_pending(&endpoint); + + match (endpoint, error) { + (PendingPoint::Dialer { .. }, Either::Left(error)) => { + return Poll::Ready(PoolEvent::PendingOutboundConnectionError { + id, + error, + peer: peer_id, + }); + } + ( + PendingPoint::Listener { + send_back_addr, + local_addr, + }, + Either::Right(error), + ) => { + return Poll::Ready(PoolEvent::PendingInboundConnectionError { + id, + error, + send_back_addr, + local_addr, + }); + } + (PendingPoint::Dialer { .. }, Either::Right(_)) => { + unreachable!("Inbound error for outbound connection.") + } + (PendingPoint::Listener { .. }, Either::Left(_)) => { + unreachable!("Outbound error for inbound connection.") + } + } + } + } + } + } + + self.executor.advance_local(cx); + + Poll::Pending + } +} + +/// Opaque type for a new connection. +/// +/// This connection has just been established but isn't part of the [`Pool`] yet. +/// It either needs to be spawned via [`Pool::spawn_connection`] or dropped if undesired. +/// +/// On drop, this type send the connection back to the [`Pool`] where it will be gracefully closed. +#[derive(Debug)] +pub(crate) struct NewConnection { + connection: Option, + drop_sender: Option>, +} + +impl NewConnection { + fn new(conn: StreamMuxerBox) -> (Self, oneshot::Receiver) { + let (sender, receiver) = oneshot::channel(); + + ( + Self { + connection: Some(conn), + drop_sender: Some(sender), + }, + receiver, + ) + } + + fn extract(mut self) -> StreamMuxerBox { + self.connection.take().unwrap() + } +} + +impl Drop for NewConnection { + fn drop(&mut self) { + if let Some(connection) = self.connection.take() { + let _ = self + .drop_sender + .take() + .expect("`drop_sender` to always be `Some`") + .send(connection); + } + } +} + +/// Network connection information. +#[derive(Debug, Clone)] +pub struct ConnectionCounters { + /// The current number of incoming connections. + pending_incoming: u32, + /// The current number of outgoing connections. + pending_outgoing: u32, + /// The current number of established inbound connections. + established_incoming: u32, + /// The current number of established outbound connections. + established_outgoing: u32, +} + +impl ConnectionCounters { + fn new() -> Self { + Self { + pending_incoming: 0, + pending_outgoing: 0, + established_incoming: 0, + established_outgoing: 0, + } + } + + /// The total number of connections, both pending and established. + pub fn num_connections(&self) -> u32 { + self.num_pending() + self.num_established() + } + + /// The total number of pending connections, both incoming and outgoing. + pub fn num_pending(&self) -> u32 { + self.pending_incoming + self.pending_outgoing + } + + /// The number of incoming connections being established. + pub fn num_pending_incoming(&self) -> u32 { + self.pending_incoming + } + + /// The number of outgoing connections being established. + pub fn num_pending_outgoing(&self) -> u32 { + self.pending_outgoing + } + + /// The number of established incoming connections. + pub fn num_established_incoming(&self) -> u32 { + self.established_incoming + } + + /// The number of established outgoing connections. + pub fn num_established_outgoing(&self) -> u32 { + self.established_outgoing + } + + /// The total number of established connections. + pub fn num_established(&self) -> u32 { + self.established_outgoing + self.established_incoming + } + + fn inc_pending(&mut self, endpoint: &PendingPoint) { + match endpoint { + PendingPoint::Dialer { .. } => { + self.pending_outgoing += 1; + } + PendingPoint::Listener { .. } => { + self.pending_incoming += 1; + } + } + } + + fn inc_pending_incoming(&mut self) { + self.pending_incoming += 1; + } + + fn dec_pending(&mut self, endpoint: &PendingPoint) { + match endpoint { + PendingPoint::Dialer { .. } => { + self.pending_outgoing -= 1; + } + PendingPoint::Listener { .. } => { + self.pending_incoming -= 1; + } + } + } + + fn inc_established(&mut self, endpoint: &ConnectedPoint) { + match endpoint { + ConnectedPoint::Dialer { .. } => { + self.established_outgoing += 1; + } + ConnectedPoint::Listener { .. } => { + self.established_incoming += 1; + } + } + } + + fn dec_established(&mut self, endpoint: &ConnectedPoint) { + match endpoint { + ConnectedPoint::Dialer { .. } => { + self.established_outgoing -= 1; + } + ConnectedPoint::Listener { .. } => { + self.established_incoming -= 1; + } + } + } +} + +/// Configuration options when creating a [`Pool`]. +/// +/// The default configuration specifies no dedicated task executor, a +/// task event buffer size of 32, and a task command buffer size of 7. +pub(crate) struct PoolConfig { + /// Executor to use to spawn tasks. + pub(crate) executor: Option>, + /// Size of the task command buffer (per task). + pub(crate) task_command_buffer_size: usize, + /// Size of the pending connection task event buffer and the established connection task event + /// buffer. + pub(crate) per_connection_event_buffer_size: usize, + /// Number of addresses concurrently dialed for a single outbound connection attempt. + pub(crate) dial_concurrency_factor: NonZeroU8, + /// How long a connection should be kept alive once it is idling. + pub(crate) idle_connection_timeout: Duration, + /// The configured override for substream protocol upgrades, if any. + substream_upgrade_protocol_override: Option, + + /// The maximum number of inbound streams concurrently negotiating on a connection. + /// + /// See [`Connection::max_negotiating_inbound_streams`]. + max_negotiating_inbound_streams: usize, +} + +impl PoolConfig { + pub(crate) fn new(executor: Option>) -> Self { + Self { + executor, + task_command_buffer_size: 32, + per_connection_event_buffer_size: 7, + dial_concurrency_factor: NonZeroU8::new(8).expect("8 > 0"), + idle_connection_timeout: Duration::ZERO, + substream_upgrade_protocol_override: None, + max_negotiating_inbound_streams: 128, + } + } + + /// Sets the maximum number of events sent to a connection's background task + /// that may be buffered, if the task cannot keep up with their consumption and + /// delivery to the connection handler. + /// + /// When the buffer for a particular connection is full, `notify_handler` will no + /// longer be able to deliver events to the associated [`Connection`], + /// thus exerting back-pressure on the connection and peer API. + pub(crate) fn with_notify_handler_buffer_size(mut self, n: NonZeroUsize) -> Self { + self.task_command_buffer_size = n.get() - 1; + self + } + + /// Sets the maximum number of buffered connection events (beyond a guaranteed + /// buffer of 1 event per connection). + /// + /// When the buffer is full, the background tasks of all connections will stall. + /// In this way, the consumers of network events exert back-pressure on + /// the network connection I/O. + pub(crate) fn with_per_connection_event_buffer_size(mut self, n: usize) -> Self { + self.per_connection_event_buffer_size = n; + self + } + + /// Number of addresses concurrently dialed for a single outbound connection attempt. + pub(crate) fn with_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self { + self.dial_concurrency_factor = factor; + self + } + + /// Configures an override for the substream upgrade protocol to use. + pub(crate) fn with_substream_upgrade_protocol_override( + mut self, + v: libp2p_core::upgrade::Version, + ) -> Self { + self.substream_upgrade_protocol_override = Some(v); + self + } + + /// The maximum number of inbound streams concurrently negotiating on a connection. + /// + /// See [`Connection::max_negotiating_inbound_streams`]. + pub(crate) fn with_max_negotiating_inbound_streams(mut self, v: usize) -> Self { + self.max_negotiating_inbound_streams = v; + self + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/pool/concurrent_dial.rs b/third-party/libp2p-swarm-0.45.1/src/connection/pool/concurrent_dial.rs new file mode 100644 index 00000000000..57e4b078098 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/connection/pool/concurrent_dial.rs @@ -0,0 +1,103 @@ +// Copyright 2021 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::{transport::TransportError, Multiaddr}; +use futures::{ + future::{BoxFuture, Future}, + ready, + stream::{FuturesUnordered, StreamExt}, +}; +use libp2p_core::muxing::StreamMuxerBox; +use libp2p_identity::PeerId; +use std::{ + num::NonZeroU8, + pin::Pin, + task::{Context, Poll}, +}; + +type Dial = BoxFuture< + 'static, + ( + Multiaddr, + Result<(PeerId, StreamMuxerBox), TransportError>, + ), +>; + +pub(crate) struct ConcurrentDial { + dials: FuturesUnordered, + pending_dials: Box + Send>, + errors: Vec<(Multiaddr, TransportError)>, +} + +impl Unpin for ConcurrentDial {} + +impl ConcurrentDial { + pub(crate) fn new(pending_dials: Vec, concurrency_factor: NonZeroU8) -> Self { + let mut pending_dials = pending_dials.into_iter(); + + let dials = FuturesUnordered::new(); + for dial in pending_dials.by_ref() { + dials.push(dial); + if dials.len() == concurrency_factor.get() as usize { + break; + } + } + + Self { + dials, + errors: Default::default(), + pending_dials: Box::new(pending_dials), + } + } +} + +impl Future for ConcurrentDial { + type Output = Result< + // Either one dial succeeded, returning the negotiated [`PeerId`], the address, the + // muxer and the addresses and errors of the dials that failed before. + ( + Multiaddr, + (PeerId, StreamMuxerBox), + Vec<(Multiaddr, TransportError)>, + ), + // Or all dials failed, thus returning the address and error for each dial. + Vec<(Multiaddr, TransportError)>, + >; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + loop { + match ready!(self.dials.poll_next_unpin(cx)) { + Some((addr, Ok(output))) => { + let errors = std::mem::take(&mut self.errors); + return Poll::Ready(Ok((addr, output, errors))); + } + Some((addr, Err(e))) => { + self.errors.push((addr, e)); + if let Some(dial) = self.pending_dials.next() { + self.dials.push(dial) + } + } + None => { + return Poll::Ready(Err(std::mem::take(&mut self.errors))); + } + } + } + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/pool/task.rs b/third-party/libp2p-swarm-0.45.1/src/connection/pool/task.rs new file mode 100644 index 00000000000..08674fd2ee5 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/connection/pool/task.rs @@ -0,0 +1,265 @@ +// Copyright 2021 Protocol Labs. +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +//! Async functions driving pending and established connections in the form of a task. + +use super::concurrent_dial::ConcurrentDial; +use crate::{ + connection::{ + self, ConnectionError, ConnectionId, PendingInboundConnectionError, + PendingOutboundConnectionError, + }, + transport::TransportError, + ConnectionHandler, Multiaddr, PeerId, +}; +use futures::{ + channel::{mpsc, oneshot}, + future::{poll_fn, Either, Future}, + SinkExt, StreamExt, +}; +use libp2p_core::muxing::StreamMuxerBox; +use std::pin::Pin; +use void::Void; + +/// Commands that can be sent to a task driving an established connection. +#[derive(Debug)] +pub(crate) enum Command { + /// Notify the connection handler of an event. + NotifyHandler(T), + /// Gracefully close the connection (active close) before + /// terminating the task. + Close, +} + +pub(crate) enum PendingConnectionEvent { + ConnectionEstablished { + id: ConnectionId, + output: (PeerId, StreamMuxerBox), + /// [`Some`] when the new connection is an outgoing connection. + /// Addresses are dialed in parallel. Contains the addresses and errors + /// of dial attempts that failed before the one successful dial. + outgoing: Option<(Multiaddr, Vec<(Multiaddr, TransportError)>)>, + }, + /// A pending connection failed. + PendingFailed { + id: ConnectionId, + error: Either, + }, +} + +#[derive(Debug)] +pub(crate) enum EstablishedConnectionEvent { + /// A node we are connected to has changed its address. + AddressChange { + id: ConnectionId, + peer_id: PeerId, + new_address: Multiaddr, + }, + /// Notify the manager of an event from the connection. + Notify { + id: ConnectionId, + peer_id: PeerId, + event: ToBehaviour, + }, + /// A connection closed, possibly due to an error. + /// + /// If `error` is `None`, the connection has completed + /// an active orderly close. + Closed { + id: ConnectionId, + peer_id: PeerId, + error: Option, + }, +} + +pub(crate) async fn new_for_pending_outgoing_connection( + connection_id: ConnectionId, + dial: ConcurrentDial, + abort_receiver: oneshot::Receiver, + mut events: mpsc::Sender, +) { + match futures::future::select(abort_receiver, Box::pin(dial)).await { + Either::Left((Err(oneshot::Canceled), _)) => { + let _ = events + .send(PendingConnectionEvent::PendingFailed { + id: connection_id, + error: Either::Left(PendingOutboundConnectionError::Aborted), + }) + .await; + } + Either::Left((Ok(v), _)) => void::unreachable(v), + Either::Right((Ok((address, output, errors)), _)) => { + let _ = events + .send(PendingConnectionEvent::ConnectionEstablished { + id: connection_id, + output, + outgoing: Some((address, errors)), + }) + .await; + } + Either::Right((Err(e), _)) => { + let _ = events + .send(PendingConnectionEvent::PendingFailed { + id: connection_id, + error: Either::Left(PendingOutboundConnectionError::Transport(e)), + }) + .await; + } + } +} + +pub(crate) async fn new_for_pending_incoming_connection( + connection_id: ConnectionId, + future: TFut, + abort_receiver: oneshot::Receiver, + mut events: mpsc::Sender, +) where + TFut: Future> + Send + 'static, +{ + match futures::future::select(abort_receiver, Box::pin(future)).await { + Either::Left((Err(oneshot::Canceled), _)) => { + let _ = events + .send(PendingConnectionEvent::PendingFailed { + id: connection_id, + error: Either::Right(PendingInboundConnectionError::Aborted), + }) + .await; + } + Either::Left((Ok(v), _)) => void::unreachable(v), + Either::Right((Ok(output), _)) => { + let _ = events + .send(PendingConnectionEvent::ConnectionEstablished { + id: connection_id, + output, + outgoing: None, + }) + .await; + } + Either::Right((Err(e), _)) => { + let _ = events + .send(PendingConnectionEvent::PendingFailed { + id: connection_id, + error: Either::Right(PendingInboundConnectionError::Transport( + TransportError::Other(e), + )), + }) + .await; + } + } +} + +pub(crate) async fn new_for_established_connection( + connection_id: ConnectionId, + peer_id: PeerId, + mut connection: crate::connection::Connection, + mut command_receiver: mpsc::Receiver>, + mut events: mpsc::Sender>, +) where + THandler: ConnectionHandler, +{ + loop { + match futures::future::select( + command_receiver.next(), + poll_fn(|cx| Pin::new(&mut connection).poll(cx)), + ) + .await + { + Either::Left((Some(command), _)) => match command { + Command::NotifyHandler(event) => connection.on_behaviour_event(event), + Command::Close => { + command_receiver.close(); + let (remaining_events, closing_muxer) = connection.close(); + + let _ = events + .send_all(&mut remaining_events.map(|event| { + Ok(EstablishedConnectionEvent::Notify { + id: connection_id, + event, + peer_id, + }) + })) + .await; + + let error = closing_muxer.await.err().map(ConnectionError::IO); + + let _ = events + .send(EstablishedConnectionEvent::Closed { + id: connection_id, + peer_id, + error, + }) + .await; + return; + } + }, + + // The manager has disappeared; abort. + Either::Left((None, _)) => return, + + Either::Right((event, _)) => { + match event { + Ok(connection::Event::Handler(event)) => { + let _ = events + .send(EstablishedConnectionEvent::Notify { + id: connection_id, + peer_id, + event, + }) + .await; + } + Ok(connection::Event::AddressChange(new_address)) => { + let _ = events + .send(EstablishedConnectionEvent::AddressChange { + id: connection_id, + peer_id, + new_address, + }) + .await; + } + Err(error) => { + command_receiver.close(); + let (remaining_events, _closing_muxer) = connection.close(); + + let _ = events + .send_all(&mut remaining_events.map(|event| { + Ok(EstablishedConnectionEvent::Notify { + id: connection_id, + event, + peer_id, + }) + })) + .await; + + // Terminate the task with the error, dropping the connection. + let _ = events + .send(EstablishedConnectionEvent::Closed { + id: connection_id, + peer_id, + error: Some(error), + }) + .await; + return; + } + } + } + } + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/supported_protocols.rs b/third-party/libp2p-swarm-0.45.1/src/connection/supported_protocols.rs new file mode 100644 index 00000000000..124ec93d669 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/connection/supported_protocols.rs @@ -0,0 +1,92 @@ +use crate::handler::ProtocolsChange; +use crate::StreamProtocol; +use std::collections::HashSet; + +#[derive(Default, Clone, Debug)] +pub struct SupportedProtocols { + protocols: HashSet, +} + +impl SupportedProtocols { + pub fn on_protocols_change(&mut self, change: ProtocolsChange) -> bool { + match change { + ProtocolsChange::Added(added) => { + let mut changed = false; + + for p in added { + changed |= self.protocols.insert(p.clone()); + } + + changed + } + ProtocolsChange::Removed(removed) => { + let mut changed = false; + + for p in removed { + changed |= self.protocols.remove(p); + } + + changed + } + } + } + + pub fn iter(&self) -> impl Iterator { + self.protocols.iter() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::handler::{ProtocolsAdded, ProtocolsRemoved}; + + #[test] + fn protocols_change_added_returns_correct_changed_value() { + let mut protocols = SupportedProtocols::default(); + + let changed = protocols.on_protocols_change(add_foo()); + assert!(changed); + + let changed = protocols.on_protocols_change(add_foo()); + assert!(!changed); + + let changed = protocols.on_protocols_change(add_foo_bar()); + assert!(changed); + } + + #[test] + fn protocols_change_removed_returns_correct_changed_value() { + let mut protocols = SupportedProtocols::default(); + + let changed = protocols.on_protocols_change(remove_foo()); + assert!(!changed); + + protocols.on_protocols_change(add_foo()); + + let changed = protocols.on_protocols_change(remove_foo()); + assert!(changed); + } + + fn add_foo() -> ProtocolsChange<'static> { + ProtocolsChange::Added(ProtocolsAdded { + protocols: FOO_PROTOCOLS.iter(), + }) + } + + fn add_foo_bar() -> ProtocolsChange<'static> { + ProtocolsChange::Added(ProtocolsAdded { + protocols: FOO_BAR_PROTOCOLS.iter(), + }) + } + + fn remove_foo() -> ProtocolsChange<'static> { + ProtocolsChange::Removed(ProtocolsRemoved { + protocols: FOO_PROTOCOLS.iter(), + }) + } + + static FOO_PROTOCOLS: &[StreamProtocol] = &[StreamProtocol::new("/foo")]; + static FOO_BAR_PROTOCOLS: &[StreamProtocol] = + &[StreamProtocol::new("/foo"), StreamProtocol::new("/bar")]; +} diff --git a/third-party/libp2p-swarm-0.45.1/src/dial_opts.rs b/third-party/libp2p-swarm-0.45.1/src/dial_opts.rs new file mode 100644 index 00000000000..4f5b621327c --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/dial_opts.rs @@ -0,0 +1,348 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2021 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::ConnectionId; +use libp2p_core::connection::Endpoint; +use libp2p_core::multiaddr::Protocol; +use libp2p_core::transport::PortUse; +use libp2p_core::Multiaddr; +use libp2p_identity::PeerId; +use std::num::NonZeroU8; + +macro_rules! fn_override_role { + () => { + /// Override role of local node on connection. I.e. execute the dial _as a + /// listener_. + /// + /// See + /// [`ConnectedPoint::Dialer`](libp2p_core::connection::ConnectedPoint::Dialer) + /// for details. + pub fn override_role(mut self) -> Self { + self.role_override = Endpoint::Listener; + self + } + }; +} + +macro_rules! fn_allocate_new_port { + () => { + /// Enforce the allocation of a new port. + /// Default behaviour is best effort reuse of existing ports. If there is no existing + /// fitting listener, a new port is allocated. + pub fn allocate_new_port(mut self) -> Self { + self.port_use = PortUse::New; + self + } + }; +} + +/// Options to configure a dial to a known or unknown peer. +/// +/// Used in [`Swarm::dial`](crate::Swarm::dial) and +/// [`ToSwarm::Dial`](crate::behaviour::ToSwarm::Dial). +/// +/// To construct use either of: +/// +/// - [`DialOpts::peer_id`] dialing a known peer +/// +/// - [`DialOpts::unknown_peer_id`] dialing an unknown peer +#[derive(Debug)] +pub struct DialOpts { + peer_id: Option, + condition: PeerCondition, + addresses: Vec, + extend_addresses_through_behaviour: bool, + role_override: Endpoint, + dial_concurrency_factor_override: Option, + connection_id: ConnectionId, + port_use: PortUse, +} + +impl DialOpts { + /// Dial a known peer. + /// + /// ``` + /// # use libp2p_swarm::dial_opts::{DialOpts, PeerCondition}; + /// # use libp2p_identity::PeerId; + /// DialOpts::peer_id(PeerId::random()) + /// .condition(PeerCondition::Disconnected) + /// .addresses(vec!["/ip6/::1/tcp/12345".parse().unwrap()]) + /// .extend_addresses_through_behaviour() + /// .build(); + /// ``` + pub fn peer_id(peer_id: PeerId) -> WithPeerId { + WithPeerId { + peer_id, + condition: Default::default(), + role_override: Endpoint::Dialer, + dial_concurrency_factor_override: Default::default(), + port_use: PortUse::Reuse, + } + } + + /// Dial an unknown peer. + /// + /// ``` + /// # use libp2p_swarm::dial_opts::DialOpts; + /// DialOpts::unknown_peer_id() + /// .address("/ip6/::1/tcp/12345".parse().unwrap()) + /// .build(); + /// ``` + pub fn unknown_peer_id() -> WithoutPeerId { + WithoutPeerId {} + } + + /// Retrieves the [`PeerId`] from the [`DialOpts`] if specified or otherwise tries to extract it + /// from the multihash in the `/p2p` part of the address, if present. + pub fn get_peer_id(&self) -> Option { + if let Some(peer_id) = self.peer_id { + return Some(peer_id); + } + + let first_address = self.addresses.first()?; + let last_protocol = first_address.iter().last()?; + + if let Protocol::P2p(p) = last_protocol { + return Some(p); + } + + None + } + + /// Get the [`ConnectionId`] of this dial attempt. + /// + /// All future events of this dial will be associated with this ID. + /// See [`DialFailure`](crate::DialFailure) and [`ConnectionEstablished`](crate::behaviour::ConnectionEstablished). + pub fn connection_id(&self) -> ConnectionId { + self.connection_id + } + + pub(crate) fn get_addresses(&self) -> Vec { + self.addresses.clone() + } + + pub(crate) fn extend_addresses_through_behaviour(&self) -> bool { + self.extend_addresses_through_behaviour + } + + pub(crate) fn peer_condition(&self) -> PeerCondition { + self.condition + } + + pub(crate) fn dial_concurrency_override(&self) -> Option { + self.dial_concurrency_factor_override + } + + pub(crate) fn role_override(&self) -> Endpoint { + self.role_override + } + + pub(crate) fn port_use(&self) -> PortUse { + self.port_use + } +} + +impl From for DialOpts { + fn from(address: Multiaddr) -> Self { + DialOpts::unknown_peer_id().address(address).build() + } +} + +impl From for DialOpts { + fn from(peer_id: PeerId) -> Self { + DialOpts::peer_id(peer_id).build() + } +} + +#[derive(Debug)] +pub struct WithPeerId { + peer_id: PeerId, + condition: PeerCondition, + role_override: Endpoint, + dial_concurrency_factor_override: Option, + port_use: PortUse, +} + +impl WithPeerId { + /// Specify a [`PeerCondition`] for the dial. + pub fn condition(mut self, condition: PeerCondition) -> Self { + self.condition = condition; + self + } + + /// Override + /// Number of addresses concurrently dialed for a single outbound connection attempt. + pub fn override_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self { + self.dial_concurrency_factor_override = Some(factor); + self + } + + /// Specify a set of addresses to be used to dial the known peer. + pub fn addresses(self, addresses: Vec) -> WithPeerIdWithAddresses { + WithPeerIdWithAddresses { + peer_id: self.peer_id, + condition: self.condition, + addresses, + extend_addresses_through_behaviour: false, + role_override: self.role_override, + dial_concurrency_factor_override: self.dial_concurrency_factor_override, + port_use: self.port_use, + } + } + + fn_override_role!(); + fn_allocate_new_port!(); + + /// Build the final [`DialOpts`]. + pub fn build(self) -> DialOpts { + DialOpts { + peer_id: Some(self.peer_id), + condition: self.condition, + addresses: vec![], + extend_addresses_through_behaviour: true, + role_override: self.role_override, + dial_concurrency_factor_override: self.dial_concurrency_factor_override, + connection_id: ConnectionId::next(), + port_use: self.port_use, + } + } +} + +#[derive(Debug)] +pub struct WithPeerIdWithAddresses { + peer_id: PeerId, + condition: PeerCondition, + addresses: Vec, + extend_addresses_through_behaviour: bool, + role_override: Endpoint, + dial_concurrency_factor_override: Option, + port_use: PortUse, +} + +impl WithPeerIdWithAddresses { + /// Specify a [`PeerCondition`] for the dial. + pub fn condition(mut self, condition: PeerCondition) -> Self { + self.condition = condition; + self + } + + /// In addition to the provided addresses, extend the set via + /// [`NetworkBehaviour::handle_pending_outbound_connection`](crate::behaviour::NetworkBehaviour::handle_pending_outbound_connection). + pub fn extend_addresses_through_behaviour(mut self) -> Self { + self.extend_addresses_through_behaviour = true; + self + } + + fn_override_role!(); + fn_allocate_new_port!(); + + /// Override + /// Number of addresses concurrently dialed for a single outbound connection attempt. + pub fn override_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self { + self.dial_concurrency_factor_override = Some(factor); + self + } + + /// Build the final [`DialOpts`]. + pub fn build(self) -> DialOpts { + DialOpts { + peer_id: Some(self.peer_id), + condition: self.condition, + addresses: self.addresses, + extend_addresses_through_behaviour: self.extend_addresses_through_behaviour, + role_override: self.role_override, + dial_concurrency_factor_override: self.dial_concurrency_factor_override, + connection_id: ConnectionId::next(), + port_use: self.port_use, + } + } +} + +#[derive(Debug)] +pub struct WithoutPeerId {} + +impl WithoutPeerId { + /// Specify a single address to dial the unknown peer. + pub fn address(self, address: Multiaddr) -> WithoutPeerIdWithAddress { + WithoutPeerIdWithAddress { + address, + role_override: Endpoint::Dialer, + port_use: PortUse::Reuse, + } + } +} + +#[derive(Debug)] +pub struct WithoutPeerIdWithAddress { + address: Multiaddr, + role_override: Endpoint, + port_use: PortUse, +} + +impl WithoutPeerIdWithAddress { + fn_override_role!(); + fn_allocate_new_port!(); + + /// Build the final [`DialOpts`]. + pub fn build(self) -> DialOpts { + DialOpts { + peer_id: None, + condition: PeerCondition::Always, + addresses: vec![self.address], + extend_addresses_through_behaviour: false, + role_override: self.role_override, + dial_concurrency_factor_override: None, + connection_id: ConnectionId::next(), + port_use: self.port_use, + } + } +} + +/// The available conditions under which a new dialing attempt to +/// a known peer is initiated. +/// +/// ``` +/// # use libp2p_swarm::dial_opts::{DialOpts, PeerCondition}; +/// # use libp2p_identity::PeerId; +/// # +/// DialOpts::peer_id(PeerId::random()) +/// .condition(PeerCondition::Disconnected) +/// .build(); +/// ``` +#[derive(Debug, Copy, Clone, Default)] +pub enum PeerCondition { + /// A new dialing attempt is initiated _only if_ the peer is currently + /// considered disconnected, i.e. there is no established connection. + Disconnected, + /// A new dialing attempt is initiated _only if_ there is currently + /// no ongoing dialing attempt, i.e. the peer is either considered + /// disconnected or connected but without an ongoing dialing attempt. + NotDialing, + /// A combination of [`Disconnected`](PeerCondition::Disconnected) and + /// [`NotDialing`](PeerCondition::NotDialing). A new dialing attempt is + /// iniated _only if_ the peer is both considered disconnected and there + /// is currently no ongoing dialing attempt. + #[default] + DisconnectedAndNotDialing, + /// A new dialing attempt is always initiated, only subject to the + /// configured connection limits. + Always, +} diff --git a/third-party/libp2p-swarm-0.45.1/src/dummy.rs b/third-party/libp2p-swarm-0.45.1/src/dummy.rs new file mode 100644 index 00000000000..6e1b4d56eb9 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/dummy.rs @@ -0,0 +1,120 @@ +use crate::behaviour::{FromSwarm, NetworkBehaviour, ToSwarm}; +use crate::connection::ConnectionId; +use crate::handler::{ + ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, +}; +use crate::{ + ConnectionDenied, ConnectionHandlerEvent, StreamUpgradeError, SubstreamProtocol, THandler, + THandlerInEvent, THandlerOutEvent, +}; +use libp2p_core::transport::PortUse; +use libp2p_core::upgrade::DeniedUpgrade; +use libp2p_core::Endpoint; +use libp2p_core::Multiaddr; +use libp2p_identity::PeerId; +use std::task::{Context, Poll}; +use void::Void; + +/// Implementation of [`NetworkBehaviour`] that doesn't do anything. +pub struct Behaviour; + +impl NetworkBehaviour for Behaviour { + type ConnectionHandler = ConnectionHandler; + type ToSwarm = Void; + + fn handle_established_inbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result, ConnectionDenied> { + Ok(ConnectionHandler) + } + + fn handle_established_outbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: Endpoint, + _: PortUse, + ) -> Result, ConnectionDenied> { + Ok(ConnectionHandler) + } + + fn on_connection_handler_event( + &mut self, + _: PeerId, + _: ConnectionId, + event: THandlerOutEvent, + ) { + void::unreachable(event) + } + + fn poll(&mut self, _: &mut Context<'_>) -> Poll>> { + Poll::Pending + } + + fn on_swarm_event(&mut self, _event: FromSwarm) {} +} + +/// An implementation of [`ConnectionHandler`] that neither handles any protocols nor does it keep the connection alive. +#[derive(Clone)] +pub struct ConnectionHandler; + +impl crate::handler::ConnectionHandler for ConnectionHandler { + type FromBehaviour = Void; + type ToBehaviour = Void; + type InboundProtocol = DeniedUpgrade; + type OutboundProtocol = DeniedUpgrade; + type InboundOpenInfo = (); + type OutboundOpenInfo = Void; + + fn listen_protocol(&self) -> SubstreamProtocol { + SubstreamProtocol::new(DeniedUpgrade, ()) + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + void::unreachable(event) + } + + fn poll( + &mut self, + _: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + Poll::Pending + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { + protocol, .. + }) => void::unreachable(protocol), + ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { + protocol, .. + }) => void::unreachable(protocol), + ConnectionEvent::DialUpgradeError(DialUpgradeError { info: _, error }) => match error { + StreamUpgradeError::Timeout => unreachable!(), + StreamUpgradeError::Apply(e) => void::unreachable(e), + StreamUpgradeError::NegotiationFailed | StreamUpgradeError::Io(_) => { + unreachable!("Denied upgrade does not support any protocols") + } + }, + ConnectionEvent::AddressChange(_) + | ConnectionEvent::ListenUpgradeError(_) + | ConnectionEvent::LocalProtocolsChange(_) + | ConnectionEvent::RemoteProtocolsChange(_) => {} + } + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/executor.rs b/third-party/libp2p-swarm-0.45.1/src/executor.rs new file mode 100644 index 00000000000..a2abbbde6ef --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/executor.rs @@ -0,0 +1,70 @@ +//! Provides executors for spawning background tasks. +use futures::executor::ThreadPool; +use std::{future::Future, pin::Pin}; + +/// Implemented on objects that can run a `Future` in the background. +/// +/// > **Note**: While it may be tempting to implement this trait on types such as +/// > [`futures::stream::FuturesUnordered`], please note that passing an `Executor` is +/// > optional, and that `FuturesUnordered` (or a similar struct) will automatically +/// > be used as fallback by libp2p. The `Executor` trait should therefore only be +/// > about running `Future`s on a separate task. +pub trait Executor { + /// Run the given future in the background until it ends. + #[track_caller] + fn exec(&self, future: Pin + Send>>); +} + +impl + Send>>)> Executor for F { + fn exec(&self, f: Pin + Send>>) { + self(f) + } +} + +impl Executor for ThreadPool { + fn exec(&self, future: Pin + Send>>) { + self.spawn_ok(future) + } +} + +#[cfg(all( + feature = "tokio", + not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) +))] +#[derive(Default, Debug, Clone, Copy)] +pub(crate) struct TokioExecutor; +#[cfg(all( + feature = "tokio", + not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) +))] +impl Executor for TokioExecutor { + fn exec(&self, future: Pin + Send>>) { + tokio::spawn(future); + } +} + +#[cfg(all( + feature = "async-std", + not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) +))] +#[derive(Default, Debug, Clone, Copy)] +pub(crate) struct AsyncStdExecutor; +#[cfg(all( + feature = "async-std", + not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) +))] +impl Executor for AsyncStdExecutor { + fn exec(&self, future: Pin + Send>>) { + async_std::task::spawn(future); + } +} + +#[cfg(feature = "wasm-bindgen")] +#[derive(Default, Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub(crate) struct WasmBindgenExecutor; +#[cfg(feature = "wasm-bindgen")] +impl Executor for WasmBindgenExecutor { + fn exec(&self, future: Pin + Send>>) { + wasm_bindgen_futures::spawn_local(future) + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler.rs b/third-party/libp2p-swarm-0.45.1/src/handler.rs new file mode 100644 index 00000000000..610b95b8cf1 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/handler.rs @@ -0,0 +1,896 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +//! Once a connection to a remote peer is established, a [`ConnectionHandler`] negotiates +//! and handles one or more specific protocols on the connection. +//! +//! Protocols are negotiated and used on individual substreams of the connection. Thus a +//! [`ConnectionHandler`] defines the inbound and outbound upgrades to apply when creating a new +//! inbound or outbound substream, respectively, and is notified by a [`Swarm`](crate::Swarm) when +//! these upgrades have been successfully applied, including the final output of the upgrade. A +//! [`ConnectionHandler`] can then continue communicating with the peer over the substream using the +//! negotiated protocol(s). +//! +//! Two [`ConnectionHandler`]s can be composed with [`ConnectionHandler::select()`] +//! in order to build a new handler supporting the combined set of protocols, +//! with methods being dispatched to the appropriate handler according to the +//! used protocol(s) determined by the associated types of the handlers. +//! +//! > **Note**: A [`ConnectionHandler`] handles one or more protocols in the context of a single +//! > connection with a remote. In order to handle a protocol that requires knowledge of +//! > the network as a whole, see the +//! > [`NetworkBehaviour`](crate::behaviour::NetworkBehaviour) trait. + +pub mod either; +mod map_in; +mod map_out; +pub mod multi; +mod one_shot; +mod pending; +mod select; + +use crate::connection::AsStrHashEq; +pub use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, SendWrapper, UpgradeInfoSend}; +pub use map_in::MapInEvent; +pub use map_out::MapOutEvent; +pub use one_shot::{OneShotHandler, OneShotHandlerConfig}; +pub use pending::PendingConnectionHandler; +pub use select::ConnectionHandlerSelect; +use smallvec::SmallVec; + +use crate::StreamProtocol; +use core::slice; +use libp2p_core::Multiaddr; +use std::collections::{HashMap, HashSet}; +use std::{error, fmt, io, task::Context, task::Poll, time::Duration}; + +/// A handler for a set of protocols used on a connection with a remote. +/// +/// This trait should be implemented for a type that maintains the state for +/// the execution of a specific protocol with a remote. +/// +/// # Handling a protocol +/// +/// Communication with a remote over a set of protocols is initiated in one of two ways: +/// +/// 1. Dialing by initiating a new outbound substream. In order to do so, +/// [`ConnectionHandler::poll()`] must return an [`ConnectionHandlerEvent::OutboundSubstreamRequest`], +/// providing an instance of [`libp2p_core::upgrade::OutboundUpgrade`] that is used to negotiate the +/// protocol(s). Upon success, [`ConnectionHandler::on_connection_event`] is called with +/// [`ConnectionEvent::FullyNegotiatedOutbound`] translating the final output of the upgrade. +/// +/// 2. Listening by accepting a new inbound substream. When a new inbound substream +/// is created on a connection, [`ConnectionHandler::listen_protocol`] is called +/// to obtain an instance of [`libp2p_core::upgrade::InboundUpgrade`] that is used to +/// negotiate the protocol(s). Upon success, +/// [`ConnectionHandler::on_connection_event`] is called with [`ConnectionEvent::FullyNegotiatedInbound`] +/// translating the final output of the upgrade. +/// +/// +/// # Connection Keep-Alive +/// +/// A [`ConnectionHandler`] can influence the lifetime of the underlying connection +/// through [`ConnectionHandler::connection_keep_alive`]. That is, the protocol +/// implemented by the handler can include conditions for terminating the connection. +/// The lifetime of successfully negotiated substreams is fully controlled by the handler. +/// +/// Implementors of this trait should keep in mind that the connection can be closed at any time. +/// When a connection is closed gracefully, the substreams used by the handler may still +/// continue reading data until the remote closes its side of the connection. +pub trait ConnectionHandler: Send + 'static { + /// A type representing the message(s) a [`NetworkBehaviour`](crate::behaviour::NetworkBehaviour) can send to a [`ConnectionHandler`] via [`ToSwarm::NotifyHandler`](crate::behaviour::ToSwarm::NotifyHandler) + type FromBehaviour: fmt::Debug + Send + 'static; + /// A type representing message(s) a [`ConnectionHandler`] can send to a [`NetworkBehaviour`](crate::behaviour::NetworkBehaviour) via [`ConnectionHandlerEvent::NotifyBehaviour`]. + type ToBehaviour: fmt::Debug + Send + 'static; + /// The inbound upgrade for the protocol(s) used by the handler. + type InboundProtocol: InboundUpgradeSend; + /// The outbound upgrade for the protocol(s) used by the handler. + type OutboundProtocol: OutboundUpgradeSend; + /// The type of additional information returned from `listen_protocol`. + type InboundOpenInfo: Send + 'static; + /// The type of additional information passed to an `OutboundSubstreamRequest`. + type OutboundOpenInfo: Send + 'static; + + /// The [`InboundUpgrade`](libp2p_core::upgrade::InboundUpgrade) to apply on inbound + /// substreams to negotiate the desired protocols. + /// + /// > **Note**: The returned `InboundUpgrade` should always accept all the generally + /// > supported protocols, even if in a specific context a particular one is + /// > not supported, (eg. when only allowing one substream at a time for a protocol). + /// > This allows a remote to put the list of supported protocols in a cache. + fn listen_protocol(&self) -> SubstreamProtocol; + + /// Returns whether the connection should be kept alive. + /// + /// ## Keep alive algorithm + /// + /// A connection is always kept alive: + /// + /// - Whilst a [`ConnectionHandler`] returns [`Poll::Ready`]. + /// - We are negotiating inbound or outbound streams. + /// - There are active [`Stream`](crate::Stream)s on the connection. + /// + /// The combination of the above means that _most_ protocols will not need to override this method. + /// This method is only invoked when all of the above are `false`, i.e. when the connection is entirely idle. + /// + /// ## Exceptions + /// + /// - Protocols like [circuit-relay v2](https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md) need to keep a connection alive beyond these circumstances and can thus override this method. + /// - Protocols like [ping](https://github.com/libp2p/specs/blob/master/ping/ping.md) **don't** want to keep a connection alive despite an active streams. + /// + /// In that case, protocol authors can use [`Stream::ignore_for_keep_alive`](crate::Stream::ignore_for_keep_alive) to opt-out a particular stream from the keep-alive algorithm. + fn connection_keep_alive(&self) -> bool { + false + } + + /// Should behave like `Stream::poll()`. + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + >; + + /// Gracefully close the [`ConnectionHandler`]. + /// + /// The contract for this function is equivalent to a [`Stream`](futures::Stream). + /// When a connection is being shut down, we will first poll this function to completion. + /// Following that, the physical connection will be shut down. + /// + /// This is also called when the shutdown was initiated due to an error on the connection. + /// We therefore cannot guarantee that performing IO within here will succeed. + /// + /// To signal completion, [`Poll::Ready(None)`] should be returned. + /// + /// Implementations MUST have a [`fuse`](futures::StreamExt::fuse)-like behaviour. + /// That is, [`Poll::Ready(None)`] MUST be returned on repeated calls to [`ConnectionHandler::poll_close`]. + fn poll_close(&mut self, _: &mut Context<'_>) -> Poll> { + Poll::Ready(None) + } + + /// Adds a closure that turns the input event into something else. + fn map_in_event(self, map: TMap) -> MapInEvent + where + Self: Sized, + TMap: Fn(&TNewIn) -> Option<&Self::FromBehaviour>, + { + MapInEvent::new(self, map) + } + + /// Adds a closure that turns the output event into something else. + fn map_out_event(self, map: TMap) -> MapOutEvent + where + Self: Sized, + TMap: FnMut(Self::ToBehaviour) -> TNewOut, + { + MapOutEvent::new(self, map) + } + + /// Creates a new [`ConnectionHandler`] that selects either this handler or + /// `other` by delegating methods calls appropriately. + fn select(self, other: TProto2) -> ConnectionHandlerSelect + where + Self: Sized, + { + ConnectionHandlerSelect::new(self, other) + } + + /// Informs the handler about an event from the [`NetworkBehaviour`](super::NetworkBehaviour). + fn on_behaviour_event(&mut self, _event: Self::FromBehaviour); + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ); +} + +/// Enumeration with the list of the possible stream events +/// to pass to [`on_connection_event`](ConnectionHandler::on_connection_event). +#[non_exhaustive] +pub enum ConnectionEvent<'a, IP: InboundUpgradeSend, OP: OutboundUpgradeSend, IOI, OOI> { + /// Informs the handler about the output of a successful upgrade on a new inbound substream. + FullyNegotiatedInbound(FullyNegotiatedInbound), + /// Informs the handler about the output of a successful upgrade on a new outbound stream. + FullyNegotiatedOutbound(FullyNegotiatedOutbound), + /// Informs the handler about a change in the address of the remote. + AddressChange(AddressChange<'a>), + /// Informs the handler that upgrading an outbound substream to the given protocol has failed. + DialUpgradeError(DialUpgradeError), + /// Informs the handler that upgrading an inbound substream to the given protocol has failed. + ListenUpgradeError(ListenUpgradeError), + /// The local [`ConnectionHandler`] added or removed support for one or more protocols. + LocalProtocolsChange(ProtocolsChange<'a>), + /// The remote [`ConnectionHandler`] now supports a different set of protocols. + RemoteProtocolsChange(ProtocolsChange<'a>), +} + +impl<'a, IP, OP, IOI, OOI> fmt::Debug for ConnectionEvent<'a, IP, OP, IOI, OOI> +where + IP: InboundUpgradeSend + fmt::Debug, + IP::Output: fmt::Debug, + IP::Error: fmt::Debug, + OP: OutboundUpgradeSend + fmt::Debug, + OP::Output: fmt::Debug, + OP::Error: fmt::Debug, + IOI: fmt::Debug, + OOI: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ConnectionEvent::FullyNegotiatedInbound(v) => { + f.debug_tuple("FullyNegotiatedInbound").field(v).finish() + } + ConnectionEvent::FullyNegotiatedOutbound(v) => { + f.debug_tuple("FullyNegotiatedOutbound").field(v).finish() + } + ConnectionEvent::AddressChange(v) => f.debug_tuple("AddressChange").field(v).finish(), + ConnectionEvent::DialUpgradeError(v) => { + f.debug_tuple("DialUpgradeError").field(v).finish() + } + ConnectionEvent::ListenUpgradeError(v) => { + f.debug_tuple("ListenUpgradeError").field(v).finish() + } + ConnectionEvent::LocalProtocolsChange(v) => { + f.debug_tuple("LocalProtocolsChange").field(v).finish() + } + ConnectionEvent::RemoteProtocolsChange(v) => { + f.debug_tuple("RemoteProtocolsChange").field(v).finish() + } + } + } +} + +impl<'a, IP: InboundUpgradeSend, OP: OutboundUpgradeSend, IOI, OOI> + ConnectionEvent<'a, IP, OP, IOI, OOI> +{ + /// Whether the event concerns an outbound stream. + pub fn is_outbound(&self) -> bool { + match self { + ConnectionEvent::DialUpgradeError(_) | ConnectionEvent::FullyNegotiatedOutbound(_) => { + true + } + ConnectionEvent::FullyNegotiatedInbound(_) + | ConnectionEvent::AddressChange(_) + | ConnectionEvent::LocalProtocolsChange(_) + | ConnectionEvent::RemoteProtocolsChange(_) + | ConnectionEvent::ListenUpgradeError(_) => false, + } + } + + /// Whether the event concerns an inbound stream. + pub fn is_inbound(&self) -> bool { + match self { + ConnectionEvent::FullyNegotiatedInbound(_) | ConnectionEvent::ListenUpgradeError(_) => { + true + } + ConnectionEvent::FullyNegotiatedOutbound(_) + | ConnectionEvent::AddressChange(_) + | ConnectionEvent::LocalProtocolsChange(_) + | ConnectionEvent::RemoteProtocolsChange(_) + | ConnectionEvent::DialUpgradeError(_) => false, + } + } +} + +/// [`ConnectionEvent`] variant that informs the handler about +/// the output of a successful upgrade on a new inbound substream. +/// +/// Note that it is up to the [`ConnectionHandler`] implementation to manage the lifetime of the +/// negotiated inbound substreams. E.g. the implementation has to enforce a limit on the number +/// of simultaneously open negotiated inbound substreams. In other words it is up to the +/// [`ConnectionHandler`] implementation to stop a malicious remote node to open and keep alive +/// an excessive amount of inbound substreams. +#[derive(Debug)] +pub struct FullyNegotiatedInbound { + pub protocol: IP::Output, + pub info: IOI, +} + +/// [`ConnectionEvent`] variant that informs the handler about successful upgrade on a new outbound stream. +/// +/// The `protocol` field is the information that was previously passed to +/// [`ConnectionHandlerEvent::OutboundSubstreamRequest`]. +#[derive(Debug)] +pub struct FullyNegotiatedOutbound { + pub protocol: OP::Output, + pub info: OOI, +} + +/// [`ConnectionEvent`] variant that informs the handler about a change in the address of the remote. +#[derive(Debug)] +pub struct AddressChange<'a> { + pub new_address: &'a Multiaddr, +} + +/// [`ConnectionEvent`] variant that informs the handler about a change in the protocols supported on the connection. +#[derive(Debug, Clone)] +pub enum ProtocolsChange<'a> { + Added(ProtocolsAdded<'a>), + Removed(ProtocolsRemoved<'a>), +} + +impl<'a> ProtocolsChange<'a> { + /// Compute the protocol change for the initial set of protocols. + pub(crate) fn from_initial_protocols<'b, T: AsRef + 'b>( + new_protocols: impl IntoIterator, + buffer: &'a mut Vec, + ) -> Self { + buffer.clear(); + buffer.extend( + new_protocols + .into_iter() + .filter_map(|i| StreamProtocol::try_from_owned(i.as_ref().to_owned()).ok()), + ); + + ProtocolsChange::Added(ProtocolsAdded { + protocols: buffer.iter(), + }) + } + + /// Compute the [`ProtocolsChange`] that results from adding `to_add` to `existing_protocols`. + /// + /// Returns `None` if the change is a no-op, i.e. `to_add` is a subset of `existing_protocols`. + pub(crate) fn add( + existing_protocols: &HashSet, + to_add: HashSet, + buffer: &'a mut Vec, + ) -> Option { + buffer.clear(); + buffer.extend( + to_add + .into_iter() + .filter(|i| !existing_protocols.contains(i)), + ); + + if buffer.is_empty() { + return None; + } + + Some(Self::Added(ProtocolsAdded { + protocols: buffer.iter(), + })) + } + + /// Compute the [`ProtocolsChange`] that results from removing `to_remove` from `existing_protocols`. Removes the protocols from `existing_protocols`. + /// + /// Returns `None` if the change is a no-op, i.e. none of the protocols in `to_remove` are in `existing_protocols`. + pub(crate) fn remove( + existing_protocols: &mut HashSet, + to_remove: HashSet, + buffer: &'a mut Vec, + ) -> Option { + buffer.clear(); + buffer.extend( + to_remove + .into_iter() + .filter_map(|i| existing_protocols.take(&i)), + ); + + if buffer.is_empty() { + return None; + } + + Some(Self::Removed(ProtocolsRemoved { + protocols: buffer.iter(), + })) + } + + /// Compute the [`ProtocolsChange`]s required to go from `existing_protocols` to `new_protocols`. + pub(crate) fn from_full_sets>( + existing_protocols: &mut HashMap, bool>, + new_protocols: impl IntoIterator, + buffer: &'a mut Vec, + ) -> SmallVec<[Self; 2]> { + buffer.clear(); + + // Initially, set the boolean for all protocols to `false`, meaning "not visited". + for v in existing_protocols.values_mut() { + *v = false; + } + + let mut new_protocol_count = 0; // We can only iterate `new_protocols` once, so keep track of its length separately. + for new_protocol in new_protocols { + existing_protocols + .entry(AsStrHashEq(new_protocol)) + .and_modify(|v| *v = true) // Mark protocol as visited (i.e. we still support it) + .or_insert_with_key(|k| { + // Encountered a previously unsupported protocol, remember it in `buffer`. + buffer.extend(StreamProtocol::try_from_owned(k.0.as_ref().to_owned()).ok()); + true + }); + new_protocol_count += 1; + } + + if new_protocol_count == existing_protocols.len() && buffer.is_empty() { + return SmallVec::new(); + } + + let num_new_protocols = buffer.len(); + // Drain all protocols that we haven't visited. + // For existing protocols that are not in `new_protocols`, the boolean will be false, meaning we need to remove it. + existing_protocols.retain(|p, &mut is_supported| { + if !is_supported { + buffer.extend(StreamProtocol::try_from_owned(p.0.as_ref().to_owned()).ok()); + } + + is_supported + }); + + let (added, removed) = buffer.split_at(num_new_protocols); + let mut changes = SmallVec::new(); + if !added.is_empty() { + changes.push(ProtocolsChange::Added(ProtocolsAdded { + protocols: added.iter(), + })); + } + if !removed.is_empty() { + changes.push(ProtocolsChange::Removed(ProtocolsRemoved { + protocols: removed.iter(), + })); + } + changes + } +} + +/// An [`Iterator`] over all protocols that have been added. +#[derive(Debug, Clone)] +pub struct ProtocolsAdded<'a> { + pub(crate) protocols: slice::Iter<'a, StreamProtocol>, +} + +/// An [`Iterator`] over all protocols that have been removed. +#[derive(Debug, Clone)] +pub struct ProtocolsRemoved<'a> { + pub(crate) protocols: slice::Iter<'a, StreamProtocol>, +} + +impl<'a> Iterator for ProtocolsAdded<'a> { + type Item = &'a StreamProtocol; + fn next(&mut self) -> Option { + self.protocols.next() + } +} + +impl<'a> Iterator for ProtocolsRemoved<'a> { + type Item = &'a StreamProtocol; + fn next(&mut self) -> Option { + self.protocols.next() + } +} + +/// [`ConnectionEvent`] variant that informs the handler +/// that upgrading an outbound substream to the given protocol has failed. +#[derive(Debug)] +pub struct DialUpgradeError { + pub info: OOI, + pub error: StreamUpgradeError, +} + +/// [`ConnectionEvent`] variant that informs the handler +/// that upgrading an inbound substream to the given protocol has failed. +#[derive(Debug)] +pub struct ListenUpgradeError { + pub info: IOI, + pub error: IP::Error, +} + +/// Configuration of inbound or outbound substream protocol(s) +/// for a [`ConnectionHandler`]. +/// +/// The inbound substream protocol(s) are defined by [`ConnectionHandler::listen_protocol`] +/// and the outbound substream protocol(s) by [`ConnectionHandlerEvent::OutboundSubstreamRequest`]. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct SubstreamProtocol { + upgrade: TUpgrade, + info: TInfo, + timeout: Duration, +} + +impl SubstreamProtocol { + /// Create a new `SubstreamProtocol` from the given upgrade. + /// + /// The default timeout for applying the given upgrade on a substream is + /// 10 seconds. + pub fn new(upgrade: TUpgrade, info: TInfo) -> Self { + SubstreamProtocol { + upgrade, + info, + timeout: Duration::from_secs(10), + } + } + + /// Maps a function over the protocol upgrade. + pub fn map_upgrade(self, f: F) -> SubstreamProtocol + where + F: FnOnce(TUpgrade) -> U, + { + SubstreamProtocol { + upgrade: f(self.upgrade), + info: self.info, + timeout: self.timeout, + } + } + + /// Maps a function over the protocol info. + pub fn map_info(self, f: F) -> SubstreamProtocol + where + F: FnOnce(TInfo) -> U, + { + SubstreamProtocol { + upgrade: self.upgrade, + info: f(self.info), + timeout: self.timeout, + } + } + + /// Sets a new timeout for the protocol upgrade. + pub fn with_timeout(mut self, timeout: Duration) -> Self { + self.timeout = timeout; + self + } + + /// Borrows the contained protocol upgrade. + pub fn upgrade(&self) -> &TUpgrade { + &self.upgrade + } + + /// Borrows the contained protocol info. + pub fn info(&self) -> &TInfo { + &self.info + } + + /// Borrows the timeout for the protocol upgrade. + pub fn timeout(&self) -> &Duration { + &self.timeout + } + + /// Converts the substream protocol configuration into the contained upgrade. + pub fn into_upgrade(self) -> (TUpgrade, TInfo) { + (self.upgrade, self.info) + } +} + +/// Event produced by a handler. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum ConnectionHandlerEvent { + /// Request a new outbound substream to be opened with the remote. + OutboundSubstreamRequest { + /// The protocol(s) to apply on the substream. + protocol: SubstreamProtocol, + }, + /// We learned something about the protocols supported by the remote. + ReportRemoteProtocols(ProtocolSupport), + + /// Event that is sent to a [`NetworkBehaviour`](crate::behaviour::NetworkBehaviour). + NotifyBehaviour(TCustom), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ProtocolSupport { + /// The remote now supports these additional protocols. + Added(HashSet), + /// The remote no longer supports these protocols. + Removed(HashSet), +} + +/// Event produced by a handler. +impl + ConnectionHandlerEvent +{ + /// If this is an `OutboundSubstreamRequest`, maps the `info` member from a + /// `TOutboundOpenInfo` to something else. + pub fn map_outbound_open_info( + self, + map: F, + ) -> ConnectionHandlerEvent + where + F: FnOnce(TOutboundOpenInfo) -> I, + { + match self { + ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } => { + ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: protocol.map_info(map), + } + } + ConnectionHandlerEvent::NotifyBehaviour(val) => { + ConnectionHandlerEvent::NotifyBehaviour(val) + } + ConnectionHandlerEvent::ReportRemoteProtocols(support) => { + ConnectionHandlerEvent::ReportRemoteProtocols(support) + } + } + } + + /// If this is an `OutboundSubstreamRequest`, maps the protocol (`TConnectionUpgrade`) + /// to something else. + pub fn map_protocol(self, map: F) -> ConnectionHandlerEvent + where + F: FnOnce(TConnectionUpgrade) -> I, + { + match self { + ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } => { + ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: protocol.map_upgrade(map), + } + } + ConnectionHandlerEvent::NotifyBehaviour(val) => { + ConnectionHandlerEvent::NotifyBehaviour(val) + } + ConnectionHandlerEvent::ReportRemoteProtocols(support) => { + ConnectionHandlerEvent::ReportRemoteProtocols(support) + } + } + } + + /// If this is a `Custom` event, maps the content to something else. + pub fn map_custom( + self, + map: F, + ) -> ConnectionHandlerEvent + where + F: FnOnce(TCustom) -> I, + { + match self { + ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } => { + ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } + } + ConnectionHandlerEvent::NotifyBehaviour(val) => { + ConnectionHandlerEvent::NotifyBehaviour(map(val)) + } + ConnectionHandlerEvent::ReportRemoteProtocols(support) => { + ConnectionHandlerEvent::ReportRemoteProtocols(support) + } + } + } +} + +/// Error that can happen on an outbound substream opening attempt. +#[derive(Debug)] +pub enum StreamUpgradeError { + /// The opening attempt timed out before the negotiation was fully completed. + Timeout, + /// The upgrade produced an error. + Apply(TUpgrErr), + /// No protocol could be agreed upon. + NegotiationFailed, + /// An IO or otherwise unrecoverable error happened. + Io(io::Error), +} + +impl StreamUpgradeError { + /// Map the inner [`StreamUpgradeError`] type. + pub fn map_upgrade_err(self, f: F) -> StreamUpgradeError + where + F: FnOnce(TUpgrErr) -> E, + { + match self { + StreamUpgradeError::Timeout => StreamUpgradeError::Timeout, + StreamUpgradeError::Apply(e) => StreamUpgradeError::Apply(f(e)), + StreamUpgradeError::NegotiationFailed => StreamUpgradeError::NegotiationFailed, + StreamUpgradeError::Io(e) => StreamUpgradeError::Io(e), + } + } +} + +impl fmt::Display for StreamUpgradeError +where + TUpgrErr: error::Error + 'static, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + StreamUpgradeError::Timeout => { + write!(f, "Timeout error while opening a substream") + } + StreamUpgradeError::Apply(err) => { + write!(f, "Apply: ")?; + crate::print_error_chain(f, err) + } + StreamUpgradeError::NegotiationFailed => { + write!(f, "no protocols could be agreed upon") + } + StreamUpgradeError::Io(e) => { + write!(f, "IO error: ")?; + crate::print_error_chain(f, e) + } + } + } +} + +impl error::Error for StreamUpgradeError +where + TUpgrErr: error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + None + } +} + +#[cfg(test)] +mod test { + use super::*; + + fn protocol_set_of(s: &'static str) -> HashSet { + s.split_whitespace() + .map(|p| StreamProtocol::try_from_owned(format!("/{p}")).unwrap()) + .collect() + } + + fn test_remove( + existing: &mut HashSet, + to_remove: HashSet, + ) -> HashSet { + ProtocolsChange::remove(existing, to_remove, &mut Vec::new()) + .into_iter() + .flat_map(|c| match c { + ProtocolsChange::Added(_) => panic!("unexpected added"), + ProtocolsChange::Removed(r) => r.cloned(), + }) + .collect::>() + } + + #[test] + fn test_protocol_remove_subset() { + let mut existing = protocol_set_of("a b c"); + let to_remove = protocol_set_of("a b"); + + let change = test_remove(&mut existing, to_remove); + + assert_eq!(existing, protocol_set_of("c")); + assert_eq!(change, protocol_set_of("a b")); + } + + #[test] + fn test_protocol_remove_all() { + let mut existing = protocol_set_of("a b c"); + let to_remove = protocol_set_of("a b c"); + + let change = test_remove(&mut existing, to_remove); + + assert_eq!(existing, protocol_set_of("")); + assert_eq!(change, protocol_set_of("a b c")); + } + + #[test] + fn test_protocol_remove_superset() { + let mut existing = protocol_set_of("a b c"); + let to_remove = protocol_set_of("a b c d"); + + let change = test_remove(&mut existing, to_remove); + + assert_eq!(existing, protocol_set_of("")); + assert_eq!(change, protocol_set_of("a b c")); + } + + #[test] + fn test_protocol_remove_none() { + let mut existing = protocol_set_of("a b c"); + let to_remove = protocol_set_of("d"); + + let change = test_remove(&mut existing, to_remove); + + assert_eq!(existing, protocol_set_of("a b c")); + assert_eq!(change, protocol_set_of("")); + } + + #[test] + fn test_protocol_remove_none_from_empty() { + let mut existing = protocol_set_of(""); + let to_remove = protocol_set_of("d"); + + let change = test_remove(&mut existing, to_remove); + + assert_eq!(existing, protocol_set_of("")); + assert_eq!(change, protocol_set_of("")); + } + + fn test_from_full_sets( + existing: HashSet, + new: HashSet, + ) -> [HashSet; 2] { + let mut buffer = Vec::new(); + let mut existing = existing + .iter() + .map(|p| (AsStrHashEq(p.as_ref()), true)) + .collect::>(); + + let changes = ProtocolsChange::from_full_sets( + &mut existing, + new.iter().map(AsRef::as_ref), + &mut buffer, + ); + + let mut added_changes = HashSet::new(); + let mut removed_changes = HashSet::new(); + + for change in changes { + match change { + ProtocolsChange::Added(a) => { + added_changes.extend(a.cloned()); + } + ProtocolsChange::Removed(r) => { + removed_changes.extend(r.cloned()); + } + } + } + + [removed_changes, added_changes] + } + + #[test] + fn test_from_full_stes_subset() { + let existing = protocol_set_of("a b c"); + let new = protocol_set_of("a b"); + + let [removed_changes, added_changes] = test_from_full_sets(existing, new); + + assert_eq!(added_changes, protocol_set_of("")); + assert_eq!(removed_changes, protocol_set_of("c")); + } + + #[test] + fn test_from_full_sets_superset() { + let existing = protocol_set_of("a b"); + let new = protocol_set_of("a b c"); + + let [removed_changes, added_changes] = test_from_full_sets(existing, new); + + assert_eq!(added_changes, protocol_set_of("c")); + assert_eq!(removed_changes, protocol_set_of("")); + } + + #[test] + fn test_from_full_sets_intersection() { + let existing = protocol_set_of("a b c"); + let new = protocol_set_of("b c d"); + + let [removed_changes, added_changes] = test_from_full_sets(existing, new); + + assert_eq!(added_changes, protocol_set_of("d")); + assert_eq!(removed_changes, protocol_set_of("a")); + } + + #[test] + fn test_from_full_sets_disjoint() { + let existing = protocol_set_of("a b c"); + let new = protocol_set_of("d e f"); + + let [removed_changes, added_changes] = test_from_full_sets(existing, new); + + assert_eq!(added_changes, protocol_set_of("d e f")); + assert_eq!(removed_changes, protocol_set_of("a b c")); + } + + #[test] + fn test_from_full_sets_empty() { + let existing = protocol_set_of(""); + let new = protocol_set_of(""); + + let [removed_changes, added_changes] = test_from_full_sets(existing, new); + + assert_eq!(added_changes, protocol_set_of("")); + assert_eq!(removed_changes, protocol_set_of("")); + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/either.rs b/third-party/libp2p-swarm-0.45.1/src/handler/either.rs new file mode 100644 index 00000000000..a5aab9b5fee --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/handler/either.rs @@ -0,0 +1,230 @@ +// Copyright 2021 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::handler::{ + ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, FullyNegotiatedInbound, + InboundUpgradeSend, ListenUpgradeError, SubstreamProtocol, +}; +use crate::upgrade::SendWrapper; +use either::Either; +use futures::future; +use std::task::{Context, Poll}; + +impl + FullyNegotiatedInbound, SendWrapper>, Either> +where + RIP: InboundUpgradeSend, + LIP: InboundUpgradeSend, +{ + pub(crate) fn transpose( + self, + ) -> Either, FullyNegotiatedInbound> { + match self { + FullyNegotiatedInbound { + protocol: future::Either::Left(protocol), + info: Either::Left(info), + } => Either::Left(FullyNegotiatedInbound { protocol, info }), + FullyNegotiatedInbound { + protocol: future::Either::Right(protocol), + info: Either::Right(info), + } => Either::Right(FullyNegotiatedInbound { protocol, info }), + _ => unreachable!(), + } + } +} + +impl + ListenUpgradeError, Either, SendWrapper>> +where + RIP: InboundUpgradeSend, + LIP: InboundUpgradeSend, +{ + fn transpose(self) -> Either, ListenUpgradeError> { + match self { + ListenUpgradeError { + error: Either::Left(error), + info: Either::Left(info), + } => Either::Left(ListenUpgradeError { error, info }), + ListenUpgradeError { + error: Either::Right(error), + info: Either::Right(info), + } => Either::Right(ListenUpgradeError { error, info }), + _ => unreachable!(), + } + } +} + +/// Implementation of a [`ConnectionHandler`] that represents either of two [`ConnectionHandler`] +/// implementations. +impl ConnectionHandler for Either +where + L: ConnectionHandler, + R: ConnectionHandler, +{ + type FromBehaviour = Either; + type ToBehaviour = Either; + type InboundProtocol = Either, SendWrapper>; + type OutboundProtocol = + Either, SendWrapper>; + type InboundOpenInfo = Either; + type OutboundOpenInfo = Either; + + fn listen_protocol(&self) -> SubstreamProtocol { + match self { + Either::Left(a) => a + .listen_protocol() + .map_upgrade(|u| Either::Left(SendWrapper(u))) + .map_info(Either::Left), + Either::Right(b) => b + .listen_protocol() + .map_upgrade(|u| Either::Right(SendWrapper(u))) + .map_info(Either::Right), + } + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + match (self, event) { + (Either::Left(handler), Either::Left(event)) => handler.on_behaviour_event(event), + (Either::Right(handler), Either::Right(event)) => handler.on_behaviour_event(event), + _ => unreachable!(), + } + } + + fn connection_keep_alive(&self) -> bool { + match self { + Either::Left(handler) => handler.connection_keep_alive(), + Either::Right(handler) => handler.connection_keep_alive(), + } + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + let event = match self { + Either::Left(handler) => futures::ready!(handler.poll(cx)) + .map_custom(Either::Left) + .map_protocol(|p| Either::Left(SendWrapper(p))) + .map_outbound_open_info(Either::Left), + Either::Right(handler) => futures::ready!(handler.poll(cx)) + .map_custom(Either::Right) + .map_protocol(|p| Either::Right(SendWrapper(p))) + .map_outbound_open_info(Either::Right), + }; + + Poll::Ready(event) + } + + fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { + let event = match self { + Either::Left(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Left), + Either::Right(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Right), + }; + + Poll::Ready(event) + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedInbound(fully_negotiated_inbound) => { + match (fully_negotiated_inbound.transpose(), self) { + (Either::Left(fully_negotiated_inbound), Either::Left(handler)) => handler + .on_connection_event(ConnectionEvent::FullyNegotiatedInbound( + fully_negotiated_inbound, + )), + (Either::Right(fully_negotiated_inbound), Either::Right(handler)) => handler + .on_connection_event(ConnectionEvent::FullyNegotiatedInbound( + fully_negotiated_inbound, + )), + _ => unreachable!(), + } + } + ConnectionEvent::FullyNegotiatedOutbound(fully_negotiated_outbound) => { + match (fully_negotiated_outbound.transpose(), self) { + (Either::Left(fully_negotiated_outbound), Either::Left(handler)) => handler + .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( + fully_negotiated_outbound, + )), + (Either::Right(fully_negotiated_outbound), Either::Right(handler)) => handler + .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( + fully_negotiated_outbound, + )), + _ => unreachable!(), + } + } + ConnectionEvent::DialUpgradeError(dial_upgrade_error) => { + match (dial_upgrade_error.transpose(), self) { + (Either::Left(dial_upgrade_error), Either::Left(handler)) => handler + .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)), + (Either::Right(dial_upgrade_error), Either::Right(handler)) => handler + .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)), + _ => unreachable!(), + } + } + ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => { + match (listen_upgrade_error.transpose(), self) { + (Either::Left(listen_upgrade_error), Either::Left(handler)) => handler + .on_connection_event(ConnectionEvent::ListenUpgradeError( + listen_upgrade_error, + )), + (Either::Right(listen_upgrade_error), Either::Right(handler)) => handler + .on_connection_event(ConnectionEvent::ListenUpgradeError( + listen_upgrade_error, + )), + _ => unreachable!(), + } + } + ConnectionEvent::AddressChange(address_change) => match self { + Either::Left(handler) => { + handler.on_connection_event(ConnectionEvent::AddressChange(address_change)) + } + Either::Right(handler) => { + handler.on_connection_event(ConnectionEvent::AddressChange(address_change)) + } + }, + ConnectionEvent::LocalProtocolsChange(supported_protocols) => match self { + Either::Left(handler) => handler.on_connection_event( + ConnectionEvent::LocalProtocolsChange(supported_protocols), + ), + Either::Right(handler) => handler.on_connection_event( + ConnectionEvent::LocalProtocolsChange(supported_protocols), + ), + }, + ConnectionEvent::RemoteProtocolsChange(supported_protocols) => match self { + Either::Left(handler) => handler.on_connection_event( + ConnectionEvent::RemoteProtocolsChange(supported_protocols), + ), + Either::Right(handler) => handler.on_connection_event( + ConnectionEvent::RemoteProtocolsChange(supported_protocols), + ), + }, + } + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/map_in.rs b/third-party/libp2p-swarm-0.45.1/src/handler/map_in.rs new file mode 100644 index 00000000000..9316ef4d2ce --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/handler/map_in.rs @@ -0,0 +1,98 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::handler::{ + ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, SubstreamProtocol, +}; +use std::{fmt::Debug, marker::PhantomData, task::Context, task::Poll}; + +/// Wrapper around a protocol handler that turns the input event into something else. +#[derive(Debug)] +pub struct MapInEvent { + inner: TConnectionHandler, + map: TMap, + marker: PhantomData, +} + +impl MapInEvent { + /// Creates a `MapInEvent`. + pub(crate) fn new(inner: TConnectionHandler, map: TMap) -> Self { + MapInEvent { + inner, + map, + marker: PhantomData, + } + } +} + +impl ConnectionHandler + for MapInEvent +where + TConnectionHandler: ConnectionHandler, + TMap: Fn(TNewIn) -> Option, + TNewIn: Debug + Send + 'static, + TMap: Send + 'static, +{ + type FromBehaviour = TNewIn; + type ToBehaviour = TConnectionHandler::ToBehaviour; + type InboundProtocol = TConnectionHandler::InboundProtocol; + type OutboundProtocol = TConnectionHandler::OutboundProtocol; + type InboundOpenInfo = TConnectionHandler::InboundOpenInfo; + type OutboundOpenInfo = TConnectionHandler::OutboundOpenInfo; + + fn listen_protocol(&self) -> SubstreamProtocol { + self.inner.listen_protocol() + } + + fn on_behaviour_event(&mut self, event: TNewIn) { + if let Some(event) = (self.map)(event) { + self.inner.on_behaviour_event(event); + } + } + + fn connection_keep_alive(&self) -> bool { + self.inner.connection_keep_alive() + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + self.inner.poll(cx) + } + + fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_close(cx) + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + self.inner.on_connection_event(event); + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/map_out.rs b/third-party/libp2p-swarm-0.45.1/src/handler/map_out.rs new file mode 100644 index 00000000000..f877bfa6f64 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/handler/map_out.rs @@ -0,0 +1,106 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::handler::{ + ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, SubstreamProtocol, +}; +use futures::ready; +use std::fmt::Debug; +use std::task::{Context, Poll}; + +/// Wrapper around a protocol handler that turns the output event into something else. +#[derive(Debug)] +pub struct MapOutEvent { + inner: TConnectionHandler, + map: TMap, +} + +impl MapOutEvent { + /// Creates a `MapOutEvent`. + pub(crate) fn new(inner: TConnectionHandler, map: TMap) -> Self { + MapOutEvent { inner, map } + } +} + +impl ConnectionHandler for MapOutEvent +where + TConnectionHandler: ConnectionHandler, + TMap: FnMut(TConnectionHandler::ToBehaviour) -> TNewOut, + TNewOut: Debug + Send + 'static, + TMap: Send + 'static, +{ + type FromBehaviour = TConnectionHandler::FromBehaviour; + type ToBehaviour = TNewOut; + type InboundProtocol = TConnectionHandler::InboundProtocol; + type OutboundProtocol = TConnectionHandler::OutboundProtocol; + type InboundOpenInfo = TConnectionHandler::InboundOpenInfo; + type OutboundOpenInfo = TConnectionHandler::OutboundOpenInfo; + + fn listen_protocol(&self) -> SubstreamProtocol { + self.inner.listen_protocol() + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + self.inner.on_behaviour_event(event) + } + + fn connection_keep_alive(&self) -> bool { + self.inner.connection_keep_alive() + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + self.inner.poll(cx).map(|ev| match ev { + ConnectionHandlerEvent::NotifyBehaviour(ev) => { + ConnectionHandlerEvent::NotifyBehaviour((self.map)(ev)) + } + ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } => { + ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } + } + ConnectionHandlerEvent::ReportRemoteProtocols(support) => { + ConnectionHandlerEvent::ReportRemoteProtocols(support) + } + }) + } + + fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { + let Some(e) = ready!(self.inner.poll_close(cx)) else { + return Poll::Ready(None); + }; + + Poll::Ready(Some((self.map)(e))) + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + self.inner.on_connection_event(event); + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/multi.rs b/third-party/libp2p-swarm-0.45.1/src/handler/multi.rs new file mode 100644 index 00000000000..5efcde5c2bb --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/handler/multi.rs @@ -0,0 +1,456 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +//! A [`ConnectionHandler`] implementation that combines multiple other [`ConnectionHandler`]s +//! indexed by some key. + +use crate::handler::{ + AddressChange, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError, + FullyNegotiatedInbound, FullyNegotiatedOutbound, ListenUpgradeError, SubstreamProtocol, +}; +use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, UpgradeInfoSend}; +use crate::Stream; +use futures::{future::BoxFuture, prelude::*, ready}; +use rand::Rng; +use std::{ + cmp, + collections::{HashMap, HashSet}, + error, + fmt::{self, Debug}, + hash::Hash, + iter, + task::{Context, Poll}, + time::Duration, +}; + +/// A [`ConnectionHandler`] for multiple [`ConnectionHandler`]s of the same type. +#[derive(Clone)] +pub struct MultiHandler { + handlers: HashMap, +} + +impl fmt::Debug for MultiHandler +where + K: fmt::Debug + Eq + Hash, + H: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MultiHandler") + .field("handlers", &self.handlers) + .finish() + } +} + +impl MultiHandler +where + K: Clone + Debug + Hash + Eq + Send + 'static, + H: ConnectionHandler, +{ + /// Create and populate a `MultiHandler` from the given handler iterator. + /// + /// It is an error for any two protocols handlers to share the same protocol name. + pub fn try_from_iter(iter: I) -> Result + where + I: IntoIterator, + { + let m = MultiHandler { + handlers: HashMap::from_iter(iter), + }; + uniq_proto_names( + m.handlers + .values() + .map(|h| h.listen_protocol().into_upgrade().0), + )?; + Ok(m) + } + + fn on_listen_upgrade_error( + &mut self, + ListenUpgradeError { + error: (key, error), + mut info, + }: ListenUpgradeError< + ::InboundOpenInfo, + ::InboundProtocol, + >, + ) { + if let Some(h) = self.handlers.get_mut(&key) { + if let Some(i) = info.take(&key) { + h.on_connection_event(ConnectionEvent::ListenUpgradeError(ListenUpgradeError { + info: i, + error, + })); + } + } + } +} + +impl ConnectionHandler for MultiHandler +where + K: Clone + Debug + Hash + Eq + Send + 'static, + H: ConnectionHandler, + H::InboundProtocol: InboundUpgradeSend, + H::OutboundProtocol: OutboundUpgradeSend, +{ + type FromBehaviour = (K, ::FromBehaviour); + type ToBehaviour = (K, ::ToBehaviour); + type InboundProtocol = Upgrade::InboundProtocol>; + type OutboundProtocol = ::OutboundProtocol; + type InboundOpenInfo = Info::InboundOpenInfo>; + type OutboundOpenInfo = (K, ::OutboundOpenInfo); + + fn listen_protocol(&self) -> SubstreamProtocol { + let (upgrade, info, timeout) = self + .handlers + .iter() + .map(|(key, handler)| { + let proto = handler.listen_protocol(); + let timeout = *proto.timeout(); + let (upgrade, info) = proto.into_upgrade(); + (key.clone(), (upgrade, info, timeout)) + }) + .fold( + (Upgrade::new(), Info::new(), Duration::from_secs(0)), + |(mut upg, mut inf, mut timeout), (k, (u, i, t))| { + upg.upgrades.push((k.clone(), u)); + inf.infos.push((k, i)); + timeout = cmp::max(timeout, t); + (upg, inf, timeout) + }, + ); + SubstreamProtocol::new(upgrade, info).with_timeout(timeout) + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { + protocol, + info: (key, arg), + }) => { + if let Some(h) = self.handlers.get_mut(&key) { + h.on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( + FullyNegotiatedOutbound { + protocol, + info: arg, + }, + )); + } else { + tracing::error!("FullyNegotiatedOutbound: no handler for key") + } + } + ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { + protocol: (key, arg), + mut info, + }) => { + if let Some(h) = self.handlers.get_mut(&key) { + if let Some(i) = info.take(&key) { + h.on_connection_event(ConnectionEvent::FullyNegotiatedInbound( + FullyNegotiatedInbound { + protocol: arg, + info: i, + }, + )); + } + } else { + tracing::error!("FullyNegotiatedInbound: no handler for key") + } + } + ConnectionEvent::AddressChange(AddressChange { new_address }) => { + for h in self.handlers.values_mut() { + h.on_connection_event(ConnectionEvent::AddressChange(AddressChange { + new_address, + })); + } + } + ConnectionEvent::DialUpgradeError(DialUpgradeError { + info: (key, arg), + error, + }) => { + if let Some(h) = self.handlers.get_mut(&key) { + h.on_connection_event(ConnectionEvent::DialUpgradeError(DialUpgradeError { + info: arg, + error, + })); + } else { + tracing::error!("DialUpgradeError: no handler for protocol") + } + } + ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => { + self.on_listen_upgrade_error(listen_upgrade_error) + } + ConnectionEvent::LocalProtocolsChange(supported_protocols) => { + for h in self.handlers.values_mut() { + h.on_connection_event(ConnectionEvent::LocalProtocolsChange( + supported_protocols.clone(), + )); + } + } + ConnectionEvent::RemoteProtocolsChange(supported_protocols) => { + for h in self.handlers.values_mut() { + h.on_connection_event(ConnectionEvent::RemoteProtocolsChange( + supported_protocols.clone(), + )); + } + } + } + } + + fn on_behaviour_event(&mut self, (key, event): Self::FromBehaviour) { + if let Some(h) = self.handlers.get_mut(&key) { + h.on_behaviour_event(event) + } else { + tracing::error!("on_behaviour_event: no handler for key") + } + } + + fn connection_keep_alive(&self) -> bool { + self.handlers + .values() + .map(|h| h.connection_keep_alive()) + .max() + .unwrap_or(false) + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + // Calling `gen_range(0, 0)` (see below) would panic, so we have return early to avoid + // that situation. + if self.handlers.is_empty() { + return Poll::Pending; + } + + // Not always polling handlers in the same order should give anyone the chance to make progress. + let pos = rand::thread_rng().gen_range(0..self.handlers.len()); + + for (k, h) in self.handlers.iter_mut().skip(pos) { + if let Poll::Ready(e) = h.poll(cx) { + let e = e + .map_outbound_open_info(|i| (k.clone(), i)) + .map_custom(|p| (k.clone(), p)); + return Poll::Ready(e); + } + } + + for (k, h) in self.handlers.iter_mut().take(pos) { + if let Poll::Ready(e) = h.poll(cx) { + let e = e + .map_outbound_open_info(|i| (k.clone(), i)) + .map_custom(|p| (k.clone(), p)); + return Poll::Ready(e); + } + } + + Poll::Pending + } + + fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { + for (k, h) in self.handlers.iter_mut() { + let Some(e) = ready!(h.poll_close(cx)) else { + continue; + }; + return Poll::Ready(Some((k.clone(), e))); + } + + Poll::Ready(None) + } +} + +/// Split [`MultiHandler`] into parts. +impl IntoIterator for MultiHandler { + type Item = ::Item; + type IntoIter = std::collections::hash_map::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.handlers.into_iter() + } +} + +/// Index and protocol name pair used as `UpgradeInfo::Info`. +#[derive(Debug, Clone)] +pub struct IndexedProtoName(usize, H); + +impl> AsRef for IndexedProtoName { + fn as_ref(&self) -> &str { + self.1.as_ref() + } +} + +/// The aggregated `InboundOpenInfo`s of supported inbound substream protocols. +#[derive(Clone)] +pub struct Info { + infos: Vec<(K, I)>, +} + +impl Info { + fn new() -> Self { + Info { infos: Vec::new() } + } + + pub fn take(&mut self, k: &K) -> Option { + if let Some(p) = self.infos.iter().position(|(key, _)| key == k) { + return Some(self.infos.remove(p).1); + } + None + } +} + +/// Inbound and outbound upgrade for all [`ConnectionHandler`]s. +#[derive(Clone)] +pub struct Upgrade { + upgrades: Vec<(K, H)>, +} + +impl Upgrade { + fn new() -> Self { + Upgrade { + upgrades: Vec::new(), + } + } +} + +impl fmt::Debug for Upgrade +where + K: fmt::Debug + Eq + Hash, + H: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Upgrade") + .field("upgrades", &self.upgrades) + .finish() + } +} + +impl UpgradeInfoSend for Upgrade +where + H: UpgradeInfoSend, + K: Send + 'static, +{ + type Info = IndexedProtoName; + type InfoIter = std::vec::IntoIter; + + fn protocol_info(&self) -> Self::InfoIter { + self.upgrades + .iter() + .enumerate() + .flat_map(|(i, (_, h))| iter::repeat(i).zip(h.protocol_info())) + .map(|(i, h)| IndexedProtoName(i, h)) + .collect::>() + .into_iter() + } +} + +impl InboundUpgradeSend for Upgrade +where + H: InboundUpgradeSend, + K: Send + 'static, +{ + type Output = (K, ::Output); + type Error = (K, ::Error); + type Future = BoxFuture<'static, Result>; + + fn upgrade_inbound(mut self, resource: Stream, info: Self::Info) -> Self::Future { + let IndexedProtoName(index, info) = info; + let (key, upgrade) = self.upgrades.remove(index); + upgrade + .upgrade_inbound(resource, info) + .map(move |out| match out { + Ok(o) => Ok((key, o)), + Err(e) => Err((key, e)), + }) + .boxed() + } +} + +impl OutboundUpgradeSend for Upgrade +where + H: OutboundUpgradeSend, + K: Send + 'static, +{ + type Output = (K, ::Output); + type Error = (K, ::Error); + type Future = BoxFuture<'static, Result>; + + fn upgrade_outbound(mut self, resource: Stream, info: Self::Info) -> Self::Future { + let IndexedProtoName(index, info) = info; + let (key, upgrade) = self.upgrades.remove(index); + upgrade + .upgrade_outbound(resource, info) + .map(move |out| match out { + Ok(o) => Ok((key, o)), + Err(e) => Err((key, e)), + }) + .boxed() + } +} + +/// Check that no two protocol names are equal. +fn uniq_proto_names(iter: I) -> Result<(), DuplicateProtonameError> +where + I: Iterator, + T: UpgradeInfoSend, +{ + let mut set = HashSet::new(); + for infos in iter { + for i in infos.protocol_info() { + let v = Vec::from(i.as_ref()); + if set.contains(&v) { + return Err(DuplicateProtonameError(v)); + } else { + set.insert(v); + } + } + } + Ok(()) +} + +/// It is an error if two handlers share the same protocol name. +#[derive(Debug, Clone)] +pub struct DuplicateProtonameError(Vec); + +impl DuplicateProtonameError { + /// The protocol name bytes that occurred in more than one handler. + pub fn protocol_name(&self) -> &[u8] { + &self.0 + } +} + +impl fmt::Display for DuplicateProtonameError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Ok(s) = std::str::from_utf8(&self.0) { + write!(f, "duplicate protocol name: {s}") + } else { + write!(f, "duplicate protocol name: {:?}", self.0) + } + } +} + +impl error::Error for DuplicateProtonameError {} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/one_shot.rs b/third-party/libp2p-swarm-0.45.1/src/handler/one_shot.rs new file mode 100644 index 00000000000..fc1074b31e4 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/handler/one_shot.rs @@ -0,0 +1,237 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::handler::{ + ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError, + FullyNegotiatedInbound, FullyNegotiatedOutbound, SubstreamProtocol, +}; +use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend}; +use crate::StreamUpgradeError; +use smallvec::SmallVec; +use std::{error, fmt::Debug, task::Context, task::Poll, time::Duration}; + +/// A [`ConnectionHandler`] that opens a new substream for each request. +// TODO: Debug +pub struct OneShotHandler +where + TOutbound: OutboundUpgradeSend, +{ + /// The upgrade for inbound substreams. + listen_protocol: SubstreamProtocol, + /// Queue of events to produce in `poll()`. + events_out: SmallVec<[Result>; 4]>, + /// Queue of outbound substreams to open. + dial_queue: SmallVec<[TOutbound; 4]>, + /// Current number of concurrent outbound substreams being opened. + dial_negotiated: u32, + /// The configuration container for the handler + config: OneShotHandlerConfig, +} + +impl OneShotHandler +where + TOutbound: OutboundUpgradeSend, +{ + /// Creates a `OneShotHandler`. + pub fn new( + listen_protocol: SubstreamProtocol, + config: OneShotHandlerConfig, + ) -> Self { + OneShotHandler { + listen_protocol, + events_out: SmallVec::new(), + dial_queue: SmallVec::new(), + dial_negotiated: 0, + config, + } + } + + /// Returns the number of pending requests. + pub fn pending_requests(&self) -> u32 { + self.dial_negotiated + self.dial_queue.len() as u32 + } + + /// Returns a reference to the listen protocol configuration. + /// + /// > **Note**: If you modify the protocol, modifications will only applies to future inbound + /// > substreams, not the ones already being negotiated. + pub fn listen_protocol_ref(&self) -> &SubstreamProtocol { + &self.listen_protocol + } + + /// Returns a mutable reference to the listen protocol configuration. + /// + /// > **Note**: If you modify the protocol, modifications will only applies to future inbound + /// > substreams, not the ones already being negotiated. + pub fn listen_protocol_mut(&mut self) -> &mut SubstreamProtocol { + &mut self.listen_protocol + } + + /// Opens an outbound substream with `upgrade`. + pub fn send_request(&mut self, upgrade: TOutbound) { + self.dial_queue.push(upgrade); + } +} + +impl Default for OneShotHandler +where + TOutbound: OutboundUpgradeSend, + TInbound: InboundUpgradeSend + Default, +{ + fn default() -> Self { + OneShotHandler::new( + SubstreamProtocol::new(Default::default(), ()), + OneShotHandlerConfig::default(), + ) + } +} + +impl ConnectionHandler for OneShotHandler +where + TInbound: InboundUpgradeSend + Send + 'static, + TOutbound: Debug + OutboundUpgradeSend, + TInbound::Output: Into, + TOutbound::Output: Into, + TOutbound::Error: error::Error + Send + 'static, + SubstreamProtocol: Clone, + TEvent: Debug + Send + 'static, +{ + type FromBehaviour = TOutbound; + type ToBehaviour = Result>; + type InboundProtocol = TInbound; + type OutboundProtocol = TOutbound; + type OutboundOpenInfo = (); + type InboundOpenInfo = (); + + fn listen_protocol(&self) -> SubstreamProtocol { + self.listen_protocol.clone() + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + self.send_request(event); + } + + fn poll( + &mut self, + _: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + if !self.events_out.is_empty() { + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour( + self.events_out.remove(0), + )); + } else { + self.events_out.shrink_to_fit(); + } + + if !self.dial_queue.is_empty() { + if self.dial_negotiated < self.config.max_dial_negotiated { + self.dial_negotiated += 1; + let upgrade = self.dial_queue.remove(0); + return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: SubstreamProtocol::new(upgrade, ()) + .with_timeout(self.config.outbound_substream_timeout), + }); + } + } else { + self.dial_queue.shrink_to_fit(); + } + + Poll::Pending + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { + protocol: out, + .. + }) => { + self.events_out.push(Ok(out.into())); + } + ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { + protocol: out, + .. + }) => { + self.dial_negotiated -= 1; + self.events_out.push(Ok(out.into())); + } + ConnectionEvent::DialUpgradeError(DialUpgradeError { error, .. }) => { + self.events_out.push(Err(error)); + } + ConnectionEvent::AddressChange(_) + | ConnectionEvent::ListenUpgradeError(_) + | ConnectionEvent::LocalProtocolsChange(_) + | ConnectionEvent::RemoteProtocolsChange(_) => {} + } + } +} + +/// Configuration parameters for the `OneShotHandler` +#[derive(Debug)] +pub struct OneShotHandlerConfig { + /// Timeout for outbound substream upgrades. + pub outbound_substream_timeout: Duration, + /// Maximum number of concurrent outbound substreams being opened. + pub max_dial_negotiated: u32, +} + +impl Default for OneShotHandlerConfig { + fn default() -> Self { + OneShotHandlerConfig { + outbound_substream_timeout: Duration::from_secs(10), + max_dial_negotiated: 8, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use futures::executor::block_on; + use futures::future::poll_fn; + use libp2p_core::upgrade::DeniedUpgrade; + use void::Void; + + #[test] + fn do_not_keep_idle_connection_alive() { + let mut handler: OneShotHandler<_, DeniedUpgrade, Void> = OneShotHandler::new( + SubstreamProtocol::new(DeniedUpgrade {}, ()), + Default::default(), + ); + + block_on(poll_fn(|cx| loop { + if handler.poll(cx).is_pending() { + return Poll::Ready(()); + } + })); + + assert!(!handler.connection_keep_alive()); + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/pending.rs b/third-party/libp2p-swarm-0.45.1/src/handler/pending.rs new file mode 100644 index 00000000000..23b9adcfd90 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/handler/pending.rs @@ -0,0 +1,97 @@ +// Copyright 2022 Protocol Labs. +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::handler::{ + ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, FullyNegotiatedInbound, + FullyNegotiatedOutbound, SubstreamProtocol, +}; +use libp2p_core::upgrade::PendingUpgrade; +use std::task::{Context, Poll}; +use void::Void; + +/// Implementation of [`ConnectionHandler`] that returns a pending upgrade. +#[derive(Clone, Debug)] +pub struct PendingConnectionHandler { + protocol_name: String, +} + +impl PendingConnectionHandler { + pub fn new(protocol_name: String) -> Self { + PendingConnectionHandler { protocol_name } + } +} + +impl ConnectionHandler for PendingConnectionHandler { + type FromBehaviour = Void; + type ToBehaviour = Void; + type InboundProtocol = PendingUpgrade; + type OutboundProtocol = PendingUpgrade; + type OutboundOpenInfo = Void; + type InboundOpenInfo = (); + + fn listen_protocol(&self) -> SubstreamProtocol { + SubstreamProtocol::new(PendingUpgrade::new(self.protocol_name.clone()), ()) + } + + fn on_behaviour_event(&mut self, v: Self::FromBehaviour) { + void::unreachable(v) + } + + fn poll( + &mut self, + _: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + Poll::Pending + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { + protocol, .. + }) => void::unreachable(protocol), + ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { + protocol, + info: _info, + }) => { + void::unreachable(protocol); + #[allow(unreachable_code, clippy::used_underscore_binding)] + { + void::unreachable(_info); + } + } + ConnectionEvent::AddressChange(_) + | ConnectionEvent::DialUpgradeError(_) + | ConnectionEvent::ListenUpgradeError(_) + | ConnectionEvent::LocalProtocolsChange(_) + | ConnectionEvent::RemoteProtocolsChange(_) => {} + } + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/select.rs b/third-party/libp2p-swarm-0.45.1/src/handler/select.rs new file mode 100644 index 00000000000..e049252d448 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/handler/select.rs @@ -0,0 +1,350 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::handler::{ + AddressChange, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError, + FullyNegotiatedInbound, FullyNegotiatedOutbound, InboundUpgradeSend, ListenUpgradeError, + OutboundUpgradeSend, StreamUpgradeError, SubstreamProtocol, +}; +use crate::upgrade::SendWrapper; +use either::Either; +use futures::{future, ready}; +use libp2p_core::upgrade::SelectUpgrade; +use std::{cmp, task::Context, task::Poll}; + +/// Implementation of [`ConnectionHandler`] that combines two protocols into one. +#[derive(Debug, Clone)] +pub struct ConnectionHandlerSelect { + /// The first protocol. + proto1: TProto1, + /// The second protocol. + proto2: TProto2, +} + +impl ConnectionHandlerSelect { + /// Builds a [`ConnectionHandlerSelect`]. + pub(crate) fn new(proto1: TProto1, proto2: TProto2) -> Self { + ConnectionHandlerSelect { proto1, proto2 } + } + + pub fn into_inner(self) -> (TProto1, TProto2) { + (self.proto1, self.proto2) + } +} + +impl + FullyNegotiatedOutbound, SendWrapper>, Either> +where + S1OP: OutboundUpgradeSend, + S2OP: OutboundUpgradeSend, + S1OOI: Send + 'static, + S2OOI: Send + 'static, +{ + pub(crate) fn transpose( + self, + ) -> Either, FullyNegotiatedOutbound> { + match self { + FullyNegotiatedOutbound { + protocol: future::Either::Left(protocol), + info: Either::Left(info), + } => Either::Left(FullyNegotiatedOutbound { protocol, info }), + FullyNegotiatedOutbound { + protocol: future::Either::Right(protocol), + info: Either::Right(info), + } => Either::Right(FullyNegotiatedOutbound { protocol, info }), + _ => panic!("wrong API usage: the protocol doesn't match the upgrade info"), + } + } +} + +impl + FullyNegotiatedInbound, SendWrapper>, (S1IOI, S2IOI)> +where + S1IP: InboundUpgradeSend, + S2IP: InboundUpgradeSend, +{ + pub(crate) fn transpose( + self, + ) -> Either, FullyNegotiatedInbound> { + match self { + FullyNegotiatedInbound { + protocol: future::Either::Left(protocol), + info: (i1, _i2), + } => Either::Left(FullyNegotiatedInbound { protocol, info: i1 }), + FullyNegotiatedInbound { + protocol: future::Either::Right(protocol), + info: (_i1, i2), + } => Either::Right(FullyNegotiatedInbound { protocol, info: i2 }), + } + } +} + +impl + DialUpgradeError, Either, SendWrapper>> +where + S1OP: OutboundUpgradeSend, + S2OP: OutboundUpgradeSend, + S1OOI: Send + 'static, + S2OOI: Send + 'static, +{ + pub(crate) fn transpose( + self, + ) -> Either, DialUpgradeError> { + match self { + DialUpgradeError { + info: Either::Left(info), + error: StreamUpgradeError::Apply(Either::Left(err)), + } => Either::Left(DialUpgradeError { + info, + error: StreamUpgradeError::Apply(err), + }), + DialUpgradeError { + info: Either::Right(info), + error: StreamUpgradeError::Apply(Either::Right(err)), + } => Either::Right(DialUpgradeError { + info, + error: StreamUpgradeError::Apply(err), + }), + DialUpgradeError { + info: Either::Left(info), + error: e, + } => Either::Left(DialUpgradeError { + info, + error: e.map_upgrade_err(|_| panic!("already handled above")), + }), + DialUpgradeError { + info: Either::Right(info), + error: e, + } => Either::Right(DialUpgradeError { + info, + error: e.map_upgrade_err(|_| panic!("already handled above")), + }), + } + } +} + +impl ConnectionHandlerSelect +where + TProto1: ConnectionHandler, + TProto2: ConnectionHandler, +{ + fn on_listen_upgrade_error( + &mut self, + ListenUpgradeError { + info: (i1, i2), + error, + }: ListenUpgradeError< + ::InboundOpenInfo, + ::InboundProtocol, + >, + ) { + match error { + Either::Left(error) => { + self.proto1 + .on_connection_event(ConnectionEvent::ListenUpgradeError(ListenUpgradeError { + info: i1, + error, + })); + } + Either::Right(error) => { + self.proto2 + .on_connection_event(ConnectionEvent::ListenUpgradeError(ListenUpgradeError { + info: i2, + error, + })); + } + } + } +} + +impl ConnectionHandler for ConnectionHandlerSelect +where + TProto1: ConnectionHandler, + TProto2: ConnectionHandler, +{ + type FromBehaviour = Either; + type ToBehaviour = Either; + type InboundProtocol = SelectUpgrade< + SendWrapper<::InboundProtocol>, + SendWrapper<::InboundProtocol>, + >; + type OutboundProtocol = + Either, SendWrapper>; + type OutboundOpenInfo = Either; + type InboundOpenInfo = (TProto1::InboundOpenInfo, TProto2::InboundOpenInfo); + + fn listen_protocol(&self) -> SubstreamProtocol { + let proto1 = self.proto1.listen_protocol(); + let proto2 = self.proto2.listen_protocol(); + let timeout = *std::cmp::max(proto1.timeout(), proto2.timeout()); + let (u1, i1) = proto1.into_upgrade(); + let (u2, i2) = proto2.into_upgrade(); + let choice = SelectUpgrade::new(SendWrapper(u1), SendWrapper(u2)); + SubstreamProtocol::new(choice, (i1, i2)).with_timeout(timeout) + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + match event { + Either::Left(event) => self.proto1.on_behaviour_event(event), + Either::Right(event) => self.proto2.on_behaviour_event(event), + } + } + + fn connection_keep_alive(&self) -> bool { + cmp::max( + self.proto1.connection_keep_alive(), + self.proto2.connection_keep_alive(), + ) + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + match self.proto1.poll(cx) { + Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(event)) => { + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(Either::Left(event))); + } + Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { protocol }) => { + return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: protocol + .map_upgrade(|u| Either::Left(SendWrapper(u))) + .map_info(Either::Left), + }); + } + Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols(support)) => { + return Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols(support)); + } + Poll::Pending => (), + }; + + match self.proto2.poll(cx) { + Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(event)) => { + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(Either::Right( + event, + ))); + } + Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { protocol }) => { + return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: protocol + .map_upgrade(|u| Either::Right(SendWrapper(u))) + .map_info(Either::Right), + }); + } + Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols(support)) => { + return Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols(support)); + } + Poll::Pending => (), + }; + + Poll::Pending + } + + fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { + if let Some(e) = ready!(self.proto1.poll_close(cx)) { + return Poll::Ready(Some(Either::Left(e))); + } + + if let Some(e) = ready!(self.proto2.poll_close(cx)) { + return Poll::Ready(Some(Either::Right(e))); + } + + Poll::Ready(None) + } + + fn on_connection_event( + &mut self, + event: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + ConnectionEvent::FullyNegotiatedOutbound(fully_negotiated_outbound) => { + match fully_negotiated_outbound.transpose() { + Either::Left(f) => self + .proto1 + .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(f)), + Either::Right(f) => self + .proto2 + .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(f)), + } + } + ConnectionEvent::FullyNegotiatedInbound(fully_negotiated_inbound) => { + match fully_negotiated_inbound.transpose() { + Either::Left(f) => self + .proto1 + .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(f)), + Either::Right(f) => self + .proto2 + .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(f)), + } + } + ConnectionEvent::AddressChange(address) => { + self.proto1 + .on_connection_event(ConnectionEvent::AddressChange(AddressChange { + new_address: address.new_address, + })); + + self.proto2 + .on_connection_event(ConnectionEvent::AddressChange(AddressChange { + new_address: address.new_address, + })); + } + ConnectionEvent::DialUpgradeError(dial_upgrade_error) => { + match dial_upgrade_error.transpose() { + Either::Left(err) => self + .proto1 + .on_connection_event(ConnectionEvent::DialUpgradeError(err)), + Either::Right(err) => self + .proto2 + .on_connection_event(ConnectionEvent::DialUpgradeError(err)), + } + } + ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => { + self.on_listen_upgrade_error(listen_upgrade_error) + } + ConnectionEvent::LocalProtocolsChange(supported_protocols) => { + self.proto1 + .on_connection_event(ConnectionEvent::LocalProtocolsChange( + supported_protocols.clone(), + )); + self.proto2 + .on_connection_event(ConnectionEvent::LocalProtocolsChange( + supported_protocols, + )); + } + ConnectionEvent::RemoteProtocolsChange(supported_protocols) => { + self.proto1 + .on_connection_event(ConnectionEvent::RemoteProtocolsChange( + supported_protocols.clone(), + )); + self.proto2 + .on_connection_event(ConnectionEvent::RemoteProtocolsChange( + supported_protocols, + )); + } + } + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/lib.rs b/third-party/libp2p-swarm-0.45.1/src/lib.rs new file mode 100644 index 00000000000..81b1ca1a68d --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/lib.rs @@ -0,0 +1,2346 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +//! High-level network manager. +//! +//! A [`Swarm`] contains the state of the network as a whole. The entire +//! behaviour of a libp2p network can be controlled through the `Swarm`. +//! The `Swarm` struct contains all active and pending connections to +//! remotes and manages the state of all the substreams that have been +//! opened, and all the upgrades that were built upon these substreams. +//! +//! # Initializing a Swarm +//! +//! Creating a `Swarm` requires three things: +//! +//! 1. A network identity of the local node in form of a [`PeerId`]. +//! 2. An implementation of the [`Transport`] trait. This is the type that +//! will be used in order to reach nodes on the network based on their +//! address. See the `transport` module for more information. +//! 3. An implementation of the [`NetworkBehaviour`] trait. This is a state +//! machine that defines how the swarm should behave once it is connected +//! to a node. +//! +//! # Network Behaviour +//! +//! The [`NetworkBehaviour`] trait is implemented on types that indicate to +//! the swarm how it should behave. This includes which protocols are supported +//! and which nodes to try to connect to. It is the `NetworkBehaviour` that +//! controls what happens on the network. Multiple types that implement +//! `NetworkBehaviour` can be composed into a single behaviour. +//! +//! # Protocols Handler +//! +//! The [`ConnectionHandler`] trait defines how each active connection to a +//! remote should behave: how to handle incoming substreams, which protocols +//! are supported, when to open a new outbound substream, etc. +//! + +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] + +mod connection; +mod executor; +mod stream; +mod stream_protocol; +#[cfg(test)] +mod test; +mod upgrade; + +pub mod behaviour; +pub mod dial_opts; +pub mod dummy; +pub mod handler; +mod listen_opts; +mod translation; + +/// Bundles all symbols required for the [`libp2p_swarm_derive::NetworkBehaviour`] macro. +#[doc(hidden)] +pub mod derive_prelude { + pub use crate::behaviour::AddressChange; + pub use crate::behaviour::ConnectionClosed; + pub use crate::behaviour::ConnectionEstablished; + pub use crate::behaviour::DialFailure; + pub use crate::behaviour::ExpiredListenAddr; + pub use crate::behaviour::ExternalAddrConfirmed; + pub use crate::behaviour::ExternalAddrExpired; + pub use crate::behaviour::FromSwarm; + pub use crate::behaviour::ListenFailure; + pub use crate::behaviour::ListenerClosed; + pub use crate::behaviour::ListenerError; + pub use crate::behaviour::NewExternalAddrCandidate; + pub use crate::behaviour::NewExternalAddrOfPeer; + pub use crate::behaviour::NewListenAddr; + pub use crate::behaviour::NewListener; + pub use crate::connection::ConnectionId; + pub use crate::ConnectionDenied; + pub use crate::ConnectionHandler; + pub use crate::ConnectionHandlerSelect; + pub use crate::DialError; + pub use crate::NetworkBehaviour; + pub use crate::THandler; + pub use crate::THandlerInEvent; + pub use crate::THandlerOutEvent; + pub use crate::ToSwarm; + pub use either::Either; + pub use futures::prelude as futures; + pub use libp2p_core::transport::{ListenerId, PortUse}; + pub use libp2p_core::ConnectedPoint; + pub use libp2p_core::Endpoint; + pub use libp2p_core::Multiaddr; + pub use libp2p_identity::PeerId; +} + +pub use behaviour::{ + AddressChange, CloseConnection, ConnectionClosed, DialFailure, ExpiredListenAddr, + ExternalAddrExpired, ExternalAddresses, FromSwarm, ListenAddresses, ListenFailure, + ListenerClosed, ListenerError, NetworkBehaviour, NewExternalAddrCandidate, + NewExternalAddrOfPeer, NewListenAddr, NotifyHandler, PeerAddresses, ToSwarm, +}; +pub use connection::pool::ConnectionCounters; +pub use connection::{ConnectionError, ConnectionId, SupportedProtocols}; +pub use executor::Executor; +pub use handler::{ + ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerSelect, OneShotHandler, + OneShotHandlerConfig, StreamUpgradeError, SubstreamProtocol, +}; +#[cfg(feature = "macros")] +pub use libp2p_swarm_derive::NetworkBehaviour; +pub use listen_opts::ListenOpts; +pub use stream::Stream; +pub use stream_protocol::{InvalidProtocol, StreamProtocol}; + +use crate::behaviour::ExternalAddrConfirmed; +use crate::handler::UpgradeInfoSend; +use connection::pool::{EstablishedConnection, Pool, PoolConfig, PoolEvent}; +use connection::IncomingInfo; +use connection::{ + PendingConnectionError, PendingInboundConnectionError, PendingOutboundConnectionError, +}; +use dial_opts::{DialOpts, PeerCondition}; +use futures::{prelude::*, stream::FusedStream}; + +use libp2p_core::{ + connection::ConnectedPoint, + muxing::StreamMuxerBox, + transport::{self, ListenerId, TransportError, TransportEvent}, + Multiaddr, Transport, +}; +use libp2p_identity::PeerId; + +use smallvec::SmallVec; +use std::collections::{HashMap, HashSet, VecDeque}; +use std::num::{NonZeroU32, NonZeroU8, NonZeroUsize}; +use std::time::Duration; +use std::{ + error, fmt, io, + pin::Pin, + task::{Context, Poll}, +}; +use tracing::Instrument; +#[doc(hidden)] +pub use translation::_address_translation; + +/// Event generated by the [`NetworkBehaviour`] that the swarm will report back. +type TBehaviourOutEvent = ::ToSwarm; + +/// [`ConnectionHandler`] of the [`NetworkBehaviour`] for all the protocols the [`NetworkBehaviour`] +/// supports. +pub type THandler = ::ConnectionHandler; + +/// Custom event that can be received by the [`ConnectionHandler`] of the +/// [`NetworkBehaviour`]. +pub type THandlerInEvent = as ConnectionHandler>::FromBehaviour; + +/// Custom event that can be produced by the [`ConnectionHandler`] of the [`NetworkBehaviour`]. +pub type THandlerOutEvent = as ConnectionHandler>::ToBehaviour; + +/// Event generated by the `Swarm`. +#[derive(Debug)] +#[non_exhaustive] +pub enum SwarmEvent { + /// Event generated by the `NetworkBehaviour`. + Behaviour(TBehaviourOutEvent), + /// A connection to the given peer has been opened. + ConnectionEstablished { + /// Identity of the peer that we have connected to. + peer_id: PeerId, + /// Identifier of the connection. + connection_id: ConnectionId, + /// Endpoint of the connection that has been opened. + endpoint: ConnectedPoint, + /// Number of established connections to this peer, including the one that has just been + /// opened. + num_established: NonZeroU32, + /// [`Some`] when the new connection is an outgoing connection. + /// Addresses are dialed concurrently. Contains the addresses and errors + /// of dial attempts that failed before the one successful dial. + concurrent_dial_errors: Option)>>, + /// How long it took to establish this connection + established_in: std::time::Duration, + }, + /// A connection with the given peer has been closed, + /// possibly as a result of an error. + ConnectionClosed { + /// Identity of the peer that we have connected to. + peer_id: PeerId, + /// Identifier of the connection. + connection_id: ConnectionId, + /// Endpoint of the connection that has been closed. + endpoint: ConnectedPoint, + /// Number of other remaining connections to this same peer. + num_established: u32, + /// Reason for the disconnection, if it was not a successful + /// active close. + cause: Option, + }, + /// A new connection arrived on a listener and is in the process of protocol negotiation. + /// + /// A corresponding [`ConnectionEstablished`](SwarmEvent::ConnectionEstablished) or + /// [`IncomingConnectionError`](SwarmEvent::IncomingConnectionError) event will later be + /// generated for this connection. + IncomingConnection { + /// Identifier of the connection. + connection_id: ConnectionId, + /// Local connection address. + /// This address has been earlier reported with a [`NewListenAddr`](SwarmEvent::NewListenAddr) + /// event. + local_addr: Multiaddr, + /// Address used to send back data to the remote. + send_back_addr: Multiaddr, + }, + /// An error happened on an inbound connection during its initial handshake. + /// + /// This can include, for example, an error during the handshake of the encryption layer, or + /// the connection unexpectedly closed. + IncomingConnectionError { + /// Identifier of the connection. + connection_id: ConnectionId, + /// Local connection address. + /// This address has been earlier reported with a [`NewListenAddr`](SwarmEvent::NewListenAddr) + /// event. + local_addr: Multiaddr, + /// Address used to send back data to the remote. + send_back_addr: Multiaddr, + /// The error that happened. + error: ListenError, + }, + /// An error happened on an outbound connection. + OutgoingConnectionError { + /// Identifier of the connection. + connection_id: ConnectionId, + /// If known, [`PeerId`] of the peer we tried to reach. + peer_id: Option, + /// Error that has been encountered. + error: DialError, + }, + /// One of our listeners has reported a new local listening address. + NewListenAddr { + /// The listener that is listening on the new address. + listener_id: ListenerId, + /// The new address that is being listened on. + address: Multiaddr, + }, + /// One of our listeners has reported the expiration of a listening address. + ExpiredListenAddr { + /// The listener that is no longer listening on the address. + listener_id: ListenerId, + /// The expired address. + address: Multiaddr, + }, + /// One of the listeners gracefully closed. + ListenerClosed { + /// The listener that closed. + listener_id: ListenerId, + /// The addresses that the listener was listening on. These addresses are now considered + /// expired, similar to if a [`ExpiredListenAddr`](SwarmEvent::ExpiredListenAddr) event + /// has been generated for each of them. + addresses: Vec, + /// Reason for the closure. Contains `Ok(())` if the stream produced `None`, or `Err` + /// if the stream produced an error. + reason: Result<(), io::Error>, + }, + /// One of the listeners reported a non-fatal error. + ListenerError { + /// The listener that errored. + listener_id: ListenerId, + /// The listener error. + error: io::Error, + }, + /// A new dialing attempt has been initiated by the [`NetworkBehaviour`] + /// implementation. + /// + /// A [`ConnectionEstablished`](SwarmEvent::ConnectionEstablished) event is + /// reported if the dialing attempt succeeds, otherwise a + /// [`OutgoingConnectionError`](SwarmEvent::OutgoingConnectionError) event + /// is reported. + Dialing { + /// Identity of the peer that we are connecting to. + peer_id: Option, + + /// Identifier of the connection. + connection_id: ConnectionId, + }, + /// We have discovered a new candidate for an external address for us. + NewExternalAddrCandidate { address: Multiaddr }, + /// An external address of the local node was confirmed. + ExternalAddrConfirmed { address: Multiaddr }, + /// An external address of the local node expired, i.e. is no-longer confirmed. + ExternalAddrExpired { address: Multiaddr }, + /// We have discovered a new address of a peer. + NewExternalAddrOfPeer { peer_id: PeerId, address: Multiaddr }, +} + +impl SwarmEvent { + /// Extract the `TBehaviourOutEvent` from this [`SwarmEvent`] in case it is the `Behaviour` variant, otherwise fail. + #[allow(clippy::result_large_err)] + pub fn try_into_behaviour_event(self) -> Result { + match self { + SwarmEvent::Behaviour(inner) => Ok(inner), + other => Err(other), + } + } +} + +/// Contains the state of the network, plus the way it should behave. +/// +/// Note: Needs to be polled via `` in order to make +/// progress. +pub struct Swarm +where + TBehaviour: NetworkBehaviour, +{ + /// [`Transport`] for dialing remote peers and listening for incoming connection. + transport: transport::Boxed<(PeerId, StreamMuxerBox)>, + + /// The nodes currently active. + pool: Pool>, + + /// The local peer ID. + local_peer_id: PeerId, + + /// Handles which nodes to connect to and how to handle the events sent back by the protocol + /// handlers. + behaviour: TBehaviour, + + /// List of protocols that the behaviour says it supports. + supported_protocols: SmallVec<[Vec; 16]>, + + confirmed_external_addr: HashSet, + + /// Multiaddresses that our listeners are listening on, + listened_addrs: HashMap>, + + /// Pending event to be delivered to connection handlers + /// (or dropped if the peer disconnected) before the `behaviour` + /// can be polled again. + pending_handler_event: Option<(PeerId, PendingNotifyHandler, THandlerInEvent)>, + + pending_swarm_events: VecDeque>, +} + +impl Unpin for Swarm where TBehaviour: NetworkBehaviour {} + +impl Swarm +where + TBehaviour: NetworkBehaviour, +{ + /// Creates a new [`Swarm`] from the given [`Transport`], [`NetworkBehaviour`], [`PeerId`] and + /// [`Config`]. + pub fn new( + transport: transport::Boxed<(PeerId, StreamMuxerBox)>, + behaviour: TBehaviour, + local_peer_id: PeerId, + config: Config, + ) -> Self { + tracing::info!(%local_peer_id); + + Swarm { + local_peer_id, + transport, + pool: Pool::new(local_peer_id, config.pool_config), + behaviour, + supported_protocols: Default::default(), + confirmed_external_addr: Default::default(), + listened_addrs: HashMap::new(), + pending_handler_event: None, + pending_swarm_events: VecDeque::default(), + } + } + + /// Returns information about the connections underlying the [`Swarm`]. + pub fn network_info(&self) -> NetworkInfo { + let num_peers = self.pool.num_peers(); + let connection_counters = self.pool.counters().clone(); + NetworkInfo { + num_peers, + connection_counters, + } + } + + /// Starts listening on the given address. + /// Returns an error if the address is not supported. + /// + /// Listeners report their new listening addresses as [`SwarmEvent::NewListenAddr`]. + /// Depending on the underlying transport, one listener may have multiple listening addresses. + pub fn listen_on(&mut self, addr: Multiaddr) -> Result> { + let opts = ListenOpts::new(addr); + let id = opts.listener_id(); + self.add_listener(opts)?; + Ok(id) + } + + /// Remove some listener. + /// + /// Returns `true` if there was a listener with this ID, `false` + /// otherwise. + pub fn remove_listener(&mut self, listener_id: ListenerId) -> bool { + self.transport.remove_listener(listener_id) + } + + /// Dial a known or unknown peer. + /// + /// See also [`DialOpts`]. + /// + /// ``` + /// # use libp2p_swarm::Swarm; + /// # use libp2p_swarm::dial_opts::{DialOpts, PeerCondition}; + /// # use libp2p_core::{Multiaddr, Transport}; + /// # use libp2p_core::transport::dummy::DummyTransport; + /// # use libp2p_swarm::dummy; + /// # use libp2p_identity::PeerId; + /// # + /// # #[tokio::main] + /// # async fn main() { + /// let mut swarm = build_swarm(); + /// + /// // Dial a known peer. + /// swarm.dial(PeerId::random()); + /// + /// // Dial an unknown peer. + /// swarm.dial("/ip6/::1/tcp/12345".parse::().unwrap()); + /// # } + /// + /// # fn build_swarm() -> Swarm { + /// # Swarm::new(DummyTransport::new().boxed(), dummy::Behaviour, PeerId::random(), libp2p_swarm::Config::with_tokio_executor()) + /// # } + /// ``` + pub fn dial(&mut self, opts: impl Into) -> Result<(), DialError> { + let dial_opts = opts.into(); + + let peer_id = dial_opts.get_peer_id(); + let condition = dial_opts.peer_condition(); + let connection_id = dial_opts.connection_id(); + + let should_dial = match (condition, peer_id) { + (_, None) => true, + (PeerCondition::Always, _) => true, + (PeerCondition::Disconnected, Some(peer_id)) => !self.pool.is_connected(peer_id), + (PeerCondition::NotDialing, Some(peer_id)) => !self.pool.is_dialing(peer_id), + (PeerCondition::DisconnectedAndNotDialing, Some(peer_id)) => { + !self.pool.is_dialing(peer_id) && !self.pool.is_connected(peer_id) + } + }; + + if !should_dial { + let e = DialError::DialPeerConditionFalse(condition); + + self.behaviour + .on_swarm_event(FromSwarm::DialFailure(DialFailure { + peer_id, + error: &e, + connection_id, + })); + + return Err(e); + } + + let addresses = { + let mut addresses_from_opts = dial_opts.get_addresses(); + + match self.behaviour.handle_pending_outbound_connection( + connection_id, + peer_id, + addresses_from_opts.as_slice(), + dial_opts.role_override(), + ) { + Ok(addresses) => { + if dial_opts.extend_addresses_through_behaviour() { + addresses_from_opts.extend(addresses) + } else { + let num_addresses = addresses.len(); + + if num_addresses > 0 { + tracing::debug!( + connection=%connection_id, + discarded_addresses_count=%num_addresses, + "discarding addresses from `NetworkBehaviour` because `DialOpts::extend_addresses_through_behaviour is `false` for connection" + ) + } + } + } + Err(cause) => { + let error = DialError::Denied { cause }; + + self.behaviour + .on_swarm_event(FromSwarm::DialFailure(DialFailure { + peer_id, + error: &error, + connection_id, + })); + + return Err(error); + } + } + + let mut unique_addresses = HashSet::new(); + addresses_from_opts.retain(|addr| { + !self.listened_addrs.values().flatten().any(|a| a == addr) + && unique_addresses.insert(addr.clone()) + }); + + if addresses_from_opts.is_empty() { + let error = DialError::NoAddresses; + self.behaviour + .on_swarm_event(FromSwarm::DialFailure(DialFailure { + peer_id, + error: &error, + connection_id, + })); + return Err(error); + }; + + addresses_from_opts + }; + + let dials = addresses + .into_iter() + .map(|a| match peer_id.map_or(Ok(a.clone()), |p| a.with_p2p(p)) { + Ok(address) => { + let dial = self.transport.dial( + address.clone(), + transport::DialOpts { + role: dial_opts.role_override(), + port_use: dial_opts.port_use(), + }, + ); + let span = tracing::debug_span!(parent: tracing::Span::none(), "Transport::dial", %address); + span.follows_from(tracing::Span::current()); + match dial { + Ok(fut) => fut + .map(|r| (address, r.map_err(TransportError::Other))) + .instrument(span) + .boxed(), + Err(err) => futures::future::ready((address, Err(err))).boxed(), + } + } + Err(address) => futures::future::ready(( + address.clone(), + Err(TransportError::MultiaddrNotSupported(address)), + )) + .boxed(), + }) + .collect(); + + self.pool.add_outgoing( + dials, + peer_id, + dial_opts.role_override(), + dial_opts.port_use(), + dial_opts.dial_concurrency_override(), + connection_id, + ); + + Ok(()) + } + + /// Returns an iterator that produces the list of addresses we're listening on. + pub fn listeners(&self) -> impl Iterator { + self.listened_addrs.values().flatten() + } + + /// Returns the peer ID of the swarm passed as parameter. + pub fn local_peer_id(&self) -> &PeerId { + &self.local_peer_id + } + + /// List all **confirmed** external address for the local node. + pub fn external_addresses(&self) -> impl Iterator { + self.confirmed_external_addr.iter() + } + + fn add_listener(&mut self, opts: ListenOpts) -> Result<(), TransportError> { + let addr = opts.address(); + let listener_id = opts.listener_id(); + + if let Err(e) = self.transport.listen_on(listener_id, addr.clone()) { + self.behaviour + .on_swarm_event(FromSwarm::ListenerError(behaviour::ListenerError { + listener_id, + err: &e, + })); + + return Err(e); + } + + self.behaviour + .on_swarm_event(FromSwarm::NewListener(behaviour::NewListener { + listener_id, + })); + + Ok(()) + } + + /// Add a **confirmed** external address for the local node. + /// + /// This function should only be called with addresses that are guaranteed to be reachable. + /// The address is broadcast to all [`NetworkBehaviour`]s via [`FromSwarm::ExternalAddrConfirmed`]. + pub fn add_external_address(&mut self, a: Multiaddr) { + self.behaviour + .on_swarm_event(FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { + addr: &a, + })); + self.confirmed_external_addr.insert(a); + } + + /// Remove an external address for the local node. + /// + /// The address is broadcast to all [`NetworkBehaviour`]s via [`FromSwarm::ExternalAddrExpired`]. + pub fn remove_external_address(&mut self, addr: &Multiaddr) { + self.behaviour + .on_swarm_event(FromSwarm::ExternalAddrExpired(ExternalAddrExpired { addr })); + self.confirmed_external_addr.remove(addr); + } + + /// Add a new external address of a remote peer. + /// + /// The address is broadcast to all [`NetworkBehaviour`]s via [`FromSwarm::NewExternalAddrOfPeer`]. + pub fn add_peer_address(&mut self, peer_id: PeerId, addr: Multiaddr) { + self.behaviour + .on_swarm_event(FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { + peer_id, + addr: &addr, + })) + } + + /// Disconnects a peer by its peer ID, closing all connections to said peer. + /// + /// Returns `Ok(())` if there was one or more established connections to the peer. + /// + /// Closing a connection via [`Swarm::disconnect_peer_id`] will poll [`ConnectionHandler::poll_close`] to completion. + /// Use this function if you want to close a connection _despite_ it still being in use by one or more handlers. + #[allow(clippy::result_unit_err)] + pub fn disconnect_peer_id(&mut self, peer_id: PeerId) -> Result<(), ()> { + let was_connected = self.pool.is_connected(peer_id); + self.pool.disconnect(peer_id); + + if was_connected { + Ok(()) + } else { + Err(()) + } + } + + /// Attempt to gracefully close a connection. + /// + /// Closing a connection is asynchronous but this function will return immediately. + /// A [`SwarmEvent::ConnectionClosed`] event will be emitted once the connection is actually closed. + /// + /// # Returns + /// + /// - `true` if the connection was established and is now being closed. + /// - `false` if the connection was not found or is no longer established. + pub fn close_connection(&mut self, connection_id: ConnectionId) -> bool { + if let Some(established) = self.pool.get_established(connection_id) { + established.start_close(); + return true; + } + + false + } + + /// Checks whether there is an established connection to a peer. + pub fn is_connected(&self, peer_id: &PeerId) -> bool { + self.pool.is_connected(*peer_id) + } + + /// Returns the currently connected peers. + pub fn connected_peers(&self) -> impl Iterator { + self.pool.iter_connected() + } + + /// Returns a reference to the provided [`NetworkBehaviour`]. + pub fn behaviour(&self) -> &TBehaviour { + &self.behaviour + } + + /// Returns a mutable reference to the provided [`NetworkBehaviour`]. + pub fn behaviour_mut(&mut self) -> &mut TBehaviour { + &mut self.behaviour + } + + fn handle_pool_event(&mut self, event: PoolEvent>) { + match event { + PoolEvent::ConnectionEstablished { + peer_id, + id, + endpoint, + connection, + concurrent_dial_errors, + established_in, + } => { + let handler = match endpoint.clone() { + ConnectedPoint::Dialer { + address, + role_override, + port_use, + } => { + match self.behaviour.handle_established_outbound_connection( + id, + peer_id, + &address, + role_override, + port_use, + ) { + Ok(handler) => handler, + Err(cause) => { + let dial_error = DialError::Denied { cause }; + self.behaviour.on_swarm_event(FromSwarm::DialFailure( + DialFailure { + connection_id: id, + error: &dial_error, + peer_id: Some(peer_id), + }, + )); + + self.pending_swarm_events.push_back( + SwarmEvent::OutgoingConnectionError { + peer_id: Some(peer_id), + connection_id: id, + error: dial_error, + }, + ); + return; + } + } + } + ConnectedPoint::Listener { + local_addr, + send_back_addr, + } => { + match self.behaviour.handle_established_inbound_connection( + id, + peer_id, + &local_addr, + &send_back_addr, + ) { + Ok(handler) => handler, + Err(cause) => { + let listen_error = ListenError::Denied { cause }; + self.behaviour.on_swarm_event(FromSwarm::ListenFailure( + ListenFailure { + local_addr: &local_addr, + send_back_addr: &send_back_addr, + error: &listen_error, + connection_id: id, + peer_id: Some(peer_id), + }, + )); + + self.pending_swarm_events.push_back( + SwarmEvent::IncomingConnectionError { + connection_id: id, + send_back_addr, + local_addr, + error: listen_error, + }, + ); + return; + } + } + } + }; + + let supported_protocols = handler + .listen_protocol() + .upgrade() + .protocol_info() + .map(|p| p.as_ref().as_bytes().to_vec()) + .collect(); + let other_established_connection_ids = self + .pool + .iter_established_connections_of_peer(&peer_id) + .collect::>(); + let num_established = NonZeroU32::new( + u32::try_from(other_established_connection_ids.len() + 1).unwrap(), + ) + .expect("n + 1 is always non-zero; qed"); + + self.pool + .spawn_connection(id, peer_id, &endpoint, connection, handler); + + tracing::debug!( + peer=%peer_id, + ?endpoint, + total_peers=%num_established, + "Connection established" + ); + let failed_addresses = concurrent_dial_errors + .as_ref() + .map(|es| { + es.iter() + .map(|(a, _)| a) + .cloned() + .collect::>() + }) + .unwrap_or_default(); + self.behaviour + .on_swarm_event(FromSwarm::ConnectionEstablished( + behaviour::ConnectionEstablished { + peer_id, + connection_id: id, + endpoint: &endpoint, + failed_addresses: &failed_addresses, + other_established: other_established_connection_ids.len(), + }, + )); + self.supported_protocols = supported_protocols; + self.pending_swarm_events + .push_back(SwarmEvent::ConnectionEstablished { + peer_id, + connection_id: id, + num_established, + endpoint, + concurrent_dial_errors, + established_in, + }); + } + PoolEvent::PendingOutboundConnectionError { + id: connection_id, + error, + peer, + } => { + let error = error.into(); + + self.behaviour + .on_swarm_event(FromSwarm::DialFailure(DialFailure { + peer_id: peer, + error: &error, + connection_id, + })); + + if let Some(peer) = peer { + tracing::debug!(%peer, "Connection attempt to peer failed with {:?}.", error,); + } else { + tracing::debug!("Connection attempt to unknown peer failed with {:?}", error); + } + + self.pending_swarm_events + .push_back(SwarmEvent::OutgoingConnectionError { + peer_id: peer, + connection_id, + error, + }); + } + PoolEvent::PendingInboundConnectionError { + id, + send_back_addr, + local_addr, + error, + } => { + let error = error.into(); + + tracing::debug!("Incoming connection failed: {:?}", error); + self.behaviour + .on_swarm_event(FromSwarm::ListenFailure(ListenFailure { + local_addr: &local_addr, + send_back_addr: &send_back_addr, + error: &error, + connection_id: id, + peer_id: None, + })); + self.pending_swarm_events + .push_back(SwarmEvent::IncomingConnectionError { + connection_id: id, + local_addr, + send_back_addr, + error, + }); + } + PoolEvent::ConnectionClosed { + id, + connected, + error, + remaining_established_connection_ids, + .. + } => { + if let Some(error) = error.as_ref() { + tracing::debug!( + total_peers=%remaining_established_connection_ids.len(), + "Connection closed with error {:?}: {:?}", + error, + connected, + ); + } else { + tracing::debug!( + total_peers=%remaining_established_connection_ids.len(), + "Connection closed: {:?}", + connected + ); + } + let peer_id = connected.peer_id; + let endpoint = connected.endpoint; + let num_established = + u32::try_from(remaining_established_connection_ids.len()).unwrap(); + + self.behaviour + .on_swarm_event(FromSwarm::ConnectionClosed(ConnectionClosed { + peer_id, + connection_id: id, + endpoint: &endpoint, + cause: error.as_ref(), + remaining_established: num_established as usize, + })); + self.pending_swarm_events + .push_back(SwarmEvent::ConnectionClosed { + peer_id, + connection_id: id, + endpoint, + cause: error, + num_established, + }); + } + PoolEvent::ConnectionEvent { peer_id, id, event } => { + self.behaviour + .on_connection_handler_event(peer_id, id, event); + } + PoolEvent::AddressChange { + peer_id, + id, + new_endpoint, + old_endpoint, + } => { + self.behaviour + .on_swarm_event(FromSwarm::AddressChange(AddressChange { + peer_id, + connection_id: id, + old: &old_endpoint, + new: &new_endpoint, + })); + } + } + } + + fn handle_transport_event( + &mut self, + event: TransportEvent< + as Transport>::ListenerUpgrade, + io::Error, + >, + ) { + match event { + TransportEvent::Incoming { + listener_id: _, + upgrade, + local_addr, + send_back_addr, + } => { + let connection_id = ConnectionId::next(); + + match self.behaviour.handle_pending_inbound_connection( + connection_id, + &local_addr, + &send_back_addr, + ) { + Ok(()) => {} + Err(cause) => { + let listen_error = ListenError::Denied { cause }; + + self.behaviour + .on_swarm_event(FromSwarm::ListenFailure(ListenFailure { + local_addr: &local_addr, + send_back_addr: &send_back_addr, + error: &listen_error, + connection_id, + peer_id: None, + })); + + self.pending_swarm_events + .push_back(SwarmEvent::IncomingConnectionError { + connection_id, + local_addr, + send_back_addr, + error: listen_error, + }); + return; + } + } + + self.pool.add_incoming( + upgrade, + IncomingInfo { + local_addr: &local_addr, + send_back_addr: &send_back_addr, + }, + connection_id, + ); + + self.pending_swarm_events + .push_back(SwarmEvent::IncomingConnection { + connection_id, + local_addr, + send_back_addr, + }) + } + TransportEvent::NewAddress { + listener_id, + listen_addr, + } => { + tracing::debug!( + listener=?listener_id, + address=%listen_addr, + "New listener address" + ); + let addrs = self.listened_addrs.entry(listener_id).or_default(); + if !addrs.contains(&listen_addr) { + addrs.push(listen_addr.clone()) + } + self.behaviour + .on_swarm_event(FromSwarm::NewListenAddr(NewListenAddr { + listener_id, + addr: &listen_addr, + })); + self.pending_swarm_events + .push_back(SwarmEvent::NewListenAddr { + listener_id, + address: listen_addr, + }) + } + TransportEvent::AddressExpired { + listener_id, + listen_addr, + } => { + tracing::debug!( + listener=?listener_id, + address=%listen_addr, + "Expired listener address" + ); + if let Some(addrs) = self.listened_addrs.get_mut(&listener_id) { + addrs.retain(|a| a != &listen_addr); + } + self.behaviour + .on_swarm_event(FromSwarm::ExpiredListenAddr(ExpiredListenAddr { + listener_id, + addr: &listen_addr, + })); + self.pending_swarm_events + .push_back(SwarmEvent::ExpiredListenAddr { + listener_id, + address: listen_addr, + }) + } + TransportEvent::ListenerClosed { + listener_id, + reason, + } => { + tracing::debug!( + listener=?listener_id, + ?reason, + "Listener closed" + ); + let addrs = self.listened_addrs.remove(&listener_id).unwrap_or_default(); + for addr in addrs.iter() { + self.behaviour.on_swarm_event(FromSwarm::ExpiredListenAddr( + ExpiredListenAddr { listener_id, addr }, + )); + } + self.behaviour + .on_swarm_event(FromSwarm::ListenerClosed(ListenerClosed { + listener_id, + reason: reason.as_ref().copied(), + })); + self.pending_swarm_events + .push_back(SwarmEvent::ListenerClosed { + listener_id, + addresses: addrs.to_vec(), + reason, + }) + } + TransportEvent::ListenerError { listener_id, error } => { + self.behaviour + .on_swarm_event(FromSwarm::ListenerError(ListenerError { + listener_id, + err: &error, + })); + self.pending_swarm_events + .push_back(SwarmEvent::ListenerError { listener_id, error }) + } + } + } + + fn handle_behaviour_event( + &mut self, + event: ToSwarm>, + ) { + match event { + ToSwarm::GenerateEvent(event) => { + self.pending_swarm_events + .push_back(SwarmEvent::Behaviour(event)); + } + ToSwarm::Dial { opts } => { + let peer_id = opts.get_peer_id(); + let connection_id = opts.connection_id(); + if let Ok(()) = self.dial(opts) { + self.pending_swarm_events.push_back(SwarmEvent::Dialing { + peer_id, + connection_id, + }); + } + } + ToSwarm::ListenOn { opts } => { + // Error is dispatched internally, safe to ignore. + let _ = self.add_listener(opts); + } + ToSwarm::RemoveListener { id } => { + self.remove_listener(id); + } + ToSwarm::NotifyHandler { + peer_id, + handler, + event, + } => { + assert!(self.pending_handler_event.is_none()); + let handler = match handler { + NotifyHandler::One(connection) => PendingNotifyHandler::One(connection), + NotifyHandler::Any => { + let ids = self + .pool + .iter_established_connections_of_peer(&peer_id) + .collect(); + PendingNotifyHandler::Any(ids) + } + }; + + self.pending_handler_event = Some((peer_id, handler, event)); + } + ToSwarm::NewExternalAddrCandidate(addr) => { + self.behaviour + .on_swarm_event(FromSwarm::NewExternalAddrCandidate( + NewExternalAddrCandidate { addr: &addr }, + )); + self.pending_swarm_events + .push_back(SwarmEvent::NewExternalAddrCandidate { address: addr }); + } + ToSwarm::ExternalAddrConfirmed(addr) => { + self.add_external_address(addr.clone()); + self.pending_swarm_events + .push_back(SwarmEvent::ExternalAddrConfirmed { address: addr }); + } + ToSwarm::ExternalAddrExpired(addr) => { + self.remove_external_address(&addr); + self.pending_swarm_events + .push_back(SwarmEvent::ExternalAddrExpired { address: addr }); + } + ToSwarm::CloseConnection { + peer_id, + connection, + } => match connection { + CloseConnection::One(connection_id) => { + if let Some(conn) = self.pool.get_established(connection_id) { + conn.start_close(); + } + } + CloseConnection::All => { + self.pool.disconnect(peer_id); + } + }, + ToSwarm::NewExternalAddrOfPeer { peer_id, address } => { + self.behaviour + .on_swarm_event(FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { + peer_id, + addr: &address, + })); + self.pending_swarm_events + .push_back(SwarmEvent::NewExternalAddrOfPeer { peer_id, address }); + } + } + } + + /// Internal function used by everything event-related. + /// + /// Polls the `Swarm` for the next event. + #[tracing::instrument(level = "debug", name = "Swarm::poll", skip(self, cx))] + fn poll_next_event( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + // We use a `this` variable because the compiler can't mutably borrow multiple times + // across a `Deref`. + let this = &mut *self; + + // This loop polls the components below in a prioritized order. + // + // 1. [`NetworkBehaviour`] + // 2. Connection [`Pool`] + // 3. [`ListenersStream`] + // + // (1) is polled before (2) to prioritize local work over work coming from a remote. + // + // (2) is polled before (3) to prioritize existing connections over upgrading new incoming connections. + loop { + if let Some(swarm_event) = this.pending_swarm_events.pop_front() { + return Poll::Ready(swarm_event); + } + + match this.pending_handler_event.take() { + // Try to deliver the pending event emitted by the [`NetworkBehaviour`] in the previous + // iteration to the connection handler(s). + Some((peer_id, handler, event)) => match handler { + PendingNotifyHandler::One(conn_id) => { + match this.pool.get_established(conn_id) { + Some(conn) => match notify_one(conn, event, cx) { + None => continue, + Some(event) => { + this.pending_handler_event = Some((peer_id, handler, event)); + } + }, + None => continue, + } + } + PendingNotifyHandler::Any(ids) => { + match notify_any::<_, TBehaviour>(ids, &mut this.pool, event, cx) { + None => continue, + Some((event, ids)) => { + let handler = PendingNotifyHandler::Any(ids); + this.pending_handler_event = Some((peer_id, handler, event)); + } + } + } + }, + // No pending event. Allow the [`NetworkBehaviour`] to make progress. + None => match this.behaviour.poll(cx) { + Poll::Pending => {} + Poll::Ready(behaviour_event) => { + this.handle_behaviour_event(behaviour_event); + + continue; + } + }, + } + + // Poll the known peers. + match this.pool.poll(cx) { + Poll::Pending => {} + Poll::Ready(pool_event) => { + this.handle_pool_event(pool_event); + continue; + } + } + + // Poll the listener(s) for new connections. + match Pin::new(&mut this.transport).poll(cx) { + Poll::Pending => {} + Poll::Ready(transport_event) => { + this.handle_transport_event(transport_event); + continue; + } + } + + return Poll::Pending; + } + } +} + +/// Connection to notify of a pending event. +/// +/// The connection IDs out of which to notify one of an event are captured at +/// the time the behaviour emits the event, in order not to forward the event to +/// a new connection which the behaviour may not have been aware of at the time +/// it issued the request for sending it. +enum PendingNotifyHandler { + One(ConnectionId), + Any(SmallVec<[ConnectionId; 10]>), +} + +/// Notify a single connection of an event. +/// +/// Returns `Some` with the given event if the connection is not currently +/// ready to receive another event, in which case the current task is +/// scheduled to be woken up. +/// +/// Returns `None` if the connection is closing or the event has been +/// successfully sent, in either case the event is consumed. +fn notify_one( + conn: &mut EstablishedConnection, + event: THandlerInEvent, + cx: &mut Context<'_>, +) -> Option { + match conn.poll_ready_notify_handler(cx) { + Poll::Pending => Some(event), + Poll::Ready(Err(())) => None, // connection is closing + Poll::Ready(Ok(())) => { + // Can now only fail if connection is closing. + let _ = conn.notify_handler(event); + None + } + } +} + +/// Notify any one of a given list of connections of a peer of an event. +/// +/// Returns `Some` with the given event and a new list of connections if +/// none of the given connections was able to receive the event but at +/// least one of them is not closing, in which case the current task +/// is scheduled to be woken up. The returned connections are those which +/// may still become ready to receive another event. +/// +/// Returns `None` if either all connections are closing or the event +/// was successfully sent to a handler, in either case the event is consumed. +fn notify_any( + ids: SmallVec<[ConnectionId; 10]>, + pool: &mut Pool, + event: THandlerInEvent, + cx: &mut Context<'_>, +) -> Option<(THandlerInEvent, SmallVec<[ConnectionId; 10]>)> +where + TBehaviour: NetworkBehaviour, + THandler: ConnectionHandler< + FromBehaviour = THandlerInEvent, + ToBehaviour = THandlerOutEvent, + >, +{ + let mut pending = SmallVec::new(); + let mut event = Some(event); // (1) + for id in ids.into_iter() { + if let Some(conn) = pool.get_established(id) { + match conn.poll_ready_notify_handler(cx) { + Poll::Pending => pending.push(id), + Poll::Ready(Err(())) => {} // connection is closing + Poll::Ready(Ok(())) => { + let e = event.take().expect("by (1),(2)"); + if let Err(e) = conn.notify_handler(e) { + event = Some(e) // (2) + } else { + break; + } + } + } + } + } + + event.and_then(|e| { + if !pending.is_empty() { + Some((e, pending)) + } else { + None + } + }) +} + +/// Stream of events returned by [`Swarm`]. +/// +/// Includes events from the [`NetworkBehaviour`] as well as events about +/// connection and listener status. See [`SwarmEvent`] for details. +/// +/// Note: This stream is infinite and it is guaranteed that +/// [`futures::Stream::poll_next`] will never return `Poll::Ready(None)`. +impl futures::Stream for Swarm +where + TBehaviour: NetworkBehaviour, +{ + type Item = SwarmEvent>; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.as_mut().poll_next_event(cx).map(Some) + } +} + +/// The stream of swarm events never terminates, so we can implement fused for it. +impl FusedStream for Swarm +where + TBehaviour: NetworkBehaviour, +{ + fn is_terminated(&self) -> bool { + false + } +} + +pub struct Config { + pool_config: PoolConfig, +} + +impl Config { + /// Creates a new [`Config`] from the given executor. The [`Swarm`] is obtained via + /// [`Swarm::new`]. + pub fn with_executor(executor: impl Executor + Send + 'static) -> Self { + Self { + pool_config: PoolConfig::new(Some(Box::new(executor))), + } + } + + #[doc(hidden)] + /// Used on connection benchmarks. + pub fn without_executor() -> Self { + Self { + pool_config: PoolConfig::new(None), + } + } + + /// Sets executor to the `wasm` executor. + /// Background tasks will be executed by the browser on the next micro-tick. + /// + /// Spawning a task is similar too: + /// ```typescript + /// function spawn(task: () => Promise) { + /// task() + /// } + /// ``` + #[cfg(feature = "wasm-bindgen")] + pub fn with_wasm_executor() -> Self { + Self::with_executor(crate::executor::WasmBindgenExecutor) + } + + /// Builds a new [`Config`] from the given `tokio` executor. + #[cfg(all( + feature = "tokio", + not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) + ))] + pub fn with_tokio_executor() -> Self { + Self::with_executor(crate::executor::TokioExecutor) + } + + /// Builds a new [`Config`] from the given `async-std` executor. + #[cfg(all( + feature = "async-std", + not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) + ))] + pub fn with_async_std_executor() -> Self { + Self::with_executor(crate::executor::AsyncStdExecutor) + } + + /// Configures the number of events from the [`NetworkBehaviour`] in + /// destination to the [`ConnectionHandler`] that can be buffered before + /// the [`Swarm`] has to wait. An individual buffer with this number of + /// events exists for each individual connection. + /// + /// The ideal value depends on the executor used, the CPU speed, and the + /// volume of events. If this value is too low, then the [`Swarm`] will + /// be sleeping more often than necessary. Increasing this value increases + /// the overall memory usage. + pub fn with_notify_handler_buffer_size(mut self, n: NonZeroUsize) -> Self { + self.pool_config = self.pool_config.with_notify_handler_buffer_size(n); + self + } + + /// Configures the size of the buffer for events sent by a [`ConnectionHandler`] to the + /// [`NetworkBehaviour`]. + /// + /// Each connection has its own buffer. + /// + /// The ideal value depends on the executor used, the CPU speed and the volume of events. + /// If this value is too low, then the [`ConnectionHandler`]s will be sleeping more often + /// than necessary. Increasing this value increases the overall memory + /// usage, and more importantly the latency between the moment when an + /// event is emitted and the moment when it is received by the + /// [`NetworkBehaviour`]. + pub fn with_per_connection_event_buffer_size(mut self, n: usize) -> Self { + self.pool_config = self.pool_config.with_per_connection_event_buffer_size(n); + self + } + + /// Number of addresses concurrently dialed for a single outbound connection attempt. + pub fn with_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self { + self.pool_config = self.pool_config.with_dial_concurrency_factor(factor); + self + } + + /// Configures an override for the substream upgrade protocol to use. + /// + /// The subtream upgrade protocol is the multistream-select protocol + /// used for protocol negotiation on substreams. Since a listener + /// supports all existing versions, the choice of upgrade protocol + /// only effects the "dialer", i.e. the peer opening a substream. + /// + /// > **Note**: If configured, specific upgrade protocols for + /// > individual [`SubstreamProtocol`]s emitted by the `NetworkBehaviour` + /// > are ignored. + pub fn with_substream_upgrade_protocol_override( + mut self, + v: libp2p_core::upgrade::Version, + ) -> Self { + self.pool_config = self.pool_config.with_substream_upgrade_protocol_override(v); + self + } + + /// The maximum number of inbound streams concurrently negotiating on a + /// connection. New inbound streams exceeding the limit are dropped and thus + /// reset. + /// + /// Note: This only enforces a limit on the number of concurrently + /// negotiating inbound streams. The total number of inbound streams on a + /// connection is the sum of negotiating and negotiated streams. A limit on + /// the total number of streams can be enforced at the + /// [`StreamMuxerBox`] level. + pub fn with_max_negotiating_inbound_streams(mut self, v: usize) -> Self { + self.pool_config = self.pool_config.with_max_negotiating_inbound_streams(v); + self + } + + /// How long to keep a connection alive once it is idling. + /// + /// Defaults to 0. + pub fn with_idle_connection_timeout(mut self, timeout: Duration) -> Self { + self.pool_config.idle_connection_timeout = timeout; + self + } +} + +/// Possible errors when trying to establish or upgrade an outbound connection. +#[derive(Debug)] +pub enum DialError { + /// The peer identity obtained on the connection matches the local peer. + LocalPeerId { endpoint: ConnectedPoint }, + /// No addresses have been provided by [`NetworkBehaviour::handle_pending_outbound_connection`] and [`DialOpts`]. + NoAddresses, + /// The provided [`dial_opts::PeerCondition`] evaluated to false and thus + /// the dial was aborted. + DialPeerConditionFalse(dial_opts::PeerCondition), + /// Pending connection attempt has been aborted. + Aborted, + /// The peer identity obtained on the connection did not match the one that was expected. + WrongPeerId { + obtained: PeerId, + endpoint: ConnectedPoint, + }, + /// One of the [`NetworkBehaviour`]s rejected the outbound connection + /// via [`NetworkBehaviour::handle_pending_outbound_connection`] or + /// [`NetworkBehaviour::handle_established_outbound_connection`]. + Denied { cause: ConnectionDenied }, + /// An error occurred while negotiating the transport protocol(s) on a connection. + Transport(Vec<(Multiaddr, TransportError)>), +} + +impl From for DialError { + fn from(error: PendingOutboundConnectionError) -> Self { + match error { + PendingConnectionError::Aborted => DialError::Aborted, + PendingConnectionError::WrongPeerId { obtained, endpoint } => { + DialError::WrongPeerId { obtained, endpoint } + } + PendingConnectionError::LocalPeerId { endpoint } => DialError::LocalPeerId { endpoint }, + PendingConnectionError::Transport(e) => DialError::Transport(e), + } + } +} + +impl fmt::Display for DialError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + DialError::NoAddresses => write!(f, "Dial error: no addresses for peer."), + DialError::LocalPeerId { endpoint } => write!( + f, + "Dial error: tried to dial local peer id at {endpoint:?}." + ), + DialError::DialPeerConditionFalse(PeerCondition::Disconnected) => write!(f, "Dial error: dial condition was configured to only happen when disconnected (`PeerCondition::Disconnected`), but node is already connected, thus cancelling new dial."), + DialError::DialPeerConditionFalse(PeerCondition::NotDialing) => write!(f, "Dial error: dial condition was configured to only happen if there is currently no ongoing dialing attempt (`PeerCondition::NotDialing`), but a dial is in progress, thus cancelling new dial."), + DialError::DialPeerConditionFalse(PeerCondition::DisconnectedAndNotDialing) => write!(f, "Dial error: dial condition was configured to only happen when both disconnected (`PeerCondition::Disconnected`) and there is currently no ongoing dialing attempt (`PeerCondition::NotDialing`), but node is already connected or dial is in progress, thus cancelling new dial."), + DialError::DialPeerConditionFalse(PeerCondition::Always) => unreachable!("Dial peer condition is by definition true."), + DialError::Aborted => write!( + f, + "Dial error: Pending connection attempt has been aborted." + ), + DialError::WrongPeerId { obtained, endpoint } => write!( + f, + "Dial error: Unexpected peer ID {obtained} at {endpoint:?}." + ), + DialError::Transport(errors) => { + write!(f, "Failed to negotiate transport protocol(s): [")?; + + for (addr, error) in errors { + write!(f, "({addr}")?; + print_error_chain(f, error)?; + write!(f, ")")?; + } + write!(f, "]")?; + + Ok(()) + } + DialError::Denied { .. } => { + write!(f, "Dial error") + } + } + } +} + +fn print_error_chain(f: &mut fmt::Formatter<'_>, e: &dyn error::Error) -> fmt::Result { + write!(f, ": {e}")?; + + if let Some(source) = e.source() { + print_error_chain(f, source)?; + } + + Ok(()) +} + +impl error::Error for DialError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + DialError::LocalPeerId { .. } => None, + DialError::NoAddresses => None, + DialError::DialPeerConditionFalse(_) => None, + DialError::Aborted => None, + DialError::WrongPeerId { .. } => None, + DialError::Transport(_) => None, + DialError::Denied { cause } => Some(cause), + } + } +} + +/// Possible errors when upgrading an inbound connection. +#[derive(Debug)] +pub enum ListenError { + /// Pending connection attempt has been aborted. + Aborted, + /// The peer identity obtained on the connection did not match the one that was expected. + WrongPeerId { + obtained: PeerId, + endpoint: ConnectedPoint, + }, + /// The connection was dropped because it resolved to our own [`PeerId`]. + LocalPeerId { + endpoint: ConnectedPoint, + }, + Denied { + cause: ConnectionDenied, + }, + /// An error occurred while negotiating the transport protocol(s) on a connection. + Transport(TransportError), +} + +impl From for ListenError { + fn from(error: PendingInboundConnectionError) -> Self { + match error { + PendingInboundConnectionError::Transport(inner) => ListenError::Transport(inner), + PendingInboundConnectionError::Aborted => ListenError::Aborted, + PendingInboundConnectionError::WrongPeerId { obtained, endpoint } => { + ListenError::WrongPeerId { obtained, endpoint } + } + PendingInboundConnectionError::LocalPeerId { endpoint } => { + ListenError::LocalPeerId { endpoint } + } + } + } +} + +impl fmt::Display for ListenError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ListenError::Aborted => write!( + f, + "Listen error: Pending connection attempt has been aborted." + ), + ListenError::WrongPeerId { obtained, endpoint } => write!( + f, + "Listen error: Unexpected peer ID {obtained} at {endpoint:?}." + ), + ListenError::Transport(_) => { + write!(f, "Listen error: Failed to negotiate transport protocol(s)") + } + ListenError::Denied { cause } => { + write!(f, "Listen error: Denied: {cause}") + } + ListenError::LocalPeerId { endpoint } => { + write!(f, "Listen error: Local peer ID at {endpoint:?}.") + } + } + } +} + +impl error::Error for ListenError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + ListenError::WrongPeerId { .. } => None, + ListenError::Transport(err) => Some(err), + ListenError::Aborted => None, + ListenError::Denied { cause } => Some(cause), + ListenError::LocalPeerId { .. } => None, + } + } +} + +/// A connection was denied. +/// +/// To figure out which [`NetworkBehaviour`] denied the connection, use [`ConnectionDenied::downcast`]. +#[derive(Debug)] +pub struct ConnectionDenied { + inner: Box, +} + +impl ConnectionDenied { + pub fn new(cause: impl Into>) -> Self { + Self { + inner: cause.into(), + } + } + + /// Attempt to downcast to a particular reason for why the connection was denied. + pub fn downcast(self) -> Result + where + E: error::Error + Send + Sync + 'static, + { + let inner = self + .inner + .downcast::() + .map_err(|inner| ConnectionDenied { inner })?; + + Ok(*inner) + } + + /// Attempt to downcast to a particular reason for why the connection was denied. + pub fn downcast_ref(&self) -> Option<&E> + where + E: error::Error + Send + Sync + 'static, + { + self.inner.downcast_ref::() + } +} + +impl fmt::Display for ConnectionDenied { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "connection denied") + } +} + +impl error::Error for ConnectionDenied { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + Some(self.inner.as_ref()) + } +} + +/// Information about the connections obtained by [`Swarm::network_info()`]. +#[derive(Clone, Debug)] +pub struct NetworkInfo { + /// The total number of connected peers. + num_peers: usize, + /// Counters of ongoing network connections. + connection_counters: ConnectionCounters, +} + +impl NetworkInfo { + /// The number of connected peers, i.e. peers with whom at least + /// one established connection exists. + pub fn num_peers(&self) -> usize { + self.num_peers + } + + /// Gets counters for ongoing network connections. + pub fn connection_counters(&self) -> &ConnectionCounters { + &self.connection_counters + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::{CallTraceBehaviour, MockBehaviour}; + use libp2p_core::multiaddr::multiaddr; + use libp2p_core::transport::memory::MemoryTransportError; + use libp2p_core::transport::{PortUse, TransportEvent}; + use libp2p_core::Endpoint; + use libp2p_core::{multiaddr, transport, upgrade}; + use libp2p_identity as identity; + use libp2p_plaintext as plaintext; + use libp2p_yamux as yamux; + use quickcheck::*; + + // Test execution state. + // Connection => Disconnecting => Connecting. + enum State { + Connecting, + Disconnecting, + } + + fn new_test_swarm( + config: Config, + ) -> Swarm>> { + let id_keys = identity::Keypair::generate_ed25519(); + let local_public_key = id_keys.public(); + let transport = transport::MemoryTransport::default() + .upgrade(upgrade::Version::V1) + .authenticate(plaintext::Config::new(&id_keys)) + .multiplex(yamux::Config::default()) + .boxed(); + let behaviour = CallTraceBehaviour::new(MockBehaviour::new(dummy::ConnectionHandler)); + + Swarm::new( + transport, + behaviour, + local_public_key.into(), + config.with_idle_connection_timeout(Duration::from_secs(5)), + ) + } + + fn swarms_connected( + swarm1: &Swarm>, + swarm2: &Swarm>, + num_connections: usize, + ) -> bool + where + TBehaviour: NetworkBehaviour, + THandlerOutEvent: Clone, + { + swarm1 + .behaviour() + .num_connections_to_peer(*swarm2.local_peer_id()) + == num_connections + && swarm2 + .behaviour() + .num_connections_to_peer(*swarm1.local_peer_id()) + == num_connections + && swarm1.is_connected(swarm2.local_peer_id()) + && swarm2.is_connected(swarm1.local_peer_id()) + } + + fn swarms_disconnected( + swarm1: &Swarm>, + swarm2: &Swarm>, + ) -> bool + where + TBehaviour: NetworkBehaviour, + THandlerOutEvent: Clone, + { + swarm1 + .behaviour() + .num_connections_to_peer(*swarm2.local_peer_id()) + == 0 + && swarm2 + .behaviour() + .num_connections_to_peer(*swarm1.local_peer_id()) + == 0 + && !swarm1.is_connected(swarm2.local_peer_id()) + && !swarm2.is_connected(swarm1.local_peer_id()) + } + + /// Establishes multiple connections between two peers, + /// after which one peer disconnects the other using [`Swarm::disconnect_peer_id`]. + /// + /// The test expects both behaviours to be notified via calls to [`NetworkBehaviour::on_swarm_event`] + /// with pairs of [`FromSwarm::ConnectionEstablished`] / [`FromSwarm::ConnectionClosed`] + #[tokio::test] + async fn test_swarm_disconnect() { + let mut swarm1 = new_test_swarm(Config::with_tokio_executor()); + let mut swarm2 = new_test_swarm(Config::with_tokio_executor()); + + let addr1: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); + let addr2: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); + + swarm1.listen_on(addr1.clone()).unwrap(); + swarm2.listen_on(addr2.clone()).unwrap(); + + let swarm1_id = *swarm1.local_peer_id(); + + let mut reconnected = false; + let num_connections = 10; + + for _ in 0..num_connections { + swarm1.dial(addr2.clone()).unwrap(); + } + let mut state = State::Connecting; + + future::poll_fn(move |cx| loop { + let poll1 = Swarm::poll_next_event(Pin::new(&mut swarm1), cx); + let poll2 = Swarm::poll_next_event(Pin::new(&mut swarm2), cx); + match state { + State::Connecting => { + if swarms_connected(&swarm1, &swarm2, num_connections) { + if reconnected { + return Poll::Ready(()); + } + swarm2 + .disconnect_peer_id(swarm1_id) + .expect("Error disconnecting"); + state = State::Disconnecting; + } + } + State::Disconnecting => { + if swarms_disconnected(&swarm1, &swarm2) { + if reconnected { + return Poll::Ready(()); + } + reconnected = true; + for _ in 0..num_connections { + swarm2.dial(addr1.clone()).unwrap(); + } + state = State::Connecting; + } + } + } + + if poll1.is_pending() && poll2.is_pending() { + return Poll::Pending; + } + }) + .await + } + + /// Establishes multiple connections between two peers, + /// after which one peer disconnects the other + /// using [`ToSwarm::CloseConnection`] returned by a [`NetworkBehaviour`]. + /// + /// The test expects both behaviours to be notified via calls to [`NetworkBehaviour::on_swarm_event`] + /// with pairs of [`FromSwarm::ConnectionEstablished`] / [`FromSwarm::ConnectionClosed`] + #[tokio::test] + async fn test_behaviour_disconnect_all() { + let mut swarm1 = new_test_swarm(Config::with_tokio_executor()); + let mut swarm2 = new_test_swarm(Config::with_tokio_executor()); + + let addr1: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); + let addr2: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); + + swarm1.listen_on(addr1.clone()).unwrap(); + swarm2.listen_on(addr2.clone()).unwrap(); + + let swarm1_id = *swarm1.local_peer_id(); + + let mut reconnected = false; + let num_connections = 10; + + for _ in 0..num_connections { + swarm1.dial(addr2.clone()).unwrap(); + } + let mut state = State::Connecting; + + future::poll_fn(move |cx| loop { + let poll1 = Swarm::poll_next_event(Pin::new(&mut swarm1), cx); + let poll2 = Swarm::poll_next_event(Pin::new(&mut swarm2), cx); + match state { + State::Connecting => { + if swarms_connected(&swarm1, &swarm2, num_connections) { + if reconnected { + return Poll::Ready(()); + } + swarm2 + .behaviour + .inner() + .next_action + .replace(ToSwarm::CloseConnection { + peer_id: swarm1_id, + connection: CloseConnection::All, + }); + state = State::Disconnecting; + continue; + } + } + State::Disconnecting => { + if swarms_disconnected(&swarm1, &swarm2) { + reconnected = true; + for _ in 0..num_connections { + swarm2.dial(addr1.clone()).unwrap(); + } + state = State::Connecting; + continue; + } + } + } + + if poll1.is_pending() && poll2.is_pending() { + return Poll::Pending; + } + }) + .await + } + + /// Establishes multiple connections between two peers, + /// after which one peer closes a single connection + /// using [`ToSwarm::CloseConnection`] returned by a [`NetworkBehaviour`]. + /// + /// The test expects both behaviours to be notified via calls to [`NetworkBehaviour::on_swarm_event`] + /// with pairs of [`FromSwarm::ConnectionEstablished`] / [`FromSwarm::ConnectionClosed`] + #[tokio::test] + async fn test_behaviour_disconnect_one() { + let mut swarm1 = new_test_swarm(Config::with_tokio_executor()); + let mut swarm2 = new_test_swarm(Config::with_tokio_executor()); + + let addr1: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); + let addr2: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); + + swarm1.listen_on(addr1).unwrap(); + swarm2.listen_on(addr2.clone()).unwrap(); + + let swarm1_id = *swarm1.local_peer_id(); + + let num_connections = 10; + + for _ in 0..num_connections { + swarm1.dial(addr2.clone()).unwrap(); + } + let mut state = State::Connecting; + let mut disconnected_conn_id = None; + + future::poll_fn(move |cx| loop { + let poll1 = Swarm::poll_next_event(Pin::new(&mut swarm1), cx); + let poll2 = Swarm::poll_next_event(Pin::new(&mut swarm2), cx); + match state { + State::Connecting => { + if swarms_connected(&swarm1, &swarm2, num_connections) { + disconnected_conn_id = { + let conn_id = + swarm2.behaviour.on_connection_established[num_connections / 2].1; + swarm2.behaviour.inner().next_action.replace( + ToSwarm::CloseConnection { + peer_id: swarm1_id, + connection: CloseConnection::One(conn_id), + }, + ); + Some(conn_id) + }; + state = State::Disconnecting; + } + } + State::Disconnecting => { + for s in &[&swarm1, &swarm2] { + assert!(s + .behaviour + .on_connection_closed + .iter() + .all(|(.., remaining_conns)| *remaining_conns > 0)); + assert_eq!(s.behaviour.on_connection_established.len(), num_connections); + s.behaviour.assert_connected(num_connections, 1); + } + if [&swarm1, &swarm2] + .iter() + .all(|s| s.behaviour.on_connection_closed.len() == 1) + { + let conn_id = swarm2.behaviour.on_connection_closed[0].1; + assert_eq!(Some(conn_id), disconnected_conn_id); + return Poll::Ready(()); + } + } + } + + if poll1.is_pending() && poll2.is_pending() { + return Poll::Pending; + } + }) + .await + } + + #[test] + fn concurrent_dialing() { + #[derive(Clone, Debug)] + struct DialConcurrencyFactor(NonZeroU8); + + impl Arbitrary for DialConcurrencyFactor { + fn arbitrary(g: &mut Gen) -> Self { + Self(NonZeroU8::new(g.gen_range(1..11)).unwrap()) + } + } + + fn prop(concurrency_factor: DialConcurrencyFactor) { + tokio::runtime::Runtime::new().unwrap().block_on(async { + let mut swarm = new_test_swarm( + Config::with_tokio_executor() + .with_dial_concurrency_factor(concurrency_factor.0), + ); + + // Listen on `concurrency_factor + 1` addresses. + // + // `+ 2` to ensure a subset of addresses is dialed by network_2. + let num_listen_addrs = concurrency_factor.0.get() + 2; + let mut listen_addresses = Vec::new(); + let mut transports = Vec::new(); + for _ in 0..num_listen_addrs { + let mut transport = transport::MemoryTransport::default().boxed(); + transport + .listen_on(ListenerId::next(), "/memory/0".parse().unwrap()) + .unwrap(); + + match transport.select_next_some().await { + TransportEvent::NewAddress { listen_addr, .. } => { + listen_addresses.push(listen_addr); + } + _ => panic!("Expected `NewListenAddr` event."), + } + + transports.push(transport); + } + + // Have swarm dial each listener and wait for each listener to receive the incoming + // connections. + swarm + .dial( + DialOpts::peer_id(PeerId::random()) + .addresses(listen_addresses) + .build(), + ) + .unwrap(); + for mut transport in transports.into_iter() { + match futures::future::select(transport.select_next_some(), swarm.next()).await + { + future::Either::Left((TransportEvent::Incoming { .. }, _)) => {} + future::Either::Left(_) => { + panic!("Unexpected transport event.") + } + future::Either::Right((e, _)) => { + panic!("Expect swarm to not emit any event {e:?}") + } + } + } + + match swarm.next().await.unwrap() { + SwarmEvent::OutgoingConnectionError { .. } => {} + e => panic!("Unexpected swarm event {e:?}"), + } + }) + } + + QuickCheck::new().tests(10).quickcheck(prop as fn(_) -> _); + } + + #[tokio::test] + async fn invalid_peer_id() { + // Checks whether dialing an address containing the wrong peer id raises an error + // for the expected peer id instead of the obtained peer id. + + let mut swarm1 = new_test_swarm(Config::with_tokio_executor()); + let mut swarm2 = new_test_swarm(Config::with_tokio_executor()); + + swarm1.listen_on("/memory/0".parse().unwrap()).unwrap(); + + let address = future::poll_fn(|cx| match swarm1.poll_next_unpin(cx) { + Poll::Ready(Some(SwarmEvent::NewListenAddr { address, .. })) => Poll::Ready(address), + Poll::Pending => Poll::Pending, + _ => panic!("Was expecting the listen address to be reported"), + }) + .await; + + let other_id = PeerId::random(); + let other_addr = address.with(multiaddr::Protocol::P2p(other_id)); + + swarm2.dial(other_addr.clone()).unwrap(); + + let (peer_id, error) = future::poll_fn(|cx| { + if let Poll::Ready(Some(SwarmEvent::IncomingConnection { .. })) = + swarm1.poll_next_unpin(cx) + {} + + match swarm2.poll_next_unpin(cx) { + Poll::Ready(Some(SwarmEvent::OutgoingConnectionError { + peer_id, error, .. + })) => Poll::Ready((peer_id, error)), + Poll::Ready(x) => panic!("unexpected {x:?}"), + Poll::Pending => Poll::Pending, + } + }) + .await; + assert_eq!(peer_id.unwrap(), other_id); + match error { + DialError::WrongPeerId { obtained, endpoint } => { + assert_eq!(obtained, *swarm1.local_peer_id()); + assert_eq!( + endpoint, + ConnectedPoint::Dialer { + address: other_addr, + role_override: Endpoint::Dialer, + port_use: PortUse::Reuse, + } + ); + } + x => panic!("wrong error {x:?}"), + } + } + + #[tokio::test] + async fn dial_self() { + // Check whether dialing ourselves correctly fails. + // + // Dialing the same address we're listening should result in three events: + // + // - The incoming connection notification (before we know the incoming peer ID). + // - The connection error for the dialing endpoint (once we've determined that it's our own ID). + // - The connection error for the listening endpoint (once we've determined that it's our own ID). + // + // The last two can happen in any order. + + let mut swarm = new_test_swarm(Config::with_tokio_executor()); + swarm.listen_on("/memory/0".parse().unwrap()).unwrap(); + + let local_address = future::poll_fn(|cx| match swarm.poll_next_unpin(cx) { + Poll::Ready(Some(SwarmEvent::NewListenAddr { address, .. })) => Poll::Ready(address), + Poll::Pending => Poll::Pending, + _ => panic!("Was expecting the listen address to be reported"), + }) + .await; + + swarm.listened_addrs.clear(); // This is a hack to actually execute the dial to ourselves which would otherwise be filtered. + + swarm.dial(local_address.clone()).unwrap(); + + let mut got_dial_err = false; + let mut got_inc_err = false; + future::poll_fn(|cx| -> Poll> { + loop { + match swarm.poll_next_unpin(cx) { + Poll::Ready(Some(SwarmEvent::OutgoingConnectionError { + peer_id, + error: DialError::LocalPeerId { .. }, + .. + })) => { + assert_eq!(&peer_id.unwrap(), swarm.local_peer_id()); + assert!(!got_dial_err); + got_dial_err = true; + if got_inc_err { + return Poll::Ready(Ok(())); + } + } + Poll::Ready(Some(SwarmEvent::IncomingConnectionError { + local_addr, .. + })) => { + assert!(!got_inc_err); + assert_eq!(local_addr, local_address); + got_inc_err = true; + if got_dial_err { + return Poll::Ready(Ok(())); + } + } + Poll::Ready(Some(SwarmEvent::IncomingConnection { local_addr, .. })) => { + assert_eq!(local_addr, local_address); + } + Poll::Ready(ev) => { + panic!("Unexpected event: {ev:?}") + } + Poll::Pending => break Poll::Pending, + } + } + }) + .await + .unwrap(); + } + + #[tokio::test] + async fn dial_self_by_id() { + // Trying to dial self by passing the same `PeerId` shouldn't even be possible in the first + // place. + let swarm = new_test_swarm(Config::with_tokio_executor()); + let peer_id = *swarm.local_peer_id(); + assert!(!swarm.is_connected(&peer_id)); + } + + #[tokio::test] + async fn multiple_addresses_err() { + // Tries dialing multiple addresses, and makes sure there's one dialing error per address. + + let target = PeerId::random(); + + let mut swarm = new_test_swarm(Config::with_tokio_executor()); + + let addresses = HashSet::from([ + multiaddr![Ip4([0, 0, 0, 0]), Tcp(rand::random::())], + multiaddr![Ip4([0, 0, 0, 0]), Tcp(rand::random::())], + multiaddr![Ip4([0, 0, 0, 0]), Tcp(rand::random::())], + multiaddr![Udp(rand::random::())], + multiaddr![Udp(rand::random::())], + multiaddr![Udp(rand::random::())], + multiaddr![Udp(rand::random::())], + multiaddr![Udp(rand::random::())], + ]); + + swarm + .dial( + DialOpts::peer_id(target) + .addresses(addresses.iter().cloned().collect()) + .build(), + ) + .unwrap(); + + match swarm.next().await.unwrap() { + SwarmEvent::OutgoingConnectionError { + peer_id, + // multiaddr, + error: DialError::Transport(errors), + .. + } => { + assert_eq!(target, peer_id.unwrap()); + + let failed_addresses = errors.into_iter().map(|(addr, _)| addr).collect::>(); + let expected_addresses = addresses + .into_iter() + .map(|addr| addr.with(multiaddr::Protocol::P2p(target))) + .collect::>(); + + assert_eq!(expected_addresses, failed_addresses); + } + e => panic!("Unexpected event: {e:?}"), + } + } + + #[tokio::test] + async fn aborting_pending_connection_surfaces_error() { + let _ = tracing_subscriber::fmt() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .try_init(); + + let mut dialer = new_test_swarm(Config::with_tokio_executor()); + let mut listener = new_test_swarm(Config::with_tokio_executor()); + + let listener_peer_id = *listener.local_peer_id(); + listener.listen_on(multiaddr![Memory(0u64)]).unwrap(); + let listener_address = match listener.next().await.unwrap() { + SwarmEvent::NewListenAddr { address, .. } => address, + e => panic!("Unexpected network event: {e:?}"), + }; + + dialer + .dial( + DialOpts::peer_id(listener_peer_id) + .addresses(vec![listener_address]) + .build(), + ) + .unwrap(); + + dialer + .disconnect_peer_id(listener_peer_id) + .expect_err("Expect peer to not yet be connected."); + + match dialer.next().await.unwrap() { + SwarmEvent::OutgoingConnectionError { + error: DialError::Aborted, + .. + } => {} + e => panic!("Unexpected swarm event {e:?}."), + } + } + + #[test] + fn dial_error_prints_sources() { + // This constitutes a fairly typical error for chained transports. + let error = DialError::Transport(vec![( + "/ip4/127.0.0.1/tcp/80".parse().unwrap(), + TransportError::Other(io::Error::new( + io::ErrorKind::Other, + MemoryTransportError::Unreachable, + )), + )]); + + let string = format!("{error}"); + + // Unfortunately, we have some "empty" errors that lead to multiple colons without text but that is the best we can do. + assert_eq!("Failed to negotiate transport protocol(s): [(/ip4/127.0.0.1/tcp/80: : No listener on the given port.)]", string) + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/listen_opts.rs b/third-party/libp2p-swarm-0.45.1/src/listen_opts.rs new file mode 100644 index 00000000000..9c4d69a6fa0 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/listen_opts.rs @@ -0,0 +1,33 @@ +use crate::ListenerId; +use libp2p_core::Multiaddr; + +#[derive(Debug)] +pub struct ListenOpts { + id: ListenerId, + address: Multiaddr, +} + +impl ListenOpts { + pub fn new(address: Multiaddr) -> ListenOpts { + ListenOpts { + id: ListenerId::next(), + address, + } + } + + /// Get the [`ListenerId`] of this listen attempt + pub fn listener_id(&self) -> ListenerId { + self.id + } + + /// Get the [`Multiaddr`] that is being listened on + pub fn address(&self) -> &Multiaddr { + &self.address + } +} + +impl From for ListenOpts { + fn from(addr: Multiaddr) -> Self { + ListenOpts::new(addr) + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/stream.rs b/third-party/libp2p-swarm-0.45.1/src/stream.rs new file mode 100644 index 00000000000..871352f3c6a --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/stream.rs @@ -0,0 +1,98 @@ +use futures::{AsyncRead, AsyncWrite}; +use libp2p_core::muxing::SubstreamBox; +use libp2p_core::Negotiated; +use std::{ + io::{IoSlice, IoSliceMut}, + pin::Pin, + sync::Arc, + task::{Context, Poll}, +}; + +/// Counter for the number of active streams on a connection. +#[derive(Debug, Clone)] +pub(crate) struct ActiveStreamCounter(Arc<()>); + +impl ActiveStreamCounter { + pub(crate) fn default() -> Self { + Self(Arc::new(())) + } + + pub(crate) fn has_no_active_streams(&self) -> bool { + self.num_alive_streams() == 1 + } + + fn num_alive_streams(&self) -> usize { + Arc::strong_count(&self.0) + } +} + +#[derive(Debug)] +pub struct Stream { + stream: Negotiated, + counter: Option, +} + +impl Stream { + pub(crate) fn new(stream: Negotiated, counter: ActiveStreamCounter) -> Self { + Self { + stream, + counter: Some(counter), + } + } + + /// Ignore this stream in the [Swarm](crate::Swarm)'s connection-keep-alive algorithm. + /// + /// By default, any active stream keeps a connection alive. For most protocols, + /// this is a good default as it ensures that the protocol is completed before + /// a connection is shut down. + /// Some protocols like libp2p's [ping](https://github.com/libp2p/specs/blob/master/ping/ping.md) + /// for example never complete and are of an auxiliary nature. + /// These protocols should opt-out of the keep alive algorithm using this method. + pub fn ignore_for_keep_alive(&mut self) { + self.counter.take(); + } +} + +impl AsyncRead for Stream { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + Pin::new(&mut self.get_mut().stream).poll_read(cx, buf) + } + + fn poll_read_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &mut [IoSliceMut<'_>], + ) -> Poll> { + Pin::new(&mut self.get_mut().stream).poll_read_vectored(cx, bufs) + } +} + +impl AsyncWrite for Stream { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + Pin::new(&mut self.get_mut().stream).poll_write(cx, buf) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + Pin::new(&mut self.get_mut().stream).poll_write_vectored(cx, bufs) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.get_mut().stream).poll_flush(cx) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.get_mut().stream).poll_close(cx) + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/stream_protocol.rs b/third-party/libp2p-swarm-0.45.1/src/stream_protocol.rs new file mode 100644 index 00000000000..f746429a3d7 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/stream_protocol.rs @@ -0,0 +1,132 @@ +use either::Either; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::sync::Arc; + +/// Identifies a protocol for a stream. +/// +/// libp2p nodes use stream protocols to negotiate what to do with a newly opened stream. +/// Stream protocols are string-based and must start with a forward slash: `/`. +#[derive(Clone, Eq)] +pub struct StreamProtocol { + inner: Either<&'static str, Arc>, +} + +impl StreamProtocol { + /// Construct a new protocol from a static string slice. + /// + /// # Panics + /// + /// This function panics if the protocol does not start with a forward slash: `/`. + pub const fn new(s: &'static str) -> Self { + match s.as_bytes() { + [b'/', ..] => {} + _ => panic!("Protocols should start with a /"), + } + + StreamProtocol { + inner: Either::Left(s), + } + } + + /// Attempt to construct a protocol from an owned string. + /// + /// This function will fail if the protocol does not start with a forward slash: `/`. + /// Where possible, you should use [`StreamProtocol::new`] instead to avoid allocations. + pub fn try_from_owned(protocol: String) -> Result { + if !protocol.starts_with('/') { + return Err(InvalidProtocol::missing_forward_slash()); + } + + Ok(StreamProtocol { + inner: Either::Right(Arc::from(protocol)), // FIXME: Can we somehow reuse the allocation from the owned string? + }) + } +} + +impl AsRef for StreamProtocol { + fn as_ref(&self) -> &str { + either::for_both!(&self.inner, s => s) + } +} + +impl fmt::Debug for StreamProtocol { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + either::for_both!(&self.inner, s => s.fmt(f)) + } +} + +impl fmt::Display for StreamProtocol { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) + } +} + +impl PartialEq<&str> for StreamProtocol { + fn eq(&self, other: &&str) -> bool { + self.as_ref() == *other + } +} + +impl PartialEq for &str { + fn eq(&self, other: &StreamProtocol) -> bool { + *self == other.as_ref() + } +} + +impl PartialEq for StreamProtocol { + fn eq(&self, other: &Self) -> bool { + self.as_ref() == other.as_ref() + } +} + +impl Hash for StreamProtocol { + fn hash(&self, state: &mut H) { + self.as_ref().hash(state) + } +} + +#[derive(Debug)] +pub struct InvalidProtocol { + // private field to prevent construction outside of this module + _private: (), +} + +impl InvalidProtocol { + pub(crate) fn missing_forward_slash() -> Self { + InvalidProtocol { _private: () } + } +} + +impl fmt::Display for InvalidProtocol { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "invalid protocol: string does not start with a forward slash" + ) + } +} + +impl std::error::Error for InvalidProtocol {} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn stream_protocol_print() { + let protocol = StreamProtocol::new("/foo/bar/1.0.0"); + + let debug = format!("{protocol:?}"); + let display = format!("{protocol}"); + + assert_eq!( + debug, r#""/foo/bar/1.0.0""#, + "protocol to debug print as string with quotes" + ); + assert_eq!( + display, "/foo/bar/1.0.0", + "protocol to display print as string without quotes" + ); + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/test.rs b/third-party/libp2p-swarm-0.45.1/src/test.rs new file mode 100644 index 00000000000..a6cb7c4d4eb --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/test.rs @@ -0,0 +1,522 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::behaviour::{ + ConnectionClosed, ConnectionEstablished, DialFailure, ExpiredListenAddr, ExternalAddrExpired, + FromSwarm, ListenerClosed, ListenerError, NewExternalAddrCandidate, NewListenAddr, NewListener, +}; +use crate::{ + ConnectionDenied, ConnectionHandler, ConnectionId, NetworkBehaviour, THandler, THandlerInEvent, + THandlerOutEvent, ToSwarm, +}; +use libp2p_core::transport::PortUse; +use libp2p_core::{multiaddr::Multiaddr, transport::ListenerId, ConnectedPoint, Endpoint}; +use libp2p_identity::PeerId; +use std::collections::HashMap; +use std::task::{Context, Poll}; + +/// A `MockBehaviour` is a `NetworkBehaviour` that allows for +/// the instrumentation of return values, without keeping +/// any further state. +pub(crate) struct MockBehaviour +where + THandler: ConnectionHandler + Clone, + THandler::ToBehaviour: Clone, + TOutEvent: Send + 'static, +{ + /// The prototype protocols handler that is cloned for every + /// invocation of [`NetworkBehaviour::handle_established_inbound_connection`] and [`NetworkBehaviour::handle_established_outbound_connection`] + pub(crate) handler_proto: THandler, + /// The addresses to return from [`NetworkBehaviour::handle_established_outbound_connection`]. + pub(crate) addresses: HashMap>, + /// The next action to return from `poll`. + /// + /// An action is only returned once. + pub(crate) next_action: Option>, +} + +impl MockBehaviour +where + THandler: ConnectionHandler + Clone, + THandler::ToBehaviour: Clone, + TOutEvent: Send + 'static, +{ + pub(crate) fn new(handler_proto: THandler) -> Self { + MockBehaviour { + handler_proto, + addresses: HashMap::new(), + next_action: None, + } + } +} + +impl NetworkBehaviour for MockBehaviour +where + THandler: ConnectionHandler + Clone, + THandler::ToBehaviour: Clone, + TOutEvent: Send + 'static, +{ + type ConnectionHandler = THandler; + type ToSwarm = TOutEvent; + + fn handle_established_inbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result { + Ok(self.handler_proto.clone()) + } + + fn handle_established_outbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: Endpoint, + _: PortUse, + ) -> Result { + Ok(self.handler_proto.clone()) + } + + fn handle_pending_outbound_connection( + &mut self, + _connection_id: ConnectionId, + maybe_peer: Option, + _addresses: &[Multiaddr], + _effective_role: Endpoint, + ) -> Result, ConnectionDenied> { + let p = match maybe_peer { + None => return Ok(vec![]), + Some(peer) => peer, + }; + + Ok(self.addresses.get(&p).map_or(Vec::new(), |v| v.clone())) + } + + fn poll(&mut self, _: &mut Context<'_>) -> Poll>> { + self.next_action.take().map_or(Poll::Pending, Poll::Ready) + } + + fn on_swarm_event(&mut self, _event: FromSwarm) {} + + fn on_connection_handler_event( + &mut self, + _peer_id: PeerId, + _connection_id: ConnectionId, + _event: THandlerOutEvent, + ) { + } +} + +/// A `CallTraceBehaviour` is a `NetworkBehaviour` that tracks +/// invocations of callback methods and their arguments, wrapping +/// around an inner behaviour. It ensures certain invariants are met. +pub(crate) struct CallTraceBehaviour +where + TInner: NetworkBehaviour, +{ + inner: TInner, + + pub(crate) handle_pending_inbound_connection: Vec<(ConnectionId, Multiaddr, Multiaddr)>, + pub(crate) handle_pending_outbound_connection: + Vec<(Option, Vec, Endpoint, ConnectionId)>, + pub(crate) handle_established_inbound_connection: + Vec<(PeerId, ConnectionId, Multiaddr, Multiaddr)>, + pub(crate) handle_established_outbound_connection: + Vec<(PeerId, Multiaddr, Endpoint, ConnectionId)>, + pub(crate) on_connection_established: Vec<(PeerId, ConnectionId, ConnectedPoint, usize)>, + pub(crate) on_connection_closed: Vec<(PeerId, ConnectionId, ConnectedPoint, usize)>, + pub(crate) on_connection_handler_event: Vec<(PeerId, ConnectionId, THandlerOutEvent)>, + pub(crate) on_dial_failure: Vec>, + pub(crate) on_new_listener: Vec, + pub(crate) on_new_listen_addr: Vec<(ListenerId, Multiaddr)>, + pub(crate) on_new_external_addr: Vec, + pub(crate) on_expired_listen_addr: Vec<(ListenerId, Multiaddr)>, + pub(crate) on_expired_external_addr: Vec, + pub(crate) on_listener_error: Vec, + pub(crate) on_listener_closed: Vec<(ListenerId, bool)>, + pub(crate) poll: usize, +} + +impl CallTraceBehaviour +where + TInner: NetworkBehaviour, + THandlerOutEvent: Clone, +{ + pub(crate) fn new(inner: TInner) -> Self { + Self { + inner, + handle_pending_inbound_connection: Vec::new(), + handle_pending_outbound_connection: Vec::new(), + handle_established_inbound_connection: Vec::new(), + handle_established_outbound_connection: Vec::new(), + on_connection_established: Vec::new(), + on_connection_closed: Vec::new(), + on_connection_handler_event: Vec::new(), + on_dial_failure: Vec::new(), + on_new_listener: Vec::new(), + on_new_listen_addr: Vec::new(), + on_new_external_addr: Vec::new(), + on_expired_listen_addr: Vec::new(), + on_expired_external_addr: Vec::new(), + on_listener_error: Vec::new(), + on_listener_closed: Vec::new(), + poll: 0, + } + } + + #[allow(dead_code)] + pub(crate) fn reset(&mut self) { + self.handle_pending_inbound_connection = Vec::new(); + self.handle_pending_outbound_connection = Vec::new(); + self.handle_established_inbound_connection = Vec::new(); + self.handle_established_outbound_connection = Vec::new(); + self.on_connection_established = Vec::new(); + self.on_connection_closed = Vec::new(); + self.on_connection_handler_event = Vec::new(); + self.on_dial_failure = Vec::new(); + self.on_new_listen_addr = Vec::new(); + self.on_new_external_addr = Vec::new(); + self.on_expired_listen_addr = Vec::new(); + self.on_listener_error = Vec::new(); + self.on_listener_closed = Vec::new(); + self.poll = 0; + } + + pub(crate) fn inner(&mut self) -> &mut TInner { + &mut self.inner + } + + pub(crate) fn num_connections_to_peer(&self, peer: PeerId) -> usize { + self.on_connection_established + .iter() + .filter(|(peer_id, _, _, _)| *peer_id == peer) + .count() + - self + .on_connection_closed + .iter() + .filter(|(peer_id, _, _, _)| *peer_id == peer) + .count() + } + + /// Checks that when the expected number of established connection notifications are received, + /// a given number of expected connections have been received as well. + /// + /// Returns if the first condition is met. + pub(crate) fn assert_connected( + &self, + expected_established_connections: usize, + expected_connections: usize, + ) -> bool { + if self.on_connection_established.len() == expected_established_connections { + assert_eq!( + self.on_connection_established + .iter() + .filter(|(.., reported_aditional_connections)| { + *reported_aditional_connections == 0 + }) + .count(), + expected_connections + ); + return true; + } + + false + } + + fn on_connection_established( + &mut self, + ConnectionEstablished { + peer_id, + connection_id, + endpoint, + failed_addresses, + other_established, + }: ConnectionEstablished, + ) { + let mut other_peer_connections = self + .on_connection_established + .iter() + .rev() // take last to first + .filter_map(|(peer, .., other_established)| { + if &peer_id == peer { + Some(other_established) + } else { + None + } + }) + .take(other_established); + + // We are informed that there are `other_established` additional connections. Ensure that the + // number of previous connections is consistent with this + if let Some(&prev) = other_peer_connections.next() { + if prev < other_established { + assert_eq!( + prev, + other_established - 1, + "Inconsistent connection reporting" + ) + } + assert_eq!(other_peer_connections.count(), other_established - 1); + } else { + assert_eq!(other_established, 0) + } + self.on_connection_established.push(( + peer_id, + connection_id, + endpoint.clone(), + other_established, + )); + self.inner + .on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { + peer_id, + connection_id, + endpoint, + failed_addresses, + other_established, + })); + } + + fn on_connection_closed( + &mut self, + ConnectionClosed { + peer_id, + connection_id, + endpoint, + remaining_established, + cause, + }: ConnectionClosed, + ) { + let mut other_closed_connections = self + .on_connection_established + .iter() + .rev() // take last to first + .filter_map(|(peer, .., remaining_established)| { + if &peer_id == peer { + Some(remaining_established) + } else { + None + } + }) + .take(remaining_established); + + // We are informed that there are `other_established` additional connections. Ensure that the + // number of previous connections is consistent with this + if let Some(&prev) = other_closed_connections.next() { + if prev < remaining_established { + assert_eq!( + prev, + remaining_established - 1, + "Inconsistent closed connection reporting" + ) + } + assert_eq!(other_closed_connections.count(), remaining_established - 1); + } else { + assert_eq!(remaining_established, 0) + } + assert!( + self.on_connection_established + .iter() + .any(|(peer, conn_id, endpoint, _)| (peer, conn_id, endpoint) + == (&peer_id, &connection_id, endpoint)), + "`on_swarm_event` with `FromSwarm::ConnectionClosed is called only for connections for\ + which `on_swarm_event` with `FromSwarm::ConnectionEstablished` was called first." + ); + self.on_connection_closed.push(( + peer_id, + connection_id, + endpoint.clone(), + remaining_established, + )); + self.inner + .on_swarm_event(FromSwarm::ConnectionClosed(ConnectionClosed { + peer_id, + connection_id, + endpoint, + remaining_established, + cause, + })); + } +} + +impl NetworkBehaviour for CallTraceBehaviour +where + TInner: NetworkBehaviour, + THandlerOutEvent: Clone, +{ + type ConnectionHandler = TInner::ConnectionHandler; + type ToSwarm = TInner::ToSwarm; + + fn handle_pending_inbound_connection( + &mut self, + connection_id: ConnectionId, + local_addr: &Multiaddr, + remote_addr: &Multiaddr, + ) -> Result<(), ConnectionDenied> { + self.handle_pending_inbound_connection.push(( + connection_id, + local_addr.clone(), + remote_addr.clone(), + )); + self.inner + .handle_pending_inbound_connection(connection_id, local_addr, remote_addr) + } + + fn handle_established_inbound_connection( + &mut self, + connection_id: ConnectionId, + peer: PeerId, + local_addr: &Multiaddr, + remote_addr: &Multiaddr, + ) -> Result, ConnectionDenied> { + self.handle_established_inbound_connection.push(( + peer, + connection_id, + local_addr.clone(), + remote_addr.clone(), + )); + self.inner.handle_established_inbound_connection( + connection_id, + peer, + local_addr, + remote_addr, + ) + } + + fn handle_pending_outbound_connection( + &mut self, + connection_id: ConnectionId, + maybe_peer: Option, + addresses: &[Multiaddr], + effective_role: Endpoint, + ) -> Result, ConnectionDenied> { + self.handle_pending_outbound_connection.push(( + maybe_peer, + addresses.to_vec(), + effective_role, + connection_id, + )); + self.inner.handle_pending_outbound_connection( + connection_id, + maybe_peer, + addresses, + effective_role, + ) + } + + fn handle_established_outbound_connection( + &mut self, + connection_id: ConnectionId, + peer: PeerId, + addr: &Multiaddr, + role_override: Endpoint, + port_use: PortUse, + ) -> Result, ConnectionDenied> { + self.handle_established_outbound_connection.push(( + peer, + addr.clone(), + role_override, + connection_id, + )); + self.inner.handle_established_outbound_connection( + connection_id, + peer, + addr, + role_override, + port_use, + ) + } + + fn on_swarm_event(&mut self, event: FromSwarm) { + self.inner.on_swarm_event(event); + + match event { + FromSwarm::ConnectionEstablished(connection_established) => { + self.on_connection_established(connection_established) + } + FromSwarm::ConnectionClosed(connection_closed) => { + self.on_connection_closed(connection_closed) + } + FromSwarm::DialFailure(DialFailure { peer_id, .. }) => { + self.on_dial_failure.push(peer_id); + } + FromSwarm::NewListener(NewListener { listener_id }) => { + self.on_new_listener.push(listener_id); + } + FromSwarm::NewListenAddr(NewListenAddr { listener_id, addr }) => { + self.on_new_listen_addr.push((listener_id, addr.clone())); + } + FromSwarm::ExpiredListenAddr(ExpiredListenAddr { listener_id, addr }) => { + self.on_expired_listen_addr + .push((listener_id, addr.clone())); + } + FromSwarm::NewExternalAddrCandidate(NewExternalAddrCandidate { addr }) => { + self.on_new_external_addr.push(addr.clone()); + } + FromSwarm::ExternalAddrExpired(ExternalAddrExpired { addr }) => { + self.on_expired_external_addr.push(addr.clone()); + } + FromSwarm::ListenerError(ListenerError { listener_id, .. }) => { + self.on_listener_error.push(listener_id); + } + FromSwarm::ListenerClosed(ListenerClosed { + listener_id, + reason, + }) => { + self.on_listener_closed.push((listener_id, reason.is_ok())); + } + _ => {} + } + } + + fn on_connection_handler_event( + &mut self, + p: PeerId, + c: ConnectionId, + e: THandlerOutEvent, + ) { + assert!( + self.on_connection_established + .iter() + .any(|(peer_id, conn_id, ..)| *peer_id == p && c == *conn_id), + "`on_connection_handler_event` is called for reported connections." + ); + assert!( + !self + .on_connection_closed + .iter() + .any(|(peer_id, conn_id, ..)| *peer_id == p && c == *conn_id), + "`on_connection_handler_event` is never called for closed connections." + ); + + self.on_connection_handler_event.push((p, c, e.clone())); + self.inner.on_connection_handler_event(p, c, e); + } + + fn poll( + &mut self, + cx: &mut Context<'_>, + ) -> Poll>> { + self.poll += 1; + self.inner.poll(cx) + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/translation.rs b/third-party/libp2p-swarm-0.45.1/src/translation.rs new file mode 100644 index 00000000000..baa80c907b5 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/translation.rs @@ -0,0 +1,115 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use libp2p_core::{multiaddr::Protocol, Multiaddr}; + +/// Perform IP address translation. +/// +/// Given an `original` [`Multiaddr`] and some `observed` [`Multiaddr`], replace the first protocol +/// of the `original` with the first protocol of the `observed` [`Multiaddr`] and return this +/// translated [`Multiaddr`]. +/// +/// This function can for example be useful when handling tcp connections. Tcp does not listen and +/// dial on the same port by default. Thus when receiving an observed address on a connection that +/// we initiated, it will contain our dialing port, not our listening port. We need to take the ip +/// address or dns address from the observed address and the port from the original address. +/// +/// This is a mixed-mode translation, i.e. an IPv4 / DNS4 address may be replaced by an IPv6 / DNS6 +/// address and vice versa. +/// +/// If the first [`Protocol`]s are not IP addresses, `None` is returned instead. +#[doc(hidden)] +pub fn _address_translation(original: &Multiaddr, observed: &Multiaddr) -> Option { + original.replace(0, move |proto| match proto { + Protocol::Ip4(_) + | Protocol::Ip6(_) + | Protocol::Dns(_) + | Protocol::Dns4(_) + | Protocol::Dns6(_) => match observed.iter().next() { + x @ Some(Protocol::Ip4(_)) => x, + x @ Some(Protocol::Ip6(_)) => x, + x @ Some(Protocol::Dns(_)) => x, + x @ Some(Protocol::Dns4(_)) => x, + x @ Some(Protocol::Dns6(_)) => x, + _ => None, + }, + _ => None, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_address_translation() { + struct Test { + original: Multiaddr, + observed: Multiaddr, + expected: Multiaddr, + } + + let tests = [ + // Basic ipv4. + Test { + original: "/ip4/192.0.2.1/tcp/1".parse().unwrap(), + observed: "/ip4/192.0.2.2/tcp/2".parse().unwrap(), + expected: "/ip4/192.0.2.2/tcp/1".parse().unwrap(), + }, + // Basic ipv6. + Test { + original: "/ip6/2001:db8:0:0:0:0:0:0/tcp/1".parse().unwrap(), + observed: "/ip6/2001:db8:0:0:0:0:0:1/tcp/2".parse().unwrap(), + expected: "/ip6/2001:db8:0:0:0:0:0:1/tcp/1".parse().unwrap(), + }, + // Ipv4 ipv6 mix. + Test { + original: "/ip4/192.0.2.1/tcp/1".parse().unwrap(), + observed: "/ip6/2001:db8:0:0:0:0:0:1/tcp/2".parse().unwrap(), + expected: "/ip6/2001:db8:0:0:0:0:0:1/tcp/1".parse().unwrap(), + }, + // Ipv6 ipv4 mix. + Test { + original: "/ip6/2001:db8:0:0:0:0:0:0/tcp/1".parse().unwrap(), + observed: "/ip4/192.0.2.2/tcp/2".parse().unwrap(), + expected: "/ip4/192.0.2.2/tcp/1".parse().unwrap(), + }, + // Dns. + Test { + original: "/dns4/foo/tcp/1".parse().unwrap(), + observed: "/dns4/bar/tcp/2".parse().unwrap(), + expected: "/dns4/bar/tcp/1".parse().unwrap(), + }, + // Ipv4 Dns mix. + Test { + original: "/ip4/192.0.2.1/tcp/1".parse().unwrap(), + observed: "/dns4/bar/tcp/2".parse().unwrap(), + expected: "/dns4/bar/tcp/1".parse().unwrap(), + }, + ]; + + for test in tests.iter() { + assert_eq!( + _address_translation(&test.original, &test.observed), + Some(test.expected.clone()) + ); + } + } +} diff --git a/third-party/libp2p-swarm-0.45.1/src/upgrade.rs b/third-party/libp2p-swarm-0.45.1/src/upgrade.rs new file mode 100644 index 00000000000..53b627458c9 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/src/upgrade.rs @@ -0,0 +1,158 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use crate::Stream; + +use futures::prelude::*; +use libp2p_core::upgrade; + +/// Implemented automatically on all types that implement [`UpgradeInfo`](upgrade::UpgradeInfo) +/// and `Send + 'static`. +/// +/// Do not implement this trait yourself. Instead, please implement +/// [`UpgradeInfo`](upgrade::UpgradeInfo). +pub trait UpgradeInfoSend: Send + 'static { + /// Equivalent to [`UpgradeInfo::Info`](upgrade::UpgradeInfo::Info). + type Info: AsRef + Clone + Send + 'static; + /// Equivalent to [`UpgradeInfo::InfoIter`](upgrade::UpgradeInfo::InfoIter). + type InfoIter: Iterator + Send + 'static; + + /// Equivalent to [`UpgradeInfo::protocol_info`](upgrade::UpgradeInfo::protocol_info). + fn protocol_info(&self) -> Self::InfoIter; +} + +impl UpgradeInfoSend for T +where + T: upgrade::UpgradeInfo + Send + 'static, + T::Info: Send + 'static, + ::IntoIter: Send + 'static, +{ + type Info = T::Info; + type InfoIter = ::IntoIter; + + fn protocol_info(&self) -> Self::InfoIter { + upgrade::UpgradeInfo::protocol_info(self).into_iter() + } +} + +/// Implemented automatically on all types that implement +/// [`OutboundUpgrade`](upgrade::OutboundUpgrade) and `Send + 'static`. +/// +/// Do not implement this trait yourself. Instead, please implement +/// [`OutboundUpgrade`](upgrade::OutboundUpgrade). +pub trait OutboundUpgradeSend: UpgradeInfoSend { + /// Equivalent to [`OutboundUpgrade::Output`](upgrade::OutboundUpgrade::Output). + type Output: Send + 'static; + /// Equivalent to [`OutboundUpgrade::Error`](upgrade::OutboundUpgrade::Error). + type Error: Send + 'static; + /// Equivalent to [`OutboundUpgrade::Future`](upgrade::OutboundUpgrade::Future). + type Future: Future> + Send + 'static; + + /// Equivalent to [`OutboundUpgrade::upgrade_outbound`](upgrade::OutboundUpgrade::upgrade_outbound). + fn upgrade_outbound(self, socket: Stream, info: Self::Info) -> Self::Future; +} + +impl OutboundUpgradeSend for T +where + T: upgrade::OutboundUpgrade + UpgradeInfoSend, + TInfo: AsRef + Clone + Send + 'static, + T::Output: Send + 'static, + T::Error: Send + 'static, + T::Future: Send + 'static, +{ + type Output = T::Output; + type Error = T::Error; + type Future = T::Future; + + fn upgrade_outbound(self, socket: Stream, info: TInfo) -> Self::Future { + upgrade::OutboundUpgrade::upgrade_outbound(self, socket, info) + } +} + +/// Implemented automatically on all types that implement +/// [`InboundUpgrade`](upgrade::InboundUpgrade) and `Send + 'static`. +/// +/// Do not implement this trait yourself. Instead, please implement +/// [`InboundUpgrade`](upgrade::InboundUpgrade). +pub trait InboundUpgradeSend: UpgradeInfoSend { + /// Equivalent to [`InboundUpgrade::Output`](upgrade::InboundUpgrade::Output). + type Output: Send + 'static; + /// Equivalent to [`InboundUpgrade::Error`](upgrade::InboundUpgrade::Error). + type Error: Send + 'static; + /// Equivalent to [`InboundUpgrade::Future`](upgrade::InboundUpgrade::Future). + type Future: Future> + Send + 'static; + + /// Equivalent to [`InboundUpgrade::upgrade_inbound`](upgrade::InboundUpgrade::upgrade_inbound). + fn upgrade_inbound(self, socket: Stream, info: Self::Info) -> Self::Future; +} + +impl InboundUpgradeSend for T +where + T: upgrade::InboundUpgrade + UpgradeInfoSend, + TInfo: AsRef + Clone + Send + 'static, + T::Output: Send + 'static, + T::Error: Send + 'static, + T::Future: Send + 'static, +{ + type Output = T::Output; + type Error = T::Error; + type Future = T::Future; + + fn upgrade_inbound(self, socket: Stream, info: TInfo) -> Self::Future { + upgrade::InboundUpgrade::upgrade_inbound(self, socket, info) + } +} + +/// Wraps around a type that implements [`OutboundUpgradeSend`], [`InboundUpgradeSend`], or +/// both, and implements [`OutboundUpgrade`](upgrade::OutboundUpgrade) and/or +/// [`InboundUpgrade`](upgrade::InboundUpgrade). +/// +/// > **Note**: This struct is mostly an implementation detail of the library and normally +/// > doesn't need to be used directly. +pub struct SendWrapper(pub T); + +impl upgrade::UpgradeInfo for SendWrapper { + type Info = T::Info; + type InfoIter = T::InfoIter; + + fn protocol_info(&self) -> Self::InfoIter { + UpgradeInfoSend::protocol_info(&self.0) + } +} + +impl upgrade::OutboundUpgrade for SendWrapper { + type Output = T::Output; + type Error = T::Error; + type Future = T::Future; + + fn upgrade_outbound(self, socket: Stream, info: T::Info) -> Self::Future { + OutboundUpgradeSend::upgrade_outbound(self.0, socket, info) + } +} + +impl upgrade::InboundUpgrade for SendWrapper { + type Output = T::Output; + type Error = T::Error; + type Future = T::Future; + + fn upgrade_inbound(self, socket: Stream, info: T::Info) -> Self::Future { + InboundUpgradeSend::upgrade_inbound(self.0, socket, info) + } +} diff --git a/third-party/libp2p-swarm-0.45.1/tests/connection_close.rs b/third-party/libp2p-swarm-0.45.1/tests/connection_close.rs new file mode 100644 index 00000000000..4d530f47684 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/tests/connection_close.rs @@ -0,0 +1,148 @@ +use libp2p_core::transport::PortUse; +use libp2p_core::upgrade::DeniedUpgrade; +use libp2p_core::{Endpoint, Multiaddr}; +use libp2p_identity::PeerId; +use libp2p_swarm::handler::ConnectionEvent; +use libp2p_swarm::{ + ConnectionDenied, ConnectionHandler, ConnectionHandlerEvent, ConnectionId, FromSwarm, + NetworkBehaviour, SubstreamProtocol, Swarm, SwarmEvent, THandler, THandlerInEvent, + THandlerOutEvent, ToSwarm, +}; +use libp2p_swarm_test::SwarmExt; +use std::task::{Context, Poll}; +use void::Void; + +#[async_std::test] +async fn sends_remaining_events_to_behaviour_on_connection_close() { + let mut swarm1 = Swarm::new_ephemeral(|_| Behaviour::new(3)); + let mut swarm2 = Swarm::new_ephemeral(|_| Behaviour::new(3)); + + swarm2.listen().with_memory_addr_external().await; + swarm1.connect(&mut swarm2).await; + + swarm1.disconnect_peer_id(*swarm2.local_peer_id()).unwrap(); + + match libp2p_swarm_test::drive(&mut swarm1, &mut swarm2).await { + ([SwarmEvent::ConnectionClosed { .. }], [SwarmEvent::ConnectionClosed { .. }]) => { + assert_eq!(swarm1.behaviour().state, 0); + assert_eq!(swarm2.behaviour().state, 0); + } + (e1, e2) => panic!("Unexpected events: {:?} {:?}", e1, e2), + } +} + +struct HandlerWithState { + precious_state: u64, +} + +struct Behaviour { + state: u64, +} + +impl Behaviour { + fn new(state: u64) -> Self { + Behaviour { state } + } +} + +impl NetworkBehaviour for Behaviour { + type ConnectionHandler = HandlerWithState; + type ToSwarm = (); + + fn handle_established_inbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result, ConnectionDenied> { + Ok(HandlerWithState { + precious_state: self.state, + }) + } + + fn handle_established_outbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: Endpoint, + _: PortUse, + ) -> Result, ConnectionDenied> { + Ok(HandlerWithState { + precious_state: self.state, + }) + } + + fn on_swarm_event(&mut self, event: FromSwarm) { + if let FromSwarm::ConnectionClosed(_) = event { + assert_eq!(self.state, 0); + } + } + + fn on_connection_handler_event( + &mut self, + _peer_id: PeerId, + _connection_id: ConnectionId, + event: THandlerOutEvent, + ) { + assert_eq!(self.state, event); + self.state -= 1; + } + + fn poll(&mut self, _: &mut Context<'_>) -> Poll>> { + Poll::Pending + } +} + +impl ConnectionHandler for HandlerWithState { + type FromBehaviour = Void; + type ToBehaviour = u64; + type InboundProtocol = DeniedUpgrade; + type OutboundProtocol = DeniedUpgrade; + type InboundOpenInfo = (); + type OutboundOpenInfo = (); + + fn listen_protocol(&self) -> SubstreamProtocol { + SubstreamProtocol::new(DeniedUpgrade, ()) + } + + fn connection_keep_alive(&self) -> bool { + true + } + + fn poll( + &mut self, + _: &mut Context<'_>, + ) -> Poll< + ConnectionHandlerEvent, + > { + Poll::Pending + } + + fn poll_close(&mut self, _: &mut Context<'_>) -> Poll> { + if self.precious_state > 0 { + let state = self.precious_state; + self.precious_state -= 1; + + return Poll::Ready(Some(state)); + } + + Poll::Ready(None) + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + void::unreachable(event) + } + + fn on_connection_event( + &mut self, + _: ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + } +} diff --git a/third-party/libp2p-swarm-0.45.1/tests/listener.rs b/third-party/libp2p-swarm-0.45.1/tests/listener.rs new file mode 100644 index 00000000000..160b1f5b064 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/tests/listener.rs @@ -0,0 +1,144 @@ +use std::{ + collections::{HashSet, VecDeque}, + task::{Context, Poll}, +}; + +use libp2p_core::{ + multiaddr::Protocol, + transport::{ListenerId, PortUse}, + Endpoint, Multiaddr, +}; +use libp2p_identity::PeerId; +use libp2p_swarm::{ + derive_prelude::NewListener, dummy, ConnectionDenied, ConnectionId, FromSwarm, ListenOpts, + ListenerClosed, ListenerError, NetworkBehaviour, NewListenAddr, Swarm, SwarmEvent, THandler, + THandlerInEvent, THandlerOutEvent, ToSwarm, +}; + +use libp2p_swarm_test::SwarmExt; + +#[async_std::test] +async fn behaviour_listener() { + let mut swarm = Swarm::new_ephemeral(|_| Behaviour::default()); + let addr: Multiaddr = Protocol::Memory(0).into(); + let id = swarm.behaviour_mut().listen(addr.clone()); + + let address = swarm + .wait(|e| match e { + SwarmEvent::NewListenAddr { + listener_id, + address, + } => { + assert_eq!(listener_id, id); + Some(address) + } + _ => None, + }) + .await; + + swarm.behaviour_mut().stop_listening(id); + + swarm + .wait(|e| match e { + SwarmEvent::ListenerClosed { + listener_id, + addresses, + reason, + } => { + assert_eq!(listener_id, id); + assert!(addresses.contains(&address)); + assert!(reason.is_ok()); + Some(()) + } + _ => None, + }) + .await; +} + +#[derive(Default)] +struct Behaviour { + events: VecDeque::ToSwarm, THandlerInEvent>>, + listeners: HashSet, +} + +impl Behaviour { + pub(crate) fn listen(&mut self, addr: Multiaddr) -> ListenerId { + let opts = ListenOpts::new(addr); + let listener_id = opts.listener_id(); + assert!(!self.listeners.contains(&listener_id)); + self.events.push_back(ToSwarm::ListenOn { opts }); + self.listeners.insert(listener_id); + + listener_id + } + + pub(crate) fn stop_listening(&mut self, id: ListenerId) { + self.events.push_back(ToSwarm::RemoveListener { id }); + } +} + +impl NetworkBehaviour for Behaviour { + type ConnectionHandler = dummy::ConnectionHandler; + type ToSwarm = void::Void; + + fn handle_established_inbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result, ConnectionDenied> { + Ok(dummy::ConnectionHandler) + } + + fn handle_established_outbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: Endpoint, + _: PortUse, + ) -> Result, ConnectionDenied> { + Ok(dummy::ConnectionHandler) + } + + fn on_connection_handler_event( + &mut self, + _: PeerId, + _: ConnectionId, + _: THandlerOutEvent, + ) { + } + + fn on_swarm_event(&mut self, event: FromSwarm) { + match event { + FromSwarm::NewListener(NewListener { listener_id }) => { + assert!(self.listeners.contains(&listener_id)); + } + FromSwarm::NewListenAddr(NewListenAddr { listener_id, .. }) => { + assert!(self.listeners.contains(&listener_id)); + } + FromSwarm::ListenerError(ListenerError { listener_id, err }) => { + panic!("Error for listener {listener_id:?}: {err}"); + } + FromSwarm::ListenerClosed(ListenerClosed { + listener_id, + reason, + }) => { + assert!(self.listeners.contains(&listener_id)); + assert!(reason.is_ok()); + self.listeners.remove(&listener_id); + assert!(!self.listeners.contains(&listener_id)); + } + _ => {} + } + } + + fn poll(&mut self, _: &mut Context<'_>) -> Poll>> { + if let Some(event) = self.events.pop_front() { + return Poll::Ready(event); + } + + Poll::Pending + } +} diff --git a/third-party/libp2p-swarm-0.45.1/tests/swarm_derive.rs b/third-party/libp2p-swarm-0.45.1/tests/swarm_derive.rs new file mode 100644 index 00000000000..919ed0cab7f --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/tests/swarm_derive.rs @@ -0,0 +1,618 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use futures::StreamExt; +use libp2p_core::{transport::PortUse, Endpoint, Multiaddr}; +use libp2p_identify as identify; +use libp2p_ping as ping; +use libp2p_swarm::{ + behaviour::FromSwarm, dummy, ConnectionDenied, NetworkBehaviour, SwarmEvent, THandler, + THandlerInEvent, THandlerOutEvent, +}; +use std::fmt::Debug; + +/// Small utility to check that a type implements `NetworkBehaviour`. +#[allow(dead_code)] +fn require_net_behaviour() {} + +// TODO: doesn't compile +/*#[test] +fn empty() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + struct Foo {} +}*/ + +#[test] +fn one_field() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + ping: ping::Behaviour, + } + + #[allow( + dead_code, + unreachable_code, + clippy::diverging_sub_expression, + clippy::used_underscore_binding + )] + fn foo() { + let _out_event: ::ToSwarm = unimplemented!(); + match _out_event { + FooEvent::Ping(ping::Event { .. }) => {} + } + } +} + +#[test] +fn two_fields() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + ping: ping::Behaviour, + identify: identify::Behaviour, + } + + #[allow( + dead_code, + unreachable_code, + clippy::diverging_sub_expression, + clippy::used_underscore_binding + )] + fn foo() { + let _out_event: ::ToSwarm = unimplemented!(); + match _out_event { + FooEvent::Ping(ping::Event { .. }) => {} + FooEvent::Identify(event) => { + let _: identify::Event = event; + } + } + } +} + +#[test] +fn three_fields() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + ping: ping::Behaviour, + identify: identify::Behaviour, + kad: libp2p_kad::Behaviour, + } + + #[allow( + dead_code, + unreachable_code, + clippy::diverging_sub_expression, + clippy::used_underscore_binding + )] + fn foo() { + let _out_event: ::ToSwarm = unimplemented!(); + match _out_event { + FooEvent::Ping(ping::Event { .. }) => {} + FooEvent::Identify(event) => { + let _: identify::Event = event; + } + FooEvent::Kad(event) => { + let _: libp2p_kad::Event = event; + } + } + } +} + +#[test] +fn custom_event() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(to_swarm = "MyEvent", prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + ping: ping::Behaviour, + identify: identify::Behaviour, + } + + #[allow(clippy::large_enum_variant)] + enum MyEvent { + Ping, + Identify, + } + + impl From for MyEvent { + fn from(_event: ping::Event) -> Self { + MyEvent::Ping + } + } + + impl From for MyEvent { + fn from(_event: identify::Event) -> Self { + MyEvent::Identify + } + } + + #[allow(dead_code)] + fn foo() { + require_net_behaviour::(); + } +} + +#[test] +fn custom_event_mismatching_field_names() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(to_swarm = "MyEvent", prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + a: ping::Behaviour, + b: identify::Behaviour, + } + + #[allow(clippy::large_enum_variant)] + enum MyEvent { + Ping, + Identify, + } + + impl From for MyEvent { + fn from(_event: ping::Event) -> Self { + MyEvent::Ping + } + } + + impl From for MyEvent { + fn from(_event: identify::Event) -> Self { + MyEvent::Identify + } + } + + #[allow(dead_code)] + fn foo() { + require_net_behaviour::(); + } +} + +#[test] +fn bound() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo + where + ::ToSwarm: Debug, + { + ping: ping::Behaviour, + bar: T, + } +} + +#[test] +fn where_clause() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo + where + T: Copy + NetworkBehaviour, + ::ToSwarm: Debug, + { + ping: ping::Behaviour, + bar: T, + } +} + +#[test] +fn nested_derives_with_import() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + ping: ping::Behaviour, + } + + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Bar { + foo: Foo, + } + + #[allow( + dead_code, + unreachable_code, + clippy::diverging_sub_expression, + clippy::used_underscore_binding + )] + fn foo() { + let _out_event: ::ToSwarm = unimplemented!(); + match _out_event { + BarEvent::Foo(FooEvent::Ping(ping::Event { .. })) => {} + } + } +} + +#[test] +fn custom_event_emit_event_through_poll() { + #[allow(clippy::large_enum_variant)] + enum BehaviourOutEvent { + Ping, + Identify, + } + + impl From for BehaviourOutEvent { + fn from(_event: ping::Event) -> Self { + BehaviourOutEvent::Ping + } + } + + impl From for BehaviourOutEvent { + fn from(_event: identify::Event) -> Self { + BehaviourOutEvent::Identify + } + } + + #[allow(dead_code, clippy::large_enum_variant)] + #[derive(NetworkBehaviour)] + #[behaviour( + to_swarm = "BehaviourOutEvent", + prelude = "libp2p_swarm::derive_prelude" + )] + struct Foo { + ping: ping::Behaviour, + identify: identify::Behaviour, + } + + #[allow( + dead_code, + unreachable_code, + clippy::diverging_sub_expression, + clippy::used_underscore_binding + )] + async fn bar() { + require_net_behaviour::(); + + let mut _swarm: libp2p_swarm::Swarm = unimplemented!(); + + // check that the event is bubbled up all the way to swarm + loop { + match _swarm.select_next_some().await { + SwarmEvent::Behaviour(BehaviourOutEvent::Ping) => break, + SwarmEvent::Behaviour(BehaviourOutEvent::Identify) => break, + _ => {} + } + } + } +} + +#[test] +fn with_toggle() { + use libp2p_swarm::behaviour::toggle::Toggle; + + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + identify: identify::Behaviour, + ping: Toggle, + } + + #[allow(dead_code)] + fn foo() { + require_net_behaviour::(); + } +} + +#[test] +fn with_either() { + use either::Either; + + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + kad: libp2p_kad::Behaviour, + ping_or_identify: Either, + } + + #[allow(dead_code)] + fn foo() { + require_net_behaviour::(); + } +} + +#[test] +fn with_generics() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + a: A, + b: B, + } + + #[allow(dead_code)] + fn foo() { + require_net_behaviour::< + Foo, libp2p_ping::Behaviour>, + >(); + } +} + +#[test] +fn with_generics_mixed() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + a: A, + ping: libp2p_ping::Behaviour, + } + + #[allow(dead_code)] + fn foo() { + require_net_behaviour::>>(); + } +} + +#[test] +fn with_generics_constrained() { + use std::task::{Context, Poll}; + trait Mark {} + struct Marked; + impl Mark for Marked {} + + /// A struct with a generic constraint, for which we manually implement `NetworkBehaviour`. + #[allow(dead_code)] + struct Bar { + a: A, + } + + impl NetworkBehaviour for Bar { + type ConnectionHandler = dummy::ConnectionHandler; + type ToSwarm = void::Void; + + fn handle_established_inbound_connection( + &mut self, + _: libp2p_swarm::ConnectionId, + _: libp2p_identity::PeerId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result, ConnectionDenied> { + Ok(dummy::ConnectionHandler) + } + + fn handle_established_outbound_connection( + &mut self, + _: libp2p_swarm::ConnectionId, + _: libp2p_identity::PeerId, + _: &Multiaddr, + _: Endpoint, + _: PortUse, + ) -> Result, ConnectionDenied> { + Ok(dummy::ConnectionHandler) + } + + fn on_swarm_event(&mut self, _event: FromSwarm) {} + + fn on_connection_handler_event( + &mut self, + _: libp2p_identity::PeerId, + _: libp2p_swarm::ConnectionId, + _: THandlerOutEvent, + ) { + } + + fn poll( + &mut self, + _: &mut Context<'_>, + ) -> Poll>> { + Poll::Pending + } + } + + /// A struct which uses the above, inheriting the generic constraint, + /// for which we want to derive the `NetworkBehaviour`. + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo1 { + bar: Bar, + } + + /// A struct which uses the above, inheriting the generic constraint, + /// for which we want to derive the `NetworkBehaviour`. + /// + /// Using a where clause instead of inline constraint. + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo2 + where + A: Mark, + { + bar: Bar, + } + + #[allow(dead_code)] + fn foo() { + require_net_behaviour::>(); + require_net_behaviour::>(); + } +} + +#[test] +fn custom_event_with_either() { + use either::Either; + + enum BehaviourOutEvent { + Kad, + PingOrIdentify, + } + + impl From for BehaviourOutEvent { + fn from(_event: libp2p_kad::Event) -> Self { + BehaviourOutEvent::Kad + } + } + + impl From> for BehaviourOutEvent { + fn from(_event: Either) -> Self { + BehaviourOutEvent::PingOrIdentify + } + } + + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour( + to_swarm = "BehaviourOutEvent", + prelude = "libp2p_swarm::derive_prelude" + )] + struct Foo { + kad: libp2p_kad::Behaviour, + ping_or_identify: Either, + } + + #[allow(dead_code)] + fn foo() { + require_net_behaviour::(); + } +} + +#[test] +fn generated_out_event_derive_debug() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + ping: ping::Behaviour, + } + + fn require_debug() + where + T: NetworkBehaviour, + ::ToSwarm: Debug, + { + } + + require_debug::(); +} + +#[test] +fn multiple_behaviour_attributes() { + #[allow(dead_code)] + #[derive(NetworkBehaviour)] + #[behaviour(to_swarm = "FooEvent")] + #[behaviour(prelude = "libp2p_swarm::derive_prelude")] + struct Foo { + ping: ping::Behaviour, + } + + require_net_behaviour::(); + + struct FooEvent; + + impl From for FooEvent { + fn from(_: ping::Event) -> Self { + unimplemented!() + } + } +} + +#[test] +fn custom_out_event_no_type_parameters() { + use libp2p_identity::PeerId; + use libp2p_swarm::{ConnectionId, ToSwarm}; + use std::task::Context; + use std::task::Poll; + + pub(crate) struct TemplatedBehaviour { + _data: T, + } + + impl NetworkBehaviour for TemplatedBehaviour { + type ConnectionHandler = dummy::ConnectionHandler; + type ToSwarm = void::Void; + + fn handle_established_inbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result, ConnectionDenied> { + Ok(dummy::ConnectionHandler) + } + + fn handle_established_outbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: Endpoint, + _: PortUse, + ) -> Result, ConnectionDenied> { + Ok(dummy::ConnectionHandler) + } + + fn on_connection_handler_event( + &mut self, + _peer: PeerId, + _connection: ConnectionId, + message: THandlerOutEvent, + ) { + void::unreachable(message); + } + + fn poll( + &mut self, + _: &mut Context<'_>, + ) -> Poll>> { + Poll::Pending + } + + fn on_swarm_event(&mut self, _event: FromSwarm) {} + } + + #[derive(NetworkBehaviour)] + #[behaviour(to_swarm = "OutEvent", prelude = "libp2p_swarm::derive_prelude")] + struct Behaviour { + custom: TemplatedBehaviour, + } + + #[derive(Debug)] + enum OutEvent { + None, + } + + impl From for OutEvent { + fn from(_e: void::Void) -> Self { + Self::None + } + } + + require_net_behaviour::>(); + require_net_behaviour::>(); +} + +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/fail/*.rs"); +} diff --git a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.rs b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.rs new file mode 100644 index 00000000000..727f2439ec0 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.rs @@ -0,0 +1,11 @@ +use libp2p_ping as ping; + +#[derive(libp2p_swarm::NetworkBehaviour)] +#[behaviour(prelude = libp2p_swarm::derive_prelude)] +struct Foo { + ping: ping::Behaviour, +} + +fn main() { + +} diff --git a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.stderr b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.stderr new file mode 100644 index 00000000000..2c2a79805d9 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.stderr @@ -0,0 +1,5 @@ +error: expected a string literal + --> tests/ui/fail/prelude_not_string.rs:4:23 + | +4 | #[behaviour(prelude = libp2p_swarm::derive_prelude)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.rs b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.rs new file mode 100644 index 00000000000..e0ff56e41a7 --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.rs @@ -0,0 +1,19 @@ +use libp2p_ping as ping; + +#[derive(libp2p_swarm::NetworkBehaviour)] +#[behaviour(out_event = FooEvent, prelude = "libp2p_swarm::derive_prelude")] +struct Foo { + ping: ping::Behaviour, +} + +struct FooEvent; + +impl From for FooEvent { + fn from(_: ping::Event) -> Self { + unimplemented!() + } +} + +fn main() { + +} diff --git a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.stderr b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.stderr new file mode 100644 index 00000000000..f2fbba685cb --- /dev/null +++ b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.stderr @@ -0,0 +1,5 @@ +error: expected a string literal + --> tests/ui/fail/to_swarm_not_string.rs:4:25 + | +4 | #[behaviour(out_event = FooEvent, prelude = "libp2p_swarm::derive_prelude")] + | ^^^^^^^^ diff --git a/utils/gear-workspace-hack/Cargo.toml b/utils/gear-workspace-hack/Cargo.toml index aaa6dc26ec2..fa86c45f610 100644 --- a/utils/gear-workspace-hack/Cargo.toml +++ b/utils/gear-workspace-hack/Cargo.toml @@ -284,6 +284,8 @@ elliptic-curve = { version = "0.13", default-features = false, features = ["dige enumflags2 = { version = "0.7", default-features = false, features = ["std"] } env_filter = { version = "0.1" } environmental = { version = "1" } +event-listener = { version = "5" } +event-listener-strategy = { version = "0.5" } finality-grandpa = { version = "0.16", features = ["derive-codec"] } fixed-hash = { version = "0.8", default-features = false, features = ["std"] } fnv = { version = "1" } @@ -337,13 +339,12 @@ jsonrpsee-core = { version = "0.24", features = ["async-client", "async-wasm-cli k256 = { version = "0.13", features = ["serde"] } keccak = { version = "0.1", default-features = false, features = ["asm"] } libc = { version = "0.2" } -libp2p = { version = "0.54", default-features = false, features = ["cbor", "dns", "ecdsa", "ed25519", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "serde", "tcp", "tls", "tokio", "websocket", "yamux"] } -libp2p-core = { version = "0.42", default-features = false, features = ["serde"] } -libp2p-gossipsub = { version = "0.47", default-features = false, features = ["serde"] } +libp2p = { version = "0.56", default-features = false, features = ["cbor", "dns", "ecdsa", "ed25519", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "serde", "tcp", "tls", "tokio", "yamux"] } +libp2p-core = { version = "0.43", default-features = false, features = ["serde"] } +libp2p-gossipsub = { version = "0.49", default-features = false, features = ["metrics", "serde"] } libp2p-identity = { version = "0.2", default-features = false, features = ["ecdsa", "ed25519", "peerid", "rand", "secp256k1", "serde"] } -libp2p-kad = { version = "0.46", default-features = false, features = ["serde"] } -libp2p-request-response = { version = "0.27", default-features = false, features = ["cbor"] } -libp2p-swarm = { version = "0.45", default-features = false, features = ["async-std", "macros", "tokio"] } +libp2p-kad = { version = "0.48", default-features = false, features = ["serde"] } +libp2p-request-response = { version = "0.29", default-features = false, features = ["cbor"] } libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context", "std"] } libsecp256k1-core = { version = "0.3" } log = { version = "0.4", default-features = false, features = ["std"] } @@ -398,7 +399,6 @@ rustc-demangle = { version = "0.1", default-features = false, features = ["std"] rustc-hash-dff4ba8e3ae991db = { package = "rustc-hash", version = "1" } rustc-hash-f595c2ba2a3f28df = { package = "rustc-hash", version = "2" } rustc-hex = { version = "2", default-features = false, features = ["std"] } -rustix = { version = "1", default-features = false, features = ["fs", "mm", "net", "param", "std", "use-libc"] } rustls = { version = "0.23", default-features = false, features = ["logging", "ring", "std", "tls12"] } rustls-webpki = { version = "0.103", default-features = false, features = ["ring", "std"] } scale-bits = { version = "0.7" } @@ -584,6 +584,8 @@ elliptic-curve = { version = "0.13", default-features = false, features = ["dige enumflags2 = { version = "0.7", default-features = false, features = ["std"] } env_filter = { version = "0.1" } environmental = { version = "1" } +event-listener = { version = "5" } +event-listener-strategy = { version = "0.5" } finality-grandpa = { version = "0.16", features = ["derive-codec"] } fixed-hash = { version = "0.8", default-features = false, features = ["std"] } fnv = { version = "1" } @@ -638,13 +640,12 @@ jsonrpsee-core = { version = "0.24", features = ["async-client", "async-wasm-cli k256 = { version = "0.13", features = ["serde"] } keccak = { version = "0.1", default-features = false, features = ["asm"] } libc = { version = "0.2" } -libp2p = { version = "0.54", default-features = false, features = ["cbor", "dns", "ecdsa", "ed25519", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "serde", "tcp", "tls", "tokio", "websocket", "yamux"] } -libp2p-core = { version = "0.42", default-features = false, features = ["serde"] } -libp2p-gossipsub = { version = "0.47", default-features = false, features = ["serde"] } +libp2p = { version = "0.56", default-features = false, features = ["cbor", "dns", "ecdsa", "ed25519", "gossipsub", "identify", "kad", "macros", "mdns", "metrics", "noise", "ping", "plaintext", "quic", "request-response", "secp256k1", "serde", "tcp", "tls", "tokio", "yamux"] } +libp2p-core = { version = "0.43", default-features = false, features = ["serde"] } +libp2p-gossipsub = { version = "0.49", default-features = false, features = ["metrics", "serde"] } libp2p-identity = { version = "0.2", default-features = false, features = ["ecdsa", "ed25519", "peerid", "rand", "secp256k1", "serde"] } -libp2p-kad = { version = "0.46", default-features = false, features = ["serde"] } -libp2p-request-response = { version = "0.27", default-features = false, features = ["cbor"] } -libp2p-swarm = { version = "0.45", default-features = false, features = ["async-std", "macros", "tokio"] } +libp2p-kad = { version = "0.48", default-features = false, features = ["serde"] } +libp2p-request-response = { version = "0.29", default-features = false, features = ["cbor"] } libsecp256k1 = { version = "0.7", default-features = false, features = ["static-context", "std"] } libsecp256k1-core = { version = "0.3" } log = { version = "0.4", default-features = false, features = ["std"] } @@ -701,7 +702,6 @@ rustc-demangle = { version = "0.1", default-features = false, features = ["std"] rustc-hash-dff4ba8e3ae991db = { package = "rustc-hash", version = "1" } rustc-hash-f595c2ba2a3f28df = { package = "rustc-hash", version = "2" } rustc-hex = { version = "2", default-features = false, features = ["std"] } -rustix = { version = "1", default-features = false, features = ["fs", "mm", "net", "param", "std", "use-libc"] } rustls = { version = "0.23", default-features = false, features = ["logging", "ring", "std", "tls12"] } rustls-webpki = { version = "0.103", default-features = false, features = ["ring", "std"] } scale-bits = { version = "0.7" } @@ -811,31 +811,25 @@ zeroize = { version = "1", features = ["derive", "std"] } [target.'cfg(all(target_arch = "x86_64", target_vendor = "unknown", target_os = "linux", target_env = "gnu", not(any(target_arch = "wasm32", loom))))'.dependencies] errno = { version = "0.3" } -event-listener = { version = "5" } -event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } -hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } +hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } +hickory-resolver = { version = "0.25" } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } -if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } -linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } -log = { version = "0.4", default-features = false, features = ["kv_unstable"] } +linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } -netlink-proto = { version = "0.11", default-features = false, features = ["smol_socket", "tokio_socket"] } -netlink-sys = { version = "0.8", features = ["smol_socket", "tokio_socket"] } nix = { version = "0.26" } rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } -rtnetlink = { version = "0.13", default-features = false, features = ["smol_socket", "tokio_socket"] } -rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "thread", "time", "use-libc"] } rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } -rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +rustls-webpki = { version = "0.103", features = ["aws-lc-rs"] } secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } +socket2 = { version = "0.5", default-features = false, features = ["all"] } tikv-jemalloc-sys = { version = "0.6", features = ["stats", "unprefixed_malloc_on_supported_platforms"] } tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } yasna = { version = "0.5", features = ["std", "time"] } @@ -843,31 +837,25 @@ zerocopy = { version = "0.8", default-features = false, features = ["derive", "s [target.'cfg(all(target_arch = "x86_64", target_vendor = "unknown", target_os = "linux", target_env = "gnu", not(any(target_arch = "wasm32", loom))))'.build-dependencies] errno = { version = "0.3" } -event-listener = { version = "5" } -event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } -hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } +hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } +hickory-resolver = { version = "0.25" } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } -if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } -linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } -log = { version = "0.4", default-features = false, features = ["kv_unstable"] } +linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } -netlink-proto = { version = "0.11", default-features = false, features = ["smol_socket", "tokio_socket"] } -netlink-sys = { version = "0.8", features = ["smol_socket", "tokio_socket"] } nix = { version = "0.26" } rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } -rtnetlink = { version = "0.13", default-features = false, features = ["smol_socket", "tokio_socket"] } -rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "thread", "time", "use-libc"] } rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } -rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +rustls-webpki = { version = "0.103", features = ["aws-lc-rs"] } secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } +socket2 = { version = "0.5", default-features = false, features = ["all"] } tikv-jemalloc-sys = { version = "0.6", features = ["stats", "unprefixed_malloc_on_supported_platforms"] } tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } yasna = { version = "0.5", features = ["std", "time"] } @@ -875,31 +863,25 @@ zerocopy = { version = "0.8", default-features = false, features = ["derive", "s [target.'cfg(all(target_arch = "aarch64", target_vendor = "unknown", target_os = "linux", target_env = "gnu", not(any(target_arch = "wasm32", loom))))'.dependencies] errno = { version = "0.3" } -event-listener = { version = "5" } -event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } -hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } +hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } +hickory-resolver = { version = "0.25" } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } -if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } -linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } -log = { version = "0.4", default-features = false, features = ["kv_unstable"] } +linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } -netlink-proto = { version = "0.11", default-features = false, features = ["smol_socket", "tokio_socket"] } -netlink-sys = { version = "0.8", features = ["smol_socket", "tokio_socket"] } nix = { version = "0.26" } rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } -rtnetlink = { version = "0.13", default-features = false, features = ["smol_socket", "tokio_socket"] } -rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "thread", "time", "use-libc"] } rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } -rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +rustls-webpki = { version = "0.103", features = ["aws-lc-rs"] } secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } +socket2 = { version = "0.5", default-features = false, features = ["all"] } tikv-jemalloc-sys = { version = "0.6", features = ["stats", "unprefixed_malloc_on_supported_platforms"] } tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } yasna = { version = "0.5", features = ["std", "time"] } @@ -907,31 +889,25 @@ zerocopy = { version = "0.8", default-features = false, features = ["derive", "s [target.'cfg(all(target_arch = "aarch64", target_vendor = "unknown", target_os = "linux", target_env = "gnu", not(any(target_arch = "wasm32", loom))))'.build-dependencies] errno = { version = "0.3" } -event-listener = { version = "5" } -event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } -hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } +hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } +hickory-resolver = { version = "0.25" } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } -if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } -linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } -log = { version = "0.4", default-features = false, features = ["kv_unstable"] } +linux-raw-sys = { version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } mio = { version = "1", features = ["net", "os-ext"] } -netlink-proto = { version = "0.11", default-features = false, features = ["smol_socket", "tokio_socket"] } -netlink-sys = { version = "0.8", features = ["smol_socket", "tokio_socket"] } nix = { version = "0.26" } rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } -rtnetlink = { version = "0.13", default-features = false, features = ["smol_socket", "tokio_socket"] } -rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "thread", "time", "use-libc"] } rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } -rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +rustls-webpki = { version = "0.103", features = ["aws-lc-rs"] } secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } +socket2 = { version = "0.5", default-features = false, features = ["all"] } tikv-jemalloc-sys = { version = "0.6", features = ["stats", "unprefixed_malloc_on_supported_platforms"] } tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } yasna = { version = "0.5", features = ["std", "time"] } @@ -939,52 +915,48 @@ zerocopy = { version = "0.8", default-features = false, features = ["derive", "s [target.'cfg(all(target_arch = "aarch64", target_vendor = "apple", target_os = "macos", not(any(target_arch = "wasm32", loom))))'.dependencies] errno = { version = "0.3" } -event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } -hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } +hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } +hickory-resolver = { version = "0.25" } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } -if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } -log = { version = "0.4", default-features = false, features = ["kv_unstable"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } -rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "thread", "use-libc"] } rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } -rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +rustls-webpki = { version = "0.103", features = ["aws-lc-rs"] } secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } security-framework = { version = "3", features = ["OSX_10_14"] } security-framework-sys = { version = "2", features = ["OSX_10_14"] } +socket2 = { version = "0.5", default-features = false, features = ["all"] } tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } yasna = { version = "0.5", features = ["std", "time"] } zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] } [target.'cfg(all(target_arch = "aarch64", target_vendor = "apple", target_os = "macos", not(any(target_arch = "wasm32", loom))))'.build-dependencies] errno = { version = "0.3" } -event-listener-strategy = { version = "0.5" } futures-rustls = { version = "0.26", default-features = false, features = ["ring"] } -hickory-proto = { version = "0.24", default-features = false, features = ["mdns", "tokio-runtime"] } +hickory-proto = { version = "0.25", default-features = false, features = ["mdns", "tokio"] } +hickory-resolver = { version = "0.25" } hyper-rustls = { version = "0.27", default-features = false, features = ["aws-lc-rs", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-proxy"] } idna = { version = "1" } -if-watch = { version = "3", default-features = false, features = ["smol", "tokio"] } itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } libc = { version = "0.2", default-features = false, features = ["extra_traits"] } -libp2p-tcp = { version = "0.42", default-features = false, features = ["async-io", "tokio"] } librocksdb-sys = { version = "0.17", default-features = false, features = ["jemalloc", "snappy", "static"] } -log = { version = "0.4", default-features = false, features = ["kv_unstable"] } miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } rocksdb = { version = "0.24", default-features = false, features = ["jemalloc", "snappy"] } -rustix = { version = "1", features = ["event", "pipe", "process", "termios", "thread", "time"] } +rustix = { version = "1", features = ["fs", "mm", "param", "process", "termios", "thread", "use-libc"] } rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs", "aws_lc_rs"] } -rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs"] } +rustls-webpki = { version = "0.103", features = ["aws-lc-rs"] } secp256k1-sys = { version = "0.9", default-features = false, features = ["recovery", "std"] } security-framework = { version = "3", features = ["OSX_10_14"] } security-framework-sys = { version = "2", features = ["OSX_10_14"] } +socket2 = { version = "0.5", default-features = false, features = ["all"] } tokio-rustls = { version = "0.26", default-features = false, features = ["aws-lc-rs"] } yasna = { version = "0.5", features = ["std", "time"] } zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] } From 6bcd397704483b132a8e1ef3c6a8eec376551f4b Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Wed, 10 Jun 2026 16:19:32 +0400 Subject: [PATCH 07/13] Patch libp2p swarm derive via git source --- Cargo.lock | 1 + Cargo.toml | 3 +- THIRD_PARTY_NOTICES.md | 9 - .../libp2p-swarm-0.45.1/.cargo_vcs_info.json | 6 - third-party/libp2p-swarm-0.45.1/CHANGELOG.md | 1003 ------- third-party/libp2p-swarm-0.45.1/Cargo.toml | 189 -- .../libp2p-swarm-0.45.1/Cargo.toml.orig | 76 - .../benches/connection_handler.rs | 360 --- .../libp2p-swarm-0.45.1/src/behaviour.rs | 585 ---- .../src/behaviour/either.rs | 168 -- .../src/behaviour/external_addresses.rs | 182 -- .../src/behaviour/listen_addresses.rs | 78 - .../src/behaviour/peer_addresses.rs | 338 --- .../src/behaviour/toggle.rs | 377 --- .../libp2p-swarm-0.45.1/src/connection.rs | 1387 ---------- .../src/connection/error.rs | 147 -- .../src/connection/pool.rs | 1044 -------- .../src/connection/pool/concurrent_dial.rs | 103 - .../src/connection/pool/task.rs | 265 -- .../src/connection/supported_protocols.rs | 92 - .../libp2p-swarm-0.45.1/src/dial_opts.rs | 348 --- third-party/libp2p-swarm-0.45.1/src/dummy.rs | 120 - .../libp2p-swarm-0.45.1/src/executor.rs | 70 - .../libp2p-swarm-0.45.1/src/handler.rs | 896 ------- .../libp2p-swarm-0.45.1/src/handler/either.rs | 230 -- .../libp2p-swarm-0.45.1/src/handler/map_in.rs | 98 - .../src/handler/map_out.rs | 106 - .../libp2p-swarm-0.45.1/src/handler/multi.rs | 456 ---- .../src/handler/one_shot.rs | 237 -- .../src/handler/pending.rs | 97 - .../libp2p-swarm-0.45.1/src/handler/select.rs | 350 --- third-party/libp2p-swarm-0.45.1/src/lib.rs | 2346 ----------------- .../libp2p-swarm-0.45.1/src/listen_opts.rs | 33 - third-party/libp2p-swarm-0.45.1/src/stream.rs | 98 - .../src/stream_protocol.rs | 132 - third-party/libp2p-swarm-0.45.1/src/test.rs | 522 ---- .../libp2p-swarm-0.45.1/src/translation.rs | 115 - .../libp2p-swarm-0.45.1/src/upgrade.rs | 158 -- .../tests/connection_close.rs | 148 -- .../libp2p-swarm-0.45.1/tests/listener.rs | 144 - .../libp2p-swarm-0.45.1/tests/swarm_derive.rs | 618 ----- .../tests/ui/fail/prelude_not_string.rs | 11 - .../tests/ui/fail/prelude_not_string.stderr | 5 - .../tests/ui/fail/to_swarm_not_string.rs | 19 - .../tests/ui/fail/to_swarm_not_string.stderr | 5 - 45 files changed, 2 insertions(+), 13773 deletions(-) delete mode 100644 third-party/libp2p-swarm-0.45.1/.cargo_vcs_info.json delete mode 100644 third-party/libp2p-swarm-0.45.1/CHANGELOG.md delete mode 100644 third-party/libp2p-swarm-0.45.1/Cargo.toml delete mode 100644 third-party/libp2p-swarm-0.45.1/Cargo.toml.orig delete mode 100644 third-party/libp2p-swarm-0.45.1/benches/connection_handler.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/either.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/external_addresses.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/listen_addresses.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/peer_addresses.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/behaviour/toggle.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/connection.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/error.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/pool.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/pool/concurrent_dial.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/pool/task.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/connection/supported_protocols.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/dial_opts.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/dummy.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/executor.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/handler.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/either.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/map_in.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/map_out.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/multi.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/one_shot.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/pending.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/handler/select.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/lib.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/listen_opts.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/stream.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/stream_protocol.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/test.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/translation.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/src/upgrade.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/tests/connection_close.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/tests/listener.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/tests/swarm_derive.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.stderr delete mode 100644 third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.rs delete mode 100644 third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.stderr diff --git a/Cargo.lock b/Cargo.lock index 965006d8e06..cafdcf63b96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11139,6 +11139,7 @@ dependencies = [ [[package]] name = "libp2p-swarm" version = "0.45.1" +source = "git+https://github.com/gear-tech/rust-libp2p?rev=dc3cefa6db9958faa330aaf3e9cce8edd8740a19#dc3cefa6db9958faa330aaf3e9cce8edd8740a19" dependencies = [ "either", "fnv", diff --git a/Cargo.toml b/Cargo.toml index 59247dde79e..0a86abdc98e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ exclude = [ "ethexe/docker", "ethexe/malachite", "ethexe/scripts", - "third-party/libp2p-swarm-0.45.1", ] members = [ @@ -723,7 +722,7 @@ debug = true [patch.crates-io] gear-workspace-hack = { path = "utils/gear-workspace-hack" } -libp2p-swarm = { path = "third-party/libp2p-swarm-0.45.1" } +libp2p-swarm = { git = "https://github.com/gear-tech/rust-libp2p", rev = "dc3cefa6db9958faa330aaf3e9cce8edd8740a19", package = "libp2p-swarm" } # core2 0.4.0 was yanked on crates.io; pin upstream git so cargo metadata doesn't fail on yanked lookup. # Needed by cid -> sc-network transitive; triggers during wasm-builder sub-project resolve. core2 = { git = "https://github.com/bbqsrc/core2", rev = "545e84bcb0f235b12e21351e0c69767958efe2a7" } diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index d02995e0509..76deb85ddd8 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -25,15 +25,6 @@ uses upstream `sc-mixnet` from the Polkadot SDK source reference above. Additional third-party file: `substrate/runtime-executor/wasmtime/src/test-guard-page-skip.wat` is a modified WebAssembly testsuite fixture from , licensed under Apache-2.0. -## libp2p Copied Source - -`third-party/libp2p-swarm-0.45.1` is copied from the crates.io -`libp2p-swarm` 0.45.1 package, originally published from -. Gear patches only its -`libp2p-swarm-derive` dependency to `=0.35.1` so the stable2603 Substrate -networking stack can coexist with ethexe's upstream libp2p 0.56 dependency -line. `libp2p-swarm` declares the MIT license in its package manifest. - Apache-2.0 license text: MIT license text: GPL-3.0-or-later WITH Classpath-exception-2.0 license text: [`LICENSE`](LICENSE) diff --git a/third-party/libp2p-swarm-0.45.1/.cargo_vcs_info.json b/third-party/libp2p-swarm-0.45.1/.cargo_vcs_info.json deleted file mode 100644 index 4929f430a48..00000000000 --- a/third-party/libp2p-swarm-0.45.1/.cargo_vcs_info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "git": { - "sha1": "87101870709aaf64e141e07624855155ed4faaac" - }, - "path_in_vcs": "swarm" -} \ No newline at end of file diff --git a/third-party/libp2p-swarm-0.45.1/CHANGELOG.md b/third-party/libp2p-swarm-0.45.1/CHANGELOG.md deleted file mode 100644 index b5fb72d68ac..00000000000 --- a/third-party/libp2p-swarm-0.45.1/CHANGELOG.md +++ /dev/null @@ -1,1003 +0,0 @@ -## 0.45.1 - -- Update `libp2p-swarm-derive` to version `0.35.0`, see [PR XXXX] - -[PR XXXX]: https://github.com/libp2p/rust-libp2p/pull/XXXX - -## 0.45.0 - -- Implement refactored `Transport`. - See [PR 4568] -- Move `address_translation` into swarm and into `libp2p-identify`. - See [PR 4568] - -[PR 4568]: https://github.com/libp2p/rust-libp2p/pull/4568 - -## 0.44.3 -- Optimize internal connection `fn poll`. New implementation now scales much better with number of listen protocols active. - No changes to public API introduced. - See [PR 5026](https://github.com/libp2p/rust-libp2p/pull/5026) -- Add peer_id to `FromSwarm::ListenFailure`. - See [PR 4818](https://github.com/libp2p/rust-libp2p/pull/4818). -- Use `web-time` instead of `instant`. - See [PR 5347](https://github.com/libp2p/rust-libp2p/pull/5347). -- Add `#[track_caller]` on all `spawn` wrappers. - See [PR 5465](https://github.com/libp2p/rust-libp2p/pull/5465). -- Add ConnectionError to FromSwarm::ConnectionClosed. - See [PR 5485](https://github.com/libp2p/rust-libp2p/pull/5485). - -## 0.44.2 - -- Allow `NetworkBehaviour`s to share addresses of peers. - This is enabled via the new `ToSwarm::NewExternalAddrOfPeer` event. - The address is broadcast to all behaviours via `FromSwarm::NewExternalAddrOfPeer`. - Protocols that want to collect these addresses can use the new `PeerAddresses` utility. - See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371). - -## 0.44.1 - -- Implement `Clone` & `Copy` for `FromSwarm. - This makes it easier to forward these events when wrapping other behaviours. - See [PR 4825](https://github.com/libp2p/rust-libp2p/pull/4825). - -## 0.44.0 - -- Add `#[non_exhaustive]` to `FromSwarm`, `ToSwarm`, `SwarmEvent`, `ConnectionHandlerEvent`, `ConnectionEvent`. - See [PR 4581](https://github.com/libp2p/rust-libp2p/pull/4581). -- Remove `handler` field from `ConnectionClosed`. - If you need to transfer state from a `ConnectionHandler` to its `NetworkBehaviour` when a connection closes, use `ConnectionHandler::poll_close`. - See [PR 4076](https://github.com/libp2p/rust-libp2p/pull/4076). -- Remove deprecated `PollParameters` from `NetworkBehaviour::poll` function. - See [PR 4490](https://github.com/libp2p/rust-libp2p/pull/4490). -- Remove deprecated `ConnectionHandlerEvent::Close` and `ConnectionHandler::Error`. - `ConnectionHandler`s should not close connections directly as the connection might still be in use by other handlers. - See [PR 4755](https://github.com/libp2p/rust-libp2p/pull/4755). -- Add `PeerCondition::DisconnectedAndNotDialing` variant, combining pre-existing conditions. - This is the new default. - A new dialing attempt is iniated _only if_ the peer is both considered disconnected and there is currently no ongoing dialing attempt. - See [PR 4225](https://github.com/libp2p/rust-libp2p/pull/4225). -- Remove deprecated `keep_alive_timeout` in `OneShotHandlerConfig`. - See [PR 4677](https://github.com/libp2p/rust-libp2p/pull/4677). -- Don't close entire connection upon `DialUpgradeError`s within `OneShotHandler`. - Instead, the error is reported as `Err(e)` via `ConnectionHandler::ToBehaviour`. - See [PR 4715](https://github.com/libp2p/rust-libp2p/pull/4715). -- Log `PeerId` of `Swarm` even when constructed with new `SwarmBuilder`. - See [PR 4671](https://github.com/libp2p/rust-libp2p/pull/4671). -- Add `SwarmEvent::{NewExternalAddrCandidate,ExternalAddrConfirmed,ExternalAddrExpired}` variants. - See [PR 4721](https://github.com/libp2p/rust-libp2p/pull/4721). -- Remove deprecated symbols. - See [PR 4737](https://github.com/libp2p/rust-libp2p/pull/4737). - -## 0.43.7 - -- Deprecate `ConnectionHandlerEvent::Close`. - See [issue 3591](https://github.com/libp2p/rust-libp2p/issues/3591) for details. - See [PR 4714](https://github.com/libp2p/rust-libp2p/pull/4714). - -## 0.43.6 - -- Deprecate `libp2p::swarm::SwarmBuilder`. - Most users should use `libp2p::SwarmBuilder`. - In some special cases, users may need to use `Swarm::new` and `Config` instead of the new `libp2p::SwarmBuilder`. - See [PR 4120]. -- Make the `Debug` implementation of `StreamProtocol` more concise. - See [PR 4631](https://github.com/libp2p/rust-libp2p/pull/4631). -- Fix overflow in `KeepAlive` computation that could occur panic at `Delay::new` if `SwarmBuilder::idle_connection_timeout` is configured too large. - See [PR 4644](https://github.com/libp2p/rust-libp2p/pull/4644). -- Deprecate `KeepAlive::Until`. - Individual protocols should not keep connections alive for longer than necessary. - Users should use `swarm::Config::idle_connection_timeout` instead. - See [PR 4656](https://github.com/libp2p/rust-libp2p/pull/4656). -- Deprecate `keep_alive_timeout` in `OneShotHandlerConfig`. - See [PR 4680](https://github.com/libp2p/rust-libp2p/pull/4680). - -[PR 4120]: https://github.com/libp2p/rust-libp2p/pull/4120 - -## 0.43.5 - -- Fix overflow in `KeepAlive` computation that could occur if `SwarmBuilder::idle_connection_timeout` is configured with `u64::MAX`. - See [PR 4559](https://github.com/libp2p/rust-libp2p/pull/4559). - -## 0.43.4 - -- Implement `Debug` for event structs. - See [PR 4426]. - -- Improve error message when `DialPeerCondition` prevents a dial. - See [PR 4409]. - -- Introduce `SwarmBuilder::idle_conncetion_timeout` and deprecate `keep_alive::Behaviour` as a result. - See [PR 4161]. - -[PR 4426]: https://github.com/libp2p/rust-libp2p/pull/4426 -[PR 4409]: https://github.com/libp2p/rust-libp2p/pull/4409 -[PR 4161]: https://github.com/libp2p/rust-libp2p/pull/4161 - -## 0.43.3 - -- Implement `Display` for `ConnectionId`. - See [PR 4278]. - -[PR 4278]: https://github.com/libp2p/rust-libp2p/pull/4278 - -## 0.43.2 -- Display the cause of a `ListenError::Denied`. - See [PR 4232] - -[PR 4232]: https://github.com/libp2p/rust-libp2p/pull/4158 - -## 0.43.1 - -- Do not announce external address candidate before address translation, unless translation does not apply. - This will prevent ephemeral TCP addresses being announced as external address candidates. - See [PR 4158]. - -[PR 4158]: https://github.com/libp2p/rust-libp2p/pull/4158 - -## 0.43.0 - -- Allow `NetworkBehaviours` to create and remove listeners. - See [PR 3292]. - -- Raise MSRV to 1.65. - See [PR 3715]. - -- Introduce `StreamProtocol` type. - This type enforces invariants on protocol names, such as leading forward slashes and correct UTF8 encoding. - See [PR 3746]. - -- Return a bool from `ExternalAddresses::on_swarm_event` and `ListenAddresses::on_swarm_event` indicating whether any state was changed. - See [PR 3865]. - -- Remove deprecated banning API from `Swarm`. - Users should migrate to `libp2p::allow_block_list`. - See [PR 3886]. - -- Remove `ConnectionHandlerUpgrErr::Timer` variant. - This variant was never constructed and thus dead code. - See [PR 3605]. - -- Remove deprecated `IntoConnectionHandler` and all its implementations. - This also removes the `NetworkBehaviour::new_handler` and `NetworkBehaviour::addresses_of_peer` methods. - See changelog for `0.42` on how to migrate. - See [PR 3884]. - -- Remove `ConnectionHandlerUpgrErr::Timer` variant. - This variant was never constructed and thus dead code. - See [PR 3605]. - -- Flatten `ConnectionHandlerUpgrErr` and rename to `StreamUpgradeError`. - See [PR 3882]. - -- Remove deprecated `ConnectionLimits`. - Users should migrate to `libp2p::connection_limits::Behaviour`. - See [PR 3885]. - -- Allow `ConnectionHandler`s to report and learn about the supported protocols on a connection. - The newly introduced API elements are: - - `ConnectionHandlerEvent::ReportRemoteProtocols` - - `ConnectionEvent::LocalProtocolsChange` - - `ConnectionEvent::RemoteProtocolsChange` - - See [PR 3651]. - -- Deprecate the `NegotiatedSubstream` type and replace it with `Stream`. - See [PR 3912]. - -- Rename `NetworkBehaviour::OutEvent` to `NetworkBehaviour::ToSwarm`, `ConnectionHandler::InEvent` to `ConnectionHandler::FromBehaviour`, `ConnectionHandler::OutEvent` to `ConnectionHandler::ToBehaviour`. See [PR 3848]. - -- Remove deprecated `NetworkBehaviourAction` type. - See [PR 3919]. - -- Expose `ConnectionId` on `SwarmEvent::{ConnectionEstablished,ConnectionClosed,IncomingConnection,IncomingConnectionError,OutgoingConnectionError,Dialing}`. - Also emit `SwarmEvent::Dialing` for dials with unknown `PeerId`. - See [PR 3927]. - -- Rename `ConnectionHandlerEvent::Custom` to `ConnectionHandlerEvent::NotifyBehaviour`. See [PR 3955]. - -- Remove `DialError::InvalidPeerId` variant. With the move to `multiaddr` `v0.18.0` peer IDs in `/p2p` are type safe and thus usage of the contained peer ID can not result in a parsing error. - See [PR 4037]. - -- Remove deprecated items. See [PR 3956]. - -- Add ability to `downcast_ref` ConnectionDenied errors. See [PR 4020]. - -[PR 3292]: https://github.com/libp2p/rust-libp2p/pull/3292 -[PR 3605]: https://github.com/libp2p/rust-libp2p/pull/3605 -[PR 3651]: https://github.com/libp2p/rust-libp2p/pull/3651 -[PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 -[PR 3746]: https://github.com/libp2p/rust-libp2p/pull/3746 -[PR 3848]: https://github.com/libp2p/rust-libp2p/pull/3848 -[PR 3865]: https://github.com/libp2p/rust-libp2p/pull/3865 -[PR 3882]: https://github.com/libp2p/rust-libp2p/pull/3882 -[PR 3884]: https://github.com/libp2p/rust-libp2p/pull/3884 -[PR 3885]: https://github.com/libp2p/rust-libp2p/pull/3885 -[PR 3886]: https://github.com/libp2p/rust-libp2p/pull/3886 -[PR 3912]: https://github.com/libp2p/rust-libp2p/pull/3912 -[PR 3919]: https://github.com/libp2p/rust-libp2p/pull/3919 -[PR 3927]: https://github.com/libp2p/rust-libp2p/pull/3927 -[PR 3955]: https://github.com/libp2p/rust-libp2p/pull/3955 -[PR 3956]: https://github.com/libp2p/rust-libp2p/pull/3956 -[PR 4020]: https://github.com/libp2p/rust-libp2p/pull/4020 -[PR 4037]: https://github.com/libp2p/rust-libp2p/pull/4037 - -## 0.42.2 - -- Add `ConnectionEvent::{is_outbound,is_inbound}`. See [PR 3625]. - -[PR 3625]: https://github.com/libp2p/rust-libp2p/pull/3625 - -## 0.42.1 - -- Deprecate `ConnectionLimits` in favor of `libp2p::connection_limits`. - See [PR 3386]. - -- Introduce `ConnectionId::new_unchecked` to allow for more sophisticated, manual tests of `NetworkBehaviour`. - See [PR 3652]. - -- Deprecate `Swarm::ban_peer_id` in favor of the new `libp2p::allow_block_list` module. - See [PR 3590]. - -- Rename `NetworkBehaviourAction` to `ToSwarm`. - A deprecated type-alias is provided to ease the transition. - The new name is meant to better indicate the message-passing relationship between `Swarm` and `NetworkBehaviour`. - See [PR 3658]. - -[PR 3386]: https://github.com/libp2p/rust-libp2p/pull/3386 -[PR 3652]: https://github.com/libp2p/rust-libp2p/pull/3652 -[PR 3590]: https://github.com/libp2p/rust-libp2p/pull/3590 -[PR 3658]: https://github.com/libp2p/rust-libp2p/pull/3658 - -## 0.42.0 - -- Allow `NetworkBehaviour`s to manage connections. - We deprecate `NetworkBehaviour::new_handler` and `NetworkBehaviour::addresses_of_peer` in favor of four new callbacks: - - - `NetworkBehaviour::handle_pending_inbound_connection` - - `NetworkBehaviour::handle_pending_outbound_connection` - - `NetworkBehaviour::handle_established_inbound_connection` - - `NetworkBehaviour::handle_established_outbound_connection` - - Please note that due to [limitations](https://github.com/rust-lang/rust/issues/98990) in the Rust compiler, _implementations_ of `new_handler` and `addresses_of_peer` are not flagged as deprecated. - Nevertheless, they will be removed in the future. - - All four are fallible and returning an error from any of them will abort the given connection. - This allows you to create dedicated `NetworkBehaviour`s that only concern themselves with managing connections. - For example: - - checking the `PeerId` of a newly established connection against an allow/block list - - only allowing X connection upgrades at any one time - - denying incoming or outgoing connections from a certain IP range - - only allowing N connections to or from the same peer - - See [PR 3254]. - -- Remove `handler` field from `NetworkBehaviourAction::Dial`. - Instead of constructing the handler early, you can now access the `ConnectionId` of the future connection on `DialOpts`. - `ConnectionId`s are `Copy` and will be used throughout the entire lifetime of the connection to report events. - This allows you to send events to a very specific connection, much like you previously could directly set state in the handler. - - Removing the `handler` field also reduces the type parameters of `NetworkBehaviourAction` from three to two. - The third one used to be defaulted to the `InEvent` of the `ConnectionHandler`. - You now have to manually specify that where you previously had to specify the `ConnectionHandler`. - This very likely will trigger **convoluted compile errors** about traits not being implemented. - - Within `NetworkBehaviourAction::poll`, the easiest way to migrate is to do this (in the example of `libp2p-floodsub`): - ```diff - --- a/protocols/floodsub/src/layer.rs - +++ b/protocols/floodsub/src/layer.rs - @@ -472,7 +465,7 @@ impl NetworkBehaviour for Floodsub { - &mut self, - _: &mut Context<'_>, - _: &mut impl PollParameters, - - ) -> Poll> { - + ) -> Poll>> { - ``` - - In other words: - - |Search|Replace| - |---|---| - |`NetworkBehaviourAction`|`NetworkBehaviourAction>`| - - If you reference `NetworkBehaviourAction` somewhere else as well, - you may have to fill in the type of `ConnectionHandler::InEvent` manually as the 2nd parameter. - - See [PR 3328]. - -- Update to `libp2p-core` `v0.39.0`. - -- Removed deprecated Swarm constructors. For transition notes see [0.41.0](#0.41.0). See [PR 3170]. - -- Deprecate functions on `PollParameters` in preparation for `PollParameters` to be removed entirely eventually. See [PR 3153]. - -- Add `estblished_in` to `SwarmEvent::ConnectionEstablished`. See [PR 3134]. - -- Remove deprecated `inject_*` methods from `NetworkBehaviour` and `ConnectionHandler`. - Make the implementation of `on_swarm_event` and `on_connection_handler_event` - both mandatory. See [PR 3264] and [PR 3364]. - -- Update to `libp2p-swarm-derive` `v0.32.0`. - -- Replace `SwarmBuilder::connection_event_buffer_size` with `SwarmBuilder::per_connection_event_buffer_size` . - The configured value now applies _per_ connection. - The default values remains 7. - If you have previously set `connection_event_buffer_size` you should re-evaluate what a good size for a _per connection_ buffer is. - See [PR 3188]. - -- Remove `DialError::ConnectionIo` variant. - This was never constructed. - See [PR 3374]. - -- Introduce `ListenError` and use it within `SwarmEvent::IncomingConnectionError`. - See [PR 3375]. - -- Remove `PendingConnectionError`, `PendingInboundConnectionError` and `PendingOutboundConnectionError` from the public API. - They are no longer referenced anywhere with the addition of `ListenError`. - See [PR 3497]. - -- Remove `ConnectionId::new`. Manually creating `ConnectionId`s is now unsupported. See [PR 3327]. - -- Deprecate methods `Swarm::with_executor`, `Swarm::with_*_executor`, `Swarm::without_executor`. - Introduce similar methods in `SwarmBuilder`. See [PR 3588]. - -- Gracefully disable oneshot handler on dial upgrade errors. See [PR 3577]. - -[PR 3364]: https://github.com/libp2p/rust-libp2p/pull/3364 -[PR 3170]: https://github.com/libp2p/rust-libp2p/pull/3170 -[PR 3134]: https://github.com/libp2p/rust-libp2p/pull/3134 -[PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153 -[PR 3264]: https://github.com/libp2p/rust-libp2p/pull/3264 -[PR 3272]: https://github.com/libp2p/rust-libp2p/pull/3272 -[PR 3327]: https://github.com/libp2p/rust-libp2p/pull/3327 -[PR 3328]: https://github.com/libp2p/rust-libp2p/pull/3328 -[PR 3188]: https://github.com/libp2p/rust-libp2p/pull/3188 -[PR 3377]: https://github.com/libp2p/rust-libp2p/pull/3377 -[PR 3373]: https://github.com/libp2p/rust-libp2p/pull/3373 -[PR 3374]: https://github.com/libp2p/rust-libp2p/pull/3374 -[PR 3375]: https://github.com/libp2p/rust-libp2p/pull/3375 -[PR 3254]: https://github.com/libp2p/rust-libp2p/pull/3254 -[PR 3497]: https://github.com/libp2p/rust-libp2p/pull/3497 -[PR 3588]: https://github.com/libp2p/rust-libp2p/pull/3588 -[PR 3577]: https://github.com/libp2p/rust-libp2p/pull/3577 - -## 0.41.1 - -- Update to `libp2p-swarm-derive` `v0.31.0`. - -## 0.41.0 - -- Update to `libp2p-core` `v0.38.0`. - -- Add new `on_connection_event` method to `ConnectionHandler` that accepts a `ConnectionEvent` enum and update - `inject_*` methods to call `on_connection_event` with the respective `ConnectionEvent` variant and deprecate - `inject_*`. - To migrate, users should replace the `ConnectionHandler::inject_*` calls with a single - implementation of `ConnectionHandler::on_connection_event` treating each `ConnectionEvent` variant in - the same way its corresponding `inject_*` call was treated. - See [PR 3085]. - -- Add new `on_behaviour_event` method with the same signature as `inject_event`, make the - default implementation of `inject_event` call `on_behaviour_event` and deprecate it. - To migrate, users should replace the `ConnectionHandler::inject_event` call - with `ConnectionHandler::on_behaviour_event`. - See [PR 3085]. - -- Add new `on_swarm_event` method to `NetworkBehaviour` that accepts a `FromSwarm` enum and update - `inject_*` methods to call `on_swarm_event` with the respective `FromSwarm` variant and deprecate - `inject_*`. - To migrate, users should replace the `NetworkBehaviour::inject_*` calls with a single - implementation of `NetworkBehaviour::on_swarm_event` treating each `FromSwarm` variant in - the same way its corresponding `inject_*` call was treated. - See [PR 3011]. - -- Add new `on_connection_handler_event` method with the same signature as `inject_event`, make the - default implementation of `inject_event` call `on_connection_handler_event` and deprecate it. - To migrate, users should replace the `NetworkBehaviour::inject_event` call - with `NetworkBehaviour::on_connection_handler_event`. - See [PR 3011]. - -- Export `NetworkBehaviour` derive as `libp2p_swarm::NetworkBehaviour`. - This follows the convention of other popular libraries. `serde` for example exports the `Serialize` trait and macro as - `serde::Serialize`. See [PR 3055]. - -- Feature-gate `NetworkBehaviour` macro behind `macros` feature flag. See [PR 3055]. - -- Make executor in Swarm constructor explicit. See [PR 3097]. - - Supported executors: - - Tokio - - Previously - ```rust - let swarm = SwarmBuilder::new(transport, behaviour, peer_id) - .executor(Box::new(|fut| { - tokio::spawn(fut); - })) - .build(); - ``` - Now - ```rust - let swarm = Swarm::with_tokio_executor(transport, behaviour, peer_id); - ``` - - Async Std - - Previously - ```rust - let swarm = SwarmBuilder::new(transport, behaviour, peer_id) - .executor(Box::new(|fut| { - async_std::task::spawn(fut); - })) - .build(); - ``` - Now - ```rust - let swarm = Swarm::with_async_std_executor(transport, behaviour, peer_id); - ``` - - ThreadPool (see [Issue 3107]) - - In most cases ThreadPool can be replaced by executors or spawning on the local task. - - Previously - ```rust - let swarm = Swarm::new(transport, behaviour, peer_id); - ``` - - Now - ```rust - let swarm = Swarm::with_threadpool_executor(transport, behaviour, peer_id); - ``` - - Without - - Spawns the tasks on the current task, this may result in bad performance so try to use an executor where possible. Previously this was just a fallback when no executor was specified and constructing a `ThreadPool` failed. - - New - ```rust - let swarm = Swarm::without_executor(transport, behaviour, peer_id); - ``` - - Deprecated APIs: - - `Swarm::new` - - `SwarmBuilder::new` - - `SwarmBuilder::executor` - -- Update `rust-version` to reflect the actual MSRV: 1.62.0. See [PR 3090]. - -[PR 3085]: https://github.com/libp2p/rust-libp2p/pull/3085 -[PR 3011]: https://github.com/libp2p/rust-libp2p/pull/3011 -[PR 3055]: https://github.com/libp2p/rust-libp2p/pull/3055 -[PR 3097]: https://github.com/libp2p/rust-libp2p/pull/3097 -[Issue 3107]: https://github.com/libp2p/rust-libp2p/issues/3107 -[PR 3090]: https://github.com/libp2p/rust-libp2p/pull/3090 - -## 0.40.1 - -- Bump rand to 0.8 and quickcheck to 1. See [PR 2857]. - -- Update to `libp2p-core` `v0.37.0`. - -- Introduce `libp2p_swarm::keep_alive::ConnectionHandler` in favor of removing `keep_alive` from - `libp2p_swarm::dummy::ConnectionHandler`. `dummy::ConnectionHandler` now literally does not do anything. In the same - spirit, introduce `libp2p_swarm::keep_alive::Behaviour` and `libp2p_swarm::dummy::Behaviour`. See [PR 2859]. - -[PR 2857]: https://github.com/libp2p/rust-libp2p/pull/2857 -[PR 2859]: https://github.com/libp2p/rust-libp2p/pull/2859/ - -- Pass actual `PeerId` of dial to `NetworkBehaviour::inject_dial_failure` on `DialError::ConnectionLimit`. See [PR 2928]. - -[PR 2928]: https://github.com/libp2p/rust-libp2p/pull/2928 - - -## 0.39.0 - -- Remove deprecated `NetworkBehaviourEventProcess`. See [libp2p-swarm v0.38.0 changelog entry] for - migration path. - -- Update to `libp2p-core` `v0.36.0`. - -- Enforce backpressure on incoming streams via `StreamMuxer` interface. In case we hit the configured limit of maximum - number of inbound streams, we will stop polling the `StreamMuxer` for new inbound streams. Depending on the muxer - implementation in use, this may lead to instant dropping of inbound streams. See [PR 2861]. - -[libp2p-swarm v0.38.0 changelog entry]: https://github.com/libp2p/rust-libp2p/blob/master/swarm/CHANGELOG.md#0380 -[PR 2861]: https://github.com/libp2p/rust-libp2p/pull/2861/ - -## 0.38.0 - -- Deprecate `NetworkBehaviourEventProcess`. When deriving `NetworkBehaviour` on a custom `struct` users - should either bring their own `OutEvent` via `#[behaviour(out_event = "MyBehaviourEvent")]` or, - when not specified, have the derive macro generate one for the user. - - See [`NetworkBehaviour` - documentation](https://docs.rs/libp2p/latest/libp2p/swarm/trait.NetworkBehaviour.html) and [PR - 2784] for details. - - Previously - - ``` rust - #[derive(NetworkBehaviour)] - #[behaviour(event_process = true)] - struct MyBehaviour { - gossipsub: Gossipsub, - mdns: Mdns, - } - - impl NetworkBehaviourEventProcess for MyBehaviour { - fn inject_event(&mut self, message: GossipsubEvent) { - todo!("Handle event") - } - } - - impl NetworkBehaviourEventProcess for MyBehaviour { - fn inject_event(&mut self, message: MdnsEvent) { - todo!("Handle event") - } - } - ``` - - Now - - ``` rust - #[derive(NetworkBehaviour)] - #[behaviour(out_event = "MyBehaviourEvent")] - struct MyBehaviour { - gossipsub: Gossipsub, - mdns: Mdns, - } - - enum MyBehaviourEvent { - Gossipsub(GossipsubEvent), - Mdns(MdnsEvent), - } - - impl From for MyBehaviourEvent { - fn from(event: GossipsubEvent) -> Self { - MyBehaviourEvent::Gossipsub(event) - } - } - - impl From for MyBehaviourEvent { - fn from(event: MdnsEvent) -> Self { - MyBehaviourEvent::Mdns(event) - } - } - - match swarm.next().await.unwrap() { - SwarmEvent::Behaviour(MyBehaviourEvent::Gossipsub(event)) => { - todo!("Handle event") - } - SwarmEvent::Behaviour(MyBehaviourEvent::Mdns(event)) => { - todo!("Handle event") - } - } - ``` - -- When deriving `NetworkBehaviour` on a custom `struct` where the user does not specify their own - `OutEvent` via `#[behaviour(out_event = "MyBehaviourEvent")]` and where the user does not enable - `#[behaviour(event_process = true)]`, then the derive macro generates an `OutEvent` definition for - the user. - - See [`NetworkBehaviour` - documentation](https://docs.rs/libp2p/latest/libp2p/swarm/trait.NetworkBehaviour.html) and [PR - 2792] for details. - -- Update dial address concurrency factor to `8`, thus dialing up to 8 addresses concurrently for a single connection attempt. See `Swarm::dial_concurrency_factor` and [PR 2741]. - -- Update to `libp2p-core` `v0.35.0`. - -[PR 2741]: https://github.com/libp2p/rust-libp2p/pull/2741/ -[PR 2784]: https://github.com/libp2p/rust-libp2p/pull/2784 -[PR 2792]: https://github.com/libp2p/rust-libp2p/pull/2792 - -## 0.37.0 - -- Update to `libp2p-core` `v0.34.0`. - -- Extend log message when exceeding inbound negotiating streams with peer ID and limit. See [PR 2716]. - -- Remove `connection::ListenersStream` and poll the `Transport` directly. See [PR 2652]. - -[PR 2716]: https://github.com/libp2p/rust-libp2p/pull/2716/ -[PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 - -## 0.36.1 - -- Limit negotiating inbound substreams per connection. See [PR 2697]. - -[PR 2697]: https://github.com/libp2p/rust-libp2p/pull/2697 - -## 0.36.0 - -- Don't require `Transport` to be `Clone`. See [PR 2529]. - -- Update to `libp2p-core` `v0.33.0`. - -- Make `behaviour::either` module private. See [PR 2610] - -- Rename `IncomingInfo::to_connected_point` to `IncomingInfo::create_connected_point`. See [PR 2620]. - -- Rename `TProtoHandler` to `TConnectionHandler`, `ToggleProtoHandler` to `ToggleConnectionHandler`, `ToggleIntoProtoHandler` to `ToggleIntoConnectionHandler`. See [PR 2640]. - -[PR 2529]: https://github.com/libp2p/rust-libp2p/pull/2529 -[PR 2610]: https://github.com/libp2p/rust-libp2p/pull/2610 -[PR 2620]: https://github.com/libp2p/rust-libp2p/pull/2620 -[PR 2640]: https://github.com/libp2p/rust-libp2p/pull/2640 - -## 0.35.0 - -- Add impl `IntoIterator` for `MultiHandler`. See [PR 2572]. -- Remove `Send` bound from `NetworkBehaviour`. See [PR 2535]. - -[PR 2572]: https://github.com/libp2p/rust-libp2p/pull/2572/ -[PR 2535]: https://github.com/libp2p/rust-libp2p/pull/2535/ - -## 0.34.0 [2022-02-22] - -- Rename `ProtocolsHandler` to `ConnectionHandler`. Upgrade should be as simple as renaming all - occurrences of `ProtocolsHandler` to `ConnectionHandler` with your favorite text manipulation tool - across your codebase. See [PR 2527]. - -- Fold `libp2p-core`'s `Network` into `Swarm`. See [PR 2492]. - -- Update to `libp2p-core` `v0.32.0`. - -- Disconnect pending connections with `Swarm::disconnect`. See [PR 2517]. - -- Report aborted connections via `SwarmEvent::OutgoingConnectionError`. See [PR 2517]. - -[PR 2492]: https://github.com/libp2p/rust-libp2p/pull/2492 -[PR 2517]: https://github.com/libp2p/rust-libp2p/pull/2517 -[PR 2527]: https://github.com/libp2p/rust-libp2p/pull/2527 - -## 0.33.0 [2022-01-27] - -- Patch reporting on banned peers and their non-banned and banned connections (see [PR 2350]). - -- Update dependencies. - -- Migrate to Rust edition 2021 (see [PR 2339]). - -- Update `Connection::address` on `inject_address_change` (see [PR 2362]). - -- Move `swarm::Toggle` to `swarm::behaviour::Toggle` (see [PR 2375]). - -- Add `Swarm::connected_peers` (see [PR 2378]). - -- Implement `swarm::NetworkBehaviour` on `either::Either` (see [PR 2370]). - -- Allow overriding _dial concurrency factor_ per dial via - `DialOpts::override_dial_concurrency_factor`. See [PR 2404]. - -- Report negotiated and expected `PeerId` as well as remote address in - `DialError::WrongPeerId` (see [PR 2428]). - -- Allow overriding role when dialing through `override_role` option on - `DialOpts`. This option is needed for NAT and firewall hole punching. See [PR - 2363]. - -- Merge NetworkBehaviour's inject_\* paired methods (see PR 2445). - -[PR 2339]: https://github.com/libp2p/rust-libp2p/pull/2339 -[PR 2350]: https://github.com/libp2p/rust-libp2p/pull/2350 -[PR 2362]: https://github.com/libp2p/rust-libp2p/pull/2362 -[PR 2370]: https://github.com/libp2p/rust-libp2p/pull/2370 -[PR 2375]: https://github.com/libp2p/rust-libp2p/pull/2375 -[PR 2378]: https://github.com/libp2p/rust-libp2p/pull/2378 -[PR 2404]: https://github.com/libp2p/rust-libp2p/pull/2404 -[PR 2428]: https://github.com/libp2p/rust-libp2p/pull/2428 -[PR 2363]: https://github.com/libp2p/rust-libp2p/pull/2363 -[PR 2445]: https://github.com/libp2p/rust-libp2p/pull/2445 - -## 0.32.0 [2021-11-16] - -- Use `instant` and `futures-timer` instead of `wasm-timer` (see [PR 2245]). - -- Enable advanced dialing requests both on `Swarm::dial` and via - `NetworkBehaviourAction::Dial`. Users can now trigger a dial with a specific - set of addresses, optionally extended via - `NetworkBehaviour::addresses_of_peer`. - - Changes required to maintain status quo: - - - Previously `swarm.dial(peer_id)` - now `swarm.dial(DialOpts::peer_id(peer_id).build())` - or `swarm.dial(peer_id)` given that `DialOpts` implements `From`. - - - Previously `swarm.dial_addr(addr)` - now `swarm.dial(DialOpts::unknown_peer_id().address(addr).build())` - or `swarm.dial(addr)` given that `DialOpts` implements `From`. - - - Previously `NetworkBehaviourAction::DialPeer { peer_id, condition, handler }` - now - - ```rust - NetworkBehaviourAction::Dial { - opts: DialOpts::peer_id(peer_id) - .condition(condition) - .build(), - handler, - } - ``` - - - Previously `NetworkBehaviourAction::DialAddress { address, handler }` - now - - ```rust - NetworkBehaviourAction::Dial { - opts: DialOpts::unknown_peer_id() - .address(address) - .build(), - handler, - } - ``` - - See [PR 2317]. - -[PR 2245]: https://github.com/libp2p/rust-libp2p/pull/2245 -[PR 2317]: https://github.com/libp2p/rust-libp2p/pull/2317 - -## 0.31.0 [2021-11-01] - -- Make default features of `libp2p-core` optional. - [PR 2181](https://github.com/libp2p/rust-libp2p/pull/2181) - -- Update dependencies. - -- Provide default implementations for all functions of `NetworkBehaviour`, - except for `new_handler`, `inject_event` and `poll`. - This should make it easier to create new implementations. See [PR 2150]. - -- Remove `Swarm` type alias and rename `ExpandedSwarm` to `Swarm`. Reduce direct - trait parameters on `Swarm` (previously `ExpandedSwarm`), deriving parameters - through associated types on `TBehaviour`. See [PR 2182]. - -- Require `ProtocolsHandler::{InEvent,OutEvent,Error}` to implement `Debug` (see - [PR 2183]). - -- Implement `ProtocolsHandler` on `either::Either`representing either of two - `ProtocolsHandler` implementations (see [PR 2192]). - -- Require implementation to provide handler in - `NetworkBehaviourAction::DialPeer` and `NetworkBehaviourAction::DialAddress`. - Note that the handler is returned to the `NetworkBehaviour` on connection - failure and connection closing. Thus it can be used to carry state, which - otherwise would have to be tracked in the `NetworkBehaviour` itself. E.g. a - message destined to an unconnected peer can be included in the handler, and - thus directly send on connection success or extracted by the - `NetworkBehaviour` on connection failure (see [PR 2191]). - -- Include handler in `NetworkBehaviour::inject_dial_failure`, - `NetworkBehaviour::inject_connection_closed`, - `NetworkBehaviour::inject_listen_failure` (see [PR 2191]). - -- Include error in `NetworkBehaviour::inject_dial_failure` and call - `NetworkBehaviour::inject_dial_failure` on `DialPeerCondition` evaluating to - false. To emulate the previous behaviour, return early within - `inject_dial_failure` on `DialError::DialPeerConditionFalse`. See [PR 2191]. - -- Make `NetworkBehaviourAction` generic over `NetworkBehaviour::OutEvent` and - `NetworkBehaviour::ProtocolsHandler`. In most cases, change your generic type - parameters to `NetworkBehaviourAction`. See [PR 2191]. - -- Return `bool` instead of `Result<(), ()>` for `Swarm::remove_listener`(see - [PR 2261]). - -- Concurrently dial address candidates within a single dial attempt (see [PR 2248]) configured via - `Swarm::dial_concurrency_factor`. - - - On success of a single address, report errors of the thus far failed dials via - `SwarmEvent::ConnectionEstablished::outgoing`. - - - On failure of all addresses, report errors via the new `SwarmEvent::OutgoingConnectionError`. - - - Remove `SwarmEvent::UnreachableAddr` and `SwarmEvent::UnknownPeerUnreachableAddr` event. - - - In `NetworkBehaviour::inject_connection_established` provide errors of all thus far failed addresses. - - - On unknown peer dial failures, call `NetworkBehaviour::inject_dial_failure` with a peer ID of `None`. - - - Remove `NetworkBehaviour::inject_addr_reach_failure`. Information is now provided via - `NetworkBehaviour::inject_connection_established` and `NetworkBehaviour::inject_dial_failure`. - -[PR 2150]: https://github.com/libp2p/rust-libp2p/pull/2150 -[PR 2182]: https://github.com/libp2p/rust-libp2p/pull/2182 -[PR 2183]: https://github.com/libp2p/rust-libp2p/pull/2183 -[PR 2192]: https://github.com/libp2p/rust-libp2p/pull/2192 -[PR 2191]: https://github.com/libp2p/rust-libp2p/pull/2191 -[PR 2248]: https://github.com/libp2p/rust-libp2p/pull/2248 -[PR 2261]: https://github.com/libp2p/rust-libp2p/pull/2261 - -## 0.30.0 [2021-07-12] - -- Update dependencies. - -- Drive `ExpandedSwarm` via `Stream` trait only. - - - Change `Stream` implementation of `ExpandedSwarm` to return all - `SwarmEvents` instead of only the `NetworkBehaviour`'s events. - - - Remove `ExpandedSwarm::next_event`. Users can use `::next` instead. - - - Remove `ExpandedSwarm::next`. Users can use `::filter_map` instead. - - See [PR 2100] for details. - -- Add `ExpandedSwarm::disconnect_peer_id` and - `NetworkBehaviourAction::CloseConnection` to close connections to a specific - peer via an `ExpandedSwarm` or `NetworkBehaviour`. See [PR 2110] for details. - -- Expose the `ListenerId` in `SwarmEvent`s that are associated with a listener. - - See [PR 2123] for details. - -[PR 2100]: https://github.com/libp2p/rust-libp2p/pull/2100 -[PR 2110]: https://github.com/libp2p/rust-libp2p/pull/2110/ -[PR 2123]: https://github.com/libp2p/rust-libp2p/pull/2123 - -## 0.29.0 [2021-04-13] - -- Remove `Deref` and `DerefMut` implementations previously dereferencing to the - `NetworkBehaviour` on `Swarm`. Instead one can access the `NetworkBehaviour` - via `Swarm::behaviour` and `Swarm::behaviour_mut`. Methods on `Swarm` can now - be accessed directly, e.g. via `my_swarm.local_peer_id()`. You may use the - command below to transform fully qualified method calls on `Swarm` to simple - method calls [PR 1995](https://github.com/libp2p/rust-libp2p/pull/1995). - - ``` bash - # Go from e.g. `Swarm::local_peer_id(&my_swarm)` to `my_swarm.local_peer_id()`. - grep -RiIl --include \*.rs --exclude-dir target . --exclude-dir .git | xargs sed -i "s/\(libp2p::\)*Swarm::\([a-z_]*\)(&mut \([a-z_0-9]*\), /\3.\2(/g" - ``` - -- Extend `NetworkBehaviour` callbacks, more concretely introducing new `fn - inject_new_listener` and `fn inject_expired_external_addr` and have `fn - inject_{new,expired}_listen_addr` provide a `ListenerId` [PR - 2011](https://github.com/libp2p/rust-libp2p/pull/2011). - -## 0.28.0 [2021-03-17] - -- New error variant `DialError::InvalidAddress` - -- `Swarm::dial_addr()` now returns a `DialError` on error. - -- Remove the option for a substream-specific multistream select protocol override. - The override at this granularity is no longer deemed useful, in particular because - it can usually not be configured for existing protocols like `libp2p-kad` and others. - There is a `Swarm`-scoped configuration for this version available since - [1858](https://github.com/libp2p/rust-libp2p/pull/1858). - -## 0.27.2 [2021-02-04] - -- Have `ToggleProtoHandler` ignore listen upgrade errors when disabled. - [PR 1945](https://github.com/libp2p/rust-libp2p/pull/1945/files). - -## 0.27.1 [2021-01-27] - -- Make `OneShotHandler`s `max_dial_negotiate` limit configurable. - [PR 1936](https://github.com/libp2p/rust-libp2p/pull/1936). - -- Fix handling of DialPeerCondition::Always. - [PR 1937](https://github.com/libp2p/rust-libp2p/pull/1937). - -## 0.27.0 [2021-01-12] - -- Update dependencies. - -## 0.26.0 [2020-12-17] - -- Update `libp2p-core`. - -- Remove `NotifyHandler::All` thus removing the requirement for events send from - a `NetworkBehaviour` to a `ProtocolsHandler` to be `Clone`. - [PR 1880](https://github.com/libp2p/rust-libp2p/pull/1880). - -## 0.25.1 [2020-11-26] - -- Add `ExpandedSwarm::is_connected`. - [PR 1862](https://github.com/libp2p/rust-libp2p/pull/1862). - -## 0.25.0 [2020-11-25] - -- Permit a configuration override for the substream upgrade protocol - to use for all (outbound) substreams. - [PR 1858](https://github.com/libp2p/rust-libp2p/pull/1858). - -- Changed parameters for connection limits from `usize` to `u32`. - Connection limits are now configured via `SwarmBuilder::connection_limits()`. - -- Update `libp2p-core`. - -- Expose configurable scores for external addresses, as well as - the ability to remove them and to add addresses that are - retained "forever" (or until explicitly removed). - [PR 1842](https://github.com/libp2p/rust-libp2p/pull/1842). - -## 0.24.0 [2020-11-09] - -- Update dependencies. - -## 0.23.0 [2020-10-16] - -- Require a `Boxed` transport to be given to the `Swarm` - or `SwarmBuilder` to avoid unnecessary double-boxing of - transports and simplify API bounds. - [PR 1794](https://github.com/libp2p/rust-libp2p/pull/1794) - -- Respect inbound timeouts and upgrade versions in the `MultiHandler`. - [PR 1786](https://github.com/libp2p/rust-libp2p/pull/1786). - -- Instead of iterating each inbound and outbound substream upgrade looking for - one to make progress, use a `FuturesUnordered` for both pending inbound and - pending outbound upgrades. As a result only those upgrades are polled that are - ready to progress. - - Implementors of `InboundUpgrade` and `OutboundUpgrade` need to ensure to wake - up the underlying task once they are ready to make progress as they won't be - polled otherwise. - - [PR 1775](https://github.com/libp2p/rust-libp2p/pull/1775) - -## 0.22.0 [2020-09-09] - -- Bump `libp2p-core` dependency. - -- Adds `ProtocolsHandler::InboundOpenInfo` type which mirrors the existing - `OutboundOpenInfo` type. A value of this type is passed as an extra argument - to `ProtocolsHandler::inject_fully_negotiated_inbound` and - `ProtocolsHandler::inject_listen_upgrade_error`. - -- `SubstreamProtocol` now has a second type parameter corresponding to - inbound or outbound information, a value of which is part of `SubstreamProtocol` - now. Consequently `ProtocolsHandlerEvent::OutboundSubstreamRequest` no longer - has a separate `info` field. - -## 0.21.0 [2020-08-18] - -- Add missing delegation calls in some `ProtocolsHandler` wrappers. -See [PR 1710](https://github.com/libp2p/rust-libp2p/pull/1710). - -- Add as_ref and as_mut functions to Toggle -[PR 1684](https://github.com/libp2p/rust-libp2p/pull/1684). - -- The `cause` of `SwarmEvent::ConnectionClosed` is now an `Option`, -and `None` indicates an active connection close not caused by an -error. - -- `DialError::Banned` has been added and is returned from `Swarm::dial` -if the peer is banned, thereby also invoking the `NetworkBehaviour::inject_dial_failure` -callback. - -- Update the `libp2p-core` dependency to `0.21`, fixing [1584](https://github.com/libp2p/rust-libp2p/issues/1584). - -- Fix connections being kept alive by `OneShotHandler` when not handling any - requests [PR 1698](https://github.com/libp2p/rust-libp2p/pull/1698). - -## 0.20.1 [2020-07-08] - -- Documentation updates. - -- Ignore addresses returned by `NetworkBehaviour::addresses_of_peer` -that the `Swarm` considers to be listening addresses of the local node. This -avoids futile dialing attempts of a node to itself, which can otherwise -even happen in genuine situations, e.g. after the local node changed -its network identity and a behaviour makes a dialing attempt to a -former identity using the same addresses. - -## 0.20.0 [2020-07-01] - -- Updated the `libp2p-core` dependency. - -- Add `ProtocolsHandler::inject_listen_upgrade_error`, the inbound -analogue of `ProtocolsHandler::inject_dial_upgrade_error`, with an -empty default implementation. No implementation is required to -retain existing behaviour. - -- Add `ProtocolsHandler::inject_address_change` and -`NetworkBehaviour::inject_address_change` to notify of a change in -the address of an existing connection. - -## 0.19.1 [2020-06-18] - -- Bugfix: Fix MultiHandler panicking when empty - ([PR 1598](https://github.com/libp2p/rust-libp2p/pull/1598)). diff --git a/third-party/libp2p-swarm-0.45.1/Cargo.toml b/third-party/libp2p-swarm-0.45.1/Cargo.toml deleted file mode 100644 index 158d5d8a721..00000000000 --- a/third-party/libp2p-swarm-0.45.1/Cargo.toml +++ /dev/null @@ -1,189 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2021" -rust-version = "1.75.0" -name = "libp2p-swarm" -version = "0.45.1" -authors = ["Parity Technologies "] -build = false -autobins = false -autoexamples = false -autotests = false -autobenches = false -description = "The libp2p swarm" -readme = false -keywords = [ - "peer-to-peer", - "libp2p", - "networking", -] -categories = [ - "network-programming", - "asynchronous", -] -license = "MIT" -repository = "https://github.com/libp2p/rust-libp2p" - -[package.metadata.docs.rs] -all-features = true - -[lib] -name = "libp2p_swarm" -path = "src/lib.rs" - -[[test]] -name = "connection_close" -path = "tests/connection_close.rs" - -[[test]] -name = "listener" -path = "tests/listener.rs" - -[[test]] -name = "swarm_derive" -path = "tests/swarm_derive.rs" -required-features = ["macros"] - -[[bench]] -name = "connection_handler" -path = "benches/connection_handler.rs" -harness = false - -[dependencies.either] -version = "1.11.0" - -[dependencies.fnv] -version = "1.0" - -[dependencies.futures] -version = "0.3.30" - -[dependencies.futures-timer] -version = "3.0.3" - -[dependencies.getrandom] -version = "0.2.15" -features = ["js"] -optional = true - -[dependencies.libp2p-core] -version = "0.42.0" - -[dependencies.libp2p-identity] -version = "0.2.9" - -[dependencies.libp2p-swarm-derive] -version = "=0.35.1" -optional = true - -[dependencies.lru] -version = "0.12.3" - -[dependencies.multistream-select] -version = "0.13.0" - -[dependencies.once_cell] -version = "1.19.0" - -[dependencies.rand] -version = "0.8" - -[dependencies.smallvec] -version = "1.13.2" - -[dependencies.tracing] -version = "0.1.37" - -[dependencies.void] -version = "1" - -[dependencies.wasm-bindgen-futures] -version = "0.4.42" -optional = true - -[dependencies.web-time] -version = "1.1.0" - -[dev-dependencies.async-std] -version = "1.6.2" -features = ["attributes"] - -[dev-dependencies.criterion] -version = "0.5" -features = ["async_tokio"] - -[dev-dependencies.either] -version = "1.11.0" - -[dev-dependencies.futures] -version = "0.3.30" - -[dev-dependencies.libp2p-identity] -version = "0.2.9" -features = ["ed25519"] - -[dev-dependencies.once_cell] -version = "1.19.0" - -[dev-dependencies.tokio] -version = "1.38" -features = [ - "time", - "rt", - "macros", - "rt-multi-thread", -] -default-features = false - -[dev-dependencies.tracing-subscriber] -version = "0.3" -features = ["env-filter"] - -[dev-dependencies.trybuild] -version = "1.0.95" - -[dev-dependencies.void] -version = "1" - -[features] -async-std = ["dep:async-std"] -macros = ["dep:libp2p-swarm-derive"] -tokio = ["dep:tokio"] -wasm-bindgen = [ - "dep:wasm-bindgen-futures", - "dep:getrandom", -] - -[target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies.async-std] -version = "1.6.2" -optional = true - -[target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies.tokio] -version = "1.38" -features = ["rt"] -optional = true -default-features = false - -[lints.clippy] -dbg_macro = "warn" -manual_let_else = "warn" -type_complexity = "allow" -unnecessary_wraps = "warn" -used_underscore_binding = "warn" - -[lints.clippy.pedantic] -level = "allow" -priority = -1 - -[lints.rust] -unreachable_pub = "warn" diff --git a/third-party/libp2p-swarm-0.45.1/Cargo.toml.orig b/third-party/libp2p-swarm-0.45.1/Cargo.toml.orig deleted file mode 100644 index 3d0b1a84eee..00000000000 --- a/third-party/libp2p-swarm-0.45.1/Cargo.toml.orig +++ /dev/null @@ -1,76 +0,0 @@ -[package] -name = "libp2p-swarm" -edition = "2021" -rust-version = { workspace = true } -description = "The libp2p swarm" -version = "0.45.1" -authors = ["Parity Technologies "] -license = "MIT" -repository = "https://github.com/libp2p/rust-libp2p" -keywords = ["peer-to-peer", "libp2p", "networking"] -categories = ["network-programming", "asynchronous"] - -[dependencies] -either = "1.11.0" -fnv = "1.0" -futures = { workspace = true } -futures-timer = "3.0.3" -getrandom = { version = "0.2.15", features = ["js"], optional = true } # Explicit dependency to be used in `wasm-bindgen` feature -web-time = { workspace = true } -libp2p-core = { workspace = true } -libp2p-identity = { workspace = true } -libp2p-swarm-derive = { workspace = true, optional = true } -lru = "0.12.3" -multistream-select = { workspace = true } -once_cell = "1.19.0" -rand = "0.8" -smallvec = "1.13.2" -tracing = { workspace = true } -void = "1" -wasm-bindgen-futures = { version = "0.4.42", optional = true } - -[target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies] -async-std = { version = "1.6.2", optional = true } -tokio = { workspace = true, features = ["rt"], optional = true } - -[features] -macros = ["dep:libp2p-swarm-derive"] -tokio = ["dep:tokio"] -async-std = ["dep:async-std"] -wasm-bindgen = ["dep:wasm-bindgen-futures", "dep:getrandom"] - -[dev-dependencies] -async-std = { version = "1.6.2", features = ["attributes"] } -either = "1.11.0" -futures = { workspace = true } -libp2p-identify = { path = "../protocols/identify" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. -libp2p-identity = { workspace = true, features = ["ed25519"] } -libp2p-kad = { path = "../protocols/kad" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. -libp2p-ping = { path = "../protocols/ping" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. -libp2p-plaintext = { path = "../transports/plaintext" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. -libp2p-swarm-derive = { path = "../swarm-derive" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. -libp2p-swarm-test = { path = "../swarm-test" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. -libp2p-yamux = { path = "../muxers/yamux" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. -quickcheck = { workspace = true } -criterion = { version = "0.5", features = ["async_tokio"] } -void = "1" -once_cell = "1.19.0" -trybuild = "1.0.95" -tokio = { workspace = true, features = ["time", "rt", "macros", "rt-multi-thread"] } -tracing-subscriber = { workspace = true, features = ["env-filter"] } - -[[test]] -name = "swarm_derive" -required-features = ["macros"] - -# Passing arguments to the docsrs builder in order to properly document cfg's. -# More information: https://docs.rs/about/builds#cross-compiling -[package.metadata.docs.rs] -all-features = true - -[[bench]] -name = "connection_handler" -harness = false - -[lints] -workspace = true diff --git a/third-party/libp2p-swarm-0.45.1/benches/connection_handler.rs b/third-party/libp2p-swarm-0.45.1/benches/connection_handler.rs deleted file mode 100644 index 09340421f83..00000000000 --- a/third-party/libp2p-swarm-0.45.1/benches/connection_handler.rs +++ /dev/null @@ -1,360 +0,0 @@ -use async_std::stream::StreamExt; -use criterion::{criterion_group, criterion_main, Criterion}; -use libp2p_core::{ - transport::MemoryTransport, InboundUpgrade, Multiaddr, OutboundUpgrade, Transport, UpgradeInfo, -}; -use libp2p_identity::PeerId; -use libp2p_swarm::{ConnectionHandler, NetworkBehaviour, StreamProtocol}; -use std::{convert::Infallible, sync::atomic::AtomicUsize}; -use web_time::Duration; - -macro_rules! gen_behaviour { - ($($name:ident {$($field:ident),*};)*) => {$( - #[derive(libp2p_swarm::NetworkBehaviour, Default)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct $name { - $($field: SpinningBehaviour,)* - } - - impl BigBehaviour for $name { - fn behaviours(&mut self) -> &mut [SpinningBehaviour] { - unsafe { - std::slice::from_raw_parts_mut( - self as *mut Self as *mut SpinningBehaviour, - std::mem::size_of::() / std::mem::size_of::(), - ) - } - } - } - )*}; -} - -macro_rules! benchmarks { - ($( - $group:ident::[$( - $beh:ident::bench() - .name($name:ident) - .poll_count($count:expr) - .protocols_per_behaviour($protocols:expr), - )+]; - )*) => { - - $( - $( - fn $name(c: &mut Criterion) { - <$beh>::run_bench(c, $protocols, $count, true); - } - )+ - - criterion_group!($group, $($name),*); - )* - - criterion_main!($($group),*); - }; -} - -// fans go brrr -gen_behaviour! { - SpinningBehaviour5 { a, b, c, d, e }; - SpinningBehaviour10 { a, b, c, d, e, f, g, h, i, j }; - SpinningBehaviour20 { a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u }; -} - -benchmarks! { - singles::[ - SpinningBehaviour::bench().name(b).poll_count(1000).protocols_per_behaviour(10), - SpinningBehaviour::bench().name(c).poll_count(1000).protocols_per_behaviour(100), - SpinningBehaviour::bench().name(d).poll_count(1000).protocols_per_behaviour(1000), - ]; - big_5::[ - SpinningBehaviour5::bench().name(e).poll_count(1000).protocols_per_behaviour(2), - SpinningBehaviour5::bench().name(f).poll_count(1000).protocols_per_behaviour(20), - SpinningBehaviour5::bench().name(g).poll_count(1000).protocols_per_behaviour(200), - ]; - top_10::[ - SpinningBehaviour10::bench().name(h).poll_count(1000).protocols_per_behaviour(1), - SpinningBehaviour10::bench().name(i).poll_count(1000).protocols_per_behaviour(10), - SpinningBehaviour10::bench().name(j).poll_count(1000).protocols_per_behaviour(100), - ]; - lucky_20::[ - SpinningBehaviour20::bench().name(k).poll_count(500).protocols_per_behaviour(1), - SpinningBehaviour20::bench().name(l).poll_count(500).protocols_per_behaviour(10), - SpinningBehaviour20::bench().name(m).poll_count(500).protocols_per_behaviour(100), - ]; -} -//fn main() {} - -trait BigBehaviour: Sized { - fn behaviours(&mut self) -> &mut [SpinningBehaviour]; - - fn for_each_beh(&mut self, f: impl FnMut(&mut SpinningBehaviour)) { - self.behaviours().iter_mut().for_each(f); - } - - fn any_beh(&mut self, f: impl FnMut(&mut SpinningBehaviour) -> bool) -> bool { - self.behaviours().iter_mut().any(f) - } - - fn run_bench( - c: &mut Criterion, - protocols_per_behaviour: usize, - spam_count: usize, - static_protocols: bool, - ) where - Self: Default + NetworkBehaviour, - { - let name = format!( - "{}::bench().poll_count({}).protocols_per_behaviour({})", - std::any::type_name::(), - spam_count, - protocols_per_behaviour - ); - - let init = || { - let mut swarm_a = new_swarm(Self::default()); - let mut swarm_b = new_swarm(Self::default()); - - let behaviour_count = swarm_a.behaviours().len(); - let protocol_count = behaviour_count * protocols_per_behaviour; - let protocols = (0..protocol_count) - .map(|i| { - if static_protocols { - StreamProtocol::new(format!("/protocol/{i}").leak()) - } else { - StreamProtocol::try_from_owned(format!("/protocol/{i}")).unwrap() - } - }) - .collect::>() - .leak(); - - let mut protocol_chunks = protocols.chunks(protocols_per_behaviour); - swarm_a.for_each_beh(|b| b.protocols = protocol_chunks.next().unwrap()); - let mut protocol_chunks = protocols.chunks(protocols_per_behaviour); - swarm_b.for_each_beh(|b| b.protocols = protocol_chunks.next().unwrap()); - - swarm_a.for_each_beh(|b| b.iter_count = spam_count); - swarm_b.for_each_beh(|b| b.iter_count = 0); - - swarm_a.for_each_beh(|b| b.other_peer = Some(*swarm_b.local_peer_id())); - swarm_b.for_each_beh(|b| b.other_peer = Some(*swarm_a.local_peer_id())); - - static OFFSET: AtomicUsize = AtomicUsize::new(8000); - let offset = OFFSET.fetch_add(1, std::sync::atomic::Ordering::Relaxed); - - swarm_a - .listen_on(format!("/memory/{offset}").parse().unwrap()) - .unwrap(); - swarm_b - .dial(format!("/memory/{offset}").parse::().unwrap()) - .unwrap(); - - (swarm_a, swarm_b) - }; - - c.bench_function(&name, |b| { - b.to_async(tokio::runtime::Builder::new_multi_thread().build().unwrap()) - .iter_batched( - init, - |(mut swarm_a, mut swarm_b)| async move { - while swarm_a.any_beh(|b| !b.finished) || swarm_b.any_beh(|b| !b.finished) { - futures::future::select(swarm_b.next(), swarm_a.next()).await; - } - }, - criterion::BatchSize::LargeInput, - ); - }); - } -} - -impl BigBehaviour for libp2p_swarm::Swarm { - fn behaviours(&mut self) -> &mut [SpinningBehaviour] { - self.behaviour_mut().behaviours() - } -} - -fn new_swarm(beh: T) -> libp2p_swarm::Swarm { - let keypair = libp2p_identity::Keypair::generate_ed25519(); - libp2p_swarm::Swarm::new( - MemoryTransport::default() - .upgrade(multistream_select::Version::V1) - .authenticate(libp2p_plaintext::Config::new(&keypair)) - .multiplex(libp2p_yamux::Config::default()) - .boxed(), - beh, - keypair.public().to_peer_id(), - libp2p_swarm::Config::without_executor().with_idle_connection_timeout(Duration::MAX), - ) -} - -/// Whole purpose of the behaviour is to rapidly call `poll` on the handler -/// configured amount of times and then emit event when finished. -#[derive(Default)] -struct SpinningBehaviour { - iter_count: usize, - protocols: &'static [StreamProtocol], - finished: bool, - emitted: bool, - other_peer: Option, -} - -#[derive(Debug)] -struct FinishedSpinning; - -impl NetworkBehaviour for SpinningBehaviour { - type ConnectionHandler = SpinningHandler; - type ToSwarm = FinishedSpinning; - - fn handle_established_inbound_connection( - &mut self, - _connection_id: libp2p_swarm::ConnectionId, - _peer: libp2p_identity::PeerId, - _local_addr: &libp2p_core::Multiaddr, - _remote_addr: &libp2p_core::Multiaddr, - ) -> Result, libp2p_swarm::ConnectionDenied> { - Ok(SpinningHandler { - iter_count: 0, - protocols: self.protocols, - }) - } - - fn handle_established_outbound_connection( - &mut self, - _connection_id: libp2p_swarm::ConnectionId, - _peer: libp2p_identity::PeerId, - _addr: &libp2p_core::Multiaddr, - _role_override: libp2p_core::Endpoint, - _port_use: libp2p_core::transport::PortUse, - ) -> Result, libp2p_swarm::ConnectionDenied> { - Ok(SpinningHandler { - iter_count: self.iter_count, - protocols: self.protocols, - }) - } - - fn on_swarm_event(&mut self, _: libp2p_swarm::FromSwarm) {} - - fn on_connection_handler_event( - &mut self, - _peer_id: libp2p_identity::PeerId, - _connection_id: libp2p_swarm::ConnectionId, - _event: libp2p_swarm::THandlerOutEvent, - ) { - self.finished = true; - } - - fn poll( - &mut self, - _: &mut std::task::Context<'_>, - ) -> std::task::Poll>> - { - if self.finished && !self.emitted { - self.emitted = true; - std::task::Poll::Ready(libp2p_swarm::ToSwarm::GenerateEvent(FinishedSpinning)) - } else { - std::task::Poll::Pending - } - } -} - -impl BigBehaviour for SpinningBehaviour { - fn behaviours(&mut self) -> &mut [SpinningBehaviour] { - std::slice::from_mut(self) - } -} - -struct SpinningHandler { - iter_count: usize, - protocols: &'static [StreamProtocol], -} - -impl ConnectionHandler for SpinningHandler { - type FromBehaviour = Infallible; - - type ToBehaviour = FinishedSpinning; - - type InboundProtocol = Upgrade; - - type OutboundProtocol = Upgrade; - - type InboundOpenInfo = (); - - type OutboundOpenInfo = (); - - fn listen_protocol( - &self, - ) -> libp2p_swarm::SubstreamProtocol { - libp2p_swarm::SubstreamProtocol::new(Upgrade(self.protocols), ()) - } - - fn poll( - &mut self, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll< - libp2p_swarm::ConnectionHandlerEvent< - Self::OutboundProtocol, - Self::OutboundOpenInfo, - Self::ToBehaviour, - >, - > { - if self.iter_count == usize::MAX { - return std::task::Poll::Pending; - } - - if self.iter_count != 0 { - self.iter_count -= 1; - cx.waker().wake_by_ref(); - return std::task::Poll::Pending; - } - - self.iter_count = usize::MAX; - std::task::Poll::Ready(libp2p_swarm::ConnectionHandlerEvent::NotifyBehaviour( - FinishedSpinning, - )) - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - match event {} - } - - fn on_connection_event( - &mut self, - _event: libp2p_swarm::handler::ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - } -} - -pub struct Upgrade(&'static [StreamProtocol]); - -impl UpgradeInfo for Upgrade { - type Info = &'static StreamProtocol; - type InfoIter = std::slice::Iter<'static, StreamProtocol>; - - fn protocol_info(&self) -> Self::InfoIter { - self.0.iter() - } -} - -impl OutboundUpgrade for Upgrade { - type Output = libp2p_swarm::Stream; - type Error = Infallible; - type Future = futures::future::Ready>; - - fn upgrade_outbound(self, s: libp2p_swarm::Stream, _: Self::Info) -> Self::Future { - futures::future::ready(Ok(s)) - } -} - -impl InboundUpgrade for Upgrade { - type Output = libp2p_swarm::Stream; - type Error = Infallible; - type Future = futures::future::Ready>; - - fn upgrade_inbound(self, s: libp2p_swarm::Stream, _: Self::Info) -> Self::Future { - futures::future::ready(Ok(s)) - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour.rs deleted file mode 100644 index 35aed12fba5..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/behaviour.rs +++ /dev/null @@ -1,585 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -mod either; -mod external_addresses; -mod listen_addresses; -mod peer_addresses; -pub mod toggle; - -pub use external_addresses::ExternalAddresses; -pub use listen_addresses::ListenAddresses; -pub use peer_addresses::PeerAddresses; - -use crate::connection::ConnectionId; -use crate::dial_opts::DialOpts; -use crate::listen_opts::ListenOpts; -use crate::{ - ConnectionDenied, ConnectionError, ConnectionHandler, DialError, ListenError, THandler, - THandlerInEvent, THandlerOutEvent, -}; -use libp2p_core::{ - transport::{ListenerId, PortUse}, - ConnectedPoint, Endpoint, Multiaddr, -}; -use libp2p_identity::PeerId; -use std::{task::Context, task::Poll}; - -/// A [`NetworkBehaviour`] defines the behaviour of the local node on the network. -/// -/// In contrast to [`Transport`](libp2p_core::Transport) which defines **how** to send bytes on the -/// network, [`NetworkBehaviour`] defines **what** bytes to send and **to whom**. -/// -/// Each protocol (e.g. `libp2p-ping`, `libp2p-identify` or `libp2p-kad`) implements -/// [`NetworkBehaviour`]. Multiple implementations of [`NetworkBehaviour`] can be composed into a -/// hierarchy of [`NetworkBehaviour`]s where parent implementations delegate to child -/// implementations. Finally the root of the [`NetworkBehaviour`] hierarchy is passed to -/// [`Swarm`](crate::Swarm) where it can then control the behaviour of the local node on a libp2p -/// network. -/// -/// # Hierarchy of [`NetworkBehaviour`] -/// -/// To compose multiple [`NetworkBehaviour`] implementations into a single [`NetworkBehaviour`] -/// implementation, potentially building a multi-level hierarchy of [`NetworkBehaviour`]s, one can -/// use one of the [`NetworkBehaviour`] combinators, and/or use the [`NetworkBehaviour`] derive -/// macro. -/// -/// ## Combinators -/// -/// [`NetworkBehaviour`] combinators wrap one or more [`NetworkBehaviour`] implementations and -/// implement [`NetworkBehaviour`] themselves. Example is the -/// [`Toggle`](crate::behaviour::toggle::Toggle) [`NetworkBehaviour`]. -/// -/// ``` rust -/// # use libp2p_swarm::dummy; -/// # use libp2p_swarm::behaviour::toggle::Toggle; -/// let my_behaviour = dummy::Behaviour; -/// let my_toggled_behaviour = Toggle::from(Some(my_behaviour)); -/// ``` -/// -/// ## Custom [`NetworkBehaviour`] with the Derive Macro -/// -/// One can derive [`NetworkBehaviour`] for a custom `struct` via the `#[derive(NetworkBehaviour)]` -/// proc macro re-exported by the `libp2p` crate. The macro generates a delegating `trait` -/// implementation for the custom `struct`. Each [`NetworkBehaviour`] trait method is simply -/// delegated to each `struct` member in the order the `struct` is defined. For example for -/// [`NetworkBehaviour::poll`] it will first poll the first `struct` member until it returns -/// [`Poll::Pending`] before moving on to later members. -/// -/// Events ([`NetworkBehaviour::ToSwarm`]) returned by each `struct` member are wrapped in a new -/// `enum` event, with an `enum` variant for each `struct` member. Users can define this event -/// `enum` themselves and provide the name to the derive macro via `#[behaviour(to_swarm = -/// "MyCustomOutEvent")]`. If the user does not specify an `to_swarm`, the derive macro generates -/// the event definition itself, naming it `Event`. -/// -/// The aforementioned conversion of each of the event types generated by the struct members to the -/// custom `to_swarm` is handled by [`From`] implementations which the user needs to define in -/// addition to the event `enum` itself. -/// -/// ``` rust -/// # use libp2p_identify as identify; -/// # use libp2p_ping as ping; -/// # use libp2p_swarm_derive::NetworkBehaviour; -/// #[derive(NetworkBehaviour)] -/// #[behaviour(to_swarm = "Event")] -/// # #[behaviour(prelude = "libp2p_swarm::derive_prelude")] -/// struct MyBehaviour { -/// identify: identify::Behaviour, -/// ping: ping::Behaviour, -/// } -/// -/// enum Event { -/// Identify(identify::Event), -/// Ping(ping::Event), -/// } -/// -/// impl From for Event { -/// fn from(event: identify::Event) -> Self { -/// Self::Identify(event) -/// } -/// } -/// -/// impl From for Event { -/// fn from(event: ping::Event) -> Self { -/// Self::Ping(event) -/// } -/// } -/// ``` -pub trait NetworkBehaviour: 'static { - /// Handler for all the protocols the network behaviour supports. - type ConnectionHandler: ConnectionHandler; - - /// Event generated by the `NetworkBehaviour` and that the swarm will report back. - type ToSwarm: Send + 'static; - - /// Callback that is invoked for every new inbound connection. - /// - /// At this point in the connection lifecycle, only the remote's and our local address are known. - /// We have also already allocated a [`ConnectionId`]. - /// - /// Any error returned from this function will immediately abort the dial attempt. - fn handle_pending_inbound_connection( - &mut self, - _connection_id: ConnectionId, - _local_addr: &Multiaddr, - _remote_addr: &Multiaddr, - ) -> Result<(), ConnectionDenied> { - Ok(()) - } - - /// Callback that is invoked for every established inbound connection. - /// - /// This is invoked once another peer has successfully dialed us. - /// - /// At this point, we have verified their [`PeerId`] and we know, which particular [`Multiaddr`] succeeded in the dial. - /// In order to actually use this connection, this function must return a [`ConnectionHandler`]. - /// Returning an error will immediately close the connection. - /// - /// Note when any composed behaviour returns an error the connection will be closed and a - /// [`FromSwarm::ListenFailure`] event will be emitted. - fn handle_established_inbound_connection( - &mut self, - _connection_id: ConnectionId, - peer: PeerId, - local_addr: &Multiaddr, - remote_addr: &Multiaddr, - ) -> Result, ConnectionDenied>; - - /// Callback that is invoked for every outbound connection attempt. - /// - /// We have access to: - /// - /// - The [`PeerId`], if known. Remember that we can dial without a [`PeerId`]. - /// - All addresses passed to [`DialOpts`] are passed in here too. - /// - The effective [`Role`](Endpoint) of this peer in the dial attempt. Typically, this is set to [`Endpoint::Dialer`] except if we are attempting a hole-punch. - /// - The [`ConnectionId`] identifying the future connection resulting from this dial, if successful. - /// - /// Note that the addresses returned from this function are only used for dialing if [`WithPeerIdWithAddresses::extend_addresses_through_behaviour`](crate::dial_opts::WithPeerIdWithAddresses::extend_addresses_through_behaviour) is set. - /// - /// Any error returned from this function will immediately abort the dial attempt. - fn handle_pending_outbound_connection( - &mut self, - _connection_id: ConnectionId, - _maybe_peer: Option, - _addresses: &[Multiaddr], - _effective_role: Endpoint, - ) -> Result, ConnectionDenied> { - Ok(vec![]) - } - - /// Callback that is invoked for every established outbound connection. - /// - /// This is invoked once we have successfully dialed a peer. - /// At this point, we have verified their [`PeerId`] and we know, which particular [`Multiaddr`] succeeded in the dial. - /// In order to actually use this connection, this function must return a [`ConnectionHandler`]. - /// Returning an error will immediately close the connection. - /// - /// Note when any composed behaviour returns an error the connection will be closed and a - /// [`FromSwarm::DialFailure`] event will be emitted. - fn handle_established_outbound_connection( - &mut self, - _connection_id: ConnectionId, - peer: PeerId, - addr: &Multiaddr, - role_override: Endpoint, - port_use: PortUse, - ) -> Result, ConnectionDenied>; - - /// Informs the behaviour about an event from the [`Swarm`](crate::Swarm). - fn on_swarm_event(&mut self, event: FromSwarm); - - /// Informs the behaviour about an event generated by the [`ConnectionHandler`] - /// dedicated to the peer identified by `peer_id`. for the behaviour. - /// - /// The [`PeerId`] is guaranteed to be in a connected state. In other words, - /// [`FromSwarm::ConnectionEstablished`] has previously been received with this [`PeerId`]. - fn on_connection_handler_event( - &mut self, - _peer_id: PeerId, - _connection_id: ConnectionId, - _event: THandlerOutEvent, - ); - - /// Polls for things that swarm should do. - /// - /// This API mimics the API of the `Stream` trait. The method may register the current task in - /// order to wake it up at a later point in time. - fn poll(&mut self, cx: &mut Context<'_>) - -> Poll>>; -} - -/// A command issued from a [`NetworkBehaviour`] for the [`Swarm`]. -/// -/// [`Swarm`]: super::Swarm -#[derive(Debug)] -#[non_exhaustive] -pub enum ToSwarm { - /// Instructs the `Swarm` to return an event when it is being polled. - GenerateEvent(TOutEvent), - - /// Instructs the swarm to start a dial. - /// - /// On success, [`NetworkBehaviour::on_swarm_event`] with `ConnectionEstablished` is invoked. - /// On failure, [`NetworkBehaviour::on_swarm_event`] with `DialFailure` is invoked. - /// - /// [`DialOpts`] provides access to the [`ConnectionId`] via [`DialOpts::connection_id`]. - /// This [`ConnectionId`] will be used throughout the connection's lifecycle to associate events with it. - /// This allows a [`NetworkBehaviour`] to identify a connection that resulted out of its own dial request. - Dial { opts: DialOpts }, - - /// Instructs the [`Swarm`](crate::Swarm) to listen on the provided address. - ListenOn { opts: ListenOpts }, - - /// Instructs the [`Swarm`](crate::Swarm) to remove the listener. - RemoveListener { id: ListenerId }, - - /// Instructs the `Swarm` to send an event to the handler dedicated to a - /// connection with a peer. - /// - /// If the `Swarm` is connected to the peer, the message is delivered to the [`ConnectionHandler`] - /// instance identified by the peer ID and connection ID. - /// - /// If the specified connection no longer exists, the event is silently dropped. - /// - /// Typically the connection ID given is the same as the one passed to - /// [`NetworkBehaviour::on_connection_handler_event`], i.e. whenever the behaviour wishes to - /// respond to a request on the same connection (and possibly the same - /// substream, as per the implementation of [`ConnectionHandler`]). - /// - /// Note that even if the peer is currently connected, connections can get closed - /// at any time and thus the event may not reach a handler. - NotifyHandler { - /// The peer for whom a [`ConnectionHandler`] should be notified. - peer_id: PeerId, - /// The options w.r.t. which connection handler to notify of the event. - handler: NotifyHandler, - /// The event to send. - event: TInEvent, - }, - - /// Reports a **new** candidate for an external address to the [`Swarm`](crate::Swarm). - /// - /// The emphasis on a **new** candidate is important. - /// Protocols MUST take care to only emit a candidate once per "source". - /// For example, the observed address of a TCP connection does not change throughout its lifetime. - /// Thus, only one candidate should be emitted per connection. - /// - /// This makes the report frequency of an address a meaningful data-point for consumers of this event. - /// This address will be shared with all [`NetworkBehaviour`]s via [`FromSwarm::NewExternalAddrCandidate`]. - /// - /// This address could come from a variety of sources: - /// - A protocol such as identify obtained it from a remote. - /// - The user provided it based on configuration. - /// - We made an educated guess based on one of our listen addresses. - NewExternalAddrCandidate(Multiaddr), - - /// Indicates to the [`Swarm`](crate::Swarm) that the provided address is confirmed to be externally reachable. - /// - /// This is intended to be issued in response to a [`FromSwarm::NewExternalAddrCandidate`] if we are indeed externally reachable on this address. - /// This address will be shared with all [`NetworkBehaviour`]s via [`FromSwarm::ExternalAddrConfirmed`]. - ExternalAddrConfirmed(Multiaddr), - - /// Indicates to the [`Swarm`](crate::Swarm) that we are no longer externally reachable under the provided address. - /// - /// This expires an address that was earlier confirmed via [`ToSwarm::ExternalAddrConfirmed`]. - /// This address will be shared with all [`NetworkBehaviour`]s via [`FromSwarm::ExternalAddrExpired`]. - ExternalAddrExpired(Multiaddr), - - /// Instructs the `Swarm` to initiate a graceful close of one or all connections with the given peer. - /// - /// Closing a connection via [`ToSwarm::CloseConnection`] will poll [`ConnectionHandler::poll_close`] to completion. - /// In most cases, stopping to "use" a connection is enough to have it closed. - /// The keep-alive algorithm will close a connection automatically once all [`ConnectionHandler`]s are idle. - /// - /// Use this command if you want to close a connection _despite_ it still being in use by one or more handlers. - CloseConnection { - /// The peer to disconnect. - peer_id: PeerId, - /// Whether to close a specific or all connections to the given peer. - connection: CloseConnection, - }, - - /// Reports external address of a remote peer to the [`Swarm`](crate::Swarm) and through that to other [`NetworkBehaviour`]s. - NewExternalAddrOfPeer { peer_id: PeerId, address: Multiaddr }, -} - -impl ToSwarm { - /// Map the handler event. - pub fn map_in( - self, - f: impl FnOnce(TInEventOld) -> TInEventNew, - ) -> ToSwarm { - match self { - ToSwarm::GenerateEvent(e) => ToSwarm::GenerateEvent(e), - ToSwarm::Dial { opts } => ToSwarm::Dial { opts }, - ToSwarm::ListenOn { opts } => ToSwarm::ListenOn { opts }, - ToSwarm::RemoveListener { id } => ToSwarm::RemoveListener { id }, - ToSwarm::NotifyHandler { - peer_id, - handler, - event, - } => ToSwarm::NotifyHandler { - peer_id, - handler, - event: f(event), - }, - ToSwarm::CloseConnection { - peer_id, - connection, - } => ToSwarm::CloseConnection { - peer_id, - connection, - }, - ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), - ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), - ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), - ToSwarm::NewExternalAddrOfPeer { - address: addr, - peer_id, - } => ToSwarm::NewExternalAddrOfPeer { - address: addr, - peer_id, - }, - } - } -} - -impl ToSwarm { - /// Map the event the swarm will return. - pub fn map_out(self, f: impl FnOnce(TOutEvent) -> E) -> ToSwarm { - match self { - ToSwarm::GenerateEvent(e) => ToSwarm::GenerateEvent(f(e)), - ToSwarm::Dial { opts } => ToSwarm::Dial { opts }, - ToSwarm::ListenOn { opts } => ToSwarm::ListenOn { opts }, - ToSwarm::RemoveListener { id } => ToSwarm::RemoveListener { id }, - ToSwarm::NotifyHandler { - peer_id, - handler, - event, - } => ToSwarm::NotifyHandler { - peer_id, - handler, - event, - }, - ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), - ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), - ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), - ToSwarm::CloseConnection { - peer_id, - connection, - } => ToSwarm::CloseConnection { - peer_id, - connection, - }, - ToSwarm::NewExternalAddrOfPeer { - address: addr, - peer_id, - } => ToSwarm::NewExternalAddrOfPeer { - address: addr, - peer_id, - }, - } - } -} - -/// The options w.r.t. which connection handler to notify of an event. -#[derive(Debug, Clone)] -pub enum NotifyHandler { - /// Notify a particular connection handler. - One(ConnectionId), - /// Notify an arbitrary connection handler. - Any, -} - -/// The options which connections to close. -#[derive(Debug, Clone, Default)] -pub enum CloseConnection { - /// Disconnect a particular connection. - One(ConnectionId), - /// Disconnect all connections. - #[default] - All, -} - -/// Enumeration with the list of the possible events -/// to pass to [`on_swarm_event`](NetworkBehaviour::on_swarm_event). -#[derive(Debug, Clone, Copy)] -#[non_exhaustive] -pub enum FromSwarm<'a> { - /// Informs the behaviour about a newly established connection to a peer. - ConnectionEstablished(ConnectionEstablished<'a>), - /// Informs the behaviour about a closed connection to a peer. - /// - /// This event is always paired with an earlier - /// [`FromSwarm::ConnectionEstablished`] with the same peer ID, connection ID - /// and endpoint. - ConnectionClosed(ConnectionClosed<'a>), - /// Informs the behaviour that the [`ConnectedPoint`] of an existing - /// connection has changed. - AddressChange(AddressChange<'a>), - /// Informs the behaviour that the dial to a known - /// or unknown node failed. - DialFailure(DialFailure<'a>), - /// Informs the behaviour that an error - /// happened on an incoming connection during its initial handshake. - /// - /// This can include, for example, an error during the handshake of the encryption layer, or the - /// connection unexpectedly closed. - ListenFailure(ListenFailure<'a>), - /// Informs the behaviour that a new listener was created. - NewListener(NewListener), - /// Informs the behaviour that we have started listening on a new multiaddr. - NewListenAddr(NewListenAddr<'a>), - /// Informs the behaviour that a multiaddr - /// we were listening on has expired, - /// which means that we are no longer listening on it. - ExpiredListenAddr(ExpiredListenAddr<'a>), - /// Informs the behaviour that a listener experienced an error. - ListenerError(ListenerError<'a>), - /// Informs the behaviour that a listener closed. - ListenerClosed(ListenerClosed<'a>), - /// Informs the behaviour that we have discovered a new candidate for an external address for us. - NewExternalAddrCandidate(NewExternalAddrCandidate<'a>), - /// Informs the behaviour that an external address of the local node was confirmed. - ExternalAddrConfirmed(ExternalAddrConfirmed<'a>), - /// Informs the behaviour that an external address of the local node expired, i.e. is no-longer confirmed. - ExternalAddrExpired(ExternalAddrExpired<'a>), - /// Informs the behaviour that we have discovered a new external address for a remote peer. - NewExternalAddrOfPeer(NewExternalAddrOfPeer<'a>), -} - -/// [`FromSwarm`] variant that informs the behaviour about a newly established connection to a peer. -#[derive(Debug, Clone, Copy)] -pub struct ConnectionEstablished<'a> { - pub peer_id: PeerId, - pub connection_id: ConnectionId, - pub endpoint: &'a ConnectedPoint, - pub failed_addresses: &'a [Multiaddr], - pub other_established: usize, -} - -/// [`FromSwarm`] variant that informs the behaviour about a closed connection to a peer. -/// -/// This event is always paired with an earlier -/// [`FromSwarm::ConnectionEstablished`] with the same peer ID, connection ID -/// and endpoint. -#[derive(Debug, Clone, Copy)] -pub struct ConnectionClosed<'a> { - pub peer_id: PeerId, - pub connection_id: ConnectionId, - pub endpoint: &'a ConnectedPoint, - pub cause: Option<&'a ConnectionError>, - pub remaining_established: usize, -} - -/// [`FromSwarm`] variant that informs the behaviour that the [`ConnectedPoint`] of an existing -/// connection has changed. -#[derive(Debug, Clone, Copy)] -pub struct AddressChange<'a> { - pub peer_id: PeerId, - pub connection_id: ConnectionId, - pub old: &'a ConnectedPoint, - pub new: &'a ConnectedPoint, -} - -/// [`FromSwarm`] variant that informs the behaviour that the dial to a known -/// or unknown node failed. -#[derive(Debug, Clone, Copy)] -pub struct DialFailure<'a> { - pub peer_id: Option, - pub error: &'a DialError, - pub connection_id: ConnectionId, -} - -/// [`FromSwarm`] variant that informs the behaviour that an error -/// happened on an incoming connection during its initial handshake. -/// -/// This can include, for example, an error during the handshake of the encryption layer, or the -/// connection unexpectedly closed. -#[derive(Debug, Clone, Copy)] -pub struct ListenFailure<'a> { - pub local_addr: &'a Multiaddr, - pub send_back_addr: &'a Multiaddr, - pub error: &'a ListenError, - pub connection_id: ConnectionId, - pub peer_id: Option, -} - -/// [`FromSwarm`] variant that informs the behaviour that a new listener was created. -#[derive(Debug, Clone, Copy)] -pub struct NewListener { - pub listener_id: ListenerId, -} - -/// [`FromSwarm`] variant that informs the behaviour -/// that we have started listening on a new multiaddr. -#[derive(Debug, Clone, Copy)] -pub struct NewListenAddr<'a> { - pub listener_id: ListenerId, - pub addr: &'a Multiaddr, -} - -/// [`FromSwarm`] variant that informs the behaviour that a multiaddr -/// we were listening on has expired, -/// which means that we are no longer listening on it. -#[derive(Debug, Clone, Copy)] -pub struct ExpiredListenAddr<'a> { - pub listener_id: ListenerId, - pub addr: &'a Multiaddr, -} - -/// [`FromSwarm`] variant that informs the behaviour that a listener experienced an error. -#[derive(Debug, Clone, Copy)] -pub struct ListenerError<'a> { - pub listener_id: ListenerId, - pub err: &'a (dyn std::error::Error + 'static), -} - -/// [`FromSwarm`] variant that informs the behaviour that a listener closed. -#[derive(Debug, Clone, Copy)] -pub struct ListenerClosed<'a> { - pub listener_id: ListenerId, - pub reason: Result<(), &'a std::io::Error>, -} - -/// [`FromSwarm`] variant that informs the behaviour about a new candidate for an external address for us. -#[derive(Debug, Clone, Copy)] -pub struct NewExternalAddrCandidate<'a> { - pub addr: &'a Multiaddr, -} - -/// [`FromSwarm`] variant that informs the behaviour that an external address was confirmed. -#[derive(Debug, Clone, Copy)] -pub struct ExternalAddrConfirmed<'a> { - pub addr: &'a Multiaddr, -} - -/// [`FromSwarm`] variant that informs the behaviour that an external address was removed. -#[derive(Debug, Clone, Copy)] -pub struct ExternalAddrExpired<'a> { - pub addr: &'a Multiaddr, -} - -/// [`FromSwarm`] variant that informs the behaviour that a new external address for a remote peer was detected. -#[derive(Clone, Copy, Debug)] -pub struct NewExternalAddrOfPeer<'a> { - pub peer_id: PeerId, - pub addr: &'a Multiaddr, -} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/either.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/either.rs deleted file mode 100644 index 7a51303e74d..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/behaviour/either.rs +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2021 Protocol Labs. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::behaviour::{self, NetworkBehaviour, ToSwarm}; -use crate::connection::ConnectionId; -use crate::{ConnectionDenied, THandler, THandlerInEvent, THandlerOutEvent}; -use either::Either; -use libp2p_core::transport::PortUse; -use libp2p_core::{Endpoint, Multiaddr}; -use libp2p_identity::PeerId; -use std::{task::Context, task::Poll}; - -/// Implementation of [`NetworkBehaviour`] that can be either of two implementations. -impl NetworkBehaviour for Either -where - L: NetworkBehaviour, - R: NetworkBehaviour, -{ - type ConnectionHandler = Either, THandler>; - type ToSwarm = Either; - - fn handle_pending_inbound_connection( - &mut self, - id: ConnectionId, - local_addr: &Multiaddr, - remote_addr: &Multiaddr, - ) -> Result<(), ConnectionDenied> { - match self { - Either::Left(a) => a.handle_pending_inbound_connection(id, local_addr, remote_addr), - Either::Right(b) => b.handle_pending_inbound_connection(id, local_addr, remote_addr), - } - } - - fn handle_established_inbound_connection( - &mut self, - connection_id: ConnectionId, - peer: PeerId, - local_addr: &Multiaddr, - remote_addr: &Multiaddr, - ) -> Result, ConnectionDenied> { - let handler = match self { - Either::Left(inner) => Either::Left(inner.handle_established_inbound_connection( - connection_id, - peer, - local_addr, - remote_addr, - )?), - Either::Right(inner) => Either::Right(inner.handle_established_inbound_connection( - connection_id, - peer, - local_addr, - remote_addr, - )?), - }; - - Ok(handler) - } - - fn handle_pending_outbound_connection( - &mut self, - connection_id: ConnectionId, - maybe_peer: Option, - addresses: &[Multiaddr], - effective_role: Endpoint, - ) -> Result, ConnectionDenied> { - let addresses = match self { - Either::Left(inner) => inner.handle_pending_outbound_connection( - connection_id, - maybe_peer, - addresses, - effective_role, - )?, - Either::Right(inner) => inner.handle_pending_outbound_connection( - connection_id, - maybe_peer, - addresses, - effective_role, - )?, - }; - - Ok(addresses) - } - - fn handle_established_outbound_connection( - &mut self, - connection_id: ConnectionId, - peer: PeerId, - addr: &Multiaddr, - role_override: Endpoint, - port_use: PortUse, - ) -> Result, ConnectionDenied> { - let handler = match self { - Either::Left(inner) => Either::Left(inner.handle_established_outbound_connection( - connection_id, - peer, - addr, - role_override, - port_use, - )?), - Either::Right(inner) => Either::Right(inner.handle_established_outbound_connection( - connection_id, - peer, - addr, - role_override, - port_use, - )?), - }; - - Ok(handler) - } - - fn on_swarm_event(&mut self, event: behaviour::FromSwarm) { - match self { - Either::Left(b) => b.on_swarm_event(event), - Either::Right(b) => b.on_swarm_event(event), - } - } - - fn on_connection_handler_event( - &mut self, - peer_id: PeerId, - connection_id: ConnectionId, - event: THandlerOutEvent, - ) { - match (self, event) { - (Either::Left(left), Either::Left(event)) => { - left.on_connection_handler_event(peer_id, connection_id, event); - } - (Either::Right(right), Either::Right(event)) => { - right.on_connection_handler_event(peer_id, connection_id, event); - } - _ => unreachable!(), - } - } - - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll>> { - let event = match self { - Either::Left(behaviour) => futures::ready!(behaviour.poll(cx)) - .map_out(Either::Left) - .map_in(Either::Left), - Either::Right(behaviour) => futures::ready!(behaviour.poll(cx)) - .map_out(Either::Right) - .map_in(Either::Right), - }; - - Poll::Ready(event) - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/external_addresses.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/external_addresses.rs deleted file mode 100644 index 579f46fe486..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/behaviour/external_addresses.rs +++ /dev/null @@ -1,182 +0,0 @@ -use crate::behaviour::{ExternalAddrConfirmed, ExternalAddrExpired, FromSwarm}; -use libp2p_core::Multiaddr; - -/// The maximum number of local external addresses. When reached any -/// further externally reported addresses are ignored. The behaviour always -/// tracks all its listen addresses. -const MAX_LOCAL_EXTERNAL_ADDRS: usize = 20; - -/// Utility struct for tracking the external addresses of a [`Swarm`](crate::Swarm). -#[derive(Debug, Clone, Default)] -pub struct ExternalAddresses { - addresses: Vec, -} - -impl ExternalAddresses { - /// Returns an [`Iterator`] over all external addresses. - pub fn iter(&self) -> impl ExactSizeIterator { - self.addresses.iter() - } - - pub fn as_slice(&self) -> &[Multiaddr] { - self.addresses.as_slice() - } - - /// Feed a [`FromSwarm`] event to this struct. - /// - /// Returns whether the event changed our set of external addresses. - pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { - match event { - FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { addr }) => { - if let Some(pos) = self - .addresses - .iter() - .position(|candidate| candidate == *addr) - { - // Refresh the existing confirmed address. - self.addresses.remove(pos); - self.push_front(addr); - - tracing::debug!(address=%addr, "Refreshed external address"); - - return false; // No changes to our external addresses. - } - - self.push_front(addr); - - if self.addresses.len() > MAX_LOCAL_EXTERNAL_ADDRS { - let expired = self.addresses.pop().expect("list to be not empty"); - - tracing::debug!( - external_address=%expired, - address_limit=%MAX_LOCAL_EXTERNAL_ADDRS, - "Removing previously confirmed external address because we reached the address limit" - ); - } - - return true; - } - FromSwarm::ExternalAddrExpired(ExternalAddrExpired { - addr: expired_addr, .. - }) => { - let pos = match self - .addresses - .iter() - .position(|candidate| candidate == *expired_addr) - { - None => return false, - Some(p) => p, - }; - - self.addresses.remove(pos); - return true; - } - _ => {} - } - - false - } - - fn push_front(&mut self, addr: &Multiaddr) { - self.addresses.insert(0, addr.clone()); // We have at most `MAX_LOCAL_EXTERNAL_ADDRS` so this isn't very expensive. - } -} - -#[cfg(test)] -mod tests { - use super::*; - use libp2p_core::multiaddr::Protocol; - use once_cell::sync::Lazy; - use rand::Rng; - - #[test] - fn new_external_addr_returns_correct_changed_value() { - let mut addresses = ExternalAddresses::default(); - - let changed = addresses.on_swarm_event(&new_external_addr1()); - assert!(changed); - - let changed = addresses.on_swarm_event(&new_external_addr1()); - assert!(!changed) - } - - #[test] - fn expired_external_addr_returns_correct_changed_value() { - let mut addresses = ExternalAddresses::default(); - addresses.on_swarm_event(&new_external_addr1()); - - let changed = addresses.on_swarm_event(&expired_external_addr1()); - assert!(changed); - - let changed = addresses.on_swarm_event(&expired_external_addr1()); - assert!(!changed) - } - - #[test] - fn more_recent_external_addresses_are_prioritized() { - let mut addresses = ExternalAddresses::default(); - - addresses.on_swarm_event(&new_external_addr1()); - addresses.on_swarm_event(&new_external_addr2()); - - assert_eq!( - addresses.as_slice(), - &[(*MEMORY_ADDR_2000).clone(), (*MEMORY_ADDR_1000).clone()] - ); - } - - #[test] - fn when_pushing_more_than_max_addresses_oldest_is_evicted() { - let mut addresses = ExternalAddresses::default(); - - while addresses.as_slice().len() < MAX_LOCAL_EXTERNAL_ADDRS { - let random_address = - Multiaddr::empty().with(Protocol::Memory(rand::thread_rng().gen_range(0..1000))); - addresses.on_swarm_event(&FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { - addr: &random_address, - })); - } - - addresses.on_swarm_event(&new_external_addr2()); - - assert_eq!(addresses.as_slice().len(), 20); - assert_eq!(addresses.as_slice()[0], (*MEMORY_ADDR_2000).clone()); - } - - #[test] - fn reporting_existing_external_address_moves_it_to_the_front() { - let mut addresses = ExternalAddresses::default(); - - addresses.on_swarm_event(&new_external_addr1()); - addresses.on_swarm_event(&new_external_addr2()); - addresses.on_swarm_event(&new_external_addr1()); - - assert_eq!( - addresses.as_slice(), - &[(*MEMORY_ADDR_1000).clone(), (*MEMORY_ADDR_2000).clone()] - ); - } - - fn new_external_addr1() -> FromSwarm<'static> { - FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { - addr: &MEMORY_ADDR_1000, - }) - } - - fn new_external_addr2() -> FromSwarm<'static> { - FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { - addr: &MEMORY_ADDR_2000, - }) - } - - fn expired_external_addr1() -> FromSwarm<'static> { - FromSwarm::ExternalAddrExpired(ExternalAddrExpired { - addr: &MEMORY_ADDR_1000, - }) - } - - static MEMORY_ADDR_1000: Lazy = - Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000))); - static MEMORY_ADDR_2000: Lazy = - Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(2000))); -} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/listen_addresses.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/listen_addresses.rs deleted file mode 100644 index 6076f5e7923..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/behaviour/listen_addresses.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::behaviour::{ExpiredListenAddr, FromSwarm, NewListenAddr}; -use libp2p_core::Multiaddr; -use std::collections::HashSet; - -/// Utility struct for tracking the addresses a [`Swarm`](crate::Swarm) is listening on. -#[derive(Debug, Default, Clone)] -pub struct ListenAddresses { - addresses: HashSet, -} - -impl ListenAddresses { - /// Returns an [`Iterator`] over all listen addresses. - pub fn iter(&self) -> impl ExactSizeIterator { - self.addresses.iter() - } - - /// Feed a [`FromSwarm`] event to this struct. - /// - /// Returns whether the event changed our set of listen addresses. - pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { - match event { - FromSwarm::NewListenAddr(NewListenAddr { addr, .. }) => { - self.addresses.insert((*addr).clone()) - } - FromSwarm::ExpiredListenAddr(ExpiredListenAddr { addr, .. }) => { - self.addresses.remove(addr) - } - _ => false, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use libp2p_core::{multiaddr::Protocol, transport::ListenerId}; - use once_cell::sync::Lazy; - - #[test] - fn new_listen_addr_returns_correct_changed_value() { - let mut addresses = ListenAddresses::default(); - - let changed = addresses.on_swarm_event(&new_listen_addr()); - assert!(changed); - - let changed = addresses.on_swarm_event(&new_listen_addr()); - assert!(!changed) - } - - #[test] - fn expired_listen_addr_returns_correct_changed_value() { - let mut addresses = ListenAddresses::default(); - addresses.on_swarm_event(&new_listen_addr()); - - let changed = addresses.on_swarm_event(&expired_listen_addr()); - assert!(changed); - - let changed = addresses.on_swarm_event(&expired_listen_addr()); - assert!(!changed) - } - - fn new_listen_addr() -> FromSwarm<'static> { - FromSwarm::NewListenAddr(NewListenAddr { - listener_id: ListenerId::next(), - addr: &MEMORY_ADDR, - }) - } - - fn expired_listen_addr() -> FromSwarm<'static> { - FromSwarm::ExpiredListenAddr(ExpiredListenAddr { - listener_id: ListenerId::next(), - addr: &MEMORY_ADDR, - }) - } - - static MEMORY_ADDR: Lazy = - Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000))); -} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/peer_addresses.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/peer_addresses.rs deleted file mode 100644 index 1eeead56ca1..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/behaviour/peer_addresses.rs +++ /dev/null @@ -1,338 +0,0 @@ -use crate::behaviour::FromSwarm; -use crate::{DialError, DialFailure, NewExternalAddrOfPeer}; - -use libp2p_core::Multiaddr; -use libp2p_identity::PeerId; - -use lru::LruCache; - -use std::num::NonZeroUsize; - -/// Struct for tracking peers' external addresses of the [`Swarm`](crate::Swarm). -#[derive(Debug)] -pub struct PeerAddresses(LruCache>); - -impl PeerAddresses { - /// Creates a [`PeerAddresses`] cache with capacity for the given number of peers. - /// - /// For each peer, we will at most store 10 addresses. - pub fn new(number_of_peers: NonZeroUsize) -> Self { - Self(LruCache::new(number_of_peers)) - } - - /// Feed a [`FromSwarm`] event to this struct. - /// - /// Returns whether the event changed peer's known external addresses. - pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { - match event { - FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, addr }) => { - self.add(*peer_id, (*addr).clone()) - } - FromSwarm::DialFailure(DialFailure { - peer_id: Some(peer_id), - error: DialError::Transport(errors), - .. - }) => { - for (addr, _error) in errors { - self.remove(peer_id, addr); - } - true - } - _ => false, - } - } - - /// Adds address to cache. - /// Appends address to the existing set if peer addresses already exist. - /// Creates a new cache entry for peer_id if no addresses are present. - /// Returns true if the newly added address was not previously in the cache. - /// - pub fn add(&mut self, peer: PeerId, address: Multiaddr) -> bool { - match prepare_addr(&peer, &address) { - Ok(address) => { - if let Some(cached) = self.0.get_mut(&peer) { - cached.put(address, ()).is_none() - } else { - let mut set = LruCache::new(NonZeroUsize::new(10).expect("10 > 0")); - set.put(address, ()); - self.0.put(peer, set); - - true - } - } - Err(_) => false, - } - } - - /// Returns peer's external addresses. - pub fn get(&mut self, peer: &PeerId) -> impl Iterator + '_ { - self.0 - .get(peer) - .into_iter() - .flat_map(|c| c.iter().map(|(m, ())| m)) - .cloned() - } - - /// Removes address from peer addresses cache. - /// Returns true if the address was removed. - pub fn remove(&mut self, peer: &PeerId, address: &Multiaddr) -> bool { - match self.0.get_mut(peer) { - Some(addrs) => match prepare_addr(peer, address) { - Ok(address) => addrs.pop(&address).is_some(), - Err(_) => false, - }, - None => false, - } - } -} - -fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Result { - addr.clone().with_p2p(*peer) -} - -impl Default for PeerAddresses { - fn default() -> Self { - Self(LruCache::new(NonZeroUsize::new(100).unwrap())) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::io; - - use crate::ConnectionId; - use libp2p_core::{ - multiaddr::Protocol, - transport::{memory::MemoryTransportError, TransportError}, - }; - - use once_cell::sync::Lazy; - - #[test] - fn new_peer_addr_returns_correct_changed_value() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - - let event = new_external_addr_of_peer1(peer_id); - - let changed = cache.on_swarm_event(&event); - assert!(changed); - - let changed = cache.on_swarm_event(&event); - assert!(!changed); - } - - #[test] - fn new_peer_addr_saves_peer_addrs() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - let event = new_external_addr_of_peer1(peer_id); - - let changed = cache.on_swarm_event(&event); - assert!(changed); - - let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); - let expected = cache.get(&peer_id).collect::>(); - assert_eq!(expected, vec![addr1]); - - let event = new_external_addr_of_peer2(peer_id); - let changed = cache.on_swarm_event(&event); - - let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); - let addr2 = MEMORY_ADDR_2000.clone().with_p2p(peer_id).unwrap(); - - let expected_addrs = cache.get(&peer_id).collect::>(); - assert!(expected_addrs.contains(&addr1)); - assert!(expected_addrs.contains(&addr2)); - - let expected = cache.get(&peer_id).collect::>().len(); - assert_eq!(expected, 2); - - assert!(changed); - } - - #[test] - fn existing_addr_is_not_added_to_cache() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - - let event = new_external_addr_of_peer1(peer_id); - - let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); - let changed = cache.on_swarm_event(&event); - let expected = cache.get(&peer_id).collect::>(); - assert!(changed); - assert_eq!(expected, vec![addr1]); - - let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); - let changed = cache.on_swarm_event(&event); - let expected = cache.get(&peer_id).collect::>(); - assert!(!changed); - assert_eq!(expected, [addr1]); - } - - #[test] - fn addresses_of_peer_are_removed_when_received_dial_failure() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - - let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); - let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); - - cache.add(peer_id, addr.clone()); - cache.add(peer_id, addr2.clone()); - cache.add(peer_id, addr3.clone()); - - let error = DialError::Transport(prepare_errors(vec![addr, addr3])); - - let event = FromSwarm::DialFailure(DialFailure { - peer_id: Some(peer_id), - error: &error, - connection_id: ConnectionId::new_unchecked(8), - }); - - let changed = cache.on_swarm_event(&event); - - assert!(changed); - - let cached = cache.get(&peer_id).collect::>(); - let expected = prepare_expected_addrs(peer_id, [addr2].into_iter()); - - assert_eq!(cached, expected); - } - - #[test] - fn remove_removes_address_if_present() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - - cache.add(peer_id, addr.clone()); - - assert!(cache.remove(&peer_id, &addr)); - } - - #[test] - fn remove_returns_false_if_address_not_present() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - - assert!(!cache.remove(&peer_id, &addr)); - } - - #[test] - fn remove_returns_false_if_peer_not_present() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - - assert!(!cache.remove(&peer_id, &addr)); - } - - #[test] - fn remove_removes_address_provided_in_param() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); - let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); - - cache.add(peer_id, addr.clone()); - cache.add(peer_id, addr2.clone()); - cache.add(peer_id, addr3.clone()); - - assert!(cache.remove(&peer_id, &addr2)); - - let mut cached = cache.get(&peer_id).collect::>(); - cached.sort(); - - let expected = prepare_expected_addrs(peer_id, [addr, addr3].into_iter()); - - assert_eq!(cached, expected); - } - - #[test] - fn add_adds_new_address_to_cache() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - - assert!(cache.add(peer_id, addr.clone())); - - let mut cached = cache.get(&peer_id).collect::>(); - cached.sort(); - let expected = prepare_expected_addrs(peer_id, [addr].into_iter()); - - assert_eq!(cached, expected); - } - - #[test] - fn add_adds_address_to_cache_to_existing_key() { - let mut cache = PeerAddresses::default(); - let peer_id = PeerId::random(); - let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); - let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); - - assert!(cache.add(peer_id, addr.clone())); - - cache.add(peer_id, addr2.clone()); - cache.add(peer_id, addr3.clone()); - - let expected = prepare_expected_addrs(peer_id, [addr, addr2, addr3].into_iter()); - - let mut cached = cache.get(&peer_id).collect::>(); - cached.sort(); - - assert_eq!(cached, expected); - } - - fn prepare_expected_addrs( - peer_id: PeerId, - addrs: impl Iterator, - ) -> Vec { - let mut addrs = addrs - .filter_map(|a| a.with_p2p(peer_id).ok()) - .collect::>(); - addrs.sort(); - addrs - } - - fn new_external_addr_of_peer1(peer_id: PeerId) -> FromSwarm<'static> { - FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { - peer_id, - addr: &MEMORY_ADDR_1000, - }) - } - - fn new_external_addr_of_peer2(peer_id: PeerId) -> FromSwarm<'static> { - FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { - peer_id, - addr: &MEMORY_ADDR_2000, - }) - } - - fn prepare_errors(addrs: Vec) -> Vec<(Multiaddr, TransportError)> { - let errors: Vec<(Multiaddr, TransportError)> = addrs - .iter() - .map(|addr| { - ( - addr.clone(), - TransportError::Other(io::Error::new( - io::ErrorKind::Other, - MemoryTransportError::Unreachable, - )), - ) - }) - .collect(); - errors - } - - static MEMORY_ADDR_1000: Lazy = - Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000))); - static MEMORY_ADDR_2000: Lazy = - Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(2000))); -} diff --git a/third-party/libp2p-swarm-0.45.1/src/behaviour/toggle.rs b/third-party/libp2p-swarm-0.45.1/src/behaviour/toggle.rs deleted file mode 100644 index 398c919ae86..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/behaviour/toggle.rs +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::behaviour::FromSwarm; -use crate::connection::ConnectionId; -use crate::handler::{ - AddressChange, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError, - FullyNegotiatedInbound, FullyNegotiatedOutbound, ListenUpgradeError, SubstreamProtocol, -}; -use crate::upgrade::SendWrapper; -use crate::{ - ConnectionDenied, NetworkBehaviour, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, -}; -use either::Either; -use futures::future; -use libp2p_core::transport::PortUse; -use libp2p_core::{upgrade::DeniedUpgrade, Endpoint, Multiaddr}; -use libp2p_identity::PeerId; -use std::{task::Context, task::Poll}; - -/// Implementation of `NetworkBehaviour` that can be either in the disabled or enabled state. -/// -/// The state can only be chosen at initialization. -pub struct Toggle { - inner: Option, -} - -impl Toggle { - /// Returns `true` if `Toggle` is enabled and `false` if it's disabled. - pub fn is_enabled(&self) -> bool { - self.inner.is_some() - } - - /// Returns a reference to the inner `NetworkBehaviour`. - pub fn as_ref(&self) -> Option<&TBehaviour> { - self.inner.as_ref() - } - - /// Returns a mutable reference to the inner `NetworkBehaviour`. - pub fn as_mut(&mut self) -> Option<&mut TBehaviour> { - self.inner.as_mut() - } -} - -impl From> for Toggle { - fn from(inner: Option) -> Self { - Toggle { inner } - } -} - -impl NetworkBehaviour for Toggle -where - TBehaviour: NetworkBehaviour, -{ - type ConnectionHandler = ToggleConnectionHandler>; - type ToSwarm = TBehaviour::ToSwarm; - - fn handle_pending_inbound_connection( - &mut self, - connection_id: ConnectionId, - local_addr: &Multiaddr, - remote_addr: &Multiaddr, - ) -> Result<(), ConnectionDenied> { - let inner = match self.inner.as_mut() { - None => return Ok(()), - Some(inner) => inner, - }; - - inner.handle_pending_inbound_connection(connection_id, local_addr, remote_addr)?; - - Ok(()) - } - - fn handle_established_inbound_connection( - &mut self, - connection_id: ConnectionId, - peer: PeerId, - local_addr: &Multiaddr, - remote_addr: &Multiaddr, - ) -> Result, ConnectionDenied> { - let inner = match self.inner.as_mut() { - None => return Ok(ToggleConnectionHandler { inner: None }), - Some(inner) => inner, - }; - - let handler = inner.handle_established_inbound_connection( - connection_id, - peer, - local_addr, - remote_addr, - )?; - - Ok(ToggleConnectionHandler { - inner: Some(handler), - }) - } - - fn handle_pending_outbound_connection( - &mut self, - connection_id: ConnectionId, - maybe_peer: Option, - addresses: &[Multiaddr], - effective_role: Endpoint, - ) -> Result, ConnectionDenied> { - let inner = match self.inner.as_mut() { - None => return Ok(vec![]), - Some(inner) => inner, - }; - - let addresses = inner.handle_pending_outbound_connection( - connection_id, - maybe_peer, - addresses, - effective_role, - )?; - - Ok(addresses) - } - - fn handle_established_outbound_connection( - &mut self, - connection_id: ConnectionId, - peer: PeerId, - addr: &Multiaddr, - role_override: Endpoint, - port_use: PortUse, - ) -> Result, ConnectionDenied> { - let inner = match self.inner.as_mut() { - None => return Ok(ToggleConnectionHandler { inner: None }), - Some(inner) => inner, - }; - - let handler = inner.handle_established_outbound_connection( - connection_id, - peer, - addr, - role_override, - port_use, - )?; - - Ok(ToggleConnectionHandler { - inner: Some(handler), - }) - } - - fn on_swarm_event(&mut self, event: FromSwarm) { - if let Some(behaviour) = &mut self.inner { - behaviour.on_swarm_event(event); - } - } - - fn on_connection_handler_event( - &mut self, - peer_id: PeerId, - connection_id: ConnectionId, - event: THandlerOutEvent, - ) { - if let Some(behaviour) = &mut self.inner { - behaviour.on_connection_handler_event(peer_id, connection_id, event) - } - } - - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll>> { - if let Some(inner) = self.inner.as_mut() { - inner.poll(cx) - } else { - Poll::Pending - } - } -} - -/// Implementation of [`ConnectionHandler`] that can be in the disabled state. -pub struct ToggleConnectionHandler { - inner: Option, -} - -impl ToggleConnectionHandler -where - TInner: ConnectionHandler, -{ - fn on_fully_negotiated_inbound( - &mut self, - FullyNegotiatedInbound { - protocol: out, - info, - }: FullyNegotiatedInbound< - ::InboundProtocol, - ::InboundOpenInfo, - >, - ) { - let out = match out { - future::Either::Left(out) => out, - future::Either::Right(v) => void::unreachable(v), - }; - - if let Either::Left(info) = info { - self.inner - .as_mut() - .expect("Can't receive an inbound substream if disabled; QED") - .on_connection_event(ConnectionEvent::FullyNegotiatedInbound( - FullyNegotiatedInbound { - protocol: out, - info, - }, - )); - } else { - panic!("Unexpected Either::Right in enabled `on_fully_negotiated_inbound`.") - } - } - - fn on_listen_upgrade_error( - &mut self, - ListenUpgradeError { info, error: err }: ListenUpgradeError< - ::InboundOpenInfo, - ::InboundProtocol, - >, - ) { - let (inner, info) = match (self.inner.as_mut(), info) { - (Some(inner), Either::Left(info)) => (inner, info), - // Ignore listen upgrade errors in disabled state. - (None, Either::Right(())) => return, - (Some(_), Either::Right(())) => panic!( - "Unexpected `Either::Right` inbound info through \ - `on_listen_upgrade_error` in enabled state.", - ), - (None, Either::Left(_)) => panic!( - "Unexpected `Either::Left` inbound info through \ - `on_listen_upgrade_error` in disabled state.", - ), - }; - - let err = match err { - Either::Left(e) => e, - Either::Right(v) => void::unreachable(v), - }; - - inner.on_connection_event(ConnectionEvent::ListenUpgradeError(ListenUpgradeError { - info, - error: err, - })); - } -} - -impl ConnectionHandler for ToggleConnectionHandler -where - TInner: ConnectionHandler, -{ - type FromBehaviour = TInner::FromBehaviour; - type ToBehaviour = TInner::ToBehaviour; - type InboundProtocol = Either, SendWrapper>; - type OutboundProtocol = TInner::OutboundProtocol; - type OutboundOpenInfo = TInner::OutboundOpenInfo; - type InboundOpenInfo = Either; - - fn listen_protocol(&self) -> SubstreamProtocol { - if let Some(inner) = self.inner.as_ref() { - inner - .listen_protocol() - .map_upgrade(|u| Either::Left(SendWrapper(u))) - .map_info(Either::Left) - } else { - SubstreamProtocol::new(Either::Right(SendWrapper(DeniedUpgrade)), Either::Right(())) - } - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - self.inner - .as_mut() - .expect("Can't receive events if disabled; QED") - .on_behaviour_event(event) - } - - fn connection_keep_alive(&self) -> bool { - self.inner - .as_ref() - .map(|h| h.connection_keep_alive()) - .unwrap_or(false) - } - - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - if let Some(inner) = self.inner.as_mut() { - inner.poll(cx) - } else { - Poll::Pending - } - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - match event { - ConnectionEvent::FullyNegotiatedInbound(fully_negotiated_inbound) => { - self.on_fully_negotiated_inbound(fully_negotiated_inbound) - } - ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { - protocol: out, - info, - }) => self - .inner - .as_mut() - .expect("Can't receive an outbound substream if disabled; QED") - .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( - FullyNegotiatedOutbound { - protocol: out, - info, - }, - )), - ConnectionEvent::AddressChange(address_change) => { - if let Some(inner) = self.inner.as_mut() { - inner.on_connection_event(ConnectionEvent::AddressChange(AddressChange { - new_address: address_change.new_address, - })); - } - } - ConnectionEvent::DialUpgradeError(DialUpgradeError { info, error: err }) => self - .inner - .as_mut() - .expect("Can't receive an outbound substream if disabled; QED") - .on_connection_event(ConnectionEvent::DialUpgradeError(DialUpgradeError { - info, - error: err, - })), - ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => { - self.on_listen_upgrade_error(listen_upgrade_error) - } - ConnectionEvent::LocalProtocolsChange(change) => { - if let Some(inner) = self.inner.as_mut() { - inner.on_connection_event(ConnectionEvent::LocalProtocolsChange(change)); - } - } - ConnectionEvent::RemoteProtocolsChange(change) => { - if let Some(inner) = self.inner.as_mut() { - inner.on_connection_event(ConnectionEvent::RemoteProtocolsChange(change)); - } - } - } - } - - fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { - let Some(inner) = self.inner.as_mut() else { - return Poll::Ready(None); - }; - - inner.poll_close(cx) - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection.rs b/third-party/libp2p-swarm-0.45.1/src/connection.rs deleted file mode 100644 index 603a5b0d7c4..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/connection.rs +++ /dev/null @@ -1,1387 +0,0 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -mod error; - -pub(crate) mod pool; -mod supported_protocols; - -pub use error::ConnectionError; -pub(crate) use error::{ - PendingConnectionError, PendingInboundConnectionError, PendingOutboundConnectionError, -}; -use libp2p_core::transport::PortUse; -pub use supported_protocols::SupportedProtocols; - -use crate::handler::{ - AddressChange, ConnectionEvent, ConnectionHandler, DialUpgradeError, FullyNegotiatedInbound, - FullyNegotiatedOutbound, ListenUpgradeError, ProtocolSupport, ProtocolsChange, UpgradeInfoSend, -}; -use crate::stream::ActiveStreamCounter; -use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend}; -use crate::{ - ConnectionHandlerEvent, Stream, StreamProtocol, StreamUpgradeError, SubstreamProtocol, -}; -use futures::future::BoxFuture; -use futures::stream::FuturesUnordered; -use futures::StreamExt; -use futures::{stream, FutureExt}; -use futures_timer::Delay; -use libp2p_core::connection::ConnectedPoint; -use libp2p_core::multiaddr::Multiaddr; -use libp2p_core::muxing::{StreamMuxerBox, StreamMuxerEvent, StreamMuxerExt, SubstreamBox}; -use libp2p_core::upgrade; -use libp2p_core::upgrade::{NegotiationError, ProtocolError}; -use libp2p_core::Endpoint; -use libp2p_identity::PeerId; -use std::collections::{HashMap, HashSet}; -use std::fmt::{Display, Formatter}; -use std::future::Future; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::task::Waker; -use std::time::Duration; -use std::{fmt, io, mem, pin::Pin, task::Context, task::Poll}; -use web_time::Instant; - -static NEXT_CONNECTION_ID: AtomicUsize = AtomicUsize::new(1); - -/// Connection identifier. -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct ConnectionId(usize); - -impl ConnectionId { - /// Creates an _unchecked_ [`ConnectionId`]. - /// - /// [`Swarm`](crate::Swarm) enforces that [`ConnectionId`]s are unique and not reused. - /// This constructor does not, hence the _unchecked_. - /// - /// It is primarily meant for allowing manual tests of [`NetworkBehaviour`](crate::NetworkBehaviour)s. - pub fn new_unchecked(id: usize) -> Self { - Self(id) - } - - /// Returns the next available [`ConnectionId`]. - pub(crate) fn next() -> Self { - Self(NEXT_CONNECTION_ID.fetch_add(1, Ordering::SeqCst)) - } -} - -impl Display for ConnectionId { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -/// Information about a successfully established connection. -#[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) struct Connected { - /// The connected endpoint, including network address information. - pub(crate) endpoint: ConnectedPoint, - /// Information obtained from the transport. - pub(crate) peer_id: PeerId, -} - -/// Event generated by a [`Connection`]. -#[derive(Debug, Clone)] -pub(crate) enum Event { - /// Event generated by the [`ConnectionHandler`]. - Handler(T), - /// Address of the remote has changed. - AddressChange(Multiaddr), -} - -/// A multiplexed connection to a peer with an associated [`ConnectionHandler`]. -pub(crate) struct Connection -where - THandler: ConnectionHandler, -{ - /// Node that handles the muxing. - muxing: StreamMuxerBox, - /// The underlying handler. - handler: THandler, - /// Futures that upgrade incoming substreams. - negotiating_in: FuturesUnordered< - StreamUpgrade< - THandler::InboundOpenInfo, - ::Output, - ::Error, - >, - >, - /// Futures that upgrade outgoing substreams. - negotiating_out: FuturesUnordered< - StreamUpgrade< - THandler::OutboundOpenInfo, - ::Output, - ::Error, - >, - >, - /// The currently planned connection & handler shutdown. - shutdown: Shutdown, - /// The substream upgrade protocol override, if any. - substream_upgrade_protocol_override: Option, - /// The maximum number of inbound streams concurrently negotiating on a - /// connection. New inbound streams exceeding the limit are dropped and thus - /// reset. - /// - /// Note: This only enforces a limit on the number of concurrently - /// negotiating inbound streams. The total number of inbound streams on a - /// connection is the sum of negotiating and negotiated streams. A limit on - /// the total number of streams can be enforced at the [`StreamMuxerBox`] level. - max_negotiating_inbound_streams: usize, - /// Contains all upgrades that are waiting for a new outbound substream. - /// - /// The upgrade timeout is already ticking here so this may fail in case the remote is not quick - /// enough in providing us with a new stream. - requested_substreams: FuturesUnordered< - SubstreamRequested, - >, - - local_supported_protocols: - HashMap::Info>, bool>, - remote_supported_protocols: HashSet, - protocol_buffer: Vec, - - idle_timeout: Duration, - stream_counter: ActiveStreamCounter, -} - -impl fmt::Debug for Connection -where - THandler: ConnectionHandler + fmt::Debug, - THandler::OutboundOpenInfo: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Connection") - .field("handler", &self.handler) - .finish() - } -} - -impl Unpin for Connection where THandler: ConnectionHandler {} - -impl Connection -where - THandler: ConnectionHandler, -{ - /// Builds a new `Connection` from the given substream multiplexer - /// and connection handler. - pub(crate) fn new( - muxer: StreamMuxerBox, - mut handler: THandler, - substream_upgrade_protocol_override: Option, - max_negotiating_inbound_streams: usize, - idle_timeout: Duration, - ) -> Self { - let initial_protocols = gather_supported_protocols(&handler); - let mut buffer = Vec::new(); - - if !initial_protocols.is_empty() { - handler.on_connection_event(ConnectionEvent::LocalProtocolsChange( - ProtocolsChange::from_initial_protocols( - initial_protocols.keys().map(|e| &e.0), - &mut buffer, - ), - )); - } - - Connection { - muxing: muxer, - handler, - negotiating_in: Default::default(), - negotiating_out: Default::default(), - shutdown: Shutdown::None, - substream_upgrade_protocol_override, - max_negotiating_inbound_streams, - requested_substreams: Default::default(), - local_supported_protocols: initial_protocols, - remote_supported_protocols: Default::default(), - protocol_buffer: buffer, - idle_timeout, - stream_counter: ActiveStreamCounter::default(), - } - } - - /// Notifies the connection handler of an event. - pub(crate) fn on_behaviour_event(&mut self, event: THandler::FromBehaviour) { - self.handler.on_behaviour_event(event); - } - - /// Begins an orderly shutdown of the connection, returning a stream of final events and a `Future` that resolves when connection shutdown is complete. - pub(crate) fn close( - self, - ) -> ( - impl futures::Stream, - impl Future>, - ) { - let Connection { - mut handler, - muxing, - .. - } = self; - - ( - stream::poll_fn(move |cx| handler.poll_close(cx)), - muxing.close(), - ) - } - - /// Polls the handler and the substream, forwarding events from the former to the latter and - /// vice versa. - #[tracing::instrument(level = "debug", name = "Connection::poll", skip(self, cx))] - pub(crate) fn poll( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll, ConnectionError>> { - let Self { - requested_substreams, - muxing, - handler, - negotiating_out, - negotiating_in, - shutdown, - max_negotiating_inbound_streams, - substream_upgrade_protocol_override, - local_supported_protocols: supported_protocols, - remote_supported_protocols, - protocol_buffer, - idle_timeout, - stream_counter, - .. - } = self.get_mut(); - - loop { - match requested_substreams.poll_next_unpin(cx) { - Poll::Ready(Some(Ok(()))) => continue, - Poll::Ready(Some(Err(info))) => { - handler.on_connection_event(ConnectionEvent::DialUpgradeError( - DialUpgradeError { - info, - error: StreamUpgradeError::Timeout, - }, - )); - continue; - } - Poll::Ready(None) | Poll::Pending => {} - } - - // Poll the [`ConnectionHandler`]. - match handler.poll(cx) { - Poll::Pending => {} - Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { protocol }) => { - let timeout = *protocol.timeout(); - let (upgrade, user_data) = protocol.into_upgrade(); - - requested_substreams.push(SubstreamRequested::new(user_data, timeout, upgrade)); - continue; // Poll handler until exhausted. - } - Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(event)) => { - return Poll::Ready(Ok(Event::Handler(event))); - } - Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols( - ProtocolSupport::Added(protocols), - )) => { - if let Some(added) = - ProtocolsChange::add(remote_supported_protocols, protocols, protocol_buffer) - { - handler.on_connection_event(ConnectionEvent::RemoteProtocolsChange(added)); - remote_supported_protocols.extend(protocol_buffer.drain(..)); - } - continue; - } - Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols( - ProtocolSupport::Removed(protocols), - )) => { - if let Some(removed) = ProtocolsChange::remove( - remote_supported_protocols, - protocols, - protocol_buffer, - ) { - handler - .on_connection_event(ConnectionEvent::RemoteProtocolsChange(removed)); - } - continue; - } - } - - // In case the [`ConnectionHandler`] can not make any more progress, poll the negotiating outbound streams. - match negotiating_out.poll_next_unpin(cx) { - Poll::Pending | Poll::Ready(None) => {} - Poll::Ready(Some((info, Ok(protocol)))) => { - handler.on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( - FullyNegotiatedOutbound { protocol, info }, - )); - continue; - } - Poll::Ready(Some((info, Err(error)))) => { - handler.on_connection_event(ConnectionEvent::DialUpgradeError( - DialUpgradeError { info, error }, - )); - continue; - } - } - - // In case both the [`ConnectionHandler`] and the negotiating outbound streams can not - // make any more progress, poll the negotiating inbound streams. - match negotiating_in.poll_next_unpin(cx) { - Poll::Pending | Poll::Ready(None) => {} - Poll::Ready(Some((info, Ok(protocol)))) => { - handler.on_connection_event(ConnectionEvent::FullyNegotiatedInbound( - FullyNegotiatedInbound { protocol, info }, - )); - continue; - } - Poll::Ready(Some((info, Err(StreamUpgradeError::Apply(error))))) => { - handler.on_connection_event(ConnectionEvent::ListenUpgradeError( - ListenUpgradeError { info, error }, - )); - continue; - } - Poll::Ready(Some((_, Err(StreamUpgradeError::Io(e))))) => { - tracing::debug!("failed to upgrade inbound stream: {e}"); - continue; - } - Poll::Ready(Some((_, Err(StreamUpgradeError::NegotiationFailed)))) => { - tracing::debug!("no protocol could be agreed upon for inbound stream"); - continue; - } - Poll::Ready(Some((_, Err(StreamUpgradeError::Timeout)))) => { - tracing::debug!("inbound stream upgrade timed out"); - continue; - } - } - - // Check if the connection (and handler) should be shut down. - // As long as we're still negotiating substreams or have any active streams shutdown is always postponed. - if negotiating_in.is_empty() - && negotiating_out.is_empty() - && requested_substreams.is_empty() - && stream_counter.has_no_active_streams() - { - if let Some(new_timeout) = - compute_new_shutdown(handler.connection_keep_alive(), shutdown, *idle_timeout) - { - *shutdown = new_timeout; - } - - match shutdown { - Shutdown::None => {} - Shutdown::Asap => return Poll::Ready(Err(ConnectionError::KeepAliveTimeout)), - Shutdown::Later(delay) => match Future::poll(Pin::new(delay), cx) { - Poll::Ready(_) => { - return Poll::Ready(Err(ConnectionError::KeepAliveTimeout)) - } - Poll::Pending => {} - }, - } - } else { - *shutdown = Shutdown::None; - } - - match muxing.poll_unpin(cx)? { - Poll::Pending => {} - Poll::Ready(StreamMuxerEvent::AddressChange(address)) => { - handler.on_connection_event(ConnectionEvent::AddressChange(AddressChange { - new_address: &address, - })); - return Poll::Ready(Ok(Event::AddressChange(address))); - } - } - - if let Some(requested_substream) = requested_substreams.iter_mut().next() { - match muxing.poll_outbound_unpin(cx)? { - Poll::Pending => {} - Poll::Ready(substream) => { - let (user_data, timeout, upgrade) = requested_substream.extract(); - - negotiating_out.push(StreamUpgrade::new_outbound( - substream, - user_data, - timeout, - upgrade, - *substream_upgrade_protocol_override, - stream_counter.clone(), - )); - - continue; // Go back to the top, handler can potentially make progress again. - } - } - } - - if negotiating_in.len() < *max_negotiating_inbound_streams { - match muxing.poll_inbound_unpin(cx)? { - Poll::Pending => {} - Poll::Ready(substream) => { - let protocol = handler.listen_protocol(); - - negotiating_in.push(StreamUpgrade::new_inbound( - substream, - protocol, - stream_counter.clone(), - )); - - continue; // Go back to the top, handler can potentially make progress again. - } - } - } - - let changes = ProtocolsChange::from_full_sets( - supported_protocols, - handler.listen_protocol().upgrade().protocol_info(), - protocol_buffer, - ); - - if !changes.is_empty() { - for change in changes { - handler.on_connection_event(ConnectionEvent::LocalProtocolsChange(change)); - } - continue; // Go back to the top, handler can potentially make progress again. - } - - return Poll::Pending; // Nothing can make progress, return `Pending`. - } - } - - #[cfg(test)] - fn poll_noop_waker(&mut self) -> Poll, ConnectionError>> { - Pin::new(self).poll(&mut Context::from_waker(futures::task::noop_waker_ref())) - } -} - -fn gather_supported_protocols( - handler: &C, -) -> HashMap::Info>, bool> { - handler - .listen_protocol() - .upgrade() - .protocol_info() - .map(|info| (AsStrHashEq(info), true)) - .collect() -} - -fn compute_new_shutdown( - handler_keep_alive: bool, - current_shutdown: &Shutdown, - idle_timeout: Duration, -) -> Option { - match (current_shutdown, handler_keep_alive) { - (_, false) if idle_timeout == Duration::ZERO => Some(Shutdown::Asap), - (Shutdown::Later(_), false) => None, // Do nothing, i.e. let the shutdown timer continue to tick. - (_, false) => { - let now = Instant::now(); - let safe_keep_alive = checked_add_fraction(now, idle_timeout); - - Some(Shutdown::Later(Delay::new(safe_keep_alive))) - } - (_, true) => Some(Shutdown::None), - } -} - -/// Repeatedly halves and adds the [`Duration`] to the [`Instant`] until [`Instant::checked_add`] succeeds. -/// -/// [`Instant`] depends on the underlying platform and has a limit of which points in time it can represent. -/// The [`Duration`] computed by the this function may not be the longest possible that we can add to `now` but it will work. -fn checked_add_fraction(start: Instant, mut duration: Duration) -> Duration { - while start.checked_add(duration).is_none() { - tracing::debug!(start=?start, duration=?duration, "start + duration cannot be presented, halving duration"); - - duration /= 2; - } - - duration -} - -/// Borrowed information about an incoming connection currently being negotiated. -#[derive(Debug, Copy, Clone)] -pub(crate) struct IncomingInfo<'a> { - /// Local connection address. - pub(crate) local_addr: &'a Multiaddr, - /// Address used to send back data to the remote. - pub(crate) send_back_addr: &'a Multiaddr, -} - -impl<'a> IncomingInfo<'a> { - /// Builds the [`ConnectedPoint`] corresponding to the incoming connection. - pub(crate) fn create_connected_point(&self) -> ConnectedPoint { - ConnectedPoint::Listener { - local_addr: self.local_addr.clone(), - send_back_addr: self.send_back_addr.clone(), - } - } -} - -struct StreamUpgrade { - user_data: Option, - timeout: Delay, - upgrade: BoxFuture<'static, Result>>, -} - -impl StreamUpgrade { - fn new_outbound( - substream: SubstreamBox, - user_data: UserData, - timeout: Delay, - upgrade: Upgrade, - version_override: Option, - counter: ActiveStreamCounter, - ) -> Self - where - Upgrade: OutboundUpgradeSend, - { - let effective_version = match version_override { - Some(version_override) if version_override != upgrade::Version::default() => { - tracing::debug!( - "Substream upgrade protocol override: {:?} -> {:?}", - upgrade::Version::default(), - version_override - ); - - version_override - } - _ => upgrade::Version::default(), - }; - let protocols = upgrade.protocol_info(); - - Self { - user_data: Some(user_data), - timeout, - upgrade: Box::pin(async move { - let (info, stream) = multistream_select::dialer_select_proto( - substream, - protocols, - effective_version, - ) - .await - .map_err(to_stream_upgrade_error)?; - - let output = upgrade - .upgrade_outbound(Stream::new(stream, counter), info) - .await - .map_err(StreamUpgradeError::Apply)?; - - Ok(output) - }), - } - } -} - -impl StreamUpgrade { - fn new_inbound( - substream: SubstreamBox, - protocol: SubstreamProtocol, - counter: ActiveStreamCounter, - ) -> Self - where - Upgrade: InboundUpgradeSend, - { - let timeout = *protocol.timeout(); - let (upgrade, open_info) = protocol.into_upgrade(); - let protocols = upgrade.protocol_info(); - - Self { - user_data: Some(open_info), - timeout: Delay::new(timeout), - upgrade: Box::pin(async move { - let (info, stream) = - multistream_select::listener_select_proto(substream, protocols) - .await - .map_err(to_stream_upgrade_error)?; - - let output = upgrade - .upgrade_inbound(Stream::new(stream, counter), info) - .await - .map_err(StreamUpgradeError::Apply)?; - - Ok(output) - }), - } - } -} - -fn to_stream_upgrade_error(e: NegotiationError) -> StreamUpgradeError { - match e { - NegotiationError::Failed => StreamUpgradeError::NegotiationFailed, - NegotiationError::ProtocolError(ProtocolError::IoError(e)) => StreamUpgradeError::Io(e), - NegotiationError::ProtocolError(other) => { - StreamUpgradeError::Io(io::Error::new(io::ErrorKind::Other, other)) - } - } -} - -impl Unpin for StreamUpgrade {} - -impl Future for StreamUpgrade { - type Output = (UserData, Result>); - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - match self.timeout.poll_unpin(cx) { - Poll::Ready(()) => { - return Poll::Ready(( - self.user_data - .take() - .expect("Future not to be polled again once ready."), - Err(StreamUpgradeError::Timeout), - )) - } - - Poll::Pending => {} - } - - let result = futures::ready!(self.upgrade.poll_unpin(cx)); - let user_data = self - .user_data - .take() - .expect("Future not to be polled again once ready."); - - Poll::Ready((user_data, result)) - } -} - -enum SubstreamRequested { - Waiting { - user_data: UserData, - timeout: Delay, - upgrade: Upgrade, - /// A waker to notify our [`FuturesUnordered`] that we have extracted the data. - /// - /// This will ensure that we will get polled again in the next iteration which allows us to - /// resolve with `Ok(())` and be removed from the [`FuturesUnordered`]. - extracted_waker: Option, - }, - Done, -} - -impl SubstreamRequested { - fn new(user_data: UserData, timeout: Duration, upgrade: Upgrade) -> Self { - Self::Waiting { - user_data, - timeout: Delay::new(timeout), - upgrade, - extracted_waker: None, - } - } - - fn extract(&mut self) -> (UserData, Delay, Upgrade) { - match mem::replace(self, Self::Done) { - SubstreamRequested::Waiting { - user_data, - timeout, - upgrade, - extracted_waker: waker, - } => { - if let Some(waker) = waker { - waker.wake(); - } - - (user_data, timeout, upgrade) - } - SubstreamRequested::Done => panic!("cannot extract twice"), - } - } -} - -impl Unpin for SubstreamRequested {} - -impl Future for SubstreamRequested { - type Output = Result<(), UserData>; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let this = self.get_mut(); - - match mem::replace(this, Self::Done) { - SubstreamRequested::Waiting { - user_data, - upgrade, - mut timeout, - .. - } => match timeout.poll_unpin(cx) { - Poll::Ready(()) => Poll::Ready(Err(user_data)), - Poll::Pending => { - *this = Self::Waiting { - user_data, - upgrade, - timeout, - extracted_waker: Some(cx.waker().clone()), - }; - Poll::Pending - } - }, - SubstreamRequested::Done => Poll::Ready(Ok(())), - } - } -} - -/// The options for a planned connection & handler shutdown. -/// -/// A shutdown is planned anew based on the return value of -/// [`ConnectionHandler::connection_keep_alive`] of the underlying handler -/// after every invocation of [`ConnectionHandler::poll`]. -/// -/// A planned shutdown is always postponed for as long as there are ingoing -/// or outgoing substreams being negotiated, i.e. it is a graceful, "idle" -/// shutdown. -#[derive(Debug)] -enum Shutdown { - /// No shutdown is planned. - None, - /// A shut down is planned as soon as possible. - Asap, - /// A shut down is planned for when a `Delay` has elapsed. - Later(Delay), -} - -// Structure used to avoid allocations when storing the protocols in the `HashMap. -// Instead of allocating a new `String` for the key, -// we use `T::as_ref()` in `Hash`, `Eq` and `PartialEq` requirements. -pub(crate) struct AsStrHashEq(pub(crate) T); - -impl> Eq for AsStrHashEq {} - -impl> PartialEq for AsStrHashEq { - fn eq(&self, other: &Self) -> bool { - self.0.as_ref() == other.0.as_ref() - } -} - -impl> std::hash::Hash for AsStrHashEq { - fn hash(&self, state: &mut H) { - self.0.as_ref().hash(state) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::dummy; - use futures::future; - use futures::AsyncRead; - use futures::AsyncWrite; - use libp2p_core::upgrade::{DeniedUpgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo}; - use libp2p_core::StreamMuxer; - use quickcheck::*; - use std::sync::{Arc, Weak}; - use std::time::Instant; - use tracing_subscriber::EnvFilter; - use void::Void; - - #[test] - fn max_negotiating_inbound_streams() { - let _ = tracing_subscriber::fmt() - .with_env_filter(EnvFilter::from_default_env()) - .try_init(); - - fn prop(max_negotiating_inbound_streams: u8) { - let max_negotiating_inbound_streams: usize = max_negotiating_inbound_streams.into(); - - let alive_substream_counter = Arc::new(()); - let mut connection = Connection::new( - StreamMuxerBox::new(DummyStreamMuxer { - counter: alive_substream_counter.clone(), - }), - MockConnectionHandler::new(Duration::from_secs(10)), - None, - max_negotiating_inbound_streams, - Duration::ZERO, - ); - - let result = connection.poll_noop_waker(); - - assert!(result.is_pending()); - assert_eq!( - Arc::weak_count(&alive_substream_counter), - max_negotiating_inbound_streams, - "Expect no more than the maximum number of allowed streams" - ); - } - - QuickCheck::new().quickcheck(prop as fn(_)); - } - - #[test] - fn outbound_stream_timeout_starts_on_request() { - let upgrade_timeout = Duration::from_secs(1); - let mut connection = Connection::new( - StreamMuxerBox::new(PendingStreamMuxer), - MockConnectionHandler::new(upgrade_timeout), - None, - 2, - Duration::ZERO, - ); - - connection.handler.open_new_outbound(); - let _ = connection.poll_noop_waker(); - - std::thread::sleep(upgrade_timeout + Duration::from_secs(1)); - - let _ = connection.poll_noop_waker(); - - assert!(matches!( - connection.handler.error.unwrap(), - StreamUpgradeError::Timeout - )) - } - - #[test] - fn propagates_changes_to_supported_inbound_protocols() { - let mut connection = Connection::new( - StreamMuxerBox::new(PendingStreamMuxer), - ConfigurableProtocolConnectionHandler::default(), - None, - 0, - Duration::ZERO, - ); - - // First, start listening on a single protocol. - connection.handler.listen_on(&["/foo"]); - let _ = connection.poll_noop_waker(); - - assert_eq!(connection.handler.local_added, vec![vec!["/foo"]]); - assert!(connection.handler.local_removed.is_empty()); - - // Second, listen on two protocols. - connection.handler.listen_on(&["/foo", "/bar"]); - let _ = connection.poll_noop_waker(); - - assert_eq!( - connection.handler.local_added, - vec![vec!["/foo"], vec!["/bar"]], - "expect to only receive an event for the newly added protocols" - ); - assert!(connection.handler.local_removed.is_empty()); - - // Third, stop listening on the first protocol. - connection.handler.listen_on(&["/bar"]); - let _ = connection.poll_noop_waker(); - - assert_eq!( - connection.handler.local_added, - vec![vec!["/foo"], vec!["/bar"]] - ); - assert_eq!(connection.handler.local_removed, vec![vec!["/foo"]]); - } - - #[test] - fn only_propagtes_actual_changes_to_remote_protocols_to_handler() { - let mut connection = Connection::new( - StreamMuxerBox::new(PendingStreamMuxer), - ConfigurableProtocolConnectionHandler::default(), - None, - 0, - Duration::ZERO, - ); - - // First, remote supports a single protocol. - connection.handler.remote_adds_support_for(&["/foo"]); - let _ = connection.poll_noop_waker(); - - assert_eq!(connection.handler.remote_added, vec![vec!["/foo"]]); - assert!(connection.handler.remote_removed.is_empty()); - - // Second, it adds a protocol but also still includes the first one. - connection - .handler - .remote_adds_support_for(&["/foo", "/bar"]); - let _ = connection.poll_noop_waker(); - - assert_eq!( - connection.handler.remote_added, - vec![vec!["/foo"], vec!["/bar"]], - "expect to only receive an event for the newly added protocol" - ); - assert!(connection.handler.remote_removed.is_empty()); - - // Third, stop listening on a protocol it never advertised (we can't control what handlers do so this needs to be handled gracefully). - connection.handler.remote_removes_support_for(&["/baz"]); - let _ = connection.poll_noop_waker(); - - assert_eq!( - connection.handler.remote_added, - vec![vec!["/foo"], vec!["/bar"]] - ); - assert!(&connection.handler.remote_removed.is_empty()); - - // Fourth, stop listening on a protocol that was previously supported - connection.handler.remote_removes_support_for(&["/bar"]); - let _ = connection.poll_noop_waker(); - - assert_eq!( - connection.handler.remote_added, - vec![vec!["/foo"], vec!["/bar"]] - ); - assert_eq!(connection.handler.remote_removed, vec![vec!["/bar"]]); - } - - #[tokio::test] - async fn idle_timeout_with_keep_alive_no() { - let idle_timeout = Duration::from_millis(100); - - let mut connection = Connection::new( - StreamMuxerBox::new(PendingStreamMuxer), - dummy::ConnectionHandler, - None, - 0, - idle_timeout, - ); - - assert!(connection.poll_noop_waker().is_pending()); - - tokio::time::sleep(idle_timeout).await; - - assert!(matches!( - connection.poll_noop_waker(), - Poll::Ready(Err(ConnectionError::KeepAliveTimeout)) - )); - } - - #[test] - fn checked_add_fraction_can_add_u64_max() { - let _ = tracing_subscriber::fmt() - .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) - .try_init(); - let start = Instant::now(); - - let duration = checked_add_fraction(start, Duration::from_secs(u64::MAX)); - - assert!(start.checked_add(duration).is_some()) - } - - #[test] - fn compute_new_shutdown_does_not_panic() { - let _ = tracing_subscriber::fmt() - .with_env_filter(EnvFilter::from_default_env()) - .try_init(); - - #[derive(Debug)] - struct ArbitraryShutdown(Shutdown); - - impl Clone for ArbitraryShutdown { - fn clone(&self) -> Self { - let shutdown = match self.0 { - Shutdown::None => Shutdown::None, - Shutdown::Asap => Shutdown::Asap, - Shutdown::Later(_) => Shutdown::Later( - // compute_new_shutdown does not touch the delay. Delay does not - // implement Clone. Thus use a placeholder delay. - Delay::new(Duration::from_secs(1)), - ), - }; - - ArbitraryShutdown(shutdown) - } - } - - impl Arbitrary for ArbitraryShutdown { - fn arbitrary(g: &mut Gen) -> Self { - let shutdown = match g.gen_range(1u8..4) { - 1 => Shutdown::None, - 2 => Shutdown::Asap, - 3 => Shutdown::Later(Delay::new(Duration::from_secs(u32::arbitrary(g) as u64))), - _ => unreachable!(), - }; - - Self(shutdown) - } - } - - fn prop( - handler_keep_alive: bool, - current_shutdown: ArbitraryShutdown, - idle_timeout: Duration, - ) { - compute_new_shutdown(handler_keep_alive, ¤t_shutdown.0, idle_timeout); - } - - QuickCheck::new().quickcheck(prop as fn(_, _, _)); - } - - struct DummyStreamMuxer { - counter: Arc<()>, - } - - impl StreamMuxer for DummyStreamMuxer { - type Substream = PendingSubstream; - type Error = Void; - - fn poll_inbound( - self: Pin<&mut Self>, - _: &mut Context<'_>, - ) -> Poll> { - Poll::Ready(Ok(PendingSubstream { - _weak: Arc::downgrade(&self.counter), - })) - } - - fn poll_outbound( - self: Pin<&mut Self>, - _: &mut Context<'_>, - ) -> Poll> { - Poll::Pending - } - - fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn poll( - self: Pin<&mut Self>, - _: &mut Context<'_>, - ) -> Poll> { - Poll::Pending - } - } - - /// A [`StreamMuxer`] which never returns a stream. - struct PendingStreamMuxer; - - impl StreamMuxer for PendingStreamMuxer { - type Substream = PendingSubstream; - type Error = Void; - - fn poll_inbound( - self: Pin<&mut Self>, - _: &mut Context<'_>, - ) -> Poll> { - Poll::Pending - } - - fn poll_outbound( - self: Pin<&mut Self>, - _: &mut Context<'_>, - ) -> Poll> { - Poll::Pending - } - - fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { - Poll::Pending - } - - fn poll( - self: Pin<&mut Self>, - _: &mut Context<'_>, - ) -> Poll> { - Poll::Pending - } - } - - struct PendingSubstream { - _weak: Weak<()>, - } - - impl AsyncRead for PendingSubstream { - fn poll_read( - self: Pin<&mut Self>, - _cx: &mut Context<'_>, - _buf: &mut [u8], - ) -> Poll> { - Poll::Pending - } - } - - impl AsyncWrite for PendingSubstream { - fn poll_write( - self: Pin<&mut Self>, - _cx: &mut Context<'_>, - _buf: &[u8], - ) -> Poll> { - Poll::Pending - } - - fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - Poll::Pending - } - - fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - Poll::Pending - } - } - - struct MockConnectionHandler { - outbound_requested: bool, - error: Option>, - upgrade_timeout: Duration, - } - - impl MockConnectionHandler { - fn new(upgrade_timeout: Duration) -> Self { - Self { - outbound_requested: false, - error: None, - upgrade_timeout, - } - } - - fn open_new_outbound(&mut self) { - self.outbound_requested = true; - } - } - - #[derive(Default)] - struct ConfigurableProtocolConnectionHandler { - events: Vec>, - active_protocols: HashSet, - local_added: Vec>, - local_removed: Vec>, - remote_added: Vec>, - remote_removed: Vec>, - } - - impl ConfigurableProtocolConnectionHandler { - fn listen_on(&mut self, protocols: &[&'static str]) { - self.active_protocols = protocols.iter().copied().map(StreamProtocol::new).collect(); - } - - fn remote_adds_support_for(&mut self, protocols: &[&'static str]) { - self.events - .push(ConnectionHandlerEvent::ReportRemoteProtocols( - ProtocolSupport::Added( - protocols.iter().copied().map(StreamProtocol::new).collect(), - ), - )); - } - - fn remote_removes_support_for(&mut self, protocols: &[&'static str]) { - self.events - .push(ConnectionHandlerEvent::ReportRemoteProtocols( - ProtocolSupport::Removed( - protocols.iter().copied().map(StreamProtocol::new).collect(), - ), - )); - } - } - - impl ConnectionHandler for MockConnectionHandler { - type FromBehaviour = Void; - type ToBehaviour = Void; - type InboundProtocol = DeniedUpgrade; - type OutboundProtocol = DeniedUpgrade; - type InboundOpenInfo = (); - type OutboundOpenInfo = (); - - fn listen_protocol( - &self, - ) -> SubstreamProtocol { - SubstreamProtocol::new(DeniedUpgrade, ()).with_timeout(self.upgrade_timeout) - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - match event { - ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { - protocol, - .. - }) => void::unreachable(protocol), - ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { - protocol, - .. - }) => void::unreachable(protocol), - ConnectionEvent::DialUpgradeError(DialUpgradeError { error, .. }) => { - self.error = Some(error) - } - ConnectionEvent::AddressChange(_) - | ConnectionEvent::ListenUpgradeError(_) - | ConnectionEvent::LocalProtocolsChange(_) - | ConnectionEvent::RemoteProtocolsChange(_) => {} - } - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - void::unreachable(event) - } - - fn connection_keep_alive(&self) -> bool { - true - } - - fn poll( - &mut self, - _: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent< - Self::OutboundProtocol, - Self::OutboundOpenInfo, - Self::ToBehaviour, - >, - > { - if self.outbound_requested { - self.outbound_requested = false; - return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { - protocol: SubstreamProtocol::new(DeniedUpgrade, ()) - .with_timeout(self.upgrade_timeout), - }); - } - - Poll::Pending - } - } - - impl ConnectionHandler for ConfigurableProtocolConnectionHandler { - type FromBehaviour = Void; - type ToBehaviour = Void; - type InboundProtocol = ManyProtocolsUpgrade; - type OutboundProtocol = DeniedUpgrade; - type InboundOpenInfo = (); - type OutboundOpenInfo = (); - - fn listen_protocol( - &self, - ) -> SubstreamProtocol { - SubstreamProtocol::new( - ManyProtocolsUpgrade { - protocols: Vec::from_iter(self.active_protocols.clone()), - }, - (), - ) - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - match event { - ConnectionEvent::LocalProtocolsChange(ProtocolsChange::Added(added)) => { - self.local_added.push(added.cloned().collect()) - } - ConnectionEvent::LocalProtocolsChange(ProtocolsChange::Removed(removed)) => { - self.local_removed.push(removed.cloned().collect()) - } - ConnectionEvent::RemoteProtocolsChange(ProtocolsChange::Added(added)) => { - self.remote_added.push(added.cloned().collect()) - } - ConnectionEvent::RemoteProtocolsChange(ProtocolsChange::Removed(removed)) => { - self.remote_removed.push(removed.cloned().collect()) - } - _ => {} - } - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - void::unreachable(event) - } - - fn connection_keep_alive(&self) -> bool { - true - } - - fn poll( - &mut self, - _: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent< - Self::OutboundProtocol, - Self::OutboundOpenInfo, - Self::ToBehaviour, - >, - > { - if let Some(event) = self.events.pop() { - return Poll::Ready(event); - } - - Poll::Pending - } - } - - struct ManyProtocolsUpgrade { - protocols: Vec, - } - - impl UpgradeInfo for ManyProtocolsUpgrade { - type Info = StreamProtocol; - type InfoIter = std::vec::IntoIter; - - fn protocol_info(&self) -> Self::InfoIter { - self.protocols.clone().into_iter() - } - } - - impl InboundUpgrade for ManyProtocolsUpgrade { - type Output = C; - type Error = Void; - type Future = future::Ready>; - - fn upgrade_inbound(self, stream: C, _: Self::Info) -> Self::Future { - future::ready(Ok(stream)) - } - } - - impl OutboundUpgrade for ManyProtocolsUpgrade { - type Output = C; - type Error = Void; - type Future = future::Ready>; - - fn upgrade_outbound(self, stream: C, _: Self::Info) -> Self::Future { - future::ready(Ok(stream)) - } - } -} - -/// The endpoint roles associated with a pending peer-to-peer connection. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -enum PendingPoint { - /// The socket comes from a dialer. - /// - /// There is no single address associated with the Dialer of a pending - /// connection. Addresses are dialed in parallel. Only once the first dial - /// is successful is the address of the connection known. - Dialer { - /// Same as [`ConnectedPoint::Dialer`] `role_override`. - role_override: Endpoint, - port_use: PortUse, - }, - /// The socket comes from a listener. - Listener { - /// Local connection address. - local_addr: Multiaddr, - /// Address used to send back data to the remote. - send_back_addr: Multiaddr, - }, -} - -impl From for PendingPoint { - fn from(endpoint: ConnectedPoint) -> Self { - match endpoint { - ConnectedPoint::Dialer { - role_override, - port_use, - .. - } => PendingPoint::Dialer { - role_override, - port_use, - }, - ConnectedPoint::Listener { - local_addr, - send_back_addr, - } => PendingPoint::Listener { - local_addr, - send_back_addr, - }, - } - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/error.rs b/third-party/libp2p-swarm-0.45.1/src/connection/error.rs deleted file mode 100644 index 33aa81c19a9..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/connection/error.rs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::transport::TransportError; -use crate::Multiaddr; -use crate::{ConnectedPoint, PeerId}; -use std::{fmt, io}; - -/// Errors that can occur in the context of an established `Connection`. -#[derive(Debug)] -pub enum ConnectionError { - /// An I/O error occurred on the connection. - // TODO: Eventually this should also be a custom error? - IO(io::Error), - - /// The connection keep-alive timeout expired. - KeepAliveTimeout, -} - -impl fmt::Display for ConnectionError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ConnectionError::IO(err) => write!(f, "Connection error: I/O error: {err}"), - ConnectionError::KeepAliveTimeout => { - write!(f, "Connection closed due to expired keep-alive timeout.") - } - } - } -} - -impl std::error::Error for ConnectionError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - ConnectionError::IO(err) => Some(err), - ConnectionError::KeepAliveTimeout => None, - } - } -} - -impl From for ConnectionError { - fn from(error: io::Error) -> Self { - ConnectionError::IO(error) - } -} - -/// Errors that can occur in the context of a pending outgoing `Connection`. -/// -/// Note: Addresses for an outbound connection are dialed in parallel. Thus, compared to -/// [`PendingInboundConnectionError`], one or more [`TransportError`]s can occur for a single -/// connection. -pub(crate) type PendingOutboundConnectionError = - PendingConnectionError)>>; - -/// Errors that can occur in the context of a pending incoming `Connection`. -pub(crate) type PendingInboundConnectionError = PendingConnectionError>; - -/// Errors that can occur in the context of a pending `Connection`. -#[derive(Debug)] -pub enum PendingConnectionError { - /// An error occurred while negotiating the transport protocol(s) on a connection. - Transport(TTransErr), - - /// Pending connection attempt has been aborted. - Aborted, - - /// The peer identity obtained on the connection did not - /// match the one that was expected. - WrongPeerId { - obtained: PeerId, - endpoint: ConnectedPoint, - }, - - /// The connection was dropped because it resolved to our own [`PeerId`]. - LocalPeerId { endpoint: ConnectedPoint }, -} - -impl PendingConnectionError { - pub fn map(self, f: impl FnOnce(T) -> U) -> PendingConnectionError { - match self { - PendingConnectionError::Transport(t) => PendingConnectionError::Transport(f(t)), - PendingConnectionError::Aborted => PendingConnectionError::Aborted, - PendingConnectionError::WrongPeerId { obtained, endpoint } => { - PendingConnectionError::WrongPeerId { obtained, endpoint } - } - PendingConnectionError::LocalPeerId { endpoint } => { - PendingConnectionError::LocalPeerId { endpoint } - } - } - } -} - -impl fmt::Display for PendingConnectionError -where - TTransErr: fmt::Display + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - PendingConnectionError::Aborted => write!(f, "Pending connection: Aborted."), - PendingConnectionError::Transport(err) => { - write!( - f, - "Pending connection: Transport error on connection: {err}" - ) - } - PendingConnectionError::WrongPeerId { obtained, endpoint } => { - write!( - f, - "Pending connection: Unexpected peer ID {obtained} at {endpoint:?}." - ) - } - PendingConnectionError::LocalPeerId { endpoint } => { - write!(f, "Pending connection: Local peer ID at {endpoint:?}.") - } - } - } -} - -impl std::error::Error for PendingConnectionError -where - TTransErr: std::error::Error + 'static, -{ - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - PendingConnectionError::Transport(_) => None, - PendingConnectionError::WrongPeerId { .. } => None, - PendingConnectionError::LocalPeerId { .. } => None, - PendingConnectionError::Aborted => None, - } - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/pool.rs b/third-party/libp2p-swarm-0.45.1/src/connection/pool.rs deleted file mode 100644 index 07f6968dec9..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/connection/pool.rs +++ /dev/null @@ -1,1044 +0,0 @@ -// Copyright 2021 Protocol Labs. -// Copyright 2018 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -use crate::connection::{Connection, ConnectionId, PendingPoint}; -use crate::{ - connection::{ - Connected, ConnectionError, IncomingInfo, PendingConnectionError, - PendingInboundConnectionError, PendingOutboundConnectionError, - }, - transport::TransportError, - ConnectedPoint, ConnectionHandler, Executor, Multiaddr, PeerId, -}; -use concurrent_dial::ConcurrentDial; -use fnv::FnvHashMap; -use futures::prelude::*; -use futures::stream::SelectAll; -use futures::{ - channel::{mpsc, oneshot}, - future::{poll_fn, BoxFuture, Either}, - ready, - stream::FuturesUnordered, -}; -use libp2p_core::connection::Endpoint; -use libp2p_core::muxing::{StreamMuxerBox, StreamMuxerExt}; -use libp2p_core::transport::PortUse; -use std::task::Waker; -use std::{ - collections::HashMap, - fmt, - num::{NonZeroU8, NonZeroUsize}, - pin::Pin, - task::Context, - task::Poll, -}; -use tracing::Instrument; -use void::Void; -use web_time::{Duration, Instant}; - -mod concurrent_dial; -mod task; - -enum ExecSwitch { - Executor(Box), - LocalSpawn(FuturesUnordered + Send>>>), -} - -impl ExecSwitch { - fn advance_local(&mut self, cx: &mut Context) { - match self { - ExecSwitch::Executor(_) => {} - ExecSwitch::LocalSpawn(local) => { - while let Poll::Ready(Some(())) = local.poll_next_unpin(cx) {} - } - } - } - - #[track_caller] - fn spawn(&mut self, task: impl Future + Send + 'static) { - let task = task.boxed(); - - match self { - Self::Executor(executor) => executor.exec(task), - Self::LocalSpawn(local) => local.push(task), - } - } -} - -/// A connection `Pool` manages a set of connections for each peer. -pub(crate) struct Pool -where - THandler: ConnectionHandler, -{ - local_id: PeerId, - - /// The connection counter(s). - counters: ConnectionCounters, - - /// The managed connections of each peer that are currently considered established. - established: FnvHashMap< - PeerId, - FnvHashMap>, - >, - - /// The pending connections that are currently being negotiated. - pending: HashMap, - - /// Size of the task command buffer (per task). - task_command_buffer_size: usize, - - /// Number of addresses concurrently dialed for a single outbound connection attempt. - dial_concurrency_factor: NonZeroU8, - - /// The configured override for substream protocol upgrades, if any. - substream_upgrade_protocol_override: Option, - - /// The maximum number of inbound streams concurrently negotiating on a connection. - /// - /// See [`Connection::max_negotiating_inbound_streams`]. - max_negotiating_inbound_streams: usize, - - /// How many [`task::EstablishedConnectionEvent`]s can be buffered before the connection is back-pressured. - per_connection_event_buffer_size: usize, - - /// The executor to use for running connection tasks. Can either be a global executor - /// or a local queue. - executor: ExecSwitch, - - /// Sender distributed to pending tasks for reporting events back - /// to the pool. - pending_connection_events_tx: mpsc::Sender, - - /// Receiver for events reported from pending tasks. - pending_connection_events_rx: mpsc::Receiver, - - /// Waker in case we haven't established any connections yet. - no_established_connections_waker: Option, - - /// Receivers for events reported from established connections. - established_connection_events: - SelectAll>>, - - /// Receivers for [`NewConnection`] objects that are dropped. - new_connection_dropped_listeners: FuturesUnordered>, - - /// How long a connection should be kept alive once it starts idling. - idle_connection_timeout: Duration, -} - -#[derive(Debug)] -pub(crate) struct EstablishedConnection { - endpoint: ConnectedPoint, - /// Channel endpoint to send commands to the task. - sender: mpsc::Sender>, -} - -impl EstablishedConnection { - /// (Asynchronously) sends an event to the connection handler. - /// - /// If the handler is not ready to receive the event, either because - /// it is busy or the connection is about to close, the given event - /// is returned with an `Err`. - /// - /// If execution of this method is preceded by successful execution of - /// `poll_ready_notify_handler` without another intervening execution - /// of `notify_handler`, it only fails if the connection is now about - /// to close. - pub(crate) fn notify_handler(&mut self, event: TInEvent) -> Result<(), TInEvent> { - let cmd = task::Command::NotifyHandler(event); - self.sender.try_send(cmd).map_err(|e| match e.into_inner() { - task::Command::NotifyHandler(event) => event, - _ => unreachable!("Expect failed send to return initial event."), - }) - } - - /// Checks if `notify_handler` is ready to accept an event. - /// - /// Returns `Ok(())` if the handler is ready to receive an event via `notify_handler`. - /// - /// Returns `Err(())` if the background task associated with the connection - /// is terminating and the connection is about to close. - pub(crate) fn poll_ready_notify_handler( - &mut self, - cx: &mut Context<'_>, - ) -> Poll> { - self.sender.poll_ready(cx).map_err(|_| ()) - } - - /// Initiates a graceful close of the connection. - /// - /// Has no effect if the connection is already closing. - pub(crate) fn start_close(&mut self) { - // Clone the sender so that we are guaranteed to have - // capacity for the close command (every sender gets a slot). - match self.sender.clone().try_send(task::Command::Close) { - Ok(()) => {} - Err(e) => assert!(e.is_disconnected(), "No capacity for close command."), - }; - } -} - -struct PendingConnection { - /// [`PeerId`] of the remote peer. - peer_id: Option, - endpoint: PendingPoint, - /// When dropped, notifies the task which then knows to terminate. - abort_notifier: Option>, - /// The moment we became aware of this possible connection, useful for timing metrics. - accepted_at: Instant, -} - -impl PendingConnection { - fn is_for_same_remote_as(&self, other: PeerId) -> bool { - self.peer_id.map_or(false, |peer| peer == other) - } - - /// Aborts the connection attempt, closing the connection. - fn abort(&mut self) { - if let Some(notifier) = self.abort_notifier.take() { - drop(notifier); - } - } -} - -impl fmt::Debug for Pool { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.debug_struct("Pool") - .field("counters", &self.counters) - .finish() - } -} - -/// Event that can happen on the `Pool`. -#[derive(Debug)] -pub(crate) enum PoolEvent { - /// A new connection has been established. - ConnectionEstablished { - id: ConnectionId, - peer_id: PeerId, - endpoint: ConnectedPoint, - connection: NewConnection, - /// [`Some`] when the new connection is an outgoing connection. - /// Addresses are dialed in parallel. Contains the addresses and errors - /// of dial attempts that failed before the one successful dial. - concurrent_dial_errors: Option)>>, - /// How long it took to establish this connection. - established_in: std::time::Duration, - }, - - /// An established connection was closed. - /// - /// A connection may close if - /// - /// * it encounters an error, which includes the connection being - /// closed by the remote. In this case `error` is `Some`. - /// * it was actively closed by [`EstablishedConnection::start_close`], - /// i.e. a successful, orderly close. - /// * it was actively closed by [`Pool::disconnect`], i.e. - /// dropped without an orderly close. - /// - ConnectionClosed { - id: ConnectionId, - /// Information about the connection that errored. - connected: Connected, - /// The error that occurred, if any. If `None`, the connection - /// was closed by the local peer. - error: Option, - /// The remaining established connections to the same peer. - remaining_established_connection_ids: Vec, - }, - - /// An outbound connection attempt failed. - PendingOutboundConnectionError { - /// The ID of the failed connection. - id: ConnectionId, - /// The error that occurred. - error: PendingOutboundConnectionError, - /// The (expected) peer of the failed connection. - peer: Option, - }, - - /// An inbound connection attempt failed. - PendingInboundConnectionError { - /// The ID of the failed connection. - id: ConnectionId, - /// Address used to send back data to the remote. - send_back_addr: Multiaddr, - /// Local connection address. - local_addr: Multiaddr, - /// The error that occurred. - error: PendingInboundConnectionError, - }, - - /// A node has produced an event. - ConnectionEvent { - id: ConnectionId, - peer_id: PeerId, - /// The produced event. - event: ToBehaviour, - }, - - /// The connection to a node has changed its address. - AddressChange { - id: ConnectionId, - peer_id: PeerId, - /// The new endpoint. - new_endpoint: ConnectedPoint, - /// The old endpoint. - old_endpoint: ConnectedPoint, - }, -} - -impl Pool -where - THandler: ConnectionHandler, -{ - /// Creates a new empty `Pool`. - pub(crate) fn new(local_id: PeerId, config: PoolConfig) -> Self { - let (pending_connection_events_tx, pending_connection_events_rx) = mpsc::channel(0); - let executor = match config.executor { - Some(exec) => ExecSwitch::Executor(exec), - None => ExecSwitch::LocalSpawn(Default::default()), - }; - Pool { - local_id, - counters: ConnectionCounters::new(), - established: Default::default(), - pending: Default::default(), - task_command_buffer_size: config.task_command_buffer_size, - dial_concurrency_factor: config.dial_concurrency_factor, - substream_upgrade_protocol_override: config.substream_upgrade_protocol_override, - max_negotiating_inbound_streams: config.max_negotiating_inbound_streams, - per_connection_event_buffer_size: config.per_connection_event_buffer_size, - idle_connection_timeout: config.idle_connection_timeout, - executor, - pending_connection_events_tx, - pending_connection_events_rx, - no_established_connections_waker: None, - established_connection_events: Default::default(), - new_connection_dropped_listeners: Default::default(), - } - } - - /// Gets the dedicated connection counters. - pub(crate) fn counters(&self) -> &ConnectionCounters { - &self.counters - } - - /// Gets an established connection from the pool by ID. - pub(crate) fn get_established( - &mut self, - id: ConnectionId, - ) -> Option<&mut EstablishedConnection> { - self.established - .values_mut() - .find_map(|connections| connections.get_mut(&id)) - } - - /// Returns true if we are connected to the given peer. - /// - /// This will return true only after a `NodeReached` event has been produced by `poll()`. - pub(crate) fn is_connected(&self, id: PeerId) -> bool { - self.established.contains_key(&id) - } - - /// Returns the number of connected peers, i.e. those with at least one - /// established connection in the pool. - pub(crate) fn num_peers(&self) -> usize { - self.established.len() - } - - /// (Forcefully) close all connections to the given peer. - /// - /// All connections to the peer, whether pending or established are - /// closed asap and no more events from these connections are emitted - /// by the pool effective immediately. - pub(crate) fn disconnect(&mut self, peer: PeerId) { - if let Some(conns) = self.established.get_mut(&peer) { - for (_, conn) in conns.iter_mut() { - conn.start_close(); - } - } - - for connection in self - .pending - .iter_mut() - .filter_map(|(_, info)| info.is_for_same_remote_as(peer).then_some(info)) - { - connection.abort() - } - } - - /// Returns an iterator over all established connections of `peer`. - pub(crate) fn iter_established_connections_of_peer( - &mut self, - peer: &PeerId, - ) -> impl Iterator + '_ { - match self.established.get(peer) { - Some(conns) => either::Either::Left(conns.iter().map(|(id, _)| *id)), - None => either::Either::Right(std::iter::empty()), - } - } - - /// Checks whether we are currently dialing the given peer. - pub(crate) fn is_dialing(&self, peer: PeerId) -> bool { - self.pending.iter().any(|(_, info)| { - matches!(info.endpoint, PendingPoint::Dialer { .. }) && info.is_for_same_remote_as(peer) - }) - } - - /// Returns an iterator over all connected peers, i.e. those that have - /// at least one established connection in the pool. - pub(crate) fn iter_connected(&self) -> impl Iterator { - self.established.keys() - } - - /// Adds a pending outgoing connection to the pool in the form of a `Future` - /// that establishes and negotiates the connection. - pub(crate) fn add_outgoing( - &mut self, - dials: Vec< - BoxFuture< - 'static, - ( - Multiaddr, - Result<(PeerId, StreamMuxerBox), TransportError>, - ), - >, - >, - peer: Option, - role_override: Endpoint, - port_use: PortUse, - dial_concurrency_factor_override: Option, - connection_id: ConnectionId, - ) { - let concurrency_factor = - dial_concurrency_factor_override.unwrap_or(self.dial_concurrency_factor); - let span = tracing::debug_span!(parent: tracing::Span::none(), "new_outgoing_connection", %concurrency_factor, num_dials=%dials.len(), id = %connection_id); - span.follows_from(tracing::Span::current()); - - let (abort_notifier, abort_receiver) = oneshot::channel(); - - self.executor.spawn( - task::new_for_pending_outgoing_connection( - connection_id, - ConcurrentDial::new(dials, concurrency_factor), - abort_receiver, - self.pending_connection_events_tx.clone(), - ) - .instrument(span), - ); - - let endpoint = PendingPoint::Dialer { - role_override, - port_use, - }; - - self.counters.inc_pending(&endpoint); - self.pending.insert( - connection_id, - PendingConnection { - peer_id: peer, - endpoint, - abort_notifier: Some(abort_notifier), - accepted_at: Instant::now(), - }, - ); - } - - /// Adds a pending incoming connection to the pool in the form of a - /// `Future` that establishes and negotiates the connection. - pub(crate) fn add_incoming( - &mut self, - future: TFut, - info: IncomingInfo<'_>, - connection_id: ConnectionId, - ) where - TFut: Future> + Send + 'static, - { - let endpoint = info.create_connected_point(); - - let (abort_notifier, abort_receiver) = oneshot::channel(); - - let span = tracing::debug_span!(parent: tracing::Span::none(), "new_incoming_connection", remote_addr = %info.send_back_addr, id = %connection_id); - span.follows_from(tracing::Span::current()); - - self.executor.spawn( - task::new_for_pending_incoming_connection( - connection_id, - future, - abort_receiver, - self.pending_connection_events_tx.clone(), - ) - .instrument(span), - ); - - self.counters.inc_pending_incoming(); - self.pending.insert( - connection_id, - PendingConnection { - peer_id: None, - endpoint: endpoint.into(), - abort_notifier: Some(abort_notifier), - accepted_at: Instant::now(), - }, - ); - } - - pub(crate) fn spawn_connection( - &mut self, - id: ConnectionId, - obtained_peer_id: PeerId, - endpoint: &ConnectedPoint, - connection: NewConnection, - handler: THandler, - ) { - let connection = connection.extract(); - let conns = self.established.entry(obtained_peer_id).or_default(); - self.counters.inc_established(endpoint); - - let (command_sender, command_receiver) = mpsc::channel(self.task_command_buffer_size); - let (event_sender, event_receiver) = mpsc::channel(self.per_connection_event_buffer_size); - - conns.insert( - id, - EstablishedConnection { - endpoint: endpoint.clone(), - sender: command_sender, - }, - ); - self.established_connection_events.push(event_receiver); - if let Some(waker) = self.no_established_connections_waker.take() { - waker.wake(); - } - - let connection = Connection::new( - connection, - handler, - self.substream_upgrade_protocol_override, - self.max_negotiating_inbound_streams, - self.idle_connection_timeout, - ); - - let span = tracing::debug_span!(parent: tracing::Span::none(), "new_established_connection", remote_addr = %endpoint.get_remote_address(), %id, peer = %obtained_peer_id); - span.follows_from(tracing::Span::current()); - - self.executor.spawn( - task::new_for_established_connection( - id, - obtained_peer_id, - connection, - command_receiver, - event_sender, - ) - .instrument(span), - ) - } - - /// Polls the connection pool for events. - #[tracing::instrument(level = "debug", name = "Pool::poll", skip(self, cx))] - pub(crate) fn poll(&mut self, cx: &mut Context<'_>) -> Poll> - where - THandler: ConnectionHandler + 'static, - ::OutboundOpenInfo: Send, - { - // Poll for events of established connections. - // - // Note that established connections are polled before pending connections, thus - // prioritizing established connections over pending connections. - match self.established_connection_events.poll_next_unpin(cx) { - Poll::Pending => {} - Poll::Ready(None) => { - self.no_established_connections_waker = Some(cx.waker().clone()); - } - - Poll::Ready(Some(task::EstablishedConnectionEvent::Notify { id, peer_id, event })) => { - return Poll::Ready(PoolEvent::ConnectionEvent { peer_id, id, event }); - } - Poll::Ready(Some(task::EstablishedConnectionEvent::AddressChange { - id, - peer_id, - new_address, - })) => { - let connection = self - .established - .get_mut(&peer_id) - .expect("Receive `AddressChange` event for established peer.") - .get_mut(&id) - .expect("Receive `AddressChange` event from established connection"); - let mut new_endpoint = connection.endpoint.clone(); - new_endpoint.set_remote_address(new_address); - let old_endpoint = - std::mem::replace(&mut connection.endpoint, new_endpoint.clone()); - - return Poll::Ready(PoolEvent::AddressChange { - peer_id, - id, - new_endpoint, - old_endpoint, - }); - } - Poll::Ready(Some(task::EstablishedConnectionEvent::Closed { id, peer_id, error })) => { - let connections = self - .established - .get_mut(&peer_id) - .expect("`Closed` event for established connection"); - let EstablishedConnection { endpoint, .. } = - connections.remove(&id).expect("Connection to be present"); - self.counters.dec_established(&endpoint); - let remaining_established_connection_ids: Vec = - connections.keys().cloned().collect(); - if remaining_established_connection_ids.is_empty() { - self.established.remove(&peer_id); - } - return Poll::Ready(PoolEvent::ConnectionClosed { - id, - connected: Connected { endpoint, peer_id }, - error, - remaining_established_connection_ids, - }); - } - } - - // Poll for events of pending connections. - loop { - if let Poll::Ready(Some(result)) = - self.new_connection_dropped_listeners.poll_next_unpin(cx) - { - if let Ok(dropped_connection) = result { - self.executor.spawn(async move { - let _ = dropped_connection.close().await; - }); - } - continue; - } - - let event = match self.pending_connection_events_rx.poll_next_unpin(cx) { - Poll::Ready(Some(event)) => event, - Poll::Pending => break, - Poll::Ready(None) => unreachable!("Pool holds both sender and receiver."), - }; - - match event { - task::PendingConnectionEvent::ConnectionEstablished { - id, - output: (obtained_peer_id, mut muxer), - outgoing, - } => { - let PendingConnection { - peer_id: expected_peer_id, - endpoint, - abort_notifier: _, - accepted_at, - } = self - .pending - .remove(&id) - .expect("Entry in `self.pending` for previously pending connection."); - - self.counters.dec_pending(&endpoint); - - let (endpoint, concurrent_dial_errors) = match (endpoint, outgoing) { - ( - PendingPoint::Dialer { - role_override, - port_use, - }, - Some((address, errors)), - ) => ( - ConnectedPoint::Dialer { - address, - role_override, - port_use, - }, - Some(errors), - ), - ( - PendingPoint::Listener { - local_addr, - send_back_addr, - }, - None, - ) => ( - ConnectedPoint::Listener { - local_addr, - send_back_addr, - }, - None, - ), - (PendingPoint::Dialer { .. }, None) => unreachable!( - "Established incoming connection via pending outgoing connection." - ), - (PendingPoint::Listener { .. }, Some(_)) => unreachable!( - "Established outgoing connection via pending incoming connection." - ), - }; - - let check_peer_id = || { - if let Some(peer) = expected_peer_id { - if peer != obtained_peer_id { - return Err(PendingConnectionError::WrongPeerId { - obtained: obtained_peer_id, - endpoint: endpoint.clone(), - }); - } - } - - if self.local_id == obtained_peer_id { - return Err(PendingConnectionError::LocalPeerId { - endpoint: endpoint.clone(), - }); - } - - Ok(()) - }; - - if let Err(error) = check_peer_id() { - self.executor.spawn(poll_fn(move |cx| { - if let Err(e) = ready!(muxer.poll_close_unpin(cx)) { - tracing::debug!( - peer=%obtained_peer_id, - connection=%id, - "Failed to close connection to peer: {:?}", - e - ); - } - Poll::Ready(()) - })); - - match endpoint { - ConnectedPoint::Dialer { .. } => { - return Poll::Ready(PoolEvent::PendingOutboundConnectionError { - id, - error: error - .map(|t| vec![(endpoint.get_remote_address().clone(), t)]), - peer: expected_peer_id.or(Some(obtained_peer_id)), - }) - } - ConnectedPoint::Listener { - send_back_addr, - local_addr, - } => { - return Poll::Ready(PoolEvent::PendingInboundConnectionError { - id, - error, - send_back_addr, - local_addr, - }) - } - }; - } - - let established_in = accepted_at.elapsed(); - - let (connection, drop_listener) = NewConnection::new(muxer); - self.new_connection_dropped_listeners.push(drop_listener); - - return Poll::Ready(PoolEvent::ConnectionEstablished { - peer_id: obtained_peer_id, - endpoint, - id, - connection, - concurrent_dial_errors, - established_in, - }); - } - task::PendingConnectionEvent::PendingFailed { id, error } => { - if let Some(PendingConnection { - peer_id, - endpoint, - abort_notifier: _, - accepted_at: _, // Ignoring the time it took for the connection to fail. - }) = self.pending.remove(&id) - { - self.counters.dec_pending(&endpoint); - - match (endpoint, error) { - (PendingPoint::Dialer { .. }, Either::Left(error)) => { - return Poll::Ready(PoolEvent::PendingOutboundConnectionError { - id, - error, - peer: peer_id, - }); - } - ( - PendingPoint::Listener { - send_back_addr, - local_addr, - }, - Either::Right(error), - ) => { - return Poll::Ready(PoolEvent::PendingInboundConnectionError { - id, - error, - send_back_addr, - local_addr, - }); - } - (PendingPoint::Dialer { .. }, Either::Right(_)) => { - unreachable!("Inbound error for outbound connection.") - } - (PendingPoint::Listener { .. }, Either::Left(_)) => { - unreachable!("Outbound error for inbound connection.") - } - } - } - } - } - } - - self.executor.advance_local(cx); - - Poll::Pending - } -} - -/// Opaque type for a new connection. -/// -/// This connection has just been established but isn't part of the [`Pool`] yet. -/// It either needs to be spawned via [`Pool::spawn_connection`] or dropped if undesired. -/// -/// On drop, this type send the connection back to the [`Pool`] where it will be gracefully closed. -#[derive(Debug)] -pub(crate) struct NewConnection { - connection: Option, - drop_sender: Option>, -} - -impl NewConnection { - fn new(conn: StreamMuxerBox) -> (Self, oneshot::Receiver) { - let (sender, receiver) = oneshot::channel(); - - ( - Self { - connection: Some(conn), - drop_sender: Some(sender), - }, - receiver, - ) - } - - fn extract(mut self) -> StreamMuxerBox { - self.connection.take().unwrap() - } -} - -impl Drop for NewConnection { - fn drop(&mut self) { - if let Some(connection) = self.connection.take() { - let _ = self - .drop_sender - .take() - .expect("`drop_sender` to always be `Some`") - .send(connection); - } - } -} - -/// Network connection information. -#[derive(Debug, Clone)] -pub struct ConnectionCounters { - /// The current number of incoming connections. - pending_incoming: u32, - /// The current number of outgoing connections. - pending_outgoing: u32, - /// The current number of established inbound connections. - established_incoming: u32, - /// The current number of established outbound connections. - established_outgoing: u32, -} - -impl ConnectionCounters { - fn new() -> Self { - Self { - pending_incoming: 0, - pending_outgoing: 0, - established_incoming: 0, - established_outgoing: 0, - } - } - - /// The total number of connections, both pending and established. - pub fn num_connections(&self) -> u32 { - self.num_pending() + self.num_established() - } - - /// The total number of pending connections, both incoming and outgoing. - pub fn num_pending(&self) -> u32 { - self.pending_incoming + self.pending_outgoing - } - - /// The number of incoming connections being established. - pub fn num_pending_incoming(&self) -> u32 { - self.pending_incoming - } - - /// The number of outgoing connections being established. - pub fn num_pending_outgoing(&self) -> u32 { - self.pending_outgoing - } - - /// The number of established incoming connections. - pub fn num_established_incoming(&self) -> u32 { - self.established_incoming - } - - /// The number of established outgoing connections. - pub fn num_established_outgoing(&self) -> u32 { - self.established_outgoing - } - - /// The total number of established connections. - pub fn num_established(&self) -> u32 { - self.established_outgoing + self.established_incoming - } - - fn inc_pending(&mut self, endpoint: &PendingPoint) { - match endpoint { - PendingPoint::Dialer { .. } => { - self.pending_outgoing += 1; - } - PendingPoint::Listener { .. } => { - self.pending_incoming += 1; - } - } - } - - fn inc_pending_incoming(&mut self) { - self.pending_incoming += 1; - } - - fn dec_pending(&mut self, endpoint: &PendingPoint) { - match endpoint { - PendingPoint::Dialer { .. } => { - self.pending_outgoing -= 1; - } - PendingPoint::Listener { .. } => { - self.pending_incoming -= 1; - } - } - } - - fn inc_established(&mut self, endpoint: &ConnectedPoint) { - match endpoint { - ConnectedPoint::Dialer { .. } => { - self.established_outgoing += 1; - } - ConnectedPoint::Listener { .. } => { - self.established_incoming += 1; - } - } - } - - fn dec_established(&mut self, endpoint: &ConnectedPoint) { - match endpoint { - ConnectedPoint::Dialer { .. } => { - self.established_outgoing -= 1; - } - ConnectedPoint::Listener { .. } => { - self.established_incoming -= 1; - } - } - } -} - -/// Configuration options when creating a [`Pool`]. -/// -/// The default configuration specifies no dedicated task executor, a -/// task event buffer size of 32, and a task command buffer size of 7. -pub(crate) struct PoolConfig { - /// Executor to use to spawn tasks. - pub(crate) executor: Option>, - /// Size of the task command buffer (per task). - pub(crate) task_command_buffer_size: usize, - /// Size of the pending connection task event buffer and the established connection task event - /// buffer. - pub(crate) per_connection_event_buffer_size: usize, - /// Number of addresses concurrently dialed for a single outbound connection attempt. - pub(crate) dial_concurrency_factor: NonZeroU8, - /// How long a connection should be kept alive once it is idling. - pub(crate) idle_connection_timeout: Duration, - /// The configured override for substream protocol upgrades, if any. - substream_upgrade_protocol_override: Option, - - /// The maximum number of inbound streams concurrently negotiating on a connection. - /// - /// See [`Connection::max_negotiating_inbound_streams`]. - max_negotiating_inbound_streams: usize, -} - -impl PoolConfig { - pub(crate) fn new(executor: Option>) -> Self { - Self { - executor, - task_command_buffer_size: 32, - per_connection_event_buffer_size: 7, - dial_concurrency_factor: NonZeroU8::new(8).expect("8 > 0"), - idle_connection_timeout: Duration::ZERO, - substream_upgrade_protocol_override: None, - max_negotiating_inbound_streams: 128, - } - } - - /// Sets the maximum number of events sent to a connection's background task - /// that may be buffered, if the task cannot keep up with their consumption and - /// delivery to the connection handler. - /// - /// When the buffer for a particular connection is full, `notify_handler` will no - /// longer be able to deliver events to the associated [`Connection`], - /// thus exerting back-pressure on the connection and peer API. - pub(crate) fn with_notify_handler_buffer_size(mut self, n: NonZeroUsize) -> Self { - self.task_command_buffer_size = n.get() - 1; - self - } - - /// Sets the maximum number of buffered connection events (beyond a guaranteed - /// buffer of 1 event per connection). - /// - /// When the buffer is full, the background tasks of all connections will stall. - /// In this way, the consumers of network events exert back-pressure on - /// the network connection I/O. - pub(crate) fn with_per_connection_event_buffer_size(mut self, n: usize) -> Self { - self.per_connection_event_buffer_size = n; - self - } - - /// Number of addresses concurrently dialed for a single outbound connection attempt. - pub(crate) fn with_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self { - self.dial_concurrency_factor = factor; - self - } - - /// Configures an override for the substream upgrade protocol to use. - pub(crate) fn with_substream_upgrade_protocol_override( - mut self, - v: libp2p_core::upgrade::Version, - ) -> Self { - self.substream_upgrade_protocol_override = Some(v); - self - } - - /// The maximum number of inbound streams concurrently negotiating on a connection. - /// - /// See [`Connection::max_negotiating_inbound_streams`]. - pub(crate) fn with_max_negotiating_inbound_streams(mut self, v: usize) -> Self { - self.max_negotiating_inbound_streams = v; - self - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/pool/concurrent_dial.rs b/third-party/libp2p-swarm-0.45.1/src/connection/pool/concurrent_dial.rs deleted file mode 100644 index 57e4b078098..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/connection/pool/concurrent_dial.rs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2021 Protocol Labs. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::{transport::TransportError, Multiaddr}; -use futures::{ - future::{BoxFuture, Future}, - ready, - stream::{FuturesUnordered, StreamExt}, -}; -use libp2p_core::muxing::StreamMuxerBox; -use libp2p_identity::PeerId; -use std::{ - num::NonZeroU8, - pin::Pin, - task::{Context, Poll}, -}; - -type Dial = BoxFuture< - 'static, - ( - Multiaddr, - Result<(PeerId, StreamMuxerBox), TransportError>, - ), ->; - -pub(crate) struct ConcurrentDial { - dials: FuturesUnordered, - pending_dials: Box + Send>, - errors: Vec<(Multiaddr, TransportError)>, -} - -impl Unpin for ConcurrentDial {} - -impl ConcurrentDial { - pub(crate) fn new(pending_dials: Vec, concurrency_factor: NonZeroU8) -> Self { - let mut pending_dials = pending_dials.into_iter(); - - let dials = FuturesUnordered::new(); - for dial in pending_dials.by_ref() { - dials.push(dial); - if dials.len() == concurrency_factor.get() as usize { - break; - } - } - - Self { - dials, - errors: Default::default(), - pending_dials: Box::new(pending_dials), - } - } -} - -impl Future for ConcurrentDial { - type Output = Result< - // Either one dial succeeded, returning the negotiated [`PeerId`], the address, the - // muxer and the addresses and errors of the dials that failed before. - ( - Multiaddr, - (PeerId, StreamMuxerBox), - Vec<(Multiaddr, TransportError)>, - ), - // Or all dials failed, thus returning the address and error for each dial. - Vec<(Multiaddr, TransportError)>, - >; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - loop { - match ready!(self.dials.poll_next_unpin(cx)) { - Some((addr, Ok(output))) => { - let errors = std::mem::take(&mut self.errors); - return Poll::Ready(Ok((addr, output, errors))); - } - Some((addr, Err(e))) => { - self.errors.push((addr, e)); - if let Some(dial) = self.pending_dials.next() { - self.dials.push(dial) - } - } - None => { - return Poll::Ready(Err(std::mem::take(&mut self.errors))); - } - } - } - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/pool/task.rs b/third-party/libp2p-swarm-0.45.1/src/connection/pool/task.rs deleted file mode 100644 index 08674fd2ee5..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/connection/pool/task.rs +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2021 Protocol Labs. -// Copyright 2018 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -//! Async functions driving pending and established connections in the form of a task. - -use super::concurrent_dial::ConcurrentDial; -use crate::{ - connection::{ - self, ConnectionError, ConnectionId, PendingInboundConnectionError, - PendingOutboundConnectionError, - }, - transport::TransportError, - ConnectionHandler, Multiaddr, PeerId, -}; -use futures::{ - channel::{mpsc, oneshot}, - future::{poll_fn, Either, Future}, - SinkExt, StreamExt, -}; -use libp2p_core::muxing::StreamMuxerBox; -use std::pin::Pin; -use void::Void; - -/// Commands that can be sent to a task driving an established connection. -#[derive(Debug)] -pub(crate) enum Command { - /// Notify the connection handler of an event. - NotifyHandler(T), - /// Gracefully close the connection (active close) before - /// terminating the task. - Close, -} - -pub(crate) enum PendingConnectionEvent { - ConnectionEstablished { - id: ConnectionId, - output: (PeerId, StreamMuxerBox), - /// [`Some`] when the new connection is an outgoing connection. - /// Addresses are dialed in parallel. Contains the addresses and errors - /// of dial attempts that failed before the one successful dial. - outgoing: Option<(Multiaddr, Vec<(Multiaddr, TransportError)>)>, - }, - /// A pending connection failed. - PendingFailed { - id: ConnectionId, - error: Either, - }, -} - -#[derive(Debug)] -pub(crate) enum EstablishedConnectionEvent { - /// A node we are connected to has changed its address. - AddressChange { - id: ConnectionId, - peer_id: PeerId, - new_address: Multiaddr, - }, - /// Notify the manager of an event from the connection. - Notify { - id: ConnectionId, - peer_id: PeerId, - event: ToBehaviour, - }, - /// A connection closed, possibly due to an error. - /// - /// If `error` is `None`, the connection has completed - /// an active orderly close. - Closed { - id: ConnectionId, - peer_id: PeerId, - error: Option, - }, -} - -pub(crate) async fn new_for_pending_outgoing_connection( - connection_id: ConnectionId, - dial: ConcurrentDial, - abort_receiver: oneshot::Receiver, - mut events: mpsc::Sender, -) { - match futures::future::select(abort_receiver, Box::pin(dial)).await { - Either::Left((Err(oneshot::Canceled), _)) => { - let _ = events - .send(PendingConnectionEvent::PendingFailed { - id: connection_id, - error: Either::Left(PendingOutboundConnectionError::Aborted), - }) - .await; - } - Either::Left((Ok(v), _)) => void::unreachable(v), - Either::Right((Ok((address, output, errors)), _)) => { - let _ = events - .send(PendingConnectionEvent::ConnectionEstablished { - id: connection_id, - output, - outgoing: Some((address, errors)), - }) - .await; - } - Either::Right((Err(e), _)) => { - let _ = events - .send(PendingConnectionEvent::PendingFailed { - id: connection_id, - error: Either::Left(PendingOutboundConnectionError::Transport(e)), - }) - .await; - } - } -} - -pub(crate) async fn new_for_pending_incoming_connection( - connection_id: ConnectionId, - future: TFut, - abort_receiver: oneshot::Receiver, - mut events: mpsc::Sender, -) where - TFut: Future> + Send + 'static, -{ - match futures::future::select(abort_receiver, Box::pin(future)).await { - Either::Left((Err(oneshot::Canceled), _)) => { - let _ = events - .send(PendingConnectionEvent::PendingFailed { - id: connection_id, - error: Either::Right(PendingInboundConnectionError::Aborted), - }) - .await; - } - Either::Left((Ok(v), _)) => void::unreachable(v), - Either::Right((Ok(output), _)) => { - let _ = events - .send(PendingConnectionEvent::ConnectionEstablished { - id: connection_id, - output, - outgoing: None, - }) - .await; - } - Either::Right((Err(e), _)) => { - let _ = events - .send(PendingConnectionEvent::PendingFailed { - id: connection_id, - error: Either::Right(PendingInboundConnectionError::Transport( - TransportError::Other(e), - )), - }) - .await; - } - } -} - -pub(crate) async fn new_for_established_connection( - connection_id: ConnectionId, - peer_id: PeerId, - mut connection: crate::connection::Connection, - mut command_receiver: mpsc::Receiver>, - mut events: mpsc::Sender>, -) where - THandler: ConnectionHandler, -{ - loop { - match futures::future::select( - command_receiver.next(), - poll_fn(|cx| Pin::new(&mut connection).poll(cx)), - ) - .await - { - Either::Left((Some(command), _)) => match command { - Command::NotifyHandler(event) => connection.on_behaviour_event(event), - Command::Close => { - command_receiver.close(); - let (remaining_events, closing_muxer) = connection.close(); - - let _ = events - .send_all(&mut remaining_events.map(|event| { - Ok(EstablishedConnectionEvent::Notify { - id: connection_id, - event, - peer_id, - }) - })) - .await; - - let error = closing_muxer.await.err().map(ConnectionError::IO); - - let _ = events - .send(EstablishedConnectionEvent::Closed { - id: connection_id, - peer_id, - error, - }) - .await; - return; - } - }, - - // The manager has disappeared; abort. - Either::Left((None, _)) => return, - - Either::Right((event, _)) => { - match event { - Ok(connection::Event::Handler(event)) => { - let _ = events - .send(EstablishedConnectionEvent::Notify { - id: connection_id, - peer_id, - event, - }) - .await; - } - Ok(connection::Event::AddressChange(new_address)) => { - let _ = events - .send(EstablishedConnectionEvent::AddressChange { - id: connection_id, - peer_id, - new_address, - }) - .await; - } - Err(error) => { - command_receiver.close(); - let (remaining_events, _closing_muxer) = connection.close(); - - let _ = events - .send_all(&mut remaining_events.map(|event| { - Ok(EstablishedConnectionEvent::Notify { - id: connection_id, - event, - peer_id, - }) - })) - .await; - - // Terminate the task with the error, dropping the connection. - let _ = events - .send(EstablishedConnectionEvent::Closed { - id: connection_id, - peer_id, - error: Some(error), - }) - .await; - return; - } - } - } - } - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/connection/supported_protocols.rs b/third-party/libp2p-swarm-0.45.1/src/connection/supported_protocols.rs deleted file mode 100644 index 124ec93d669..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/connection/supported_protocols.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::handler::ProtocolsChange; -use crate::StreamProtocol; -use std::collections::HashSet; - -#[derive(Default, Clone, Debug)] -pub struct SupportedProtocols { - protocols: HashSet, -} - -impl SupportedProtocols { - pub fn on_protocols_change(&mut self, change: ProtocolsChange) -> bool { - match change { - ProtocolsChange::Added(added) => { - let mut changed = false; - - for p in added { - changed |= self.protocols.insert(p.clone()); - } - - changed - } - ProtocolsChange::Removed(removed) => { - let mut changed = false; - - for p in removed { - changed |= self.protocols.remove(p); - } - - changed - } - } - } - - pub fn iter(&self) -> impl Iterator { - self.protocols.iter() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::handler::{ProtocolsAdded, ProtocolsRemoved}; - - #[test] - fn protocols_change_added_returns_correct_changed_value() { - let mut protocols = SupportedProtocols::default(); - - let changed = protocols.on_protocols_change(add_foo()); - assert!(changed); - - let changed = protocols.on_protocols_change(add_foo()); - assert!(!changed); - - let changed = protocols.on_protocols_change(add_foo_bar()); - assert!(changed); - } - - #[test] - fn protocols_change_removed_returns_correct_changed_value() { - let mut protocols = SupportedProtocols::default(); - - let changed = protocols.on_protocols_change(remove_foo()); - assert!(!changed); - - protocols.on_protocols_change(add_foo()); - - let changed = protocols.on_protocols_change(remove_foo()); - assert!(changed); - } - - fn add_foo() -> ProtocolsChange<'static> { - ProtocolsChange::Added(ProtocolsAdded { - protocols: FOO_PROTOCOLS.iter(), - }) - } - - fn add_foo_bar() -> ProtocolsChange<'static> { - ProtocolsChange::Added(ProtocolsAdded { - protocols: FOO_BAR_PROTOCOLS.iter(), - }) - } - - fn remove_foo() -> ProtocolsChange<'static> { - ProtocolsChange::Removed(ProtocolsRemoved { - protocols: FOO_PROTOCOLS.iter(), - }) - } - - static FOO_PROTOCOLS: &[StreamProtocol] = &[StreamProtocol::new("/foo")]; - static FOO_BAR_PROTOCOLS: &[StreamProtocol] = - &[StreamProtocol::new("/foo"), StreamProtocol::new("/bar")]; -} diff --git a/third-party/libp2p-swarm-0.45.1/src/dial_opts.rs b/third-party/libp2p-swarm-0.45.1/src/dial_opts.rs deleted file mode 100644 index 4f5b621327c..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/dial_opts.rs +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// Copyright 2021 Protocol Labs. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::ConnectionId; -use libp2p_core::connection::Endpoint; -use libp2p_core::multiaddr::Protocol; -use libp2p_core::transport::PortUse; -use libp2p_core::Multiaddr; -use libp2p_identity::PeerId; -use std::num::NonZeroU8; - -macro_rules! fn_override_role { - () => { - /// Override role of local node on connection. I.e. execute the dial _as a - /// listener_. - /// - /// See - /// [`ConnectedPoint::Dialer`](libp2p_core::connection::ConnectedPoint::Dialer) - /// for details. - pub fn override_role(mut self) -> Self { - self.role_override = Endpoint::Listener; - self - } - }; -} - -macro_rules! fn_allocate_new_port { - () => { - /// Enforce the allocation of a new port. - /// Default behaviour is best effort reuse of existing ports. If there is no existing - /// fitting listener, a new port is allocated. - pub fn allocate_new_port(mut self) -> Self { - self.port_use = PortUse::New; - self - } - }; -} - -/// Options to configure a dial to a known or unknown peer. -/// -/// Used in [`Swarm::dial`](crate::Swarm::dial) and -/// [`ToSwarm::Dial`](crate::behaviour::ToSwarm::Dial). -/// -/// To construct use either of: -/// -/// - [`DialOpts::peer_id`] dialing a known peer -/// -/// - [`DialOpts::unknown_peer_id`] dialing an unknown peer -#[derive(Debug)] -pub struct DialOpts { - peer_id: Option, - condition: PeerCondition, - addresses: Vec, - extend_addresses_through_behaviour: bool, - role_override: Endpoint, - dial_concurrency_factor_override: Option, - connection_id: ConnectionId, - port_use: PortUse, -} - -impl DialOpts { - /// Dial a known peer. - /// - /// ``` - /// # use libp2p_swarm::dial_opts::{DialOpts, PeerCondition}; - /// # use libp2p_identity::PeerId; - /// DialOpts::peer_id(PeerId::random()) - /// .condition(PeerCondition::Disconnected) - /// .addresses(vec!["/ip6/::1/tcp/12345".parse().unwrap()]) - /// .extend_addresses_through_behaviour() - /// .build(); - /// ``` - pub fn peer_id(peer_id: PeerId) -> WithPeerId { - WithPeerId { - peer_id, - condition: Default::default(), - role_override: Endpoint::Dialer, - dial_concurrency_factor_override: Default::default(), - port_use: PortUse::Reuse, - } - } - - /// Dial an unknown peer. - /// - /// ``` - /// # use libp2p_swarm::dial_opts::DialOpts; - /// DialOpts::unknown_peer_id() - /// .address("/ip6/::1/tcp/12345".parse().unwrap()) - /// .build(); - /// ``` - pub fn unknown_peer_id() -> WithoutPeerId { - WithoutPeerId {} - } - - /// Retrieves the [`PeerId`] from the [`DialOpts`] if specified or otherwise tries to extract it - /// from the multihash in the `/p2p` part of the address, if present. - pub fn get_peer_id(&self) -> Option { - if let Some(peer_id) = self.peer_id { - return Some(peer_id); - } - - let first_address = self.addresses.first()?; - let last_protocol = first_address.iter().last()?; - - if let Protocol::P2p(p) = last_protocol { - return Some(p); - } - - None - } - - /// Get the [`ConnectionId`] of this dial attempt. - /// - /// All future events of this dial will be associated with this ID. - /// See [`DialFailure`](crate::DialFailure) and [`ConnectionEstablished`](crate::behaviour::ConnectionEstablished). - pub fn connection_id(&self) -> ConnectionId { - self.connection_id - } - - pub(crate) fn get_addresses(&self) -> Vec { - self.addresses.clone() - } - - pub(crate) fn extend_addresses_through_behaviour(&self) -> bool { - self.extend_addresses_through_behaviour - } - - pub(crate) fn peer_condition(&self) -> PeerCondition { - self.condition - } - - pub(crate) fn dial_concurrency_override(&self) -> Option { - self.dial_concurrency_factor_override - } - - pub(crate) fn role_override(&self) -> Endpoint { - self.role_override - } - - pub(crate) fn port_use(&self) -> PortUse { - self.port_use - } -} - -impl From for DialOpts { - fn from(address: Multiaddr) -> Self { - DialOpts::unknown_peer_id().address(address).build() - } -} - -impl From for DialOpts { - fn from(peer_id: PeerId) -> Self { - DialOpts::peer_id(peer_id).build() - } -} - -#[derive(Debug)] -pub struct WithPeerId { - peer_id: PeerId, - condition: PeerCondition, - role_override: Endpoint, - dial_concurrency_factor_override: Option, - port_use: PortUse, -} - -impl WithPeerId { - /// Specify a [`PeerCondition`] for the dial. - pub fn condition(mut self, condition: PeerCondition) -> Self { - self.condition = condition; - self - } - - /// Override - /// Number of addresses concurrently dialed for a single outbound connection attempt. - pub fn override_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self { - self.dial_concurrency_factor_override = Some(factor); - self - } - - /// Specify a set of addresses to be used to dial the known peer. - pub fn addresses(self, addresses: Vec) -> WithPeerIdWithAddresses { - WithPeerIdWithAddresses { - peer_id: self.peer_id, - condition: self.condition, - addresses, - extend_addresses_through_behaviour: false, - role_override: self.role_override, - dial_concurrency_factor_override: self.dial_concurrency_factor_override, - port_use: self.port_use, - } - } - - fn_override_role!(); - fn_allocate_new_port!(); - - /// Build the final [`DialOpts`]. - pub fn build(self) -> DialOpts { - DialOpts { - peer_id: Some(self.peer_id), - condition: self.condition, - addresses: vec![], - extend_addresses_through_behaviour: true, - role_override: self.role_override, - dial_concurrency_factor_override: self.dial_concurrency_factor_override, - connection_id: ConnectionId::next(), - port_use: self.port_use, - } - } -} - -#[derive(Debug)] -pub struct WithPeerIdWithAddresses { - peer_id: PeerId, - condition: PeerCondition, - addresses: Vec, - extend_addresses_through_behaviour: bool, - role_override: Endpoint, - dial_concurrency_factor_override: Option, - port_use: PortUse, -} - -impl WithPeerIdWithAddresses { - /// Specify a [`PeerCondition`] for the dial. - pub fn condition(mut self, condition: PeerCondition) -> Self { - self.condition = condition; - self - } - - /// In addition to the provided addresses, extend the set via - /// [`NetworkBehaviour::handle_pending_outbound_connection`](crate::behaviour::NetworkBehaviour::handle_pending_outbound_connection). - pub fn extend_addresses_through_behaviour(mut self) -> Self { - self.extend_addresses_through_behaviour = true; - self - } - - fn_override_role!(); - fn_allocate_new_port!(); - - /// Override - /// Number of addresses concurrently dialed for a single outbound connection attempt. - pub fn override_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self { - self.dial_concurrency_factor_override = Some(factor); - self - } - - /// Build the final [`DialOpts`]. - pub fn build(self) -> DialOpts { - DialOpts { - peer_id: Some(self.peer_id), - condition: self.condition, - addresses: self.addresses, - extend_addresses_through_behaviour: self.extend_addresses_through_behaviour, - role_override: self.role_override, - dial_concurrency_factor_override: self.dial_concurrency_factor_override, - connection_id: ConnectionId::next(), - port_use: self.port_use, - } - } -} - -#[derive(Debug)] -pub struct WithoutPeerId {} - -impl WithoutPeerId { - /// Specify a single address to dial the unknown peer. - pub fn address(self, address: Multiaddr) -> WithoutPeerIdWithAddress { - WithoutPeerIdWithAddress { - address, - role_override: Endpoint::Dialer, - port_use: PortUse::Reuse, - } - } -} - -#[derive(Debug)] -pub struct WithoutPeerIdWithAddress { - address: Multiaddr, - role_override: Endpoint, - port_use: PortUse, -} - -impl WithoutPeerIdWithAddress { - fn_override_role!(); - fn_allocate_new_port!(); - - /// Build the final [`DialOpts`]. - pub fn build(self) -> DialOpts { - DialOpts { - peer_id: None, - condition: PeerCondition::Always, - addresses: vec![self.address], - extend_addresses_through_behaviour: false, - role_override: self.role_override, - dial_concurrency_factor_override: None, - connection_id: ConnectionId::next(), - port_use: self.port_use, - } - } -} - -/// The available conditions under which a new dialing attempt to -/// a known peer is initiated. -/// -/// ``` -/// # use libp2p_swarm::dial_opts::{DialOpts, PeerCondition}; -/// # use libp2p_identity::PeerId; -/// # -/// DialOpts::peer_id(PeerId::random()) -/// .condition(PeerCondition::Disconnected) -/// .build(); -/// ``` -#[derive(Debug, Copy, Clone, Default)] -pub enum PeerCondition { - /// A new dialing attempt is initiated _only if_ the peer is currently - /// considered disconnected, i.e. there is no established connection. - Disconnected, - /// A new dialing attempt is initiated _only if_ there is currently - /// no ongoing dialing attempt, i.e. the peer is either considered - /// disconnected or connected but without an ongoing dialing attempt. - NotDialing, - /// A combination of [`Disconnected`](PeerCondition::Disconnected) and - /// [`NotDialing`](PeerCondition::NotDialing). A new dialing attempt is - /// iniated _only if_ the peer is both considered disconnected and there - /// is currently no ongoing dialing attempt. - #[default] - DisconnectedAndNotDialing, - /// A new dialing attempt is always initiated, only subject to the - /// configured connection limits. - Always, -} diff --git a/third-party/libp2p-swarm-0.45.1/src/dummy.rs b/third-party/libp2p-swarm-0.45.1/src/dummy.rs deleted file mode 100644 index 6e1b4d56eb9..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/dummy.rs +++ /dev/null @@ -1,120 +0,0 @@ -use crate::behaviour::{FromSwarm, NetworkBehaviour, ToSwarm}; -use crate::connection::ConnectionId; -use crate::handler::{ - ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, -}; -use crate::{ - ConnectionDenied, ConnectionHandlerEvent, StreamUpgradeError, SubstreamProtocol, THandler, - THandlerInEvent, THandlerOutEvent, -}; -use libp2p_core::transport::PortUse; -use libp2p_core::upgrade::DeniedUpgrade; -use libp2p_core::Endpoint; -use libp2p_core::Multiaddr; -use libp2p_identity::PeerId; -use std::task::{Context, Poll}; -use void::Void; - -/// Implementation of [`NetworkBehaviour`] that doesn't do anything. -pub struct Behaviour; - -impl NetworkBehaviour for Behaviour { - type ConnectionHandler = ConnectionHandler; - type ToSwarm = Void; - - fn handle_established_inbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: &Multiaddr, - ) -> Result, ConnectionDenied> { - Ok(ConnectionHandler) - } - - fn handle_established_outbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: Endpoint, - _: PortUse, - ) -> Result, ConnectionDenied> { - Ok(ConnectionHandler) - } - - fn on_connection_handler_event( - &mut self, - _: PeerId, - _: ConnectionId, - event: THandlerOutEvent, - ) { - void::unreachable(event) - } - - fn poll(&mut self, _: &mut Context<'_>) -> Poll>> { - Poll::Pending - } - - fn on_swarm_event(&mut self, _event: FromSwarm) {} -} - -/// An implementation of [`ConnectionHandler`] that neither handles any protocols nor does it keep the connection alive. -#[derive(Clone)] -pub struct ConnectionHandler; - -impl crate::handler::ConnectionHandler for ConnectionHandler { - type FromBehaviour = Void; - type ToBehaviour = Void; - type InboundProtocol = DeniedUpgrade; - type OutboundProtocol = DeniedUpgrade; - type InboundOpenInfo = (); - type OutboundOpenInfo = Void; - - fn listen_protocol(&self) -> SubstreamProtocol { - SubstreamProtocol::new(DeniedUpgrade, ()) - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - void::unreachable(event) - } - - fn poll( - &mut self, - _: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - Poll::Pending - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - match event { - ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { - protocol, .. - }) => void::unreachable(protocol), - ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { - protocol, .. - }) => void::unreachable(protocol), - ConnectionEvent::DialUpgradeError(DialUpgradeError { info: _, error }) => match error { - StreamUpgradeError::Timeout => unreachable!(), - StreamUpgradeError::Apply(e) => void::unreachable(e), - StreamUpgradeError::NegotiationFailed | StreamUpgradeError::Io(_) => { - unreachable!("Denied upgrade does not support any protocols") - } - }, - ConnectionEvent::AddressChange(_) - | ConnectionEvent::ListenUpgradeError(_) - | ConnectionEvent::LocalProtocolsChange(_) - | ConnectionEvent::RemoteProtocolsChange(_) => {} - } - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/executor.rs b/third-party/libp2p-swarm-0.45.1/src/executor.rs deleted file mode 100644 index a2abbbde6ef..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/executor.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! Provides executors for spawning background tasks. -use futures::executor::ThreadPool; -use std::{future::Future, pin::Pin}; - -/// Implemented on objects that can run a `Future` in the background. -/// -/// > **Note**: While it may be tempting to implement this trait on types such as -/// > [`futures::stream::FuturesUnordered`], please note that passing an `Executor` is -/// > optional, and that `FuturesUnordered` (or a similar struct) will automatically -/// > be used as fallback by libp2p. The `Executor` trait should therefore only be -/// > about running `Future`s on a separate task. -pub trait Executor { - /// Run the given future in the background until it ends. - #[track_caller] - fn exec(&self, future: Pin + Send>>); -} - -impl + Send>>)> Executor for F { - fn exec(&self, f: Pin + Send>>) { - self(f) - } -} - -impl Executor for ThreadPool { - fn exec(&self, future: Pin + Send>>) { - self.spawn_ok(future) - } -} - -#[cfg(all( - feature = "tokio", - not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) -))] -#[derive(Default, Debug, Clone, Copy)] -pub(crate) struct TokioExecutor; -#[cfg(all( - feature = "tokio", - not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) -))] -impl Executor for TokioExecutor { - fn exec(&self, future: Pin + Send>>) { - tokio::spawn(future); - } -} - -#[cfg(all( - feature = "async-std", - not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) -))] -#[derive(Default, Debug, Clone, Copy)] -pub(crate) struct AsyncStdExecutor; -#[cfg(all( - feature = "async-std", - not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) -))] -impl Executor for AsyncStdExecutor { - fn exec(&self, future: Pin + Send>>) { - async_std::task::spawn(future); - } -} - -#[cfg(feature = "wasm-bindgen")] -#[derive(Default, Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub(crate) struct WasmBindgenExecutor; -#[cfg(feature = "wasm-bindgen")] -impl Executor for WasmBindgenExecutor { - fn exec(&self, future: Pin + Send>>) { - wasm_bindgen_futures::spawn_local(future) - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler.rs b/third-party/libp2p-swarm-0.45.1/src/handler.rs deleted file mode 100644 index 610b95b8cf1..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/handler.rs +++ /dev/null @@ -1,896 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -//! Once a connection to a remote peer is established, a [`ConnectionHandler`] negotiates -//! and handles one or more specific protocols on the connection. -//! -//! Protocols are negotiated and used on individual substreams of the connection. Thus a -//! [`ConnectionHandler`] defines the inbound and outbound upgrades to apply when creating a new -//! inbound or outbound substream, respectively, and is notified by a [`Swarm`](crate::Swarm) when -//! these upgrades have been successfully applied, including the final output of the upgrade. A -//! [`ConnectionHandler`] can then continue communicating with the peer over the substream using the -//! negotiated protocol(s). -//! -//! Two [`ConnectionHandler`]s can be composed with [`ConnectionHandler::select()`] -//! in order to build a new handler supporting the combined set of protocols, -//! with methods being dispatched to the appropriate handler according to the -//! used protocol(s) determined by the associated types of the handlers. -//! -//! > **Note**: A [`ConnectionHandler`] handles one or more protocols in the context of a single -//! > connection with a remote. In order to handle a protocol that requires knowledge of -//! > the network as a whole, see the -//! > [`NetworkBehaviour`](crate::behaviour::NetworkBehaviour) trait. - -pub mod either; -mod map_in; -mod map_out; -pub mod multi; -mod one_shot; -mod pending; -mod select; - -use crate::connection::AsStrHashEq; -pub use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, SendWrapper, UpgradeInfoSend}; -pub use map_in::MapInEvent; -pub use map_out::MapOutEvent; -pub use one_shot::{OneShotHandler, OneShotHandlerConfig}; -pub use pending::PendingConnectionHandler; -pub use select::ConnectionHandlerSelect; -use smallvec::SmallVec; - -use crate::StreamProtocol; -use core::slice; -use libp2p_core::Multiaddr; -use std::collections::{HashMap, HashSet}; -use std::{error, fmt, io, task::Context, task::Poll, time::Duration}; - -/// A handler for a set of protocols used on a connection with a remote. -/// -/// This trait should be implemented for a type that maintains the state for -/// the execution of a specific protocol with a remote. -/// -/// # Handling a protocol -/// -/// Communication with a remote over a set of protocols is initiated in one of two ways: -/// -/// 1. Dialing by initiating a new outbound substream. In order to do so, -/// [`ConnectionHandler::poll()`] must return an [`ConnectionHandlerEvent::OutboundSubstreamRequest`], -/// providing an instance of [`libp2p_core::upgrade::OutboundUpgrade`] that is used to negotiate the -/// protocol(s). Upon success, [`ConnectionHandler::on_connection_event`] is called with -/// [`ConnectionEvent::FullyNegotiatedOutbound`] translating the final output of the upgrade. -/// -/// 2. Listening by accepting a new inbound substream. When a new inbound substream -/// is created on a connection, [`ConnectionHandler::listen_protocol`] is called -/// to obtain an instance of [`libp2p_core::upgrade::InboundUpgrade`] that is used to -/// negotiate the protocol(s). Upon success, -/// [`ConnectionHandler::on_connection_event`] is called with [`ConnectionEvent::FullyNegotiatedInbound`] -/// translating the final output of the upgrade. -/// -/// -/// # Connection Keep-Alive -/// -/// A [`ConnectionHandler`] can influence the lifetime of the underlying connection -/// through [`ConnectionHandler::connection_keep_alive`]. That is, the protocol -/// implemented by the handler can include conditions for terminating the connection. -/// The lifetime of successfully negotiated substreams is fully controlled by the handler. -/// -/// Implementors of this trait should keep in mind that the connection can be closed at any time. -/// When a connection is closed gracefully, the substreams used by the handler may still -/// continue reading data until the remote closes its side of the connection. -pub trait ConnectionHandler: Send + 'static { - /// A type representing the message(s) a [`NetworkBehaviour`](crate::behaviour::NetworkBehaviour) can send to a [`ConnectionHandler`] via [`ToSwarm::NotifyHandler`](crate::behaviour::ToSwarm::NotifyHandler) - type FromBehaviour: fmt::Debug + Send + 'static; - /// A type representing message(s) a [`ConnectionHandler`] can send to a [`NetworkBehaviour`](crate::behaviour::NetworkBehaviour) via [`ConnectionHandlerEvent::NotifyBehaviour`]. - type ToBehaviour: fmt::Debug + Send + 'static; - /// The inbound upgrade for the protocol(s) used by the handler. - type InboundProtocol: InboundUpgradeSend; - /// The outbound upgrade for the protocol(s) used by the handler. - type OutboundProtocol: OutboundUpgradeSend; - /// The type of additional information returned from `listen_protocol`. - type InboundOpenInfo: Send + 'static; - /// The type of additional information passed to an `OutboundSubstreamRequest`. - type OutboundOpenInfo: Send + 'static; - - /// The [`InboundUpgrade`](libp2p_core::upgrade::InboundUpgrade) to apply on inbound - /// substreams to negotiate the desired protocols. - /// - /// > **Note**: The returned `InboundUpgrade` should always accept all the generally - /// > supported protocols, even if in a specific context a particular one is - /// > not supported, (eg. when only allowing one substream at a time for a protocol). - /// > This allows a remote to put the list of supported protocols in a cache. - fn listen_protocol(&self) -> SubstreamProtocol; - - /// Returns whether the connection should be kept alive. - /// - /// ## Keep alive algorithm - /// - /// A connection is always kept alive: - /// - /// - Whilst a [`ConnectionHandler`] returns [`Poll::Ready`]. - /// - We are negotiating inbound or outbound streams. - /// - There are active [`Stream`](crate::Stream)s on the connection. - /// - /// The combination of the above means that _most_ protocols will not need to override this method. - /// This method is only invoked when all of the above are `false`, i.e. when the connection is entirely idle. - /// - /// ## Exceptions - /// - /// - Protocols like [circuit-relay v2](https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md) need to keep a connection alive beyond these circumstances and can thus override this method. - /// - Protocols like [ping](https://github.com/libp2p/specs/blob/master/ping/ping.md) **don't** want to keep a connection alive despite an active streams. - /// - /// In that case, protocol authors can use [`Stream::ignore_for_keep_alive`](crate::Stream::ignore_for_keep_alive) to opt-out a particular stream from the keep-alive algorithm. - fn connection_keep_alive(&self) -> bool { - false - } - - /// Should behave like `Stream::poll()`. - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - >; - - /// Gracefully close the [`ConnectionHandler`]. - /// - /// The contract for this function is equivalent to a [`Stream`](futures::Stream). - /// When a connection is being shut down, we will first poll this function to completion. - /// Following that, the physical connection will be shut down. - /// - /// This is also called when the shutdown was initiated due to an error on the connection. - /// We therefore cannot guarantee that performing IO within here will succeed. - /// - /// To signal completion, [`Poll::Ready(None)`] should be returned. - /// - /// Implementations MUST have a [`fuse`](futures::StreamExt::fuse)-like behaviour. - /// That is, [`Poll::Ready(None)`] MUST be returned on repeated calls to [`ConnectionHandler::poll_close`]. - fn poll_close(&mut self, _: &mut Context<'_>) -> Poll> { - Poll::Ready(None) - } - - /// Adds a closure that turns the input event into something else. - fn map_in_event(self, map: TMap) -> MapInEvent - where - Self: Sized, - TMap: Fn(&TNewIn) -> Option<&Self::FromBehaviour>, - { - MapInEvent::new(self, map) - } - - /// Adds a closure that turns the output event into something else. - fn map_out_event(self, map: TMap) -> MapOutEvent - where - Self: Sized, - TMap: FnMut(Self::ToBehaviour) -> TNewOut, - { - MapOutEvent::new(self, map) - } - - /// Creates a new [`ConnectionHandler`] that selects either this handler or - /// `other` by delegating methods calls appropriately. - fn select(self, other: TProto2) -> ConnectionHandlerSelect - where - Self: Sized, - { - ConnectionHandlerSelect::new(self, other) - } - - /// Informs the handler about an event from the [`NetworkBehaviour`](super::NetworkBehaviour). - fn on_behaviour_event(&mut self, _event: Self::FromBehaviour); - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ); -} - -/// Enumeration with the list of the possible stream events -/// to pass to [`on_connection_event`](ConnectionHandler::on_connection_event). -#[non_exhaustive] -pub enum ConnectionEvent<'a, IP: InboundUpgradeSend, OP: OutboundUpgradeSend, IOI, OOI> { - /// Informs the handler about the output of a successful upgrade on a new inbound substream. - FullyNegotiatedInbound(FullyNegotiatedInbound), - /// Informs the handler about the output of a successful upgrade on a new outbound stream. - FullyNegotiatedOutbound(FullyNegotiatedOutbound), - /// Informs the handler about a change in the address of the remote. - AddressChange(AddressChange<'a>), - /// Informs the handler that upgrading an outbound substream to the given protocol has failed. - DialUpgradeError(DialUpgradeError), - /// Informs the handler that upgrading an inbound substream to the given protocol has failed. - ListenUpgradeError(ListenUpgradeError), - /// The local [`ConnectionHandler`] added or removed support for one or more protocols. - LocalProtocolsChange(ProtocolsChange<'a>), - /// The remote [`ConnectionHandler`] now supports a different set of protocols. - RemoteProtocolsChange(ProtocolsChange<'a>), -} - -impl<'a, IP, OP, IOI, OOI> fmt::Debug for ConnectionEvent<'a, IP, OP, IOI, OOI> -where - IP: InboundUpgradeSend + fmt::Debug, - IP::Output: fmt::Debug, - IP::Error: fmt::Debug, - OP: OutboundUpgradeSend + fmt::Debug, - OP::Output: fmt::Debug, - OP::Error: fmt::Debug, - IOI: fmt::Debug, - OOI: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ConnectionEvent::FullyNegotiatedInbound(v) => { - f.debug_tuple("FullyNegotiatedInbound").field(v).finish() - } - ConnectionEvent::FullyNegotiatedOutbound(v) => { - f.debug_tuple("FullyNegotiatedOutbound").field(v).finish() - } - ConnectionEvent::AddressChange(v) => f.debug_tuple("AddressChange").field(v).finish(), - ConnectionEvent::DialUpgradeError(v) => { - f.debug_tuple("DialUpgradeError").field(v).finish() - } - ConnectionEvent::ListenUpgradeError(v) => { - f.debug_tuple("ListenUpgradeError").field(v).finish() - } - ConnectionEvent::LocalProtocolsChange(v) => { - f.debug_tuple("LocalProtocolsChange").field(v).finish() - } - ConnectionEvent::RemoteProtocolsChange(v) => { - f.debug_tuple("RemoteProtocolsChange").field(v).finish() - } - } - } -} - -impl<'a, IP: InboundUpgradeSend, OP: OutboundUpgradeSend, IOI, OOI> - ConnectionEvent<'a, IP, OP, IOI, OOI> -{ - /// Whether the event concerns an outbound stream. - pub fn is_outbound(&self) -> bool { - match self { - ConnectionEvent::DialUpgradeError(_) | ConnectionEvent::FullyNegotiatedOutbound(_) => { - true - } - ConnectionEvent::FullyNegotiatedInbound(_) - | ConnectionEvent::AddressChange(_) - | ConnectionEvent::LocalProtocolsChange(_) - | ConnectionEvent::RemoteProtocolsChange(_) - | ConnectionEvent::ListenUpgradeError(_) => false, - } - } - - /// Whether the event concerns an inbound stream. - pub fn is_inbound(&self) -> bool { - match self { - ConnectionEvent::FullyNegotiatedInbound(_) | ConnectionEvent::ListenUpgradeError(_) => { - true - } - ConnectionEvent::FullyNegotiatedOutbound(_) - | ConnectionEvent::AddressChange(_) - | ConnectionEvent::LocalProtocolsChange(_) - | ConnectionEvent::RemoteProtocolsChange(_) - | ConnectionEvent::DialUpgradeError(_) => false, - } - } -} - -/// [`ConnectionEvent`] variant that informs the handler about -/// the output of a successful upgrade on a new inbound substream. -/// -/// Note that it is up to the [`ConnectionHandler`] implementation to manage the lifetime of the -/// negotiated inbound substreams. E.g. the implementation has to enforce a limit on the number -/// of simultaneously open negotiated inbound substreams. In other words it is up to the -/// [`ConnectionHandler`] implementation to stop a malicious remote node to open and keep alive -/// an excessive amount of inbound substreams. -#[derive(Debug)] -pub struct FullyNegotiatedInbound { - pub protocol: IP::Output, - pub info: IOI, -} - -/// [`ConnectionEvent`] variant that informs the handler about successful upgrade on a new outbound stream. -/// -/// The `protocol` field is the information that was previously passed to -/// [`ConnectionHandlerEvent::OutboundSubstreamRequest`]. -#[derive(Debug)] -pub struct FullyNegotiatedOutbound { - pub protocol: OP::Output, - pub info: OOI, -} - -/// [`ConnectionEvent`] variant that informs the handler about a change in the address of the remote. -#[derive(Debug)] -pub struct AddressChange<'a> { - pub new_address: &'a Multiaddr, -} - -/// [`ConnectionEvent`] variant that informs the handler about a change in the protocols supported on the connection. -#[derive(Debug, Clone)] -pub enum ProtocolsChange<'a> { - Added(ProtocolsAdded<'a>), - Removed(ProtocolsRemoved<'a>), -} - -impl<'a> ProtocolsChange<'a> { - /// Compute the protocol change for the initial set of protocols. - pub(crate) fn from_initial_protocols<'b, T: AsRef + 'b>( - new_protocols: impl IntoIterator, - buffer: &'a mut Vec, - ) -> Self { - buffer.clear(); - buffer.extend( - new_protocols - .into_iter() - .filter_map(|i| StreamProtocol::try_from_owned(i.as_ref().to_owned()).ok()), - ); - - ProtocolsChange::Added(ProtocolsAdded { - protocols: buffer.iter(), - }) - } - - /// Compute the [`ProtocolsChange`] that results from adding `to_add` to `existing_protocols`. - /// - /// Returns `None` if the change is a no-op, i.e. `to_add` is a subset of `existing_protocols`. - pub(crate) fn add( - existing_protocols: &HashSet, - to_add: HashSet, - buffer: &'a mut Vec, - ) -> Option { - buffer.clear(); - buffer.extend( - to_add - .into_iter() - .filter(|i| !existing_protocols.contains(i)), - ); - - if buffer.is_empty() { - return None; - } - - Some(Self::Added(ProtocolsAdded { - protocols: buffer.iter(), - })) - } - - /// Compute the [`ProtocolsChange`] that results from removing `to_remove` from `existing_protocols`. Removes the protocols from `existing_protocols`. - /// - /// Returns `None` if the change is a no-op, i.e. none of the protocols in `to_remove` are in `existing_protocols`. - pub(crate) fn remove( - existing_protocols: &mut HashSet, - to_remove: HashSet, - buffer: &'a mut Vec, - ) -> Option { - buffer.clear(); - buffer.extend( - to_remove - .into_iter() - .filter_map(|i| existing_protocols.take(&i)), - ); - - if buffer.is_empty() { - return None; - } - - Some(Self::Removed(ProtocolsRemoved { - protocols: buffer.iter(), - })) - } - - /// Compute the [`ProtocolsChange`]s required to go from `existing_protocols` to `new_protocols`. - pub(crate) fn from_full_sets>( - existing_protocols: &mut HashMap, bool>, - new_protocols: impl IntoIterator, - buffer: &'a mut Vec, - ) -> SmallVec<[Self; 2]> { - buffer.clear(); - - // Initially, set the boolean for all protocols to `false`, meaning "not visited". - for v in existing_protocols.values_mut() { - *v = false; - } - - let mut new_protocol_count = 0; // We can only iterate `new_protocols` once, so keep track of its length separately. - for new_protocol in new_protocols { - existing_protocols - .entry(AsStrHashEq(new_protocol)) - .and_modify(|v| *v = true) // Mark protocol as visited (i.e. we still support it) - .or_insert_with_key(|k| { - // Encountered a previously unsupported protocol, remember it in `buffer`. - buffer.extend(StreamProtocol::try_from_owned(k.0.as_ref().to_owned()).ok()); - true - }); - new_protocol_count += 1; - } - - if new_protocol_count == existing_protocols.len() && buffer.is_empty() { - return SmallVec::new(); - } - - let num_new_protocols = buffer.len(); - // Drain all protocols that we haven't visited. - // For existing protocols that are not in `new_protocols`, the boolean will be false, meaning we need to remove it. - existing_protocols.retain(|p, &mut is_supported| { - if !is_supported { - buffer.extend(StreamProtocol::try_from_owned(p.0.as_ref().to_owned()).ok()); - } - - is_supported - }); - - let (added, removed) = buffer.split_at(num_new_protocols); - let mut changes = SmallVec::new(); - if !added.is_empty() { - changes.push(ProtocolsChange::Added(ProtocolsAdded { - protocols: added.iter(), - })); - } - if !removed.is_empty() { - changes.push(ProtocolsChange::Removed(ProtocolsRemoved { - protocols: removed.iter(), - })); - } - changes - } -} - -/// An [`Iterator`] over all protocols that have been added. -#[derive(Debug, Clone)] -pub struct ProtocolsAdded<'a> { - pub(crate) protocols: slice::Iter<'a, StreamProtocol>, -} - -/// An [`Iterator`] over all protocols that have been removed. -#[derive(Debug, Clone)] -pub struct ProtocolsRemoved<'a> { - pub(crate) protocols: slice::Iter<'a, StreamProtocol>, -} - -impl<'a> Iterator for ProtocolsAdded<'a> { - type Item = &'a StreamProtocol; - fn next(&mut self) -> Option { - self.protocols.next() - } -} - -impl<'a> Iterator for ProtocolsRemoved<'a> { - type Item = &'a StreamProtocol; - fn next(&mut self) -> Option { - self.protocols.next() - } -} - -/// [`ConnectionEvent`] variant that informs the handler -/// that upgrading an outbound substream to the given protocol has failed. -#[derive(Debug)] -pub struct DialUpgradeError { - pub info: OOI, - pub error: StreamUpgradeError, -} - -/// [`ConnectionEvent`] variant that informs the handler -/// that upgrading an inbound substream to the given protocol has failed. -#[derive(Debug)] -pub struct ListenUpgradeError { - pub info: IOI, - pub error: IP::Error, -} - -/// Configuration of inbound or outbound substream protocol(s) -/// for a [`ConnectionHandler`]. -/// -/// The inbound substream protocol(s) are defined by [`ConnectionHandler::listen_protocol`] -/// and the outbound substream protocol(s) by [`ConnectionHandlerEvent::OutboundSubstreamRequest`]. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct SubstreamProtocol { - upgrade: TUpgrade, - info: TInfo, - timeout: Duration, -} - -impl SubstreamProtocol { - /// Create a new `SubstreamProtocol` from the given upgrade. - /// - /// The default timeout for applying the given upgrade on a substream is - /// 10 seconds. - pub fn new(upgrade: TUpgrade, info: TInfo) -> Self { - SubstreamProtocol { - upgrade, - info, - timeout: Duration::from_secs(10), - } - } - - /// Maps a function over the protocol upgrade. - pub fn map_upgrade(self, f: F) -> SubstreamProtocol - where - F: FnOnce(TUpgrade) -> U, - { - SubstreamProtocol { - upgrade: f(self.upgrade), - info: self.info, - timeout: self.timeout, - } - } - - /// Maps a function over the protocol info. - pub fn map_info(self, f: F) -> SubstreamProtocol - where - F: FnOnce(TInfo) -> U, - { - SubstreamProtocol { - upgrade: self.upgrade, - info: f(self.info), - timeout: self.timeout, - } - } - - /// Sets a new timeout for the protocol upgrade. - pub fn with_timeout(mut self, timeout: Duration) -> Self { - self.timeout = timeout; - self - } - - /// Borrows the contained protocol upgrade. - pub fn upgrade(&self) -> &TUpgrade { - &self.upgrade - } - - /// Borrows the contained protocol info. - pub fn info(&self) -> &TInfo { - &self.info - } - - /// Borrows the timeout for the protocol upgrade. - pub fn timeout(&self) -> &Duration { - &self.timeout - } - - /// Converts the substream protocol configuration into the contained upgrade. - pub fn into_upgrade(self) -> (TUpgrade, TInfo) { - (self.upgrade, self.info) - } -} - -/// Event produced by a handler. -#[derive(Debug, Clone, PartialEq, Eq)] -#[non_exhaustive] -pub enum ConnectionHandlerEvent { - /// Request a new outbound substream to be opened with the remote. - OutboundSubstreamRequest { - /// The protocol(s) to apply on the substream. - protocol: SubstreamProtocol, - }, - /// We learned something about the protocols supported by the remote. - ReportRemoteProtocols(ProtocolSupport), - - /// Event that is sent to a [`NetworkBehaviour`](crate::behaviour::NetworkBehaviour). - NotifyBehaviour(TCustom), -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ProtocolSupport { - /// The remote now supports these additional protocols. - Added(HashSet), - /// The remote no longer supports these protocols. - Removed(HashSet), -} - -/// Event produced by a handler. -impl - ConnectionHandlerEvent -{ - /// If this is an `OutboundSubstreamRequest`, maps the `info` member from a - /// `TOutboundOpenInfo` to something else. - pub fn map_outbound_open_info( - self, - map: F, - ) -> ConnectionHandlerEvent - where - F: FnOnce(TOutboundOpenInfo) -> I, - { - match self { - ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } => { - ConnectionHandlerEvent::OutboundSubstreamRequest { - protocol: protocol.map_info(map), - } - } - ConnectionHandlerEvent::NotifyBehaviour(val) => { - ConnectionHandlerEvent::NotifyBehaviour(val) - } - ConnectionHandlerEvent::ReportRemoteProtocols(support) => { - ConnectionHandlerEvent::ReportRemoteProtocols(support) - } - } - } - - /// If this is an `OutboundSubstreamRequest`, maps the protocol (`TConnectionUpgrade`) - /// to something else. - pub fn map_protocol(self, map: F) -> ConnectionHandlerEvent - where - F: FnOnce(TConnectionUpgrade) -> I, - { - match self { - ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } => { - ConnectionHandlerEvent::OutboundSubstreamRequest { - protocol: protocol.map_upgrade(map), - } - } - ConnectionHandlerEvent::NotifyBehaviour(val) => { - ConnectionHandlerEvent::NotifyBehaviour(val) - } - ConnectionHandlerEvent::ReportRemoteProtocols(support) => { - ConnectionHandlerEvent::ReportRemoteProtocols(support) - } - } - } - - /// If this is a `Custom` event, maps the content to something else. - pub fn map_custom( - self, - map: F, - ) -> ConnectionHandlerEvent - where - F: FnOnce(TCustom) -> I, - { - match self { - ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } => { - ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } - } - ConnectionHandlerEvent::NotifyBehaviour(val) => { - ConnectionHandlerEvent::NotifyBehaviour(map(val)) - } - ConnectionHandlerEvent::ReportRemoteProtocols(support) => { - ConnectionHandlerEvent::ReportRemoteProtocols(support) - } - } - } -} - -/// Error that can happen on an outbound substream opening attempt. -#[derive(Debug)] -pub enum StreamUpgradeError { - /// The opening attempt timed out before the negotiation was fully completed. - Timeout, - /// The upgrade produced an error. - Apply(TUpgrErr), - /// No protocol could be agreed upon. - NegotiationFailed, - /// An IO or otherwise unrecoverable error happened. - Io(io::Error), -} - -impl StreamUpgradeError { - /// Map the inner [`StreamUpgradeError`] type. - pub fn map_upgrade_err(self, f: F) -> StreamUpgradeError - where - F: FnOnce(TUpgrErr) -> E, - { - match self { - StreamUpgradeError::Timeout => StreamUpgradeError::Timeout, - StreamUpgradeError::Apply(e) => StreamUpgradeError::Apply(f(e)), - StreamUpgradeError::NegotiationFailed => StreamUpgradeError::NegotiationFailed, - StreamUpgradeError::Io(e) => StreamUpgradeError::Io(e), - } - } -} - -impl fmt::Display for StreamUpgradeError -where - TUpgrErr: error::Error + 'static, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - StreamUpgradeError::Timeout => { - write!(f, "Timeout error while opening a substream") - } - StreamUpgradeError::Apply(err) => { - write!(f, "Apply: ")?; - crate::print_error_chain(f, err) - } - StreamUpgradeError::NegotiationFailed => { - write!(f, "no protocols could be agreed upon") - } - StreamUpgradeError::Io(e) => { - write!(f, "IO error: ")?; - crate::print_error_chain(f, e) - } - } - } -} - -impl error::Error for StreamUpgradeError -where - TUpgrErr: error::Error + 'static, -{ - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - None - } -} - -#[cfg(test)] -mod test { - use super::*; - - fn protocol_set_of(s: &'static str) -> HashSet { - s.split_whitespace() - .map(|p| StreamProtocol::try_from_owned(format!("/{p}")).unwrap()) - .collect() - } - - fn test_remove( - existing: &mut HashSet, - to_remove: HashSet, - ) -> HashSet { - ProtocolsChange::remove(existing, to_remove, &mut Vec::new()) - .into_iter() - .flat_map(|c| match c { - ProtocolsChange::Added(_) => panic!("unexpected added"), - ProtocolsChange::Removed(r) => r.cloned(), - }) - .collect::>() - } - - #[test] - fn test_protocol_remove_subset() { - let mut existing = protocol_set_of("a b c"); - let to_remove = protocol_set_of("a b"); - - let change = test_remove(&mut existing, to_remove); - - assert_eq!(existing, protocol_set_of("c")); - assert_eq!(change, protocol_set_of("a b")); - } - - #[test] - fn test_protocol_remove_all() { - let mut existing = protocol_set_of("a b c"); - let to_remove = protocol_set_of("a b c"); - - let change = test_remove(&mut existing, to_remove); - - assert_eq!(existing, protocol_set_of("")); - assert_eq!(change, protocol_set_of("a b c")); - } - - #[test] - fn test_protocol_remove_superset() { - let mut existing = protocol_set_of("a b c"); - let to_remove = protocol_set_of("a b c d"); - - let change = test_remove(&mut existing, to_remove); - - assert_eq!(existing, protocol_set_of("")); - assert_eq!(change, protocol_set_of("a b c")); - } - - #[test] - fn test_protocol_remove_none() { - let mut existing = protocol_set_of("a b c"); - let to_remove = protocol_set_of("d"); - - let change = test_remove(&mut existing, to_remove); - - assert_eq!(existing, protocol_set_of("a b c")); - assert_eq!(change, protocol_set_of("")); - } - - #[test] - fn test_protocol_remove_none_from_empty() { - let mut existing = protocol_set_of(""); - let to_remove = protocol_set_of("d"); - - let change = test_remove(&mut existing, to_remove); - - assert_eq!(existing, protocol_set_of("")); - assert_eq!(change, protocol_set_of("")); - } - - fn test_from_full_sets( - existing: HashSet, - new: HashSet, - ) -> [HashSet; 2] { - let mut buffer = Vec::new(); - let mut existing = existing - .iter() - .map(|p| (AsStrHashEq(p.as_ref()), true)) - .collect::>(); - - let changes = ProtocolsChange::from_full_sets( - &mut existing, - new.iter().map(AsRef::as_ref), - &mut buffer, - ); - - let mut added_changes = HashSet::new(); - let mut removed_changes = HashSet::new(); - - for change in changes { - match change { - ProtocolsChange::Added(a) => { - added_changes.extend(a.cloned()); - } - ProtocolsChange::Removed(r) => { - removed_changes.extend(r.cloned()); - } - } - } - - [removed_changes, added_changes] - } - - #[test] - fn test_from_full_stes_subset() { - let existing = protocol_set_of("a b c"); - let new = protocol_set_of("a b"); - - let [removed_changes, added_changes] = test_from_full_sets(existing, new); - - assert_eq!(added_changes, protocol_set_of("")); - assert_eq!(removed_changes, protocol_set_of("c")); - } - - #[test] - fn test_from_full_sets_superset() { - let existing = protocol_set_of("a b"); - let new = protocol_set_of("a b c"); - - let [removed_changes, added_changes] = test_from_full_sets(existing, new); - - assert_eq!(added_changes, protocol_set_of("c")); - assert_eq!(removed_changes, protocol_set_of("")); - } - - #[test] - fn test_from_full_sets_intersection() { - let existing = protocol_set_of("a b c"); - let new = protocol_set_of("b c d"); - - let [removed_changes, added_changes] = test_from_full_sets(existing, new); - - assert_eq!(added_changes, protocol_set_of("d")); - assert_eq!(removed_changes, protocol_set_of("a")); - } - - #[test] - fn test_from_full_sets_disjoint() { - let existing = protocol_set_of("a b c"); - let new = protocol_set_of("d e f"); - - let [removed_changes, added_changes] = test_from_full_sets(existing, new); - - assert_eq!(added_changes, protocol_set_of("d e f")); - assert_eq!(removed_changes, protocol_set_of("a b c")); - } - - #[test] - fn test_from_full_sets_empty() { - let existing = protocol_set_of(""); - let new = protocol_set_of(""); - - let [removed_changes, added_changes] = test_from_full_sets(existing, new); - - assert_eq!(added_changes, protocol_set_of("")); - assert_eq!(removed_changes, protocol_set_of("")); - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/either.rs b/third-party/libp2p-swarm-0.45.1/src/handler/either.rs deleted file mode 100644 index a5aab9b5fee..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/handler/either.rs +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2021 Protocol Labs. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::handler::{ - ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, FullyNegotiatedInbound, - InboundUpgradeSend, ListenUpgradeError, SubstreamProtocol, -}; -use crate::upgrade::SendWrapper; -use either::Either; -use futures::future; -use std::task::{Context, Poll}; - -impl - FullyNegotiatedInbound, SendWrapper>, Either> -where - RIP: InboundUpgradeSend, - LIP: InboundUpgradeSend, -{ - pub(crate) fn transpose( - self, - ) -> Either, FullyNegotiatedInbound> { - match self { - FullyNegotiatedInbound { - protocol: future::Either::Left(protocol), - info: Either::Left(info), - } => Either::Left(FullyNegotiatedInbound { protocol, info }), - FullyNegotiatedInbound { - protocol: future::Either::Right(protocol), - info: Either::Right(info), - } => Either::Right(FullyNegotiatedInbound { protocol, info }), - _ => unreachable!(), - } - } -} - -impl - ListenUpgradeError, Either, SendWrapper>> -where - RIP: InboundUpgradeSend, - LIP: InboundUpgradeSend, -{ - fn transpose(self) -> Either, ListenUpgradeError> { - match self { - ListenUpgradeError { - error: Either::Left(error), - info: Either::Left(info), - } => Either::Left(ListenUpgradeError { error, info }), - ListenUpgradeError { - error: Either::Right(error), - info: Either::Right(info), - } => Either::Right(ListenUpgradeError { error, info }), - _ => unreachable!(), - } - } -} - -/// Implementation of a [`ConnectionHandler`] that represents either of two [`ConnectionHandler`] -/// implementations. -impl ConnectionHandler for Either -where - L: ConnectionHandler, - R: ConnectionHandler, -{ - type FromBehaviour = Either; - type ToBehaviour = Either; - type InboundProtocol = Either, SendWrapper>; - type OutboundProtocol = - Either, SendWrapper>; - type InboundOpenInfo = Either; - type OutboundOpenInfo = Either; - - fn listen_protocol(&self) -> SubstreamProtocol { - match self { - Either::Left(a) => a - .listen_protocol() - .map_upgrade(|u| Either::Left(SendWrapper(u))) - .map_info(Either::Left), - Either::Right(b) => b - .listen_protocol() - .map_upgrade(|u| Either::Right(SendWrapper(u))) - .map_info(Either::Right), - } - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - match (self, event) { - (Either::Left(handler), Either::Left(event)) => handler.on_behaviour_event(event), - (Either::Right(handler), Either::Right(event)) => handler.on_behaviour_event(event), - _ => unreachable!(), - } - } - - fn connection_keep_alive(&self) -> bool { - match self { - Either::Left(handler) => handler.connection_keep_alive(), - Either::Right(handler) => handler.connection_keep_alive(), - } - } - - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - let event = match self { - Either::Left(handler) => futures::ready!(handler.poll(cx)) - .map_custom(Either::Left) - .map_protocol(|p| Either::Left(SendWrapper(p))) - .map_outbound_open_info(Either::Left), - Either::Right(handler) => futures::ready!(handler.poll(cx)) - .map_custom(Either::Right) - .map_protocol(|p| Either::Right(SendWrapper(p))) - .map_outbound_open_info(Either::Right), - }; - - Poll::Ready(event) - } - - fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { - let event = match self { - Either::Left(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Left), - Either::Right(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Right), - }; - - Poll::Ready(event) - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - match event { - ConnectionEvent::FullyNegotiatedInbound(fully_negotiated_inbound) => { - match (fully_negotiated_inbound.transpose(), self) { - (Either::Left(fully_negotiated_inbound), Either::Left(handler)) => handler - .on_connection_event(ConnectionEvent::FullyNegotiatedInbound( - fully_negotiated_inbound, - )), - (Either::Right(fully_negotiated_inbound), Either::Right(handler)) => handler - .on_connection_event(ConnectionEvent::FullyNegotiatedInbound( - fully_negotiated_inbound, - )), - _ => unreachable!(), - } - } - ConnectionEvent::FullyNegotiatedOutbound(fully_negotiated_outbound) => { - match (fully_negotiated_outbound.transpose(), self) { - (Either::Left(fully_negotiated_outbound), Either::Left(handler)) => handler - .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( - fully_negotiated_outbound, - )), - (Either::Right(fully_negotiated_outbound), Either::Right(handler)) => handler - .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( - fully_negotiated_outbound, - )), - _ => unreachable!(), - } - } - ConnectionEvent::DialUpgradeError(dial_upgrade_error) => { - match (dial_upgrade_error.transpose(), self) { - (Either::Left(dial_upgrade_error), Either::Left(handler)) => handler - .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)), - (Either::Right(dial_upgrade_error), Either::Right(handler)) => handler - .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)), - _ => unreachable!(), - } - } - ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => { - match (listen_upgrade_error.transpose(), self) { - (Either::Left(listen_upgrade_error), Either::Left(handler)) => handler - .on_connection_event(ConnectionEvent::ListenUpgradeError( - listen_upgrade_error, - )), - (Either::Right(listen_upgrade_error), Either::Right(handler)) => handler - .on_connection_event(ConnectionEvent::ListenUpgradeError( - listen_upgrade_error, - )), - _ => unreachable!(), - } - } - ConnectionEvent::AddressChange(address_change) => match self { - Either::Left(handler) => { - handler.on_connection_event(ConnectionEvent::AddressChange(address_change)) - } - Either::Right(handler) => { - handler.on_connection_event(ConnectionEvent::AddressChange(address_change)) - } - }, - ConnectionEvent::LocalProtocolsChange(supported_protocols) => match self { - Either::Left(handler) => handler.on_connection_event( - ConnectionEvent::LocalProtocolsChange(supported_protocols), - ), - Either::Right(handler) => handler.on_connection_event( - ConnectionEvent::LocalProtocolsChange(supported_protocols), - ), - }, - ConnectionEvent::RemoteProtocolsChange(supported_protocols) => match self { - Either::Left(handler) => handler.on_connection_event( - ConnectionEvent::RemoteProtocolsChange(supported_protocols), - ), - Either::Right(handler) => handler.on_connection_event( - ConnectionEvent::RemoteProtocolsChange(supported_protocols), - ), - }, - } - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/map_in.rs b/third-party/libp2p-swarm-0.45.1/src/handler/map_in.rs deleted file mode 100644 index 9316ef4d2ce..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/handler/map_in.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::handler::{ - ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, SubstreamProtocol, -}; -use std::{fmt::Debug, marker::PhantomData, task::Context, task::Poll}; - -/// Wrapper around a protocol handler that turns the input event into something else. -#[derive(Debug)] -pub struct MapInEvent { - inner: TConnectionHandler, - map: TMap, - marker: PhantomData, -} - -impl MapInEvent { - /// Creates a `MapInEvent`. - pub(crate) fn new(inner: TConnectionHandler, map: TMap) -> Self { - MapInEvent { - inner, - map, - marker: PhantomData, - } - } -} - -impl ConnectionHandler - for MapInEvent -where - TConnectionHandler: ConnectionHandler, - TMap: Fn(TNewIn) -> Option, - TNewIn: Debug + Send + 'static, - TMap: Send + 'static, -{ - type FromBehaviour = TNewIn; - type ToBehaviour = TConnectionHandler::ToBehaviour; - type InboundProtocol = TConnectionHandler::InboundProtocol; - type OutboundProtocol = TConnectionHandler::OutboundProtocol; - type InboundOpenInfo = TConnectionHandler::InboundOpenInfo; - type OutboundOpenInfo = TConnectionHandler::OutboundOpenInfo; - - fn listen_protocol(&self) -> SubstreamProtocol { - self.inner.listen_protocol() - } - - fn on_behaviour_event(&mut self, event: TNewIn) { - if let Some(event) = (self.map)(event) { - self.inner.on_behaviour_event(event); - } - } - - fn connection_keep_alive(&self) -> bool { - self.inner.connection_keep_alive() - } - - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - self.inner.poll(cx) - } - - fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { - self.inner.poll_close(cx) - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - self.inner.on_connection_event(event); - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/map_out.rs b/third-party/libp2p-swarm-0.45.1/src/handler/map_out.rs deleted file mode 100644 index f877bfa6f64..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/handler/map_out.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::handler::{ - ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, SubstreamProtocol, -}; -use futures::ready; -use std::fmt::Debug; -use std::task::{Context, Poll}; - -/// Wrapper around a protocol handler that turns the output event into something else. -#[derive(Debug)] -pub struct MapOutEvent { - inner: TConnectionHandler, - map: TMap, -} - -impl MapOutEvent { - /// Creates a `MapOutEvent`. - pub(crate) fn new(inner: TConnectionHandler, map: TMap) -> Self { - MapOutEvent { inner, map } - } -} - -impl ConnectionHandler for MapOutEvent -where - TConnectionHandler: ConnectionHandler, - TMap: FnMut(TConnectionHandler::ToBehaviour) -> TNewOut, - TNewOut: Debug + Send + 'static, - TMap: Send + 'static, -{ - type FromBehaviour = TConnectionHandler::FromBehaviour; - type ToBehaviour = TNewOut; - type InboundProtocol = TConnectionHandler::InboundProtocol; - type OutboundProtocol = TConnectionHandler::OutboundProtocol; - type InboundOpenInfo = TConnectionHandler::InboundOpenInfo; - type OutboundOpenInfo = TConnectionHandler::OutboundOpenInfo; - - fn listen_protocol(&self) -> SubstreamProtocol { - self.inner.listen_protocol() - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - self.inner.on_behaviour_event(event) - } - - fn connection_keep_alive(&self) -> bool { - self.inner.connection_keep_alive() - } - - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - self.inner.poll(cx).map(|ev| match ev { - ConnectionHandlerEvent::NotifyBehaviour(ev) => { - ConnectionHandlerEvent::NotifyBehaviour((self.map)(ev)) - } - ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } => { - ConnectionHandlerEvent::OutboundSubstreamRequest { protocol } - } - ConnectionHandlerEvent::ReportRemoteProtocols(support) => { - ConnectionHandlerEvent::ReportRemoteProtocols(support) - } - }) - } - - fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { - let Some(e) = ready!(self.inner.poll_close(cx)) else { - return Poll::Ready(None); - }; - - Poll::Ready(Some((self.map)(e))) - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - self.inner.on_connection_event(event); - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/multi.rs b/third-party/libp2p-swarm-0.45.1/src/handler/multi.rs deleted file mode 100644 index 5efcde5c2bb..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/handler/multi.rs +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -//! A [`ConnectionHandler`] implementation that combines multiple other [`ConnectionHandler`]s -//! indexed by some key. - -use crate::handler::{ - AddressChange, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError, - FullyNegotiatedInbound, FullyNegotiatedOutbound, ListenUpgradeError, SubstreamProtocol, -}; -use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, UpgradeInfoSend}; -use crate::Stream; -use futures::{future::BoxFuture, prelude::*, ready}; -use rand::Rng; -use std::{ - cmp, - collections::{HashMap, HashSet}, - error, - fmt::{self, Debug}, - hash::Hash, - iter, - task::{Context, Poll}, - time::Duration, -}; - -/// A [`ConnectionHandler`] for multiple [`ConnectionHandler`]s of the same type. -#[derive(Clone)] -pub struct MultiHandler { - handlers: HashMap, -} - -impl fmt::Debug for MultiHandler -where - K: fmt::Debug + Eq + Hash, - H: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("MultiHandler") - .field("handlers", &self.handlers) - .finish() - } -} - -impl MultiHandler -where - K: Clone + Debug + Hash + Eq + Send + 'static, - H: ConnectionHandler, -{ - /// Create and populate a `MultiHandler` from the given handler iterator. - /// - /// It is an error for any two protocols handlers to share the same protocol name. - pub fn try_from_iter(iter: I) -> Result - where - I: IntoIterator, - { - let m = MultiHandler { - handlers: HashMap::from_iter(iter), - }; - uniq_proto_names( - m.handlers - .values() - .map(|h| h.listen_protocol().into_upgrade().0), - )?; - Ok(m) - } - - fn on_listen_upgrade_error( - &mut self, - ListenUpgradeError { - error: (key, error), - mut info, - }: ListenUpgradeError< - ::InboundOpenInfo, - ::InboundProtocol, - >, - ) { - if let Some(h) = self.handlers.get_mut(&key) { - if let Some(i) = info.take(&key) { - h.on_connection_event(ConnectionEvent::ListenUpgradeError(ListenUpgradeError { - info: i, - error, - })); - } - } - } -} - -impl ConnectionHandler for MultiHandler -where - K: Clone + Debug + Hash + Eq + Send + 'static, - H: ConnectionHandler, - H::InboundProtocol: InboundUpgradeSend, - H::OutboundProtocol: OutboundUpgradeSend, -{ - type FromBehaviour = (K, ::FromBehaviour); - type ToBehaviour = (K, ::ToBehaviour); - type InboundProtocol = Upgrade::InboundProtocol>; - type OutboundProtocol = ::OutboundProtocol; - type InboundOpenInfo = Info::InboundOpenInfo>; - type OutboundOpenInfo = (K, ::OutboundOpenInfo); - - fn listen_protocol(&self) -> SubstreamProtocol { - let (upgrade, info, timeout) = self - .handlers - .iter() - .map(|(key, handler)| { - let proto = handler.listen_protocol(); - let timeout = *proto.timeout(); - let (upgrade, info) = proto.into_upgrade(); - (key.clone(), (upgrade, info, timeout)) - }) - .fold( - (Upgrade::new(), Info::new(), Duration::from_secs(0)), - |(mut upg, mut inf, mut timeout), (k, (u, i, t))| { - upg.upgrades.push((k.clone(), u)); - inf.infos.push((k, i)); - timeout = cmp::max(timeout, t); - (upg, inf, timeout) - }, - ); - SubstreamProtocol::new(upgrade, info).with_timeout(timeout) - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - match event { - ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { - protocol, - info: (key, arg), - }) => { - if let Some(h) = self.handlers.get_mut(&key) { - h.on_connection_event(ConnectionEvent::FullyNegotiatedOutbound( - FullyNegotiatedOutbound { - protocol, - info: arg, - }, - )); - } else { - tracing::error!("FullyNegotiatedOutbound: no handler for key") - } - } - ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { - protocol: (key, arg), - mut info, - }) => { - if let Some(h) = self.handlers.get_mut(&key) { - if let Some(i) = info.take(&key) { - h.on_connection_event(ConnectionEvent::FullyNegotiatedInbound( - FullyNegotiatedInbound { - protocol: arg, - info: i, - }, - )); - } - } else { - tracing::error!("FullyNegotiatedInbound: no handler for key") - } - } - ConnectionEvent::AddressChange(AddressChange { new_address }) => { - for h in self.handlers.values_mut() { - h.on_connection_event(ConnectionEvent::AddressChange(AddressChange { - new_address, - })); - } - } - ConnectionEvent::DialUpgradeError(DialUpgradeError { - info: (key, arg), - error, - }) => { - if let Some(h) = self.handlers.get_mut(&key) { - h.on_connection_event(ConnectionEvent::DialUpgradeError(DialUpgradeError { - info: arg, - error, - })); - } else { - tracing::error!("DialUpgradeError: no handler for protocol") - } - } - ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => { - self.on_listen_upgrade_error(listen_upgrade_error) - } - ConnectionEvent::LocalProtocolsChange(supported_protocols) => { - for h in self.handlers.values_mut() { - h.on_connection_event(ConnectionEvent::LocalProtocolsChange( - supported_protocols.clone(), - )); - } - } - ConnectionEvent::RemoteProtocolsChange(supported_protocols) => { - for h in self.handlers.values_mut() { - h.on_connection_event(ConnectionEvent::RemoteProtocolsChange( - supported_protocols.clone(), - )); - } - } - } - } - - fn on_behaviour_event(&mut self, (key, event): Self::FromBehaviour) { - if let Some(h) = self.handlers.get_mut(&key) { - h.on_behaviour_event(event) - } else { - tracing::error!("on_behaviour_event: no handler for key") - } - } - - fn connection_keep_alive(&self) -> bool { - self.handlers - .values() - .map(|h| h.connection_keep_alive()) - .max() - .unwrap_or(false) - } - - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - // Calling `gen_range(0, 0)` (see below) would panic, so we have return early to avoid - // that situation. - if self.handlers.is_empty() { - return Poll::Pending; - } - - // Not always polling handlers in the same order should give anyone the chance to make progress. - let pos = rand::thread_rng().gen_range(0..self.handlers.len()); - - for (k, h) in self.handlers.iter_mut().skip(pos) { - if let Poll::Ready(e) = h.poll(cx) { - let e = e - .map_outbound_open_info(|i| (k.clone(), i)) - .map_custom(|p| (k.clone(), p)); - return Poll::Ready(e); - } - } - - for (k, h) in self.handlers.iter_mut().take(pos) { - if let Poll::Ready(e) = h.poll(cx) { - let e = e - .map_outbound_open_info(|i| (k.clone(), i)) - .map_custom(|p| (k.clone(), p)); - return Poll::Ready(e); - } - } - - Poll::Pending - } - - fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { - for (k, h) in self.handlers.iter_mut() { - let Some(e) = ready!(h.poll_close(cx)) else { - continue; - }; - return Poll::Ready(Some((k.clone(), e))); - } - - Poll::Ready(None) - } -} - -/// Split [`MultiHandler`] into parts. -impl IntoIterator for MultiHandler { - type Item = ::Item; - type IntoIter = std::collections::hash_map::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.handlers.into_iter() - } -} - -/// Index and protocol name pair used as `UpgradeInfo::Info`. -#[derive(Debug, Clone)] -pub struct IndexedProtoName(usize, H); - -impl> AsRef for IndexedProtoName { - fn as_ref(&self) -> &str { - self.1.as_ref() - } -} - -/// The aggregated `InboundOpenInfo`s of supported inbound substream protocols. -#[derive(Clone)] -pub struct Info { - infos: Vec<(K, I)>, -} - -impl Info { - fn new() -> Self { - Info { infos: Vec::new() } - } - - pub fn take(&mut self, k: &K) -> Option { - if let Some(p) = self.infos.iter().position(|(key, _)| key == k) { - return Some(self.infos.remove(p).1); - } - None - } -} - -/// Inbound and outbound upgrade for all [`ConnectionHandler`]s. -#[derive(Clone)] -pub struct Upgrade { - upgrades: Vec<(K, H)>, -} - -impl Upgrade { - fn new() -> Self { - Upgrade { - upgrades: Vec::new(), - } - } -} - -impl fmt::Debug for Upgrade -where - K: fmt::Debug + Eq + Hash, - H: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Upgrade") - .field("upgrades", &self.upgrades) - .finish() - } -} - -impl UpgradeInfoSend for Upgrade -where - H: UpgradeInfoSend, - K: Send + 'static, -{ - type Info = IndexedProtoName; - type InfoIter = std::vec::IntoIter; - - fn protocol_info(&self) -> Self::InfoIter { - self.upgrades - .iter() - .enumerate() - .flat_map(|(i, (_, h))| iter::repeat(i).zip(h.protocol_info())) - .map(|(i, h)| IndexedProtoName(i, h)) - .collect::>() - .into_iter() - } -} - -impl InboundUpgradeSend for Upgrade -where - H: InboundUpgradeSend, - K: Send + 'static, -{ - type Output = (K, ::Output); - type Error = (K, ::Error); - type Future = BoxFuture<'static, Result>; - - fn upgrade_inbound(mut self, resource: Stream, info: Self::Info) -> Self::Future { - let IndexedProtoName(index, info) = info; - let (key, upgrade) = self.upgrades.remove(index); - upgrade - .upgrade_inbound(resource, info) - .map(move |out| match out { - Ok(o) => Ok((key, o)), - Err(e) => Err((key, e)), - }) - .boxed() - } -} - -impl OutboundUpgradeSend for Upgrade -where - H: OutboundUpgradeSend, - K: Send + 'static, -{ - type Output = (K, ::Output); - type Error = (K, ::Error); - type Future = BoxFuture<'static, Result>; - - fn upgrade_outbound(mut self, resource: Stream, info: Self::Info) -> Self::Future { - let IndexedProtoName(index, info) = info; - let (key, upgrade) = self.upgrades.remove(index); - upgrade - .upgrade_outbound(resource, info) - .map(move |out| match out { - Ok(o) => Ok((key, o)), - Err(e) => Err((key, e)), - }) - .boxed() - } -} - -/// Check that no two protocol names are equal. -fn uniq_proto_names(iter: I) -> Result<(), DuplicateProtonameError> -where - I: Iterator, - T: UpgradeInfoSend, -{ - let mut set = HashSet::new(); - for infos in iter { - for i in infos.protocol_info() { - let v = Vec::from(i.as_ref()); - if set.contains(&v) { - return Err(DuplicateProtonameError(v)); - } else { - set.insert(v); - } - } - } - Ok(()) -} - -/// It is an error if two handlers share the same protocol name. -#[derive(Debug, Clone)] -pub struct DuplicateProtonameError(Vec); - -impl DuplicateProtonameError { - /// The protocol name bytes that occurred in more than one handler. - pub fn protocol_name(&self) -> &[u8] { - &self.0 - } -} - -impl fmt::Display for DuplicateProtonameError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Ok(s) = std::str::from_utf8(&self.0) { - write!(f, "duplicate protocol name: {s}") - } else { - write!(f, "duplicate protocol name: {:?}", self.0) - } - } -} - -impl error::Error for DuplicateProtonameError {} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/one_shot.rs b/third-party/libp2p-swarm-0.45.1/src/handler/one_shot.rs deleted file mode 100644 index fc1074b31e4..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/handler/one_shot.rs +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::handler::{ - ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError, - FullyNegotiatedInbound, FullyNegotiatedOutbound, SubstreamProtocol, -}; -use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend}; -use crate::StreamUpgradeError; -use smallvec::SmallVec; -use std::{error, fmt::Debug, task::Context, task::Poll, time::Duration}; - -/// A [`ConnectionHandler`] that opens a new substream for each request. -// TODO: Debug -pub struct OneShotHandler -where - TOutbound: OutboundUpgradeSend, -{ - /// The upgrade for inbound substreams. - listen_protocol: SubstreamProtocol, - /// Queue of events to produce in `poll()`. - events_out: SmallVec<[Result>; 4]>, - /// Queue of outbound substreams to open. - dial_queue: SmallVec<[TOutbound; 4]>, - /// Current number of concurrent outbound substreams being opened. - dial_negotiated: u32, - /// The configuration container for the handler - config: OneShotHandlerConfig, -} - -impl OneShotHandler -where - TOutbound: OutboundUpgradeSend, -{ - /// Creates a `OneShotHandler`. - pub fn new( - listen_protocol: SubstreamProtocol, - config: OneShotHandlerConfig, - ) -> Self { - OneShotHandler { - listen_protocol, - events_out: SmallVec::new(), - dial_queue: SmallVec::new(), - dial_negotiated: 0, - config, - } - } - - /// Returns the number of pending requests. - pub fn pending_requests(&self) -> u32 { - self.dial_negotiated + self.dial_queue.len() as u32 - } - - /// Returns a reference to the listen protocol configuration. - /// - /// > **Note**: If you modify the protocol, modifications will only applies to future inbound - /// > substreams, not the ones already being negotiated. - pub fn listen_protocol_ref(&self) -> &SubstreamProtocol { - &self.listen_protocol - } - - /// Returns a mutable reference to the listen protocol configuration. - /// - /// > **Note**: If you modify the protocol, modifications will only applies to future inbound - /// > substreams, not the ones already being negotiated. - pub fn listen_protocol_mut(&mut self) -> &mut SubstreamProtocol { - &mut self.listen_protocol - } - - /// Opens an outbound substream with `upgrade`. - pub fn send_request(&mut self, upgrade: TOutbound) { - self.dial_queue.push(upgrade); - } -} - -impl Default for OneShotHandler -where - TOutbound: OutboundUpgradeSend, - TInbound: InboundUpgradeSend + Default, -{ - fn default() -> Self { - OneShotHandler::new( - SubstreamProtocol::new(Default::default(), ()), - OneShotHandlerConfig::default(), - ) - } -} - -impl ConnectionHandler for OneShotHandler -where - TInbound: InboundUpgradeSend + Send + 'static, - TOutbound: Debug + OutboundUpgradeSend, - TInbound::Output: Into, - TOutbound::Output: Into, - TOutbound::Error: error::Error + Send + 'static, - SubstreamProtocol: Clone, - TEvent: Debug + Send + 'static, -{ - type FromBehaviour = TOutbound; - type ToBehaviour = Result>; - type InboundProtocol = TInbound; - type OutboundProtocol = TOutbound; - type OutboundOpenInfo = (); - type InboundOpenInfo = (); - - fn listen_protocol(&self) -> SubstreamProtocol { - self.listen_protocol.clone() - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - self.send_request(event); - } - - fn poll( - &mut self, - _: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - if !self.events_out.is_empty() { - return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour( - self.events_out.remove(0), - )); - } else { - self.events_out.shrink_to_fit(); - } - - if !self.dial_queue.is_empty() { - if self.dial_negotiated < self.config.max_dial_negotiated { - self.dial_negotiated += 1; - let upgrade = self.dial_queue.remove(0); - return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { - protocol: SubstreamProtocol::new(upgrade, ()) - .with_timeout(self.config.outbound_substream_timeout), - }); - } - } else { - self.dial_queue.shrink_to_fit(); - } - - Poll::Pending - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - match event { - ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { - protocol: out, - .. - }) => { - self.events_out.push(Ok(out.into())); - } - ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { - protocol: out, - .. - }) => { - self.dial_negotiated -= 1; - self.events_out.push(Ok(out.into())); - } - ConnectionEvent::DialUpgradeError(DialUpgradeError { error, .. }) => { - self.events_out.push(Err(error)); - } - ConnectionEvent::AddressChange(_) - | ConnectionEvent::ListenUpgradeError(_) - | ConnectionEvent::LocalProtocolsChange(_) - | ConnectionEvent::RemoteProtocolsChange(_) => {} - } - } -} - -/// Configuration parameters for the `OneShotHandler` -#[derive(Debug)] -pub struct OneShotHandlerConfig { - /// Timeout for outbound substream upgrades. - pub outbound_substream_timeout: Duration, - /// Maximum number of concurrent outbound substreams being opened. - pub max_dial_negotiated: u32, -} - -impl Default for OneShotHandlerConfig { - fn default() -> Self { - OneShotHandlerConfig { - outbound_substream_timeout: Duration::from_secs(10), - max_dial_negotiated: 8, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use futures::executor::block_on; - use futures::future::poll_fn; - use libp2p_core::upgrade::DeniedUpgrade; - use void::Void; - - #[test] - fn do_not_keep_idle_connection_alive() { - let mut handler: OneShotHandler<_, DeniedUpgrade, Void> = OneShotHandler::new( - SubstreamProtocol::new(DeniedUpgrade {}, ()), - Default::default(), - ); - - block_on(poll_fn(|cx| loop { - if handler.poll(cx).is_pending() { - return Poll::Ready(()); - } - })); - - assert!(!handler.connection_keep_alive()); - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/pending.rs b/third-party/libp2p-swarm-0.45.1/src/handler/pending.rs deleted file mode 100644 index 23b9adcfd90..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/handler/pending.rs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2022 Protocol Labs. -// Copyright 2018 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::handler::{ - ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, FullyNegotiatedInbound, - FullyNegotiatedOutbound, SubstreamProtocol, -}; -use libp2p_core::upgrade::PendingUpgrade; -use std::task::{Context, Poll}; -use void::Void; - -/// Implementation of [`ConnectionHandler`] that returns a pending upgrade. -#[derive(Clone, Debug)] -pub struct PendingConnectionHandler { - protocol_name: String, -} - -impl PendingConnectionHandler { - pub fn new(protocol_name: String) -> Self { - PendingConnectionHandler { protocol_name } - } -} - -impl ConnectionHandler for PendingConnectionHandler { - type FromBehaviour = Void; - type ToBehaviour = Void; - type InboundProtocol = PendingUpgrade; - type OutboundProtocol = PendingUpgrade; - type OutboundOpenInfo = Void; - type InboundOpenInfo = (); - - fn listen_protocol(&self) -> SubstreamProtocol { - SubstreamProtocol::new(PendingUpgrade::new(self.protocol_name.clone()), ()) - } - - fn on_behaviour_event(&mut self, v: Self::FromBehaviour) { - void::unreachable(v) - } - - fn poll( - &mut self, - _: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - Poll::Pending - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - match event { - ConnectionEvent::FullyNegotiatedInbound(FullyNegotiatedInbound { - protocol, .. - }) => void::unreachable(protocol), - ConnectionEvent::FullyNegotiatedOutbound(FullyNegotiatedOutbound { - protocol, - info: _info, - }) => { - void::unreachable(protocol); - #[allow(unreachable_code, clippy::used_underscore_binding)] - { - void::unreachable(_info); - } - } - ConnectionEvent::AddressChange(_) - | ConnectionEvent::DialUpgradeError(_) - | ConnectionEvent::ListenUpgradeError(_) - | ConnectionEvent::LocalProtocolsChange(_) - | ConnectionEvent::RemoteProtocolsChange(_) => {} - } - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/handler/select.rs b/third-party/libp2p-swarm-0.45.1/src/handler/select.rs deleted file mode 100644 index e049252d448..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/handler/select.rs +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::handler::{ - AddressChange, ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, DialUpgradeError, - FullyNegotiatedInbound, FullyNegotiatedOutbound, InboundUpgradeSend, ListenUpgradeError, - OutboundUpgradeSend, StreamUpgradeError, SubstreamProtocol, -}; -use crate::upgrade::SendWrapper; -use either::Either; -use futures::{future, ready}; -use libp2p_core::upgrade::SelectUpgrade; -use std::{cmp, task::Context, task::Poll}; - -/// Implementation of [`ConnectionHandler`] that combines two protocols into one. -#[derive(Debug, Clone)] -pub struct ConnectionHandlerSelect { - /// The first protocol. - proto1: TProto1, - /// The second protocol. - proto2: TProto2, -} - -impl ConnectionHandlerSelect { - /// Builds a [`ConnectionHandlerSelect`]. - pub(crate) fn new(proto1: TProto1, proto2: TProto2) -> Self { - ConnectionHandlerSelect { proto1, proto2 } - } - - pub fn into_inner(self) -> (TProto1, TProto2) { - (self.proto1, self.proto2) - } -} - -impl - FullyNegotiatedOutbound, SendWrapper>, Either> -where - S1OP: OutboundUpgradeSend, - S2OP: OutboundUpgradeSend, - S1OOI: Send + 'static, - S2OOI: Send + 'static, -{ - pub(crate) fn transpose( - self, - ) -> Either, FullyNegotiatedOutbound> { - match self { - FullyNegotiatedOutbound { - protocol: future::Either::Left(protocol), - info: Either::Left(info), - } => Either::Left(FullyNegotiatedOutbound { protocol, info }), - FullyNegotiatedOutbound { - protocol: future::Either::Right(protocol), - info: Either::Right(info), - } => Either::Right(FullyNegotiatedOutbound { protocol, info }), - _ => panic!("wrong API usage: the protocol doesn't match the upgrade info"), - } - } -} - -impl - FullyNegotiatedInbound, SendWrapper>, (S1IOI, S2IOI)> -where - S1IP: InboundUpgradeSend, - S2IP: InboundUpgradeSend, -{ - pub(crate) fn transpose( - self, - ) -> Either, FullyNegotiatedInbound> { - match self { - FullyNegotiatedInbound { - protocol: future::Either::Left(protocol), - info: (i1, _i2), - } => Either::Left(FullyNegotiatedInbound { protocol, info: i1 }), - FullyNegotiatedInbound { - protocol: future::Either::Right(protocol), - info: (_i1, i2), - } => Either::Right(FullyNegotiatedInbound { protocol, info: i2 }), - } - } -} - -impl - DialUpgradeError, Either, SendWrapper>> -where - S1OP: OutboundUpgradeSend, - S2OP: OutboundUpgradeSend, - S1OOI: Send + 'static, - S2OOI: Send + 'static, -{ - pub(crate) fn transpose( - self, - ) -> Either, DialUpgradeError> { - match self { - DialUpgradeError { - info: Either::Left(info), - error: StreamUpgradeError::Apply(Either::Left(err)), - } => Either::Left(DialUpgradeError { - info, - error: StreamUpgradeError::Apply(err), - }), - DialUpgradeError { - info: Either::Right(info), - error: StreamUpgradeError::Apply(Either::Right(err)), - } => Either::Right(DialUpgradeError { - info, - error: StreamUpgradeError::Apply(err), - }), - DialUpgradeError { - info: Either::Left(info), - error: e, - } => Either::Left(DialUpgradeError { - info, - error: e.map_upgrade_err(|_| panic!("already handled above")), - }), - DialUpgradeError { - info: Either::Right(info), - error: e, - } => Either::Right(DialUpgradeError { - info, - error: e.map_upgrade_err(|_| panic!("already handled above")), - }), - } - } -} - -impl ConnectionHandlerSelect -where - TProto1: ConnectionHandler, - TProto2: ConnectionHandler, -{ - fn on_listen_upgrade_error( - &mut self, - ListenUpgradeError { - info: (i1, i2), - error, - }: ListenUpgradeError< - ::InboundOpenInfo, - ::InboundProtocol, - >, - ) { - match error { - Either::Left(error) => { - self.proto1 - .on_connection_event(ConnectionEvent::ListenUpgradeError(ListenUpgradeError { - info: i1, - error, - })); - } - Either::Right(error) => { - self.proto2 - .on_connection_event(ConnectionEvent::ListenUpgradeError(ListenUpgradeError { - info: i2, - error, - })); - } - } - } -} - -impl ConnectionHandler for ConnectionHandlerSelect -where - TProto1: ConnectionHandler, - TProto2: ConnectionHandler, -{ - type FromBehaviour = Either; - type ToBehaviour = Either; - type InboundProtocol = SelectUpgrade< - SendWrapper<::InboundProtocol>, - SendWrapper<::InboundProtocol>, - >; - type OutboundProtocol = - Either, SendWrapper>; - type OutboundOpenInfo = Either; - type InboundOpenInfo = (TProto1::InboundOpenInfo, TProto2::InboundOpenInfo); - - fn listen_protocol(&self) -> SubstreamProtocol { - let proto1 = self.proto1.listen_protocol(); - let proto2 = self.proto2.listen_protocol(); - let timeout = *std::cmp::max(proto1.timeout(), proto2.timeout()); - let (u1, i1) = proto1.into_upgrade(); - let (u2, i2) = proto2.into_upgrade(); - let choice = SelectUpgrade::new(SendWrapper(u1), SendWrapper(u2)); - SubstreamProtocol::new(choice, (i1, i2)).with_timeout(timeout) - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - match event { - Either::Left(event) => self.proto1.on_behaviour_event(event), - Either::Right(event) => self.proto2.on_behaviour_event(event), - } - } - - fn connection_keep_alive(&self) -> bool { - cmp::max( - self.proto1.connection_keep_alive(), - self.proto2.connection_keep_alive(), - ) - } - - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - match self.proto1.poll(cx) { - Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(event)) => { - return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(Either::Left(event))); - } - Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { protocol }) => { - return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { - protocol: protocol - .map_upgrade(|u| Either::Left(SendWrapper(u))) - .map_info(Either::Left), - }); - } - Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols(support)) => { - return Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols(support)); - } - Poll::Pending => (), - }; - - match self.proto2.poll(cx) { - Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(event)) => { - return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(Either::Right( - event, - ))); - } - Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { protocol }) => { - return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { - protocol: protocol - .map_upgrade(|u| Either::Right(SendWrapper(u))) - .map_info(Either::Right), - }); - } - Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols(support)) => { - return Poll::Ready(ConnectionHandlerEvent::ReportRemoteProtocols(support)); - } - Poll::Pending => (), - }; - - Poll::Pending - } - - fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll> { - if let Some(e) = ready!(self.proto1.poll_close(cx)) { - return Poll::Ready(Some(Either::Left(e))); - } - - if let Some(e) = ready!(self.proto2.poll_close(cx)) { - return Poll::Ready(Some(Either::Right(e))); - } - - Poll::Ready(None) - } - - fn on_connection_event( - &mut self, - event: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - match event { - ConnectionEvent::FullyNegotiatedOutbound(fully_negotiated_outbound) => { - match fully_negotiated_outbound.transpose() { - Either::Left(f) => self - .proto1 - .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(f)), - Either::Right(f) => self - .proto2 - .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(f)), - } - } - ConnectionEvent::FullyNegotiatedInbound(fully_negotiated_inbound) => { - match fully_negotiated_inbound.transpose() { - Either::Left(f) => self - .proto1 - .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(f)), - Either::Right(f) => self - .proto2 - .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(f)), - } - } - ConnectionEvent::AddressChange(address) => { - self.proto1 - .on_connection_event(ConnectionEvent::AddressChange(AddressChange { - new_address: address.new_address, - })); - - self.proto2 - .on_connection_event(ConnectionEvent::AddressChange(AddressChange { - new_address: address.new_address, - })); - } - ConnectionEvent::DialUpgradeError(dial_upgrade_error) => { - match dial_upgrade_error.transpose() { - Either::Left(err) => self - .proto1 - .on_connection_event(ConnectionEvent::DialUpgradeError(err)), - Either::Right(err) => self - .proto2 - .on_connection_event(ConnectionEvent::DialUpgradeError(err)), - } - } - ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => { - self.on_listen_upgrade_error(listen_upgrade_error) - } - ConnectionEvent::LocalProtocolsChange(supported_protocols) => { - self.proto1 - .on_connection_event(ConnectionEvent::LocalProtocolsChange( - supported_protocols.clone(), - )); - self.proto2 - .on_connection_event(ConnectionEvent::LocalProtocolsChange( - supported_protocols, - )); - } - ConnectionEvent::RemoteProtocolsChange(supported_protocols) => { - self.proto1 - .on_connection_event(ConnectionEvent::RemoteProtocolsChange( - supported_protocols.clone(), - )); - self.proto2 - .on_connection_event(ConnectionEvent::RemoteProtocolsChange( - supported_protocols, - )); - } - } - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/lib.rs b/third-party/libp2p-swarm-0.45.1/src/lib.rs deleted file mode 100644 index 81b1ca1a68d..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/lib.rs +++ /dev/null @@ -1,2346 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -//! High-level network manager. -//! -//! A [`Swarm`] contains the state of the network as a whole. The entire -//! behaviour of a libp2p network can be controlled through the `Swarm`. -//! The `Swarm` struct contains all active and pending connections to -//! remotes and manages the state of all the substreams that have been -//! opened, and all the upgrades that were built upon these substreams. -//! -//! # Initializing a Swarm -//! -//! Creating a `Swarm` requires three things: -//! -//! 1. A network identity of the local node in form of a [`PeerId`]. -//! 2. An implementation of the [`Transport`] trait. This is the type that -//! will be used in order to reach nodes on the network based on their -//! address. See the `transport` module for more information. -//! 3. An implementation of the [`NetworkBehaviour`] trait. This is a state -//! machine that defines how the swarm should behave once it is connected -//! to a node. -//! -//! # Network Behaviour -//! -//! The [`NetworkBehaviour`] trait is implemented on types that indicate to -//! the swarm how it should behave. This includes which protocols are supported -//! and which nodes to try to connect to. It is the `NetworkBehaviour` that -//! controls what happens on the network. Multiple types that implement -//! `NetworkBehaviour` can be composed into a single behaviour. -//! -//! # Protocols Handler -//! -//! The [`ConnectionHandler`] trait defines how each active connection to a -//! remote should behave: how to handle incoming substreams, which protocols -//! are supported, when to open a new outbound substream, etc. -//! - -#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] - -mod connection; -mod executor; -mod stream; -mod stream_protocol; -#[cfg(test)] -mod test; -mod upgrade; - -pub mod behaviour; -pub mod dial_opts; -pub mod dummy; -pub mod handler; -mod listen_opts; -mod translation; - -/// Bundles all symbols required for the [`libp2p_swarm_derive::NetworkBehaviour`] macro. -#[doc(hidden)] -pub mod derive_prelude { - pub use crate::behaviour::AddressChange; - pub use crate::behaviour::ConnectionClosed; - pub use crate::behaviour::ConnectionEstablished; - pub use crate::behaviour::DialFailure; - pub use crate::behaviour::ExpiredListenAddr; - pub use crate::behaviour::ExternalAddrConfirmed; - pub use crate::behaviour::ExternalAddrExpired; - pub use crate::behaviour::FromSwarm; - pub use crate::behaviour::ListenFailure; - pub use crate::behaviour::ListenerClosed; - pub use crate::behaviour::ListenerError; - pub use crate::behaviour::NewExternalAddrCandidate; - pub use crate::behaviour::NewExternalAddrOfPeer; - pub use crate::behaviour::NewListenAddr; - pub use crate::behaviour::NewListener; - pub use crate::connection::ConnectionId; - pub use crate::ConnectionDenied; - pub use crate::ConnectionHandler; - pub use crate::ConnectionHandlerSelect; - pub use crate::DialError; - pub use crate::NetworkBehaviour; - pub use crate::THandler; - pub use crate::THandlerInEvent; - pub use crate::THandlerOutEvent; - pub use crate::ToSwarm; - pub use either::Either; - pub use futures::prelude as futures; - pub use libp2p_core::transport::{ListenerId, PortUse}; - pub use libp2p_core::ConnectedPoint; - pub use libp2p_core::Endpoint; - pub use libp2p_core::Multiaddr; - pub use libp2p_identity::PeerId; -} - -pub use behaviour::{ - AddressChange, CloseConnection, ConnectionClosed, DialFailure, ExpiredListenAddr, - ExternalAddrExpired, ExternalAddresses, FromSwarm, ListenAddresses, ListenFailure, - ListenerClosed, ListenerError, NetworkBehaviour, NewExternalAddrCandidate, - NewExternalAddrOfPeer, NewListenAddr, NotifyHandler, PeerAddresses, ToSwarm, -}; -pub use connection::pool::ConnectionCounters; -pub use connection::{ConnectionError, ConnectionId, SupportedProtocols}; -pub use executor::Executor; -pub use handler::{ - ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerSelect, OneShotHandler, - OneShotHandlerConfig, StreamUpgradeError, SubstreamProtocol, -}; -#[cfg(feature = "macros")] -pub use libp2p_swarm_derive::NetworkBehaviour; -pub use listen_opts::ListenOpts; -pub use stream::Stream; -pub use stream_protocol::{InvalidProtocol, StreamProtocol}; - -use crate::behaviour::ExternalAddrConfirmed; -use crate::handler::UpgradeInfoSend; -use connection::pool::{EstablishedConnection, Pool, PoolConfig, PoolEvent}; -use connection::IncomingInfo; -use connection::{ - PendingConnectionError, PendingInboundConnectionError, PendingOutboundConnectionError, -}; -use dial_opts::{DialOpts, PeerCondition}; -use futures::{prelude::*, stream::FusedStream}; - -use libp2p_core::{ - connection::ConnectedPoint, - muxing::StreamMuxerBox, - transport::{self, ListenerId, TransportError, TransportEvent}, - Multiaddr, Transport, -}; -use libp2p_identity::PeerId; - -use smallvec::SmallVec; -use std::collections::{HashMap, HashSet, VecDeque}; -use std::num::{NonZeroU32, NonZeroU8, NonZeroUsize}; -use std::time::Duration; -use std::{ - error, fmt, io, - pin::Pin, - task::{Context, Poll}, -}; -use tracing::Instrument; -#[doc(hidden)] -pub use translation::_address_translation; - -/// Event generated by the [`NetworkBehaviour`] that the swarm will report back. -type TBehaviourOutEvent = ::ToSwarm; - -/// [`ConnectionHandler`] of the [`NetworkBehaviour`] for all the protocols the [`NetworkBehaviour`] -/// supports. -pub type THandler = ::ConnectionHandler; - -/// Custom event that can be received by the [`ConnectionHandler`] of the -/// [`NetworkBehaviour`]. -pub type THandlerInEvent = as ConnectionHandler>::FromBehaviour; - -/// Custom event that can be produced by the [`ConnectionHandler`] of the [`NetworkBehaviour`]. -pub type THandlerOutEvent = as ConnectionHandler>::ToBehaviour; - -/// Event generated by the `Swarm`. -#[derive(Debug)] -#[non_exhaustive] -pub enum SwarmEvent { - /// Event generated by the `NetworkBehaviour`. - Behaviour(TBehaviourOutEvent), - /// A connection to the given peer has been opened. - ConnectionEstablished { - /// Identity of the peer that we have connected to. - peer_id: PeerId, - /// Identifier of the connection. - connection_id: ConnectionId, - /// Endpoint of the connection that has been opened. - endpoint: ConnectedPoint, - /// Number of established connections to this peer, including the one that has just been - /// opened. - num_established: NonZeroU32, - /// [`Some`] when the new connection is an outgoing connection. - /// Addresses are dialed concurrently. Contains the addresses and errors - /// of dial attempts that failed before the one successful dial. - concurrent_dial_errors: Option)>>, - /// How long it took to establish this connection - established_in: std::time::Duration, - }, - /// A connection with the given peer has been closed, - /// possibly as a result of an error. - ConnectionClosed { - /// Identity of the peer that we have connected to. - peer_id: PeerId, - /// Identifier of the connection. - connection_id: ConnectionId, - /// Endpoint of the connection that has been closed. - endpoint: ConnectedPoint, - /// Number of other remaining connections to this same peer. - num_established: u32, - /// Reason for the disconnection, if it was not a successful - /// active close. - cause: Option, - }, - /// A new connection arrived on a listener and is in the process of protocol negotiation. - /// - /// A corresponding [`ConnectionEstablished`](SwarmEvent::ConnectionEstablished) or - /// [`IncomingConnectionError`](SwarmEvent::IncomingConnectionError) event will later be - /// generated for this connection. - IncomingConnection { - /// Identifier of the connection. - connection_id: ConnectionId, - /// Local connection address. - /// This address has been earlier reported with a [`NewListenAddr`](SwarmEvent::NewListenAddr) - /// event. - local_addr: Multiaddr, - /// Address used to send back data to the remote. - send_back_addr: Multiaddr, - }, - /// An error happened on an inbound connection during its initial handshake. - /// - /// This can include, for example, an error during the handshake of the encryption layer, or - /// the connection unexpectedly closed. - IncomingConnectionError { - /// Identifier of the connection. - connection_id: ConnectionId, - /// Local connection address. - /// This address has been earlier reported with a [`NewListenAddr`](SwarmEvent::NewListenAddr) - /// event. - local_addr: Multiaddr, - /// Address used to send back data to the remote. - send_back_addr: Multiaddr, - /// The error that happened. - error: ListenError, - }, - /// An error happened on an outbound connection. - OutgoingConnectionError { - /// Identifier of the connection. - connection_id: ConnectionId, - /// If known, [`PeerId`] of the peer we tried to reach. - peer_id: Option, - /// Error that has been encountered. - error: DialError, - }, - /// One of our listeners has reported a new local listening address. - NewListenAddr { - /// The listener that is listening on the new address. - listener_id: ListenerId, - /// The new address that is being listened on. - address: Multiaddr, - }, - /// One of our listeners has reported the expiration of a listening address. - ExpiredListenAddr { - /// The listener that is no longer listening on the address. - listener_id: ListenerId, - /// The expired address. - address: Multiaddr, - }, - /// One of the listeners gracefully closed. - ListenerClosed { - /// The listener that closed. - listener_id: ListenerId, - /// The addresses that the listener was listening on. These addresses are now considered - /// expired, similar to if a [`ExpiredListenAddr`](SwarmEvent::ExpiredListenAddr) event - /// has been generated for each of them. - addresses: Vec, - /// Reason for the closure. Contains `Ok(())` if the stream produced `None`, or `Err` - /// if the stream produced an error. - reason: Result<(), io::Error>, - }, - /// One of the listeners reported a non-fatal error. - ListenerError { - /// The listener that errored. - listener_id: ListenerId, - /// The listener error. - error: io::Error, - }, - /// A new dialing attempt has been initiated by the [`NetworkBehaviour`] - /// implementation. - /// - /// A [`ConnectionEstablished`](SwarmEvent::ConnectionEstablished) event is - /// reported if the dialing attempt succeeds, otherwise a - /// [`OutgoingConnectionError`](SwarmEvent::OutgoingConnectionError) event - /// is reported. - Dialing { - /// Identity of the peer that we are connecting to. - peer_id: Option, - - /// Identifier of the connection. - connection_id: ConnectionId, - }, - /// We have discovered a new candidate for an external address for us. - NewExternalAddrCandidate { address: Multiaddr }, - /// An external address of the local node was confirmed. - ExternalAddrConfirmed { address: Multiaddr }, - /// An external address of the local node expired, i.e. is no-longer confirmed. - ExternalAddrExpired { address: Multiaddr }, - /// We have discovered a new address of a peer. - NewExternalAddrOfPeer { peer_id: PeerId, address: Multiaddr }, -} - -impl SwarmEvent { - /// Extract the `TBehaviourOutEvent` from this [`SwarmEvent`] in case it is the `Behaviour` variant, otherwise fail. - #[allow(clippy::result_large_err)] - pub fn try_into_behaviour_event(self) -> Result { - match self { - SwarmEvent::Behaviour(inner) => Ok(inner), - other => Err(other), - } - } -} - -/// Contains the state of the network, plus the way it should behave. -/// -/// Note: Needs to be polled via `` in order to make -/// progress. -pub struct Swarm -where - TBehaviour: NetworkBehaviour, -{ - /// [`Transport`] for dialing remote peers and listening for incoming connection. - transport: transport::Boxed<(PeerId, StreamMuxerBox)>, - - /// The nodes currently active. - pool: Pool>, - - /// The local peer ID. - local_peer_id: PeerId, - - /// Handles which nodes to connect to and how to handle the events sent back by the protocol - /// handlers. - behaviour: TBehaviour, - - /// List of protocols that the behaviour says it supports. - supported_protocols: SmallVec<[Vec; 16]>, - - confirmed_external_addr: HashSet, - - /// Multiaddresses that our listeners are listening on, - listened_addrs: HashMap>, - - /// Pending event to be delivered to connection handlers - /// (or dropped if the peer disconnected) before the `behaviour` - /// can be polled again. - pending_handler_event: Option<(PeerId, PendingNotifyHandler, THandlerInEvent)>, - - pending_swarm_events: VecDeque>, -} - -impl Unpin for Swarm where TBehaviour: NetworkBehaviour {} - -impl Swarm -where - TBehaviour: NetworkBehaviour, -{ - /// Creates a new [`Swarm`] from the given [`Transport`], [`NetworkBehaviour`], [`PeerId`] and - /// [`Config`]. - pub fn new( - transport: transport::Boxed<(PeerId, StreamMuxerBox)>, - behaviour: TBehaviour, - local_peer_id: PeerId, - config: Config, - ) -> Self { - tracing::info!(%local_peer_id); - - Swarm { - local_peer_id, - transport, - pool: Pool::new(local_peer_id, config.pool_config), - behaviour, - supported_protocols: Default::default(), - confirmed_external_addr: Default::default(), - listened_addrs: HashMap::new(), - pending_handler_event: None, - pending_swarm_events: VecDeque::default(), - } - } - - /// Returns information about the connections underlying the [`Swarm`]. - pub fn network_info(&self) -> NetworkInfo { - let num_peers = self.pool.num_peers(); - let connection_counters = self.pool.counters().clone(); - NetworkInfo { - num_peers, - connection_counters, - } - } - - /// Starts listening on the given address. - /// Returns an error if the address is not supported. - /// - /// Listeners report their new listening addresses as [`SwarmEvent::NewListenAddr`]. - /// Depending on the underlying transport, one listener may have multiple listening addresses. - pub fn listen_on(&mut self, addr: Multiaddr) -> Result> { - let opts = ListenOpts::new(addr); - let id = opts.listener_id(); - self.add_listener(opts)?; - Ok(id) - } - - /// Remove some listener. - /// - /// Returns `true` if there was a listener with this ID, `false` - /// otherwise. - pub fn remove_listener(&mut self, listener_id: ListenerId) -> bool { - self.transport.remove_listener(listener_id) - } - - /// Dial a known or unknown peer. - /// - /// See also [`DialOpts`]. - /// - /// ``` - /// # use libp2p_swarm::Swarm; - /// # use libp2p_swarm::dial_opts::{DialOpts, PeerCondition}; - /// # use libp2p_core::{Multiaddr, Transport}; - /// # use libp2p_core::transport::dummy::DummyTransport; - /// # use libp2p_swarm::dummy; - /// # use libp2p_identity::PeerId; - /// # - /// # #[tokio::main] - /// # async fn main() { - /// let mut swarm = build_swarm(); - /// - /// // Dial a known peer. - /// swarm.dial(PeerId::random()); - /// - /// // Dial an unknown peer. - /// swarm.dial("/ip6/::1/tcp/12345".parse::().unwrap()); - /// # } - /// - /// # fn build_swarm() -> Swarm { - /// # Swarm::new(DummyTransport::new().boxed(), dummy::Behaviour, PeerId::random(), libp2p_swarm::Config::with_tokio_executor()) - /// # } - /// ``` - pub fn dial(&mut self, opts: impl Into) -> Result<(), DialError> { - let dial_opts = opts.into(); - - let peer_id = dial_opts.get_peer_id(); - let condition = dial_opts.peer_condition(); - let connection_id = dial_opts.connection_id(); - - let should_dial = match (condition, peer_id) { - (_, None) => true, - (PeerCondition::Always, _) => true, - (PeerCondition::Disconnected, Some(peer_id)) => !self.pool.is_connected(peer_id), - (PeerCondition::NotDialing, Some(peer_id)) => !self.pool.is_dialing(peer_id), - (PeerCondition::DisconnectedAndNotDialing, Some(peer_id)) => { - !self.pool.is_dialing(peer_id) && !self.pool.is_connected(peer_id) - } - }; - - if !should_dial { - let e = DialError::DialPeerConditionFalse(condition); - - self.behaviour - .on_swarm_event(FromSwarm::DialFailure(DialFailure { - peer_id, - error: &e, - connection_id, - })); - - return Err(e); - } - - let addresses = { - let mut addresses_from_opts = dial_opts.get_addresses(); - - match self.behaviour.handle_pending_outbound_connection( - connection_id, - peer_id, - addresses_from_opts.as_slice(), - dial_opts.role_override(), - ) { - Ok(addresses) => { - if dial_opts.extend_addresses_through_behaviour() { - addresses_from_opts.extend(addresses) - } else { - let num_addresses = addresses.len(); - - if num_addresses > 0 { - tracing::debug!( - connection=%connection_id, - discarded_addresses_count=%num_addresses, - "discarding addresses from `NetworkBehaviour` because `DialOpts::extend_addresses_through_behaviour is `false` for connection" - ) - } - } - } - Err(cause) => { - let error = DialError::Denied { cause }; - - self.behaviour - .on_swarm_event(FromSwarm::DialFailure(DialFailure { - peer_id, - error: &error, - connection_id, - })); - - return Err(error); - } - } - - let mut unique_addresses = HashSet::new(); - addresses_from_opts.retain(|addr| { - !self.listened_addrs.values().flatten().any(|a| a == addr) - && unique_addresses.insert(addr.clone()) - }); - - if addresses_from_opts.is_empty() { - let error = DialError::NoAddresses; - self.behaviour - .on_swarm_event(FromSwarm::DialFailure(DialFailure { - peer_id, - error: &error, - connection_id, - })); - return Err(error); - }; - - addresses_from_opts - }; - - let dials = addresses - .into_iter() - .map(|a| match peer_id.map_or(Ok(a.clone()), |p| a.with_p2p(p)) { - Ok(address) => { - let dial = self.transport.dial( - address.clone(), - transport::DialOpts { - role: dial_opts.role_override(), - port_use: dial_opts.port_use(), - }, - ); - let span = tracing::debug_span!(parent: tracing::Span::none(), "Transport::dial", %address); - span.follows_from(tracing::Span::current()); - match dial { - Ok(fut) => fut - .map(|r| (address, r.map_err(TransportError::Other))) - .instrument(span) - .boxed(), - Err(err) => futures::future::ready((address, Err(err))).boxed(), - } - } - Err(address) => futures::future::ready(( - address.clone(), - Err(TransportError::MultiaddrNotSupported(address)), - )) - .boxed(), - }) - .collect(); - - self.pool.add_outgoing( - dials, - peer_id, - dial_opts.role_override(), - dial_opts.port_use(), - dial_opts.dial_concurrency_override(), - connection_id, - ); - - Ok(()) - } - - /// Returns an iterator that produces the list of addresses we're listening on. - pub fn listeners(&self) -> impl Iterator { - self.listened_addrs.values().flatten() - } - - /// Returns the peer ID of the swarm passed as parameter. - pub fn local_peer_id(&self) -> &PeerId { - &self.local_peer_id - } - - /// List all **confirmed** external address for the local node. - pub fn external_addresses(&self) -> impl Iterator { - self.confirmed_external_addr.iter() - } - - fn add_listener(&mut self, opts: ListenOpts) -> Result<(), TransportError> { - let addr = opts.address(); - let listener_id = opts.listener_id(); - - if let Err(e) = self.transport.listen_on(listener_id, addr.clone()) { - self.behaviour - .on_swarm_event(FromSwarm::ListenerError(behaviour::ListenerError { - listener_id, - err: &e, - })); - - return Err(e); - } - - self.behaviour - .on_swarm_event(FromSwarm::NewListener(behaviour::NewListener { - listener_id, - })); - - Ok(()) - } - - /// Add a **confirmed** external address for the local node. - /// - /// This function should only be called with addresses that are guaranteed to be reachable. - /// The address is broadcast to all [`NetworkBehaviour`]s via [`FromSwarm::ExternalAddrConfirmed`]. - pub fn add_external_address(&mut self, a: Multiaddr) { - self.behaviour - .on_swarm_event(FromSwarm::ExternalAddrConfirmed(ExternalAddrConfirmed { - addr: &a, - })); - self.confirmed_external_addr.insert(a); - } - - /// Remove an external address for the local node. - /// - /// The address is broadcast to all [`NetworkBehaviour`]s via [`FromSwarm::ExternalAddrExpired`]. - pub fn remove_external_address(&mut self, addr: &Multiaddr) { - self.behaviour - .on_swarm_event(FromSwarm::ExternalAddrExpired(ExternalAddrExpired { addr })); - self.confirmed_external_addr.remove(addr); - } - - /// Add a new external address of a remote peer. - /// - /// The address is broadcast to all [`NetworkBehaviour`]s via [`FromSwarm::NewExternalAddrOfPeer`]. - pub fn add_peer_address(&mut self, peer_id: PeerId, addr: Multiaddr) { - self.behaviour - .on_swarm_event(FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { - peer_id, - addr: &addr, - })) - } - - /// Disconnects a peer by its peer ID, closing all connections to said peer. - /// - /// Returns `Ok(())` if there was one or more established connections to the peer. - /// - /// Closing a connection via [`Swarm::disconnect_peer_id`] will poll [`ConnectionHandler::poll_close`] to completion. - /// Use this function if you want to close a connection _despite_ it still being in use by one or more handlers. - #[allow(clippy::result_unit_err)] - pub fn disconnect_peer_id(&mut self, peer_id: PeerId) -> Result<(), ()> { - let was_connected = self.pool.is_connected(peer_id); - self.pool.disconnect(peer_id); - - if was_connected { - Ok(()) - } else { - Err(()) - } - } - - /// Attempt to gracefully close a connection. - /// - /// Closing a connection is asynchronous but this function will return immediately. - /// A [`SwarmEvent::ConnectionClosed`] event will be emitted once the connection is actually closed. - /// - /// # Returns - /// - /// - `true` if the connection was established and is now being closed. - /// - `false` if the connection was not found or is no longer established. - pub fn close_connection(&mut self, connection_id: ConnectionId) -> bool { - if let Some(established) = self.pool.get_established(connection_id) { - established.start_close(); - return true; - } - - false - } - - /// Checks whether there is an established connection to a peer. - pub fn is_connected(&self, peer_id: &PeerId) -> bool { - self.pool.is_connected(*peer_id) - } - - /// Returns the currently connected peers. - pub fn connected_peers(&self) -> impl Iterator { - self.pool.iter_connected() - } - - /// Returns a reference to the provided [`NetworkBehaviour`]. - pub fn behaviour(&self) -> &TBehaviour { - &self.behaviour - } - - /// Returns a mutable reference to the provided [`NetworkBehaviour`]. - pub fn behaviour_mut(&mut self) -> &mut TBehaviour { - &mut self.behaviour - } - - fn handle_pool_event(&mut self, event: PoolEvent>) { - match event { - PoolEvent::ConnectionEstablished { - peer_id, - id, - endpoint, - connection, - concurrent_dial_errors, - established_in, - } => { - let handler = match endpoint.clone() { - ConnectedPoint::Dialer { - address, - role_override, - port_use, - } => { - match self.behaviour.handle_established_outbound_connection( - id, - peer_id, - &address, - role_override, - port_use, - ) { - Ok(handler) => handler, - Err(cause) => { - let dial_error = DialError::Denied { cause }; - self.behaviour.on_swarm_event(FromSwarm::DialFailure( - DialFailure { - connection_id: id, - error: &dial_error, - peer_id: Some(peer_id), - }, - )); - - self.pending_swarm_events.push_back( - SwarmEvent::OutgoingConnectionError { - peer_id: Some(peer_id), - connection_id: id, - error: dial_error, - }, - ); - return; - } - } - } - ConnectedPoint::Listener { - local_addr, - send_back_addr, - } => { - match self.behaviour.handle_established_inbound_connection( - id, - peer_id, - &local_addr, - &send_back_addr, - ) { - Ok(handler) => handler, - Err(cause) => { - let listen_error = ListenError::Denied { cause }; - self.behaviour.on_swarm_event(FromSwarm::ListenFailure( - ListenFailure { - local_addr: &local_addr, - send_back_addr: &send_back_addr, - error: &listen_error, - connection_id: id, - peer_id: Some(peer_id), - }, - )); - - self.pending_swarm_events.push_back( - SwarmEvent::IncomingConnectionError { - connection_id: id, - send_back_addr, - local_addr, - error: listen_error, - }, - ); - return; - } - } - } - }; - - let supported_protocols = handler - .listen_protocol() - .upgrade() - .protocol_info() - .map(|p| p.as_ref().as_bytes().to_vec()) - .collect(); - let other_established_connection_ids = self - .pool - .iter_established_connections_of_peer(&peer_id) - .collect::>(); - let num_established = NonZeroU32::new( - u32::try_from(other_established_connection_ids.len() + 1).unwrap(), - ) - .expect("n + 1 is always non-zero; qed"); - - self.pool - .spawn_connection(id, peer_id, &endpoint, connection, handler); - - tracing::debug!( - peer=%peer_id, - ?endpoint, - total_peers=%num_established, - "Connection established" - ); - let failed_addresses = concurrent_dial_errors - .as_ref() - .map(|es| { - es.iter() - .map(|(a, _)| a) - .cloned() - .collect::>() - }) - .unwrap_or_default(); - self.behaviour - .on_swarm_event(FromSwarm::ConnectionEstablished( - behaviour::ConnectionEstablished { - peer_id, - connection_id: id, - endpoint: &endpoint, - failed_addresses: &failed_addresses, - other_established: other_established_connection_ids.len(), - }, - )); - self.supported_protocols = supported_protocols; - self.pending_swarm_events - .push_back(SwarmEvent::ConnectionEstablished { - peer_id, - connection_id: id, - num_established, - endpoint, - concurrent_dial_errors, - established_in, - }); - } - PoolEvent::PendingOutboundConnectionError { - id: connection_id, - error, - peer, - } => { - let error = error.into(); - - self.behaviour - .on_swarm_event(FromSwarm::DialFailure(DialFailure { - peer_id: peer, - error: &error, - connection_id, - })); - - if let Some(peer) = peer { - tracing::debug!(%peer, "Connection attempt to peer failed with {:?}.", error,); - } else { - tracing::debug!("Connection attempt to unknown peer failed with {:?}", error); - } - - self.pending_swarm_events - .push_back(SwarmEvent::OutgoingConnectionError { - peer_id: peer, - connection_id, - error, - }); - } - PoolEvent::PendingInboundConnectionError { - id, - send_back_addr, - local_addr, - error, - } => { - let error = error.into(); - - tracing::debug!("Incoming connection failed: {:?}", error); - self.behaviour - .on_swarm_event(FromSwarm::ListenFailure(ListenFailure { - local_addr: &local_addr, - send_back_addr: &send_back_addr, - error: &error, - connection_id: id, - peer_id: None, - })); - self.pending_swarm_events - .push_back(SwarmEvent::IncomingConnectionError { - connection_id: id, - local_addr, - send_back_addr, - error, - }); - } - PoolEvent::ConnectionClosed { - id, - connected, - error, - remaining_established_connection_ids, - .. - } => { - if let Some(error) = error.as_ref() { - tracing::debug!( - total_peers=%remaining_established_connection_ids.len(), - "Connection closed with error {:?}: {:?}", - error, - connected, - ); - } else { - tracing::debug!( - total_peers=%remaining_established_connection_ids.len(), - "Connection closed: {:?}", - connected - ); - } - let peer_id = connected.peer_id; - let endpoint = connected.endpoint; - let num_established = - u32::try_from(remaining_established_connection_ids.len()).unwrap(); - - self.behaviour - .on_swarm_event(FromSwarm::ConnectionClosed(ConnectionClosed { - peer_id, - connection_id: id, - endpoint: &endpoint, - cause: error.as_ref(), - remaining_established: num_established as usize, - })); - self.pending_swarm_events - .push_back(SwarmEvent::ConnectionClosed { - peer_id, - connection_id: id, - endpoint, - cause: error, - num_established, - }); - } - PoolEvent::ConnectionEvent { peer_id, id, event } => { - self.behaviour - .on_connection_handler_event(peer_id, id, event); - } - PoolEvent::AddressChange { - peer_id, - id, - new_endpoint, - old_endpoint, - } => { - self.behaviour - .on_swarm_event(FromSwarm::AddressChange(AddressChange { - peer_id, - connection_id: id, - old: &old_endpoint, - new: &new_endpoint, - })); - } - } - } - - fn handle_transport_event( - &mut self, - event: TransportEvent< - as Transport>::ListenerUpgrade, - io::Error, - >, - ) { - match event { - TransportEvent::Incoming { - listener_id: _, - upgrade, - local_addr, - send_back_addr, - } => { - let connection_id = ConnectionId::next(); - - match self.behaviour.handle_pending_inbound_connection( - connection_id, - &local_addr, - &send_back_addr, - ) { - Ok(()) => {} - Err(cause) => { - let listen_error = ListenError::Denied { cause }; - - self.behaviour - .on_swarm_event(FromSwarm::ListenFailure(ListenFailure { - local_addr: &local_addr, - send_back_addr: &send_back_addr, - error: &listen_error, - connection_id, - peer_id: None, - })); - - self.pending_swarm_events - .push_back(SwarmEvent::IncomingConnectionError { - connection_id, - local_addr, - send_back_addr, - error: listen_error, - }); - return; - } - } - - self.pool.add_incoming( - upgrade, - IncomingInfo { - local_addr: &local_addr, - send_back_addr: &send_back_addr, - }, - connection_id, - ); - - self.pending_swarm_events - .push_back(SwarmEvent::IncomingConnection { - connection_id, - local_addr, - send_back_addr, - }) - } - TransportEvent::NewAddress { - listener_id, - listen_addr, - } => { - tracing::debug!( - listener=?listener_id, - address=%listen_addr, - "New listener address" - ); - let addrs = self.listened_addrs.entry(listener_id).or_default(); - if !addrs.contains(&listen_addr) { - addrs.push(listen_addr.clone()) - } - self.behaviour - .on_swarm_event(FromSwarm::NewListenAddr(NewListenAddr { - listener_id, - addr: &listen_addr, - })); - self.pending_swarm_events - .push_back(SwarmEvent::NewListenAddr { - listener_id, - address: listen_addr, - }) - } - TransportEvent::AddressExpired { - listener_id, - listen_addr, - } => { - tracing::debug!( - listener=?listener_id, - address=%listen_addr, - "Expired listener address" - ); - if let Some(addrs) = self.listened_addrs.get_mut(&listener_id) { - addrs.retain(|a| a != &listen_addr); - } - self.behaviour - .on_swarm_event(FromSwarm::ExpiredListenAddr(ExpiredListenAddr { - listener_id, - addr: &listen_addr, - })); - self.pending_swarm_events - .push_back(SwarmEvent::ExpiredListenAddr { - listener_id, - address: listen_addr, - }) - } - TransportEvent::ListenerClosed { - listener_id, - reason, - } => { - tracing::debug!( - listener=?listener_id, - ?reason, - "Listener closed" - ); - let addrs = self.listened_addrs.remove(&listener_id).unwrap_or_default(); - for addr in addrs.iter() { - self.behaviour.on_swarm_event(FromSwarm::ExpiredListenAddr( - ExpiredListenAddr { listener_id, addr }, - )); - } - self.behaviour - .on_swarm_event(FromSwarm::ListenerClosed(ListenerClosed { - listener_id, - reason: reason.as_ref().copied(), - })); - self.pending_swarm_events - .push_back(SwarmEvent::ListenerClosed { - listener_id, - addresses: addrs.to_vec(), - reason, - }) - } - TransportEvent::ListenerError { listener_id, error } => { - self.behaviour - .on_swarm_event(FromSwarm::ListenerError(ListenerError { - listener_id, - err: &error, - })); - self.pending_swarm_events - .push_back(SwarmEvent::ListenerError { listener_id, error }) - } - } - } - - fn handle_behaviour_event( - &mut self, - event: ToSwarm>, - ) { - match event { - ToSwarm::GenerateEvent(event) => { - self.pending_swarm_events - .push_back(SwarmEvent::Behaviour(event)); - } - ToSwarm::Dial { opts } => { - let peer_id = opts.get_peer_id(); - let connection_id = opts.connection_id(); - if let Ok(()) = self.dial(opts) { - self.pending_swarm_events.push_back(SwarmEvent::Dialing { - peer_id, - connection_id, - }); - } - } - ToSwarm::ListenOn { opts } => { - // Error is dispatched internally, safe to ignore. - let _ = self.add_listener(opts); - } - ToSwarm::RemoveListener { id } => { - self.remove_listener(id); - } - ToSwarm::NotifyHandler { - peer_id, - handler, - event, - } => { - assert!(self.pending_handler_event.is_none()); - let handler = match handler { - NotifyHandler::One(connection) => PendingNotifyHandler::One(connection), - NotifyHandler::Any => { - let ids = self - .pool - .iter_established_connections_of_peer(&peer_id) - .collect(); - PendingNotifyHandler::Any(ids) - } - }; - - self.pending_handler_event = Some((peer_id, handler, event)); - } - ToSwarm::NewExternalAddrCandidate(addr) => { - self.behaviour - .on_swarm_event(FromSwarm::NewExternalAddrCandidate( - NewExternalAddrCandidate { addr: &addr }, - )); - self.pending_swarm_events - .push_back(SwarmEvent::NewExternalAddrCandidate { address: addr }); - } - ToSwarm::ExternalAddrConfirmed(addr) => { - self.add_external_address(addr.clone()); - self.pending_swarm_events - .push_back(SwarmEvent::ExternalAddrConfirmed { address: addr }); - } - ToSwarm::ExternalAddrExpired(addr) => { - self.remove_external_address(&addr); - self.pending_swarm_events - .push_back(SwarmEvent::ExternalAddrExpired { address: addr }); - } - ToSwarm::CloseConnection { - peer_id, - connection, - } => match connection { - CloseConnection::One(connection_id) => { - if let Some(conn) = self.pool.get_established(connection_id) { - conn.start_close(); - } - } - CloseConnection::All => { - self.pool.disconnect(peer_id); - } - }, - ToSwarm::NewExternalAddrOfPeer { peer_id, address } => { - self.behaviour - .on_swarm_event(FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { - peer_id, - addr: &address, - })); - self.pending_swarm_events - .push_back(SwarmEvent::NewExternalAddrOfPeer { peer_id, address }); - } - } - } - - /// Internal function used by everything event-related. - /// - /// Polls the `Swarm` for the next event. - #[tracing::instrument(level = "debug", name = "Swarm::poll", skip(self, cx))] - fn poll_next_event( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { - // We use a `this` variable because the compiler can't mutably borrow multiple times - // across a `Deref`. - let this = &mut *self; - - // This loop polls the components below in a prioritized order. - // - // 1. [`NetworkBehaviour`] - // 2. Connection [`Pool`] - // 3. [`ListenersStream`] - // - // (1) is polled before (2) to prioritize local work over work coming from a remote. - // - // (2) is polled before (3) to prioritize existing connections over upgrading new incoming connections. - loop { - if let Some(swarm_event) = this.pending_swarm_events.pop_front() { - return Poll::Ready(swarm_event); - } - - match this.pending_handler_event.take() { - // Try to deliver the pending event emitted by the [`NetworkBehaviour`] in the previous - // iteration to the connection handler(s). - Some((peer_id, handler, event)) => match handler { - PendingNotifyHandler::One(conn_id) => { - match this.pool.get_established(conn_id) { - Some(conn) => match notify_one(conn, event, cx) { - None => continue, - Some(event) => { - this.pending_handler_event = Some((peer_id, handler, event)); - } - }, - None => continue, - } - } - PendingNotifyHandler::Any(ids) => { - match notify_any::<_, TBehaviour>(ids, &mut this.pool, event, cx) { - None => continue, - Some((event, ids)) => { - let handler = PendingNotifyHandler::Any(ids); - this.pending_handler_event = Some((peer_id, handler, event)); - } - } - } - }, - // No pending event. Allow the [`NetworkBehaviour`] to make progress. - None => match this.behaviour.poll(cx) { - Poll::Pending => {} - Poll::Ready(behaviour_event) => { - this.handle_behaviour_event(behaviour_event); - - continue; - } - }, - } - - // Poll the known peers. - match this.pool.poll(cx) { - Poll::Pending => {} - Poll::Ready(pool_event) => { - this.handle_pool_event(pool_event); - continue; - } - } - - // Poll the listener(s) for new connections. - match Pin::new(&mut this.transport).poll(cx) { - Poll::Pending => {} - Poll::Ready(transport_event) => { - this.handle_transport_event(transport_event); - continue; - } - } - - return Poll::Pending; - } - } -} - -/// Connection to notify of a pending event. -/// -/// The connection IDs out of which to notify one of an event are captured at -/// the time the behaviour emits the event, in order not to forward the event to -/// a new connection which the behaviour may not have been aware of at the time -/// it issued the request for sending it. -enum PendingNotifyHandler { - One(ConnectionId), - Any(SmallVec<[ConnectionId; 10]>), -} - -/// Notify a single connection of an event. -/// -/// Returns `Some` with the given event if the connection is not currently -/// ready to receive another event, in which case the current task is -/// scheduled to be woken up. -/// -/// Returns `None` if the connection is closing or the event has been -/// successfully sent, in either case the event is consumed. -fn notify_one( - conn: &mut EstablishedConnection, - event: THandlerInEvent, - cx: &mut Context<'_>, -) -> Option { - match conn.poll_ready_notify_handler(cx) { - Poll::Pending => Some(event), - Poll::Ready(Err(())) => None, // connection is closing - Poll::Ready(Ok(())) => { - // Can now only fail if connection is closing. - let _ = conn.notify_handler(event); - None - } - } -} - -/// Notify any one of a given list of connections of a peer of an event. -/// -/// Returns `Some` with the given event and a new list of connections if -/// none of the given connections was able to receive the event but at -/// least one of them is not closing, in which case the current task -/// is scheduled to be woken up. The returned connections are those which -/// may still become ready to receive another event. -/// -/// Returns `None` if either all connections are closing or the event -/// was successfully sent to a handler, in either case the event is consumed. -fn notify_any( - ids: SmallVec<[ConnectionId; 10]>, - pool: &mut Pool, - event: THandlerInEvent, - cx: &mut Context<'_>, -) -> Option<(THandlerInEvent, SmallVec<[ConnectionId; 10]>)> -where - TBehaviour: NetworkBehaviour, - THandler: ConnectionHandler< - FromBehaviour = THandlerInEvent, - ToBehaviour = THandlerOutEvent, - >, -{ - let mut pending = SmallVec::new(); - let mut event = Some(event); // (1) - for id in ids.into_iter() { - if let Some(conn) = pool.get_established(id) { - match conn.poll_ready_notify_handler(cx) { - Poll::Pending => pending.push(id), - Poll::Ready(Err(())) => {} // connection is closing - Poll::Ready(Ok(())) => { - let e = event.take().expect("by (1),(2)"); - if let Err(e) = conn.notify_handler(e) { - event = Some(e) // (2) - } else { - break; - } - } - } - } - } - - event.and_then(|e| { - if !pending.is_empty() { - Some((e, pending)) - } else { - None - } - }) -} - -/// Stream of events returned by [`Swarm`]. -/// -/// Includes events from the [`NetworkBehaviour`] as well as events about -/// connection and listener status. See [`SwarmEvent`] for details. -/// -/// Note: This stream is infinite and it is guaranteed that -/// [`futures::Stream::poll_next`] will never return `Poll::Ready(None)`. -impl futures::Stream for Swarm -where - TBehaviour: NetworkBehaviour, -{ - type Item = SwarmEvent>; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.as_mut().poll_next_event(cx).map(Some) - } -} - -/// The stream of swarm events never terminates, so we can implement fused for it. -impl FusedStream for Swarm -where - TBehaviour: NetworkBehaviour, -{ - fn is_terminated(&self) -> bool { - false - } -} - -pub struct Config { - pool_config: PoolConfig, -} - -impl Config { - /// Creates a new [`Config`] from the given executor. The [`Swarm`] is obtained via - /// [`Swarm::new`]. - pub fn with_executor(executor: impl Executor + Send + 'static) -> Self { - Self { - pool_config: PoolConfig::new(Some(Box::new(executor))), - } - } - - #[doc(hidden)] - /// Used on connection benchmarks. - pub fn without_executor() -> Self { - Self { - pool_config: PoolConfig::new(None), - } - } - - /// Sets executor to the `wasm` executor. - /// Background tasks will be executed by the browser on the next micro-tick. - /// - /// Spawning a task is similar too: - /// ```typescript - /// function spawn(task: () => Promise) { - /// task() - /// } - /// ``` - #[cfg(feature = "wasm-bindgen")] - pub fn with_wasm_executor() -> Self { - Self::with_executor(crate::executor::WasmBindgenExecutor) - } - - /// Builds a new [`Config`] from the given `tokio` executor. - #[cfg(all( - feature = "tokio", - not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) - ))] - pub fn with_tokio_executor() -> Self { - Self::with_executor(crate::executor::TokioExecutor) - } - - /// Builds a new [`Config`] from the given `async-std` executor. - #[cfg(all( - feature = "async-std", - not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")) - ))] - pub fn with_async_std_executor() -> Self { - Self::with_executor(crate::executor::AsyncStdExecutor) - } - - /// Configures the number of events from the [`NetworkBehaviour`] in - /// destination to the [`ConnectionHandler`] that can be buffered before - /// the [`Swarm`] has to wait. An individual buffer with this number of - /// events exists for each individual connection. - /// - /// The ideal value depends on the executor used, the CPU speed, and the - /// volume of events. If this value is too low, then the [`Swarm`] will - /// be sleeping more often than necessary. Increasing this value increases - /// the overall memory usage. - pub fn with_notify_handler_buffer_size(mut self, n: NonZeroUsize) -> Self { - self.pool_config = self.pool_config.with_notify_handler_buffer_size(n); - self - } - - /// Configures the size of the buffer for events sent by a [`ConnectionHandler`] to the - /// [`NetworkBehaviour`]. - /// - /// Each connection has its own buffer. - /// - /// The ideal value depends on the executor used, the CPU speed and the volume of events. - /// If this value is too low, then the [`ConnectionHandler`]s will be sleeping more often - /// than necessary. Increasing this value increases the overall memory - /// usage, and more importantly the latency between the moment when an - /// event is emitted and the moment when it is received by the - /// [`NetworkBehaviour`]. - pub fn with_per_connection_event_buffer_size(mut self, n: usize) -> Self { - self.pool_config = self.pool_config.with_per_connection_event_buffer_size(n); - self - } - - /// Number of addresses concurrently dialed for a single outbound connection attempt. - pub fn with_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self { - self.pool_config = self.pool_config.with_dial_concurrency_factor(factor); - self - } - - /// Configures an override for the substream upgrade protocol to use. - /// - /// The subtream upgrade protocol is the multistream-select protocol - /// used for protocol negotiation on substreams. Since a listener - /// supports all existing versions, the choice of upgrade protocol - /// only effects the "dialer", i.e. the peer opening a substream. - /// - /// > **Note**: If configured, specific upgrade protocols for - /// > individual [`SubstreamProtocol`]s emitted by the `NetworkBehaviour` - /// > are ignored. - pub fn with_substream_upgrade_protocol_override( - mut self, - v: libp2p_core::upgrade::Version, - ) -> Self { - self.pool_config = self.pool_config.with_substream_upgrade_protocol_override(v); - self - } - - /// The maximum number of inbound streams concurrently negotiating on a - /// connection. New inbound streams exceeding the limit are dropped and thus - /// reset. - /// - /// Note: This only enforces a limit on the number of concurrently - /// negotiating inbound streams. The total number of inbound streams on a - /// connection is the sum of negotiating and negotiated streams. A limit on - /// the total number of streams can be enforced at the - /// [`StreamMuxerBox`] level. - pub fn with_max_negotiating_inbound_streams(mut self, v: usize) -> Self { - self.pool_config = self.pool_config.with_max_negotiating_inbound_streams(v); - self - } - - /// How long to keep a connection alive once it is idling. - /// - /// Defaults to 0. - pub fn with_idle_connection_timeout(mut self, timeout: Duration) -> Self { - self.pool_config.idle_connection_timeout = timeout; - self - } -} - -/// Possible errors when trying to establish or upgrade an outbound connection. -#[derive(Debug)] -pub enum DialError { - /// The peer identity obtained on the connection matches the local peer. - LocalPeerId { endpoint: ConnectedPoint }, - /// No addresses have been provided by [`NetworkBehaviour::handle_pending_outbound_connection`] and [`DialOpts`]. - NoAddresses, - /// The provided [`dial_opts::PeerCondition`] evaluated to false and thus - /// the dial was aborted. - DialPeerConditionFalse(dial_opts::PeerCondition), - /// Pending connection attempt has been aborted. - Aborted, - /// The peer identity obtained on the connection did not match the one that was expected. - WrongPeerId { - obtained: PeerId, - endpoint: ConnectedPoint, - }, - /// One of the [`NetworkBehaviour`]s rejected the outbound connection - /// via [`NetworkBehaviour::handle_pending_outbound_connection`] or - /// [`NetworkBehaviour::handle_established_outbound_connection`]. - Denied { cause: ConnectionDenied }, - /// An error occurred while negotiating the transport protocol(s) on a connection. - Transport(Vec<(Multiaddr, TransportError)>), -} - -impl From for DialError { - fn from(error: PendingOutboundConnectionError) -> Self { - match error { - PendingConnectionError::Aborted => DialError::Aborted, - PendingConnectionError::WrongPeerId { obtained, endpoint } => { - DialError::WrongPeerId { obtained, endpoint } - } - PendingConnectionError::LocalPeerId { endpoint } => DialError::LocalPeerId { endpoint }, - PendingConnectionError::Transport(e) => DialError::Transport(e), - } - } -} - -impl fmt::Display for DialError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DialError::NoAddresses => write!(f, "Dial error: no addresses for peer."), - DialError::LocalPeerId { endpoint } => write!( - f, - "Dial error: tried to dial local peer id at {endpoint:?}." - ), - DialError::DialPeerConditionFalse(PeerCondition::Disconnected) => write!(f, "Dial error: dial condition was configured to only happen when disconnected (`PeerCondition::Disconnected`), but node is already connected, thus cancelling new dial."), - DialError::DialPeerConditionFalse(PeerCondition::NotDialing) => write!(f, "Dial error: dial condition was configured to only happen if there is currently no ongoing dialing attempt (`PeerCondition::NotDialing`), but a dial is in progress, thus cancelling new dial."), - DialError::DialPeerConditionFalse(PeerCondition::DisconnectedAndNotDialing) => write!(f, "Dial error: dial condition was configured to only happen when both disconnected (`PeerCondition::Disconnected`) and there is currently no ongoing dialing attempt (`PeerCondition::NotDialing`), but node is already connected or dial is in progress, thus cancelling new dial."), - DialError::DialPeerConditionFalse(PeerCondition::Always) => unreachable!("Dial peer condition is by definition true."), - DialError::Aborted => write!( - f, - "Dial error: Pending connection attempt has been aborted." - ), - DialError::WrongPeerId { obtained, endpoint } => write!( - f, - "Dial error: Unexpected peer ID {obtained} at {endpoint:?}." - ), - DialError::Transport(errors) => { - write!(f, "Failed to negotiate transport protocol(s): [")?; - - for (addr, error) in errors { - write!(f, "({addr}")?; - print_error_chain(f, error)?; - write!(f, ")")?; - } - write!(f, "]")?; - - Ok(()) - } - DialError::Denied { .. } => { - write!(f, "Dial error") - } - } - } -} - -fn print_error_chain(f: &mut fmt::Formatter<'_>, e: &dyn error::Error) -> fmt::Result { - write!(f, ": {e}")?; - - if let Some(source) = e.source() { - print_error_chain(f, source)?; - } - - Ok(()) -} - -impl error::Error for DialError { - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match self { - DialError::LocalPeerId { .. } => None, - DialError::NoAddresses => None, - DialError::DialPeerConditionFalse(_) => None, - DialError::Aborted => None, - DialError::WrongPeerId { .. } => None, - DialError::Transport(_) => None, - DialError::Denied { cause } => Some(cause), - } - } -} - -/// Possible errors when upgrading an inbound connection. -#[derive(Debug)] -pub enum ListenError { - /// Pending connection attempt has been aborted. - Aborted, - /// The peer identity obtained on the connection did not match the one that was expected. - WrongPeerId { - obtained: PeerId, - endpoint: ConnectedPoint, - }, - /// The connection was dropped because it resolved to our own [`PeerId`]. - LocalPeerId { - endpoint: ConnectedPoint, - }, - Denied { - cause: ConnectionDenied, - }, - /// An error occurred while negotiating the transport protocol(s) on a connection. - Transport(TransportError), -} - -impl From for ListenError { - fn from(error: PendingInboundConnectionError) -> Self { - match error { - PendingInboundConnectionError::Transport(inner) => ListenError::Transport(inner), - PendingInboundConnectionError::Aborted => ListenError::Aborted, - PendingInboundConnectionError::WrongPeerId { obtained, endpoint } => { - ListenError::WrongPeerId { obtained, endpoint } - } - PendingInboundConnectionError::LocalPeerId { endpoint } => { - ListenError::LocalPeerId { endpoint } - } - } - } -} - -impl fmt::Display for ListenError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ListenError::Aborted => write!( - f, - "Listen error: Pending connection attempt has been aborted." - ), - ListenError::WrongPeerId { obtained, endpoint } => write!( - f, - "Listen error: Unexpected peer ID {obtained} at {endpoint:?}." - ), - ListenError::Transport(_) => { - write!(f, "Listen error: Failed to negotiate transport protocol(s)") - } - ListenError::Denied { cause } => { - write!(f, "Listen error: Denied: {cause}") - } - ListenError::LocalPeerId { endpoint } => { - write!(f, "Listen error: Local peer ID at {endpoint:?}.") - } - } - } -} - -impl error::Error for ListenError { - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match self { - ListenError::WrongPeerId { .. } => None, - ListenError::Transport(err) => Some(err), - ListenError::Aborted => None, - ListenError::Denied { cause } => Some(cause), - ListenError::LocalPeerId { .. } => None, - } - } -} - -/// A connection was denied. -/// -/// To figure out which [`NetworkBehaviour`] denied the connection, use [`ConnectionDenied::downcast`]. -#[derive(Debug)] -pub struct ConnectionDenied { - inner: Box, -} - -impl ConnectionDenied { - pub fn new(cause: impl Into>) -> Self { - Self { - inner: cause.into(), - } - } - - /// Attempt to downcast to a particular reason for why the connection was denied. - pub fn downcast(self) -> Result - where - E: error::Error + Send + Sync + 'static, - { - let inner = self - .inner - .downcast::() - .map_err(|inner| ConnectionDenied { inner })?; - - Ok(*inner) - } - - /// Attempt to downcast to a particular reason for why the connection was denied. - pub fn downcast_ref(&self) -> Option<&E> - where - E: error::Error + Send + Sync + 'static, - { - self.inner.downcast_ref::() - } -} - -impl fmt::Display for ConnectionDenied { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "connection denied") - } -} - -impl error::Error for ConnectionDenied { - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - Some(self.inner.as_ref()) - } -} - -/// Information about the connections obtained by [`Swarm::network_info()`]. -#[derive(Clone, Debug)] -pub struct NetworkInfo { - /// The total number of connected peers. - num_peers: usize, - /// Counters of ongoing network connections. - connection_counters: ConnectionCounters, -} - -impl NetworkInfo { - /// The number of connected peers, i.e. peers with whom at least - /// one established connection exists. - pub fn num_peers(&self) -> usize { - self.num_peers - } - - /// Gets counters for ongoing network connections. - pub fn connection_counters(&self) -> &ConnectionCounters { - &self.connection_counters - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::test::{CallTraceBehaviour, MockBehaviour}; - use libp2p_core::multiaddr::multiaddr; - use libp2p_core::transport::memory::MemoryTransportError; - use libp2p_core::transport::{PortUse, TransportEvent}; - use libp2p_core::Endpoint; - use libp2p_core::{multiaddr, transport, upgrade}; - use libp2p_identity as identity; - use libp2p_plaintext as plaintext; - use libp2p_yamux as yamux; - use quickcheck::*; - - // Test execution state. - // Connection => Disconnecting => Connecting. - enum State { - Connecting, - Disconnecting, - } - - fn new_test_swarm( - config: Config, - ) -> Swarm>> { - let id_keys = identity::Keypair::generate_ed25519(); - let local_public_key = id_keys.public(); - let transport = transport::MemoryTransport::default() - .upgrade(upgrade::Version::V1) - .authenticate(plaintext::Config::new(&id_keys)) - .multiplex(yamux::Config::default()) - .boxed(); - let behaviour = CallTraceBehaviour::new(MockBehaviour::new(dummy::ConnectionHandler)); - - Swarm::new( - transport, - behaviour, - local_public_key.into(), - config.with_idle_connection_timeout(Duration::from_secs(5)), - ) - } - - fn swarms_connected( - swarm1: &Swarm>, - swarm2: &Swarm>, - num_connections: usize, - ) -> bool - where - TBehaviour: NetworkBehaviour, - THandlerOutEvent: Clone, - { - swarm1 - .behaviour() - .num_connections_to_peer(*swarm2.local_peer_id()) - == num_connections - && swarm2 - .behaviour() - .num_connections_to_peer(*swarm1.local_peer_id()) - == num_connections - && swarm1.is_connected(swarm2.local_peer_id()) - && swarm2.is_connected(swarm1.local_peer_id()) - } - - fn swarms_disconnected( - swarm1: &Swarm>, - swarm2: &Swarm>, - ) -> bool - where - TBehaviour: NetworkBehaviour, - THandlerOutEvent: Clone, - { - swarm1 - .behaviour() - .num_connections_to_peer(*swarm2.local_peer_id()) - == 0 - && swarm2 - .behaviour() - .num_connections_to_peer(*swarm1.local_peer_id()) - == 0 - && !swarm1.is_connected(swarm2.local_peer_id()) - && !swarm2.is_connected(swarm1.local_peer_id()) - } - - /// Establishes multiple connections between two peers, - /// after which one peer disconnects the other using [`Swarm::disconnect_peer_id`]. - /// - /// The test expects both behaviours to be notified via calls to [`NetworkBehaviour::on_swarm_event`] - /// with pairs of [`FromSwarm::ConnectionEstablished`] / [`FromSwarm::ConnectionClosed`] - #[tokio::test] - async fn test_swarm_disconnect() { - let mut swarm1 = new_test_swarm(Config::with_tokio_executor()); - let mut swarm2 = new_test_swarm(Config::with_tokio_executor()); - - let addr1: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); - let addr2: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); - - swarm1.listen_on(addr1.clone()).unwrap(); - swarm2.listen_on(addr2.clone()).unwrap(); - - let swarm1_id = *swarm1.local_peer_id(); - - let mut reconnected = false; - let num_connections = 10; - - for _ in 0..num_connections { - swarm1.dial(addr2.clone()).unwrap(); - } - let mut state = State::Connecting; - - future::poll_fn(move |cx| loop { - let poll1 = Swarm::poll_next_event(Pin::new(&mut swarm1), cx); - let poll2 = Swarm::poll_next_event(Pin::new(&mut swarm2), cx); - match state { - State::Connecting => { - if swarms_connected(&swarm1, &swarm2, num_connections) { - if reconnected { - return Poll::Ready(()); - } - swarm2 - .disconnect_peer_id(swarm1_id) - .expect("Error disconnecting"); - state = State::Disconnecting; - } - } - State::Disconnecting => { - if swarms_disconnected(&swarm1, &swarm2) { - if reconnected { - return Poll::Ready(()); - } - reconnected = true; - for _ in 0..num_connections { - swarm2.dial(addr1.clone()).unwrap(); - } - state = State::Connecting; - } - } - } - - if poll1.is_pending() && poll2.is_pending() { - return Poll::Pending; - } - }) - .await - } - - /// Establishes multiple connections between two peers, - /// after which one peer disconnects the other - /// using [`ToSwarm::CloseConnection`] returned by a [`NetworkBehaviour`]. - /// - /// The test expects both behaviours to be notified via calls to [`NetworkBehaviour::on_swarm_event`] - /// with pairs of [`FromSwarm::ConnectionEstablished`] / [`FromSwarm::ConnectionClosed`] - #[tokio::test] - async fn test_behaviour_disconnect_all() { - let mut swarm1 = new_test_swarm(Config::with_tokio_executor()); - let mut swarm2 = new_test_swarm(Config::with_tokio_executor()); - - let addr1: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); - let addr2: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); - - swarm1.listen_on(addr1.clone()).unwrap(); - swarm2.listen_on(addr2.clone()).unwrap(); - - let swarm1_id = *swarm1.local_peer_id(); - - let mut reconnected = false; - let num_connections = 10; - - for _ in 0..num_connections { - swarm1.dial(addr2.clone()).unwrap(); - } - let mut state = State::Connecting; - - future::poll_fn(move |cx| loop { - let poll1 = Swarm::poll_next_event(Pin::new(&mut swarm1), cx); - let poll2 = Swarm::poll_next_event(Pin::new(&mut swarm2), cx); - match state { - State::Connecting => { - if swarms_connected(&swarm1, &swarm2, num_connections) { - if reconnected { - return Poll::Ready(()); - } - swarm2 - .behaviour - .inner() - .next_action - .replace(ToSwarm::CloseConnection { - peer_id: swarm1_id, - connection: CloseConnection::All, - }); - state = State::Disconnecting; - continue; - } - } - State::Disconnecting => { - if swarms_disconnected(&swarm1, &swarm2) { - reconnected = true; - for _ in 0..num_connections { - swarm2.dial(addr1.clone()).unwrap(); - } - state = State::Connecting; - continue; - } - } - } - - if poll1.is_pending() && poll2.is_pending() { - return Poll::Pending; - } - }) - .await - } - - /// Establishes multiple connections between two peers, - /// after which one peer closes a single connection - /// using [`ToSwarm::CloseConnection`] returned by a [`NetworkBehaviour`]. - /// - /// The test expects both behaviours to be notified via calls to [`NetworkBehaviour::on_swarm_event`] - /// with pairs of [`FromSwarm::ConnectionEstablished`] / [`FromSwarm::ConnectionClosed`] - #[tokio::test] - async fn test_behaviour_disconnect_one() { - let mut swarm1 = new_test_swarm(Config::with_tokio_executor()); - let mut swarm2 = new_test_swarm(Config::with_tokio_executor()); - - let addr1: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); - let addr2: Multiaddr = multiaddr::Protocol::Memory(rand::random::()).into(); - - swarm1.listen_on(addr1).unwrap(); - swarm2.listen_on(addr2.clone()).unwrap(); - - let swarm1_id = *swarm1.local_peer_id(); - - let num_connections = 10; - - for _ in 0..num_connections { - swarm1.dial(addr2.clone()).unwrap(); - } - let mut state = State::Connecting; - let mut disconnected_conn_id = None; - - future::poll_fn(move |cx| loop { - let poll1 = Swarm::poll_next_event(Pin::new(&mut swarm1), cx); - let poll2 = Swarm::poll_next_event(Pin::new(&mut swarm2), cx); - match state { - State::Connecting => { - if swarms_connected(&swarm1, &swarm2, num_connections) { - disconnected_conn_id = { - let conn_id = - swarm2.behaviour.on_connection_established[num_connections / 2].1; - swarm2.behaviour.inner().next_action.replace( - ToSwarm::CloseConnection { - peer_id: swarm1_id, - connection: CloseConnection::One(conn_id), - }, - ); - Some(conn_id) - }; - state = State::Disconnecting; - } - } - State::Disconnecting => { - for s in &[&swarm1, &swarm2] { - assert!(s - .behaviour - .on_connection_closed - .iter() - .all(|(.., remaining_conns)| *remaining_conns > 0)); - assert_eq!(s.behaviour.on_connection_established.len(), num_connections); - s.behaviour.assert_connected(num_connections, 1); - } - if [&swarm1, &swarm2] - .iter() - .all(|s| s.behaviour.on_connection_closed.len() == 1) - { - let conn_id = swarm2.behaviour.on_connection_closed[0].1; - assert_eq!(Some(conn_id), disconnected_conn_id); - return Poll::Ready(()); - } - } - } - - if poll1.is_pending() && poll2.is_pending() { - return Poll::Pending; - } - }) - .await - } - - #[test] - fn concurrent_dialing() { - #[derive(Clone, Debug)] - struct DialConcurrencyFactor(NonZeroU8); - - impl Arbitrary for DialConcurrencyFactor { - fn arbitrary(g: &mut Gen) -> Self { - Self(NonZeroU8::new(g.gen_range(1..11)).unwrap()) - } - } - - fn prop(concurrency_factor: DialConcurrencyFactor) { - tokio::runtime::Runtime::new().unwrap().block_on(async { - let mut swarm = new_test_swarm( - Config::with_tokio_executor() - .with_dial_concurrency_factor(concurrency_factor.0), - ); - - // Listen on `concurrency_factor + 1` addresses. - // - // `+ 2` to ensure a subset of addresses is dialed by network_2. - let num_listen_addrs = concurrency_factor.0.get() + 2; - let mut listen_addresses = Vec::new(); - let mut transports = Vec::new(); - for _ in 0..num_listen_addrs { - let mut transport = transport::MemoryTransport::default().boxed(); - transport - .listen_on(ListenerId::next(), "/memory/0".parse().unwrap()) - .unwrap(); - - match transport.select_next_some().await { - TransportEvent::NewAddress { listen_addr, .. } => { - listen_addresses.push(listen_addr); - } - _ => panic!("Expected `NewListenAddr` event."), - } - - transports.push(transport); - } - - // Have swarm dial each listener and wait for each listener to receive the incoming - // connections. - swarm - .dial( - DialOpts::peer_id(PeerId::random()) - .addresses(listen_addresses) - .build(), - ) - .unwrap(); - for mut transport in transports.into_iter() { - match futures::future::select(transport.select_next_some(), swarm.next()).await - { - future::Either::Left((TransportEvent::Incoming { .. }, _)) => {} - future::Either::Left(_) => { - panic!("Unexpected transport event.") - } - future::Either::Right((e, _)) => { - panic!("Expect swarm to not emit any event {e:?}") - } - } - } - - match swarm.next().await.unwrap() { - SwarmEvent::OutgoingConnectionError { .. } => {} - e => panic!("Unexpected swarm event {e:?}"), - } - }) - } - - QuickCheck::new().tests(10).quickcheck(prop as fn(_) -> _); - } - - #[tokio::test] - async fn invalid_peer_id() { - // Checks whether dialing an address containing the wrong peer id raises an error - // for the expected peer id instead of the obtained peer id. - - let mut swarm1 = new_test_swarm(Config::with_tokio_executor()); - let mut swarm2 = new_test_swarm(Config::with_tokio_executor()); - - swarm1.listen_on("/memory/0".parse().unwrap()).unwrap(); - - let address = future::poll_fn(|cx| match swarm1.poll_next_unpin(cx) { - Poll::Ready(Some(SwarmEvent::NewListenAddr { address, .. })) => Poll::Ready(address), - Poll::Pending => Poll::Pending, - _ => panic!("Was expecting the listen address to be reported"), - }) - .await; - - let other_id = PeerId::random(); - let other_addr = address.with(multiaddr::Protocol::P2p(other_id)); - - swarm2.dial(other_addr.clone()).unwrap(); - - let (peer_id, error) = future::poll_fn(|cx| { - if let Poll::Ready(Some(SwarmEvent::IncomingConnection { .. })) = - swarm1.poll_next_unpin(cx) - {} - - match swarm2.poll_next_unpin(cx) { - Poll::Ready(Some(SwarmEvent::OutgoingConnectionError { - peer_id, error, .. - })) => Poll::Ready((peer_id, error)), - Poll::Ready(x) => panic!("unexpected {x:?}"), - Poll::Pending => Poll::Pending, - } - }) - .await; - assert_eq!(peer_id.unwrap(), other_id); - match error { - DialError::WrongPeerId { obtained, endpoint } => { - assert_eq!(obtained, *swarm1.local_peer_id()); - assert_eq!( - endpoint, - ConnectedPoint::Dialer { - address: other_addr, - role_override: Endpoint::Dialer, - port_use: PortUse::Reuse, - } - ); - } - x => panic!("wrong error {x:?}"), - } - } - - #[tokio::test] - async fn dial_self() { - // Check whether dialing ourselves correctly fails. - // - // Dialing the same address we're listening should result in three events: - // - // - The incoming connection notification (before we know the incoming peer ID). - // - The connection error for the dialing endpoint (once we've determined that it's our own ID). - // - The connection error for the listening endpoint (once we've determined that it's our own ID). - // - // The last two can happen in any order. - - let mut swarm = new_test_swarm(Config::with_tokio_executor()); - swarm.listen_on("/memory/0".parse().unwrap()).unwrap(); - - let local_address = future::poll_fn(|cx| match swarm.poll_next_unpin(cx) { - Poll::Ready(Some(SwarmEvent::NewListenAddr { address, .. })) => Poll::Ready(address), - Poll::Pending => Poll::Pending, - _ => panic!("Was expecting the listen address to be reported"), - }) - .await; - - swarm.listened_addrs.clear(); // This is a hack to actually execute the dial to ourselves which would otherwise be filtered. - - swarm.dial(local_address.clone()).unwrap(); - - let mut got_dial_err = false; - let mut got_inc_err = false; - future::poll_fn(|cx| -> Poll> { - loop { - match swarm.poll_next_unpin(cx) { - Poll::Ready(Some(SwarmEvent::OutgoingConnectionError { - peer_id, - error: DialError::LocalPeerId { .. }, - .. - })) => { - assert_eq!(&peer_id.unwrap(), swarm.local_peer_id()); - assert!(!got_dial_err); - got_dial_err = true; - if got_inc_err { - return Poll::Ready(Ok(())); - } - } - Poll::Ready(Some(SwarmEvent::IncomingConnectionError { - local_addr, .. - })) => { - assert!(!got_inc_err); - assert_eq!(local_addr, local_address); - got_inc_err = true; - if got_dial_err { - return Poll::Ready(Ok(())); - } - } - Poll::Ready(Some(SwarmEvent::IncomingConnection { local_addr, .. })) => { - assert_eq!(local_addr, local_address); - } - Poll::Ready(ev) => { - panic!("Unexpected event: {ev:?}") - } - Poll::Pending => break Poll::Pending, - } - } - }) - .await - .unwrap(); - } - - #[tokio::test] - async fn dial_self_by_id() { - // Trying to dial self by passing the same `PeerId` shouldn't even be possible in the first - // place. - let swarm = new_test_swarm(Config::with_tokio_executor()); - let peer_id = *swarm.local_peer_id(); - assert!(!swarm.is_connected(&peer_id)); - } - - #[tokio::test] - async fn multiple_addresses_err() { - // Tries dialing multiple addresses, and makes sure there's one dialing error per address. - - let target = PeerId::random(); - - let mut swarm = new_test_swarm(Config::with_tokio_executor()); - - let addresses = HashSet::from([ - multiaddr![Ip4([0, 0, 0, 0]), Tcp(rand::random::())], - multiaddr![Ip4([0, 0, 0, 0]), Tcp(rand::random::())], - multiaddr![Ip4([0, 0, 0, 0]), Tcp(rand::random::())], - multiaddr![Udp(rand::random::())], - multiaddr![Udp(rand::random::())], - multiaddr![Udp(rand::random::())], - multiaddr![Udp(rand::random::())], - multiaddr![Udp(rand::random::())], - ]); - - swarm - .dial( - DialOpts::peer_id(target) - .addresses(addresses.iter().cloned().collect()) - .build(), - ) - .unwrap(); - - match swarm.next().await.unwrap() { - SwarmEvent::OutgoingConnectionError { - peer_id, - // multiaddr, - error: DialError::Transport(errors), - .. - } => { - assert_eq!(target, peer_id.unwrap()); - - let failed_addresses = errors.into_iter().map(|(addr, _)| addr).collect::>(); - let expected_addresses = addresses - .into_iter() - .map(|addr| addr.with(multiaddr::Protocol::P2p(target))) - .collect::>(); - - assert_eq!(expected_addresses, failed_addresses); - } - e => panic!("Unexpected event: {e:?}"), - } - } - - #[tokio::test] - async fn aborting_pending_connection_surfaces_error() { - let _ = tracing_subscriber::fmt() - .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) - .try_init(); - - let mut dialer = new_test_swarm(Config::with_tokio_executor()); - let mut listener = new_test_swarm(Config::with_tokio_executor()); - - let listener_peer_id = *listener.local_peer_id(); - listener.listen_on(multiaddr![Memory(0u64)]).unwrap(); - let listener_address = match listener.next().await.unwrap() { - SwarmEvent::NewListenAddr { address, .. } => address, - e => panic!("Unexpected network event: {e:?}"), - }; - - dialer - .dial( - DialOpts::peer_id(listener_peer_id) - .addresses(vec![listener_address]) - .build(), - ) - .unwrap(); - - dialer - .disconnect_peer_id(listener_peer_id) - .expect_err("Expect peer to not yet be connected."); - - match dialer.next().await.unwrap() { - SwarmEvent::OutgoingConnectionError { - error: DialError::Aborted, - .. - } => {} - e => panic!("Unexpected swarm event {e:?}."), - } - } - - #[test] - fn dial_error_prints_sources() { - // This constitutes a fairly typical error for chained transports. - let error = DialError::Transport(vec![( - "/ip4/127.0.0.1/tcp/80".parse().unwrap(), - TransportError::Other(io::Error::new( - io::ErrorKind::Other, - MemoryTransportError::Unreachable, - )), - )]); - - let string = format!("{error}"); - - // Unfortunately, we have some "empty" errors that lead to multiple colons without text but that is the best we can do. - assert_eq!("Failed to negotiate transport protocol(s): [(/ip4/127.0.0.1/tcp/80: : No listener on the given port.)]", string) - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/listen_opts.rs b/third-party/libp2p-swarm-0.45.1/src/listen_opts.rs deleted file mode 100644 index 9c4d69a6fa0..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/listen_opts.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::ListenerId; -use libp2p_core::Multiaddr; - -#[derive(Debug)] -pub struct ListenOpts { - id: ListenerId, - address: Multiaddr, -} - -impl ListenOpts { - pub fn new(address: Multiaddr) -> ListenOpts { - ListenOpts { - id: ListenerId::next(), - address, - } - } - - /// Get the [`ListenerId`] of this listen attempt - pub fn listener_id(&self) -> ListenerId { - self.id - } - - /// Get the [`Multiaddr`] that is being listened on - pub fn address(&self) -> &Multiaddr { - &self.address - } -} - -impl From for ListenOpts { - fn from(addr: Multiaddr) -> Self { - ListenOpts::new(addr) - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/stream.rs b/third-party/libp2p-swarm-0.45.1/src/stream.rs deleted file mode 100644 index 871352f3c6a..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/stream.rs +++ /dev/null @@ -1,98 +0,0 @@ -use futures::{AsyncRead, AsyncWrite}; -use libp2p_core::muxing::SubstreamBox; -use libp2p_core::Negotiated; -use std::{ - io::{IoSlice, IoSliceMut}, - pin::Pin, - sync::Arc, - task::{Context, Poll}, -}; - -/// Counter for the number of active streams on a connection. -#[derive(Debug, Clone)] -pub(crate) struct ActiveStreamCounter(Arc<()>); - -impl ActiveStreamCounter { - pub(crate) fn default() -> Self { - Self(Arc::new(())) - } - - pub(crate) fn has_no_active_streams(&self) -> bool { - self.num_alive_streams() == 1 - } - - fn num_alive_streams(&self) -> usize { - Arc::strong_count(&self.0) - } -} - -#[derive(Debug)] -pub struct Stream { - stream: Negotiated, - counter: Option, -} - -impl Stream { - pub(crate) fn new(stream: Negotiated, counter: ActiveStreamCounter) -> Self { - Self { - stream, - counter: Some(counter), - } - } - - /// Ignore this stream in the [Swarm](crate::Swarm)'s connection-keep-alive algorithm. - /// - /// By default, any active stream keeps a connection alive. For most protocols, - /// this is a good default as it ensures that the protocol is completed before - /// a connection is shut down. - /// Some protocols like libp2p's [ping](https://github.com/libp2p/specs/blob/master/ping/ping.md) - /// for example never complete and are of an auxiliary nature. - /// These protocols should opt-out of the keep alive algorithm using this method. - pub fn ignore_for_keep_alive(&mut self) { - self.counter.take(); - } -} - -impl AsyncRead for Stream { - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll> { - Pin::new(&mut self.get_mut().stream).poll_read(cx, buf) - } - - fn poll_read_vectored( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - bufs: &mut [IoSliceMut<'_>], - ) -> Poll> { - Pin::new(&mut self.get_mut().stream).poll_read_vectored(cx, bufs) - } -} - -impl AsyncWrite for Stream { - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - Pin::new(&mut self.get_mut().stream).poll_write(cx, buf) - } - - fn poll_write_vectored( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - bufs: &[IoSlice<'_>], - ) -> Poll> { - Pin::new(&mut self.get_mut().stream).poll_write_vectored(cx, bufs) - } - - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut self.get_mut().stream).poll_flush(cx) - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut self.get_mut().stream).poll_close(cx) - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/stream_protocol.rs b/third-party/libp2p-swarm-0.45.1/src/stream_protocol.rs deleted file mode 100644 index f746429a3d7..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/stream_protocol.rs +++ /dev/null @@ -1,132 +0,0 @@ -use either::Either; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::sync::Arc; - -/// Identifies a protocol for a stream. -/// -/// libp2p nodes use stream protocols to negotiate what to do with a newly opened stream. -/// Stream protocols are string-based and must start with a forward slash: `/`. -#[derive(Clone, Eq)] -pub struct StreamProtocol { - inner: Either<&'static str, Arc>, -} - -impl StreamProtocol { - /// Construct a new protocol from a static string slice. - /// - /// # Panics - /// - /// This function panics if the protocol does not start with a forward slash: `/`. - pub const fn new(s: &'static str) -> Self { - match s.as_bytes() { - [b'/', ..] => {} - _ => panic!("Protocols should start with a /"), - } - - StreamProtocol { - inner: Either::Left(s), - } - } - - /// Attempt to construct a protocol from an owned string. - /// - /// This function will fail if the protocol does not start with a forward slash: `/`. - /// Where possible, you should use [`StreamProtocol::new`] instead to avoid allocations. - pub fn try_from_owned(protocol: String) -> Result { - if !protocol.starts_with('/') { - return Err(InvalidProtocol::missing_forward_slash()); - } - - Ok(StreamProtocol { - inner: Either::Right(Arc::from(protocol)), // FIXME: Can we somehow reuse the allocation from the owned string? - }) - } -} - -impl AsRef for StreamProtocol { - fn as_ref(&self) -> &str { - either::for_both!(&self.inner, s => s) - } -} - -impl fmt::Debug for StreamProtocol { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - either::for_both!(&self.inner, s => s.fmt(f)) - } -} - -impl fmt::Display for StreamProtocol { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.inner.fmt(f) - } -} - -impl PartialEq<&str> for StreamProtocol { - fn eq(&self, other: &&str) -> bool { - self.as_ref() == *other - } -} - -impl PartialEq for &str { - fn eq(&self, other: &StreamProtocol) -> bool { - *self == other.as_ref() - } -} - -impl PartialEq for StreamProtocol { - fn eq(&self, other: &Self) -> bool { - self.as_ref() == other.as_ref() - } -} - -impl Hash for StreamProtocol { - fn hash(&self, state: &mut H) { - self.as_ref().hash(state) - } -} - -#[derive(Debug)] -pub struct InvalidProtocol { - // private field to prevent construction outside of this module - _private: (), -} - -impl InvalidProtocol { - pub(crate) fn missing_forward_slash() -> Self { - InvalidProtocol { _private: () } - } -} - -impl fmt::Display for InvalidProtocol { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "invalid protocol: string does not start with a forward slash" - ) - } -} - -impl std::error::Error for InvalidProtocol {} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn stream_protocol_print() { - let protocol = StreamProtocol::new("/foo/bar/1.0.0"); - - let debug = format!("{protocol:?}"); - let display = format!("{protocol}"); - - assert_eq!( - debug, r#""/foo/bar/1.0.0""#, - "protocol to debug print as string with quotes" - ); - assert_eq!( - display, "/foo/bar/1.0.0", - "protocol to display print as string without quotes" - ); - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/test.rs b/third-party/libp2p-swarm-0.45.1/src/test.rs deleted file mode 100644 index a6cb7c4d4eb..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/test.rs +++ /dev/null @@ -1,522 +0,0 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::behaviour::{ - ConnectionClosed, ConnectionEstablished, DialFailure, ExpiredListenAddr, ExternalAddrExpired, - FromSwarm, ListenerClosed, ListenerError, NewExternalAddrCandidate, NewListenAddr, NewListener, -}; -use crate::{ - ConnectionDenied, ConnectionHandler, ConnectionId, NetworkBehaviour, THandler, THandlerInEvent, - THandlerOutEvent, ToSwarm, -}; -use libp2p_core::transport::PortUse; -use libp2p_core::{multiaddr::Multiaddr, transport::ListenerId, ConnectedPoint, Endpoint}; -use libp2p_identity::PeerId; -use std::collections::HashMap; -use std::task::{Context, Poll}; - -/// A `MockBehaviour` is a `NetworkBehaviour` that allows for -/// the instrumentation of return values, without keeping -/// any further state. -pub(crate) struct MockBehaviour -where - THandler: ConnectionHandler + Clone, - THandler::ToBehaviour: Clone, - TOutEvent: Send + 'static, -{ - /// The prototype protocols handler that is cloned for every - /// invocation of [`NetworkBehaviour::handle_established_inbound_connection`] and [`NetworkBehaviour::handle_established_outbound_connection`] - pub(crate) handler_proto: THandler, - /// The addresses to return from [`NetworkBehaviour::handle_established_outbound_connection`]. - pub(crate) addresses: HashMap>, - /// The next action to return from `poll`. - /// - /// An action is only returned once. - pub(crate) next_action: Option>, -} - -impl MockBehaviour -where - THandler: ConnectionHandler + Clone, - THandler::ToBehaviour: Clone, - TOutEvent: Send + 'static, -{ - pub(crate) fn new(handler_proto: THandler) -> Self { - MockBehaviour { - handler_proto, - addresses: HashMap::new(), - next_action: None, - } - } -} - -impl NetworkBehaviour for MockBehaviour -where - THandler: ConnectionHandler + Clone, - THandler::ToBehaviour: Clone, - TOutEvent: Send + 'static, -{ - type ConnectionHandler = THandler; - type ToSwarm = TOutEvent; - - fn handle_established_inbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: &Multiaddr, - ) -> Result { - Ok(self.handler_proto.clone()) - } - - fn handle_established_outbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: Endpoint, - _: PortUse, - ) -> Result { - Ok(self.handler_proto.clone()) - } - - fn handle_pending_outbound_connection( - &mut self, - _connection_id: ConnectionId, - maybe_peer: Option, - _addresses: &[Multiaddr], - _effective_role: Endpoint, - ) -> Result, ConnectionDenied> { - let p = match maybe_peer { - None => return Ok(vec![]), - Some(peer) => peer, - }; - - Ok(self.addresses.get(&p).map_or(Vec::new(), |v| v.clone())) - } - - fn poll(&mut self, _: &mut Context<'_>) -> Poll>> { - self.next_action.take().map_or(Poll::Pending, Poll::Ready) - } - - fn on_swarm_event(&mut self, _event: FromSwarm) {} - - fn on_connection_handler_event( - &mut self, - _peer_id: PeerId, - _connection_id: ConnectionId, - _event: THandlerOutEvent, - ) { - } -} - -/// A `CallTraceBehaviour` is a `NetworkBehaviour` that tracks -/// invocations of callback methods and their arguments, wrapping -/// around an inner behaviour. It ensures certain invariants are met. -pub(crate) struct CallTraceBehaviour -where - TInner: NetworkBehaviour, -{ - inner: TInner, - - pub(crate) handle_pending_inbound_connection: Vec<(ConnectionId, Multiaddr, Multiaddr)>, - pub(crate) handle_pending_outbound_connection: - Vec<(Option, Vec, Endpoint, ConnectionId)>, - pub(crate) handle_established_inbound_connection: - Vec<(PeerId, ConnectionId, Multiaddr, Multiaddr)>, - pub(crate) handle_established_outbound_connection: - Vec<(PeerId, Multiaddr, Endpoint, ConnectionId)>, - pub(crate) on_connection_established: Vec<(PeerId, ConnectionId, ConnectedPoint, usize)>, - pub(crate) on_connection_closed: Vec<(PeerId, ConnectionId, ConnectedPoint, usize)>, - pub(crate) on_connection_handler_event: Vec<(PeerId, ConnectionId, THandlerOutEvent)>, - pub(crate) on_dial_failure: Vec>, - pub(crate) on_new_listener: Vec, - pub(crate) on_new_listen_addr: Vec<(ListenerId, Multiaddr)>, - pub(crate) on_new_external_addr: Vec, - pub(crate) on_expired_listen_addr: Vec<(ListenerId, Multiaddr)>, - pub(crate) on_expired_external_addr: Vec, - pub(crate) on_listener_error: Vec, - pub(crate) on_listener_closed: Vec<(ListenerId, bool)>, - pub(crate) poll: usize, -} - -impl CallTraceBehaviour -where - TInner: NetworkBehaviour, - THandlerOutEvent: Clone, -{ - pub(crate) fn new(inner: TInner) -> Self { - Self { - inner, - handle_pending_inbound_connection: Vec::new(), - handle_pending_outbound_connection: Vec::new(), - handle_established_inbound_connection: Vec::new(), - handle_established_outbound_connection: Vec::new(), - on_connection_established: Vec::new(), - on_connection_closed: Vec::new(), - on_connection_handler_event: Vec::new(), - on_dial_failure: Vec::new(), - on_new_listener: Vec::new(), - on_new_listen_addr: Vec::new(), - on_new_external_addr: Vec::new(), - on_expired_listen_addr: Vec::new(), - on_expired_external_addr: Vec::new(), - on_listener_error: Vec::new(), - on_listener_closed: Vec::new(), - poll: 0, - } - } - - #[allow(dead_code)] - pub(crate) fn reset(&mut self) { - self.handle_pending_inbound_connection = Vec::new(); - self.handle_pending_outbound_connection = Vec::new(); - self.handle_established_inbound_connection = Vec::new(); - self.handle_established_outbound_connection = Vec::new(); - self.on_connection_established = Vec::new(); - self.on_connection_closed = Vec::new(); - self.on_connection_handler_event = Vec::new(); - self.on_dial_failure = Vec::new(); - self.on_new_listen_addr = Vec::new(); - self.on_new_external_addr = Vec::new(); - self.on_expired_listen_addr = Vec::new(); - self.on_listener_error = Vec::new(); - self.on_listener_closed = Vec::new(); - self.poll = 0; - } - - pub(crate) fn inner(&mut self) -> &mut TInner { - &mut self.inner - } - - pub(crate) fn num_connections_to_peer(&self, peer: PeerId) -> usize { - self.on_connection_established - .iter() - .filter(|(peer_id, _, _, _)| *peer_id == peer) - .count() - - self - .on_connection_closed - .iter() - .filter(|(peer_id, _, _, _)| *peer_id == peer) - .count() - } - - /// Checks that when the expected number of established connection notifications are received, - /// a given number of expected connections have been received as well. - /// - /// Returns if the first condition is met. - pub(crate) fn assert_connected( - &self, - expected_established_connections: usize, - expected_connections: usize, - ) -> bool { - if self.on_connection_established.len() == expected_established_connections { - assert_eq!( - self.on_connection_established - .iter() - .filter(|(.., reported_aditional_connections)| { - *reported_aditional_connections == 0 - }) - .count(), - expected_connections - ); - return true; - } - - false - } - - fn on_connection_established( - &mut self, - ConnectionEstablished { - peer_id, - connection_id, - endpoint, - failed_addresses, - other_established, - }: ConnectionEstablished, - ) { - let mut other_peer_connections = self - .on_connection_established - .iter() - .rev() // take last to first - .filter_map(|(peer, .., other_established)| { - if &peer_id == peer { - Some(other_established) - } else { - None - } - }) - .take(other_established); - - // We are informed that there are `other_established` additional connections. Ensure that the - // number of previous connections is consistent with this - if let Some(&prev) = other_peer_connections.next() { - if prev < other_established { - assert_eq!( - prev, - other_established - 1, - "Inconsistent connection reporting" - ) - } - assert_eq!(other_peer_connections.count(), other_established - 1); - } else { - assert_eq!(other_established, 0) - } - self.on_connection_established.push(( - peer_id, - connection_id, - endpoint.clone(), - other_established, - )); - self.inner - .on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished { - peer_id, - connection_id, - endpoint, - failed_addresses, - other_established, - })); - } - - fn on_connection_closed( - &mut self, - ConnectionClosed { - peer_id, - connection_id, - endpoint, - remaining_established, - cause, - }: ConnectionClosed, - ) { - let mut other_closed_connections = self - .on_connection_established - .iter() - .rev() // take last to first - .filter_map(|(peer, .., remaining_established)| { - if &peer_id == peer { - Some(remaining_established) - } else { - None - } - }) - .take(remaining_established); - - // We are informed that there are `other_established` additional connections. Ensure that the - // number of previous connections is consistent with this - if let Some(&prev) = other_closed_connections.next() { - if prev < remaining_established { - assert_eq!( - prev, - remaining_established - 1, - "Inconsistent closed connection reporting" - ) - } - assert_eq!(other_closed_connections.count(), remaining_established - 1); - } else { - assert_eq!(remaining_established, 0) - } - assert!( - self.on_connection_established - .iter() - .any(|(peer, conn_id, endpoint, _)| (peer, conn_id, endpoint) - == (&peer_id, &connection_id, endpoint)), - "`on_swarm_event` with `FromSwarm::ConnectionClosed is called only for connections for\ - which `on_swarm_event` with `FromSwarm::ConnectionEstablished` was called first." - ); - self.on_connection_closed.push(( - peer_id, - connection_id, - endpoint.clone(), - remaining_established, - )); - self.inner - .on_swarm_event(FromSwarm::ConnectionClosed(ConnectionClosed { - peer_id, - connection_id, - endpoint, - remaining_established, - cause, - })); - } -} - -impl NetworkBehaviour for CallTraceBehaviour -where - TInner: NetworkBehaviour, - THandlerOutEvent: Clone, -{ - type ConnectionHandler = TInner::ConnectionHandler; - type ToSwarm = TInner::ToSwarm; - - fn handle_pending_inbound_connection( - &mut self, - connection_id: ConnectionId, - local_addr: &Multiaddr, - remote_addr: &Multiaddr, - ) -> Result<(), ConnectionDenied> { - self.handle_pending_inbound_connection.push(( - connection_id, - local_addr.clone(), - remote_addr.clone(), - )); - self.inner - .handle_pending_inbound_connection(connection_id, local_addr, remote_addr) - } - - fn handle_established_inbound_connection( - &mut self, - connection_id: ConnectionId, - peer: PeerId, - local_addr: &Multiaddr, - remote_addr: &Multiaddr, - ) -> Result, ConnectionDenied> { - self.handle_established_inbound_connection.push(( - peer, - connection_id, - local_addr.clone(), - remote_addr.clone(), - )); - self.inner.handle_established_inbound_connection( - connection_id, - peer, - local_addr, - remote_addr, - ) - } - - fn handle_pending_outbound_connection( - &mut self, - connection_id: ConnectionId, - maybe_peer: Option, - addresses: &[Multiaddr], - effective_role: Endpoint, - ) -> Result, ConnectionDenied> { - self.handle_pending_outbound_connection.push(( - maybe_peer, - addresses.to_vec(), - effective_role, - connection_id, - )); - self.inner.handle_pending_outbound_connection( - connection_id, - maybe_peer, - addresses, - effective_role, - ) - } - - fn handle_established_outbound_connection( - &mut self, - connection_id: ConnectionId, - peer: PeerId, - addr: &Multiaddr, - role_override: Endpoint, - port_use: PortUse, - ) -> Result, ConnectionDenied> { - self.handle_established_outbound_connection.push(( - peer, - addr.clone(), - role_override, - connection_id, - )); - self.inner.handle_established_outbound_connection( - connection_id, - peer, - addr, - role_override, - port_use, - ) - } - - fn on_swarm_event(&mut self, event: FromSwarm) { - self.inner.on_swarm_event(event); - - match event { - FromSwarm::ConnectionEstablished(connection_established) => { - self.on_connection_established(connection_established) - } - FromSwarm::ConnectionClosed(connection_closed) => { - self.on_connection_closed(connection_closed) - } - FromSwarm::DialFailure(DialFailure { peer_id, .. }) => { - self.on_dial_failure.push(peer_id); - } - FromSwarm::NewListener(NewListener { listener_id }) => { - self.on_new_listener.push(listener_id); - } - FromSwarm::NewListenAddr(NewListenAddr { listener_id, addr }) => { - self.on_new_listen_addr.push((listener_id, addr.clone())); - } - FromSwarm::ExpiredListenAddr(ExpiredListenAddr { listener_id, addr }) => { - self.on_expired_listen_addr - .push((listener_id, addr.clone())); - } - FromSwarm::NewExternalAddrCandidate(NewExternalAddrCandidate { addr }) => { - self.on_new_external_addr.push(addr.clone()); - } - FromSwarm::ExternalAddrExpired(ExternalAddrExpired { addr }) => { - self.on_expired_external_addr.push(addr.clone()); - } - FromSwarm::ListenerError(ListenerError { listener_id, .. }) => { - self.on_listener_error.push(listener_id); - } - FromSwarm::ListenerClosed(ListenerClosed { - listener_id, - reason, - }) => { - self.on_listener_closed.push((listener_id, reason.is_ok())); - } - _ => {} - } - } - - fn on_connection_handler_event( - &mut self, - p: PeerId, - c: ConnectionId, - e: THandlerOutEvent, - ) { - assert!( - self.on_connection_established - .iter() - .any(|(peer_id, conn_id, ..)| *peer_id == p && c == *conn_id), - "`on_connection_handler_event` is called for reported connections." - ); - assert!( - !self - .on_connection_closed - .iter() - .any(|(peer_id, conn_id, ..)| *peer_id == p && c == *conn_id), - "`on_connection_handler_event` is never called for closed connections." - ); - - self.on_connection_handler_event.push((p, c, e.clone())); - self.inner.on_connection_handler_event(p, c, e); - } - - fn poll( - &mut self, - cx: &mut Context<'_>, - ) -> Poll>> { - self.poll += 1; - self.inner.poll(cx) - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/translation.rs b/third-party/libp2p-swarm-0.45.1/src/translation.rs deleted file mode 100644 index baa80c907b5..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/translation.rs +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use libp2p_core::{multiaddr::Protocol, Multiaddr}; - -/// Perform IP address translation. -/// -/// Given an `original` [`Multiaddr`] and some `observed` [`Multiaddr`], replace the first protocol -/// of the `original` with the first protocol of the `observed` [`Multiaddr`] and return this -/// translated [`Multiaddr`]. -/// -/// This function can for example be useful when handling tcp connections. Tcp does not listen and -/// dial on the same port by default. Thus when receiving an observed address on a connection that -/// we initiated, it will contain our dialing port, not our listening port. We need to take the ip -/// address or dns address from the observed address and the port from the original address. -/// -/// This is a mixed-mode translation, i.e. an IPv4 / DNS4 address may be replaced by an IPv6 / DNS6 -/// address and vice versa. -/// -/// If the first [`Protocol`]s are not IP addresses, `None` is returned instead. -#[doc(hidden)] -pub fn _address_translation(original: &Multiaddr, observed: &Multiaddr) -> Option { - original.replace(0, move |proto| match proto { - Protocol::Ip4(_) - | Protocol::Ip6(_) - | Protocol::Dns(_) - | Protocol::Dns4(_) - | Protocol::Dns6(_) => match observed.iter().next() { - x @ Some(Protocol::Ip4(_)) => x, - x @ Some(Protocol::Ip6(_)) => x, - x @ Some(Protocol::Dns(_)) => x, - x @ Some(Protocol::Dns4(_)) => x, - x @ Some(Protocol::Dns6(_)) => x, - _ => None, - }, - _ => None, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_address_translation() { - struct Test { - original: Multiaddr, - observed: Multiaddr, - expected: Multiaddr, - } - - let tests = [ - // Basic ipv4. - Test { - original: "/ip4/192.0.2.1/tcp/1".parse().unwrap(), - observed: "/ip4/192.0.2.2/tcp/2".parse().unwrap(), - expected: "/ip4/192.0.2.2/tcp/1".parse().unwrap(), - }, - // Basic ipv6. - Test { - original: "/ip6/2001:db8:0:0:0:0:0:0/tcp/1".parse().unwrap(), - observed: "/ip6/2001:db8:0:0:0:0:0:1/tcp/2".parse().unwrap(), - expected: "/ip6/2001:db8:0:0:0:0:0:1/tcp/1".parse().unwrap(), - }, - // Ipv4 ipv6 mix. - Test { - original: "/ip4/192.0.2.1/tcp/1".parse().unwrap(), - observed: "/ip6/2001:db8:0:0:0:0:0:1/tcp/2".parse().unwrap(), - expected: "/ip6/2001:db8:0:0:0:0:0:1/tcp/1".parse().unwrap(), - }, - // Ipv6 ipv4 mix. - Test { - original: "/ip6/2001:db8:0:0:0:0:0:0/tcp/1".parse().unwrap(), - observed: "/ip4/192.0.2.2/tcp/2".parse().unwrap(), - expected: "/ip4/192.0.2.2/tcp/1".parse().unwrap(), - }, - // Dns. - Test { - original: "/dns4/foo/tcp/1".parse().unwrap(), - observed: "/dns4/bar/tcp/2".parse().unwrap(), - expected: "/dns4/bar/tcp/1".parse().unwrap(), - }, - // Ipv4 Dns mix. - Test { - original: "/ip4/192.0.2.1/tcp/1".parse().unwrap(), - observed: "/dns4/bar/tcp/2".parse().unwrap(), - expected: "/dns4/bar/tcp/1".parse().unwrap(), - }, - ]; - - for test in tests.iter() { - assert_eq!( - _address_translation(&test.original, &test.observed), - Some(test.expected.clone()) - ); - } - } -} diff --git a/third-party/libp2p-swarm-0.45.1/src/upgrade.rs b/third-party/libp2p-swarm-0.45.1/src/upgrade.rs deleted file mode 100644 index 53b627458c9..00000000000 --- a/third-party/libp2p-swarm-0.45.1/src/upgrade.rs +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::Stream; - -use futures::prelude::*; -use libp2p_core::upgrade; - -/// Implemented automatically on all types that implement [`UpgradeInfo`](upgrade::UpgradeInfo) -/// and `Send + 'static`. -/// -/// Do not implement this trait yourself. Instead, please implement -/// [`UpgradeInfo`](upgrade::UpgradeInfo). -pub trait UpgradeInfoSend: Send + 'static { - /// Equivalent to [`UpgradeInfo::Info`](upgrade::UpgradeInfo::Info). - type Info: AsRef + Clone + Send + 'static; - /// Equivalent to [`UpgradeInfo::InfoIter`](upgrade::UpgradeInfo::InfoIter). - type InfoIter: Iterator + Send + 'static; - - /// Equivalent to [`UpgradeInfo::protocol_info`](upgrade::UpgradeInfo::protocol_info). - fn protocol_info(&self) -> Self::InfoIter; -} - -impl UpgradeInfoSend for T -where - T: upgrade::UpgradeInfo + Send + 'static, - T::Info: Send + 'static, - ::IntoIter: Send + 'static, -{ - type Info = T::Info; - type InfoIter = ::IntoIter; - - fn protocol_info(&self) -> Self::InfoIter { - upgrade::UpgradeInfo::protocol_info(self).into_iter() - } -} - -/// Implemented automatically on all types that implement -/// [`OutboundUpgrade`](upgrade::OutboundUpgrade) and `Send + 'static`. -/// -/// Do not implement this trait yourself. Instead, please implement -/// [`OutboundUpgrade`](upgrade::OutboundUpgrade). -pub trait OutboundUpgradeSend: UpgradeInfoSend { - /// Equivalent to [`OutboundUpgrade::Output`](upgrade::OutboundUpgrade::Output). - type Output: Send + 'static; - /// Equivalent to [`OutboundUpgrade::Error`](upgrade::OutboundUpgrade::Error). - type Error: Send + 'static; - /// Equivalent to [`OutboundUpgrade::Future`](upgrade::OutboundUpgrade::Future). - type Future: Future> + Send + 'static; - - /// Equivalent to [`OutboundUpgrade::upgrade_outbound`](upgrade::OutboundUpgrade::upgrade_outbound). - fn upgrade_outbound(self, socket: Stream, info: Self::Info) -> Self::Future; -} - -impl OutboundUpgradeSend for T -where - T: upgrade::OutboundUpgrade + UpgradeInfoSend, - TInfo: AsRef + Clone + Send + 'static, - T::Output: Send + 'static, - T::Error: Send + 'static, - T::Future: Send + 'static, -{ - type Output = T::Output; - type Error = T::Error; - type Future = T::Future; - - fn upgrade_outbound(self, socket: Stream, info: TInfo) -> Self::Future { - upgrade::OutboundUpgrade::upgrade_outbound(self, socket, info) - } -} - -/// Implemented automatically on all types that implement -/// [`InboundUpgrade`](upgrade::InboundUpgrade) and `Send + 'static`. -/// -/// Do not implement this trait yourself. Instead, please implement -/// [`InboundUpgrade`](upgrade::InboundUpgrade). -pub trait InboundUpgradeSend: UpgradeInfoSend { - /// Equivalent to [`InboundUpgrade::Output`](upgrade::InboundUpgrade::Output). - type Output: Send + 'static; - /// Equivalent to [`InboundUpgrade::Error`](upgrade::InboundUpgrade::Error). - type Error: Send + 'static; - /// Equivalent to [`InboundUpgrade::Future`](upgrade::InboundUpgrade::Future). - type Future: Future> + Send + 'static; - - /// Equivalent to [`InboundUpgrade::upgrade_inbound`](upgrade::InboundUpgrade::upgrade_inbound). - fn upgrade_inbound(self, socket: Stream, info: Self::Info) -> Self::Future; -} - -impl InboundUpgradeSend for T -where - T: upgrade::InboundUpgrade + UpgradeInfoSend, - TInfo: AsRef + Clone + Send + 'static, - T::Output: Send + 'static, - T::Error: Send + 'static, - T::Future: Send + 'static, -{ - type Output = T::Output; - type Error = T::Error; - type Future = T::Future; - - fn upgrade_inbound(self, socket: Stream, info: TInfo) -> Self::Future { - upgrade::InboundUpgrade::upgrade_inbound(self, socket, info) - } -} - -/// Wraps around a type that implements [`OutboundUpgradeSend`], [`InboundUpgradeSend`], or -/// both, and implements [`OutboundUpgrade`](upgrade::OutboundUpgrade) and/or -/// [`InboundUpgrade`](upgrade::InboundUpgrade). -/// -/// > **Note**: This struct is mostly an implementation detail of the library and normally -/// > doesn't need to be used directly. -pub struct SendWrapper(pub T); - -impl upgrade::UpgradeInfo for SendWrapper { - type Info = T::Info; - type InfoIter = T::InfoIter; - - fn protocol_info(&self) -> Self::InfoIter { - UpgradeInfoSend::protocol_info(&self.0) - } -} - -impl upgrade::OutboundUpgrade for SendWrapper { - type Output = T::Output; - type Error = T::Error; - type Future = T::Future; - - fn upgrade_outbound(self, socket: Stream, info: T::Info) -> Self::Future { - OutboundUpgradeSend::upgrade_outbound(self.0, socket, info) - } -} - -impl upgrade::InboundUpgrade for SendWrapper { - type Output = T::Output; - type Error = T::Error; - type Future = T::Future; - - fn upgrade_inbound(self, socket: Stream, info: T::Info) -> Self::Future { - InboundUpgradeSend::upgrade_inbound(self.0, socket, info) - } -} diff --git a/third-party/libp2p-swarm-0.45.1/tests/connection_close.rs b/third-party/libp2p-swarm-0.45.1/tests/connection_close.rs deleted file mode 100644 index 4d530f47684..00000000000 --- a/third-party/libp2p-swarm-0.45.1/tests/connection_close.rs +++ /dev/null @@ -1,148 +0,0 @@ -use libp2p_core::transport::PortUse; -use libp2p_core::upgrade::DeniedUpgrade; -use libp2p_core::{Endpoint, Multiaddr}; -use libp2p_identity::PeerId; -use libp2p_swarm::handler::ConnectionEvent; -use libp2p_swarm::{ - ConnectionDenied, ConnectionHandler, ConnectionHandlerEvent, ConnectionId, FromSwarm, - NetworkBehaviour, SubstreamProtocol, Swarm, SwarmEvent, THandler, THandlerInEvent, - THandlerOutEvent, ToSwarm, -}; -use libp2p_swarm_test::SwarmExt; -use std::task::{Context, Poll}; -use void::Void; - -#[async_std::test] -async fn sends_remaining_events_to_behaviour_on_connection_close() { - let mut swarm1 = Swarm::new_ephemeral(|_| Behaviour::new(3)); - let mut swarm2 = Swarm::new_ephemeral(|_| Behaviour::new(3)); - - swarm2.listen().with_memory_addr_external().await; - swarm1.connect(&mut swarm2).await; - - swarm1.disconnect_peer_id(*swarm2.local_peer_id()).unwrap(); - - match libp2p_swarm_test::drive(&mut swarm1, &mut swarm2).await { - ([SwarmEvent::ConnectionClosed { .. }], [SwarmEvent::ConnectionClosed { .. }]) => { - assert_eq!(swarm1.behaviour().state, 0); - assert_eq!(swarm2.behaviour().state, 0); - } - (e1, e2) => panic!("Unexpected events: {:?} {:?}", e1, e2), - } -} - -struct HandlerWithState { - precious_state: u64, -} - -struct Behaviour { - state: u64, -} - -impl Behaviour { - fn new(state: u64) -> Self { - Behaviour { state } - } -} - -impl NetworkBehaviour for Behaviour { - type ConnectionHandler = HandlerWithState; - type ToSwarm = (); - - fn handle_established_inbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: &Multiaddr, - ) -> Result, ConnectionDenied> { - Ok(HandlerWithState { - precious_state: self.state, - }) - } - - fn handle_established_outbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: Endpoint, - _: PortUse, - ) -> Result, ConnectionDenied> { - Ok(HandlerWithState { - precious_state: self.state, - }) - } - - fn on_swarm_event(&mut self, event: FromSwarm) { - if let FromSwarm::ConnectionClosed(_) = event { - assert_eq!(self.state, 0); - } - } - - fn on_connection_handler_event( - &mut self, - _peer_id: PeerId, - _connection_id: ConnectionId, - event: THandlerOutEvent, - ) { - assert_eq!(self.state, event); - self.state -= 1; - } - - fn poll(&mut self, _: &mut Context<'_>) -> Poll>> { - Poll::Pending - } -} - -impl ConnectionHandler for HandlerWithState { - type FromBehaviour = Void; - type ToBehaviour = u64; - type InboundProtocol = DeniedUpgrade; - type OutboundProtocol = DeniedUpgrade; - type InboundOpenInfo = (); - type OutboundOpenInfo = (); - - fn listen_protocol(&self) -> SubstreamProtocol { - SubstreamProtocol::new(DeniedUpgrade, ()) - } - - fn connection_keep_alive(&self) -> bool { - true - } - - fn poll( - &mut self, - _: &mut Context<'_>, - ) -> Poll< - ConnectionHandlerEvent, - > { - Poll::Pending - } - - fn poll_close(&mut self, _: &mut Context<'_>) -> Poll> { - if self.precious_state > 0 { - let state = self.precious_state; - self.precious_state -= 1; - - return Poll::Ready(Some(state)); - } - - Poll::Ready(None) - } - - fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { - void::unreachable(event) - } - - fn on_connection_event( - &mut self, - _: ConnectionEvent< - Self::InboundProtocol, - Self::OutboundProtocol, - Self::InboundOpenInfo, - Self::OutboundOpenInfo, - >, - ) { - } -} diff --git a/third-party/libp2p-swarm-0.45.1/tests/listener.rs b/third-party/libp2p-swarm-0.45.1/tests/listener.rs deleted file mode 100644 index 160b1f5b064..00000000000 --- a/third-party/libp2p-swarm-0.45.1/tests/listener.rs +++ /dev/null @@ -1,144 +0,0 @@ -use std::{ - collections::{HashSet, VecDeque}, - task::{Context, Poll}, -}; - -use libp2p_core::{ - multiaddr::Protocol, - transport::{ListenerId, PortUse}, - Endpoint, Multiaddr, -}; -use libp2p_identity::PeerId; -use libp2p_swarm::{ - derive_prelude::NewListener, dummy, ConnectionDenied, ConnectionId, FromSwarm, ListenOpts, - ListenerClosed, ListenerError, NetworkBehaviour, NewListenAddr, Swarm, SwarmEvent, THandler, - THandlerInEvent, THandlerOutEvent, ToSwarm, -}; - -use libp2p_swarm_test::SwarmExt; - -#[async_std::test] -async fn behaviour_listener() { - let mut swarm = Swarm::new_ephemeral(|_| Behaviour::default()); - let addr: Multiaddr = Protocol::Memory(0).into(); - let id = swarm.behaviour_mut().listen(addr.clone()); - - let address = swarm - .wait(|e| match e { - SwarmEvent::NewListenAddr { - listener_id, - address, - } => { - assert_eq!(listener_id, id); - Some(address) - } - _ => None, - }) - .await; - - swarm.behaviour_mut().stop_listening(id); - - swarm - .wait(|e| match e { - SwarmEvent::ListenerClosed { - listener_id, - addresses, - reason, - } => { - assert_eq!(listener_id, id); - assert!(addresses.contains(&address)); - assert!(reason.is_ok()); - Some(()) - } - _ => None, - }) - .await; -} - -#[derive(Default)] -struct Behaviour { - events: VecDeque::ToSwarm, THandlerInEvent>>, - listeners: HashSet, -} - -impl Behaviour { - pub(crate) fn listen(&mut self, addr: Multiaddr) -> ListenerId { - let opts = ListenOpts::new(addr); - let listener_id = opts.listener_id(); - assert!(!self.listeners.contains(&listener_id)); - self.events.push_back(ToSwarm::ListenOn { opts }); - self.listeners.insert(listener_id); - - listener_id - } - - pub(crate) fn stop_listening(&mut self, id: ListenerId) { - self.events.push_back(ToSwarm::RemoveListener { id }); - } -} - -impl NetworkBehaviour for Behaviour { - type ConnectionHandler = dummy::ConnectionHandler; - type ToSwarm = void::Void; - - fn handle_established_inbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: &Multiaddr, - ) -> Result, ConnectionDenied> { - Ok(dummy::ConnectionHandler) - } - - fn handle_established_outbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: Endpoint, - _: PortUse, - ) -> Result, ConnectionDenied> { - Ok(dummy::ConnectionHandler) - } - - fn on_connection_handler_event( - &mut self, - _: PeerId, - _: ConnectionId, - _: THandlerOutEvent, - ) { - } - - fn on_swarm_event(&mut self, event: FromSwarm) { - match event { - FromSwarm::NewListener(NewListener { listener_id }) => { - assert!(self.listeners.contains(&listener_id)); - } - FromSwarm::NewListenAddr(NewListenAddr { listener_id, .. }) => { - assert!(self.listeners.contains(&listener_id)); - } - FromSwarm::ListenerError(ListenerError { listener_id, err }) => { - panic!("Error for listener {listener_id:?}: {err}"); - } - FromSwarm::ListenerClosed(ListenerClosed { - listener_id, - reason, - }) => { - assert!(self.listeners.contains(&listener_id)); - assert!(reason.is_ok()); - self.listeners.remove(&listener_id); - assert!(!self.listeners.contains(&listener_id)); - } - _ => {} - } - } - - fn poll(&mut self, _: &mut Context<'_>) -> Poll>> { - if let Some(event) = self.events.pop_front() { - return Poll::Ready(event); - } - - Poll::Pending - } -} diff --git a/third-party/libp2p-swarm-0.45.1/tests/swarm_derive.rs b/third-party/libp2p-swarm-0.45.1/tests/swarm_derive.rs deleted file mode 100644 index 919ed0cab7f..00000000000 --- a/third-party/libp2p-swarm-0.45.1/tests/swarm_derive.rs +++ /dev/null @@ -1,618 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use futures::StreamExt; -use libp2p_core::{transport::PortUse, Endpoint, Multiaddr}; -use libp2p_identify as identify; -use libp2p_ping as ping; -use libp2p_swarm::{ - behaviour::FromSwarm, dummy, ConnectionDenied, NetworkBehaviour, SwarmEvent, THandler, - THandlerInEvent, THandlerOutEvent, -}; -use std::fmt::Debug; - -/// Small utility to check that a type implements `NetworkBehaviour`. -#[allow(dead_code)] -fn require_net_behaviour() {} - -// TODO: doesn't compile -/*#[test] -fn empty() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - struct Foo {} -}*/ - -#[test] -fn one_field() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - ping: ping::Behaviour, - } - - #[allow( - dead_code, - unreachable_code, - clippy::diverging_sub_expression, - clippy::used_underscore_binding - )] - fn foo() { - let _out_event: ::ToSwarm = unimplemented!(); - match _out_event { - FooEvent::Ping(ping::Event { .. }) => {} - } - } -} - -#[test] -fn two_fields() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - ping: ping::Behaviour, - identify: identify::Behaviour, - } - - #[allow( - dead_code, - unreachable_code, - clippy::diverging_sub_expression, - clippy::used_underscore_binding - )] - fn foo() { - let _out_event: ::ToSwarm = unimplemented!(); - match _out_event { - FooEvent::Ping(ping::Event { .. }) => {} - FooEvent::Identify(event) => { - let _: identify::Event = event; - } - } - } -} - -#[test] -fn three_fields() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - ping: ping::Behaviour, - identify: identify::Behaviour, - kad: libp2p_kad::Behaviour, - } - - #[allow( - dead_code, - unreachable_code, - clippy::diverging_sub_expression, - clippy::used_underscore_binding - )] - fn foo() { - let _out_event: ::ToSwarm = unimplemented!(); - match _out_event { - FooEvent::Ping(ping::Event { .. }) => {} - FooEvent::Identify(event) => { - let _: identify::Event = event; - } - FooEvent::Kad(event) => { - let _: libp2p_kad::Event = event; - } - } - } -} - -#[test] -fn custom_event() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(to_swarm = "MyEvent", prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - ping: ping::Behaviour, - identify: identify::Behaviour, - } - - #[allow(clippy::large_enum_variant)] - enum MyEvent { - Ping, - Identify, - } - - impl From for MyEvent { - fn from(_event: ping::Event) -> Self { - MyEvent::Ping - } - } - - impl From for MyEvent { - fn from(_event: identify::Event) -> Self { - MyEvent::Identify - } - } - - #[allow(dead_code)] - fn foo() { - require_net_behaviour::(); - } -} - -#[test] -fn custom_event_mismatching_field_names() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(to_swarm = "MyEvent", prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - a: ping::Behaviour, - b: identify::Behaviour, - } - - #[allow(clippy::large_enum_variant)] - enum MyEvent { - Ping, - Identify, - } - - impl From for MyEvent { - fn from(_event: ping::Event) -> Self { - MyEvent::Ping - } - } - - impl From for MyEvent { - fn from(_event: identify::Event) -> Self { - MyEvent::Identify - } - } - - #[allow(dead_code)] - fn foo() { - require_net_behaviour::(); - } -} - -#[test] -fn bound() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo - where - ::ToSwarm: Debug, - { - ping: ping::Behaviour, - bar: T, - } -} - -#[test] -fn where_clause() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo - where - T: Copy + NetworkBehaviour, - ::ToSwarm: Debug, - { - ping: ping::Behaviour, - bar: T, - } -} - -#[test] -fn nested_derives_with_import() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - ping: ping::Behaviour, - } - - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Bar { - foo: Foo, - } - - #[allow( - dead_code, - unreachable_code, - clippy::diverging_sub_expression, - clippy::used_underscore_binding - )] - fn foo() { - let _out_event: ::ToSwarm = unimplemented!(); - match _out_event { - BarEvent::Foo(FooEvent::Ping(ping::Event { .. })) => {} - } - } -} - -#[test] -fn custom_event_emit_event_through_poll() { - #[allow(clippy::large_enum_variant)] - enum BehaviourOutEvent { - Ping, - Identify, - } - - impl From for BehaviourOutEvent { - fn from(_event: ping::Event) -> Self { - BehaviourOutEvent::Ping - } - } - - impl From for BehaviourOutEvent { - fn from(_event: identify::Event) -> Self { - BehaviourOutEvent::Identify - } - } - - #[allow(dead_code, clippy::large_enum_variant)] - #[derive(NetworkBehaviour)] - #[behaviour( - to_swarm = "BehaviourOutEvent", - prelude = "libp2p_swarm::derive_prelude" - )] - struct Foo { - ping: ping::Behaviour, - identify: identify::Behaviour, - } - - #[allow( - dead_code, - unreachable_code, - clippy::diverging_sub_expression, - clippy::used_underscore_binding - )] - async fn bar() { - require_net_behaviour::(); - - let mut _swarm: libp2p_swarm::Swarm = unimplemented!(); - - // check that the event is bubbled up all the way to swarm - loop { - match _swarm.select_next_some().await { - SwarmEvent::Behaviour(BehaviourOutEvent::Ping) => break, - SwarmEvent::Behaviour(BehaviourOutEvent::Identify) => break, - _ => {} - } - } - } -} - -#[test] -fn with_toggle() { - use libp2p_swarm::behaviour::toggle::Toggle; - - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - identify: identify::Behaviour, - ping: Toggle, - } - - #[allow(dead_code)] - fn foo() { - require_net_behaviour::(); - } -} - -#[test] -fn with_either() { - use either::Either; - - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - kad: libp2p_kad::Behaviour, - ping_or_identify: Either, - } - - #[allow(dead_code)] - fn foo() { - require_net_behaviour::(); - } -} - -#[test] -fn with_generics() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - a: A, - b: B, - } - - #[allow(dead_code)] - fn foo() { - require_net_behaviour::< - Foo, libp2p_ping::Behaviour>, - >(); - } -} - -#[test] -fn with_generics_mixed() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - a: A, - ping: libp2p_ping::Behaviour, - } - - #[allow(dead_code)] - fn foo() { - require_net_behaviour::>>(); - } -} - -#[test] -fn with_generics_constrained() { - use std::task::{Context, Poll}; - trait Mark {} - struct Marked; - impl Mark for Marked {} - - /// A struct with a generic constraint, for which we manually implement `NetworkBehaviour`. - #[allow(dead_code)] - struct Bar { - a: A, - } - - impl NetworkBehaviour for Bar { - type ConnectionHandler = dummy::ConnectionHandler; - type ToSwarm = void::Void; - - fn handle_established_inbound_connection( - &mut self, - _: libp2p_swarm::ConnectionId, - _: libp2p_identity::PeerId, - _: &Multiaddr, - _: &Multiaddr, - ) -> Result, ConnectionDenied> { - Ok(dummy::ConnectionHandler) - } - - fn handle_established_outbound_connection( - &mut self, - _: libp2p_swarm::ConnectionId, - _: libp2p_identity::PeerId, - _: &Multiaddr, - _: Endpoint, - _: PortUse, - ) -> Result, ConnectionDenied> { - Ok(dummy::ConnectionHandler) - } - - fn on_swarm_event(&mut self, _event: FromSwarm) {} - - fn on_connection_handler_event( - &mut self, - _: libp2p_identity::PeerId, - _: libp2p_swarm::ConnectionId, - _: THandlerOutEvent, - ) { - } - - fn poll( - &mut self, - _: &mut Context<'_>, - ) -> Poll>> { - Poll::Pending - } - } - - /// A struct which uses the above, inheriting the generic constraint, - /// for which we want to derive the `NetworkBehaviour`. - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo1 { - bar: Bar, - } - - /// A struct which uses the above, inheriting the generic constraint, - /// for which we want to derive the `NetworkBehaviour`. - /// - /// Using a where clause instead of inline constraint. - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo2 - where - A: Mark, - { - bar: Bar, - } - - #[allow(dead_code)] - fn foo() { - require_net_behaviour::>(); - require_net_behaviour::>(); - } -} - -#[test] -fn custom_event_with_either() { - use either::Either; - - enum BehaviourOutEvent { - Kad, - PingOrIdentify, - } - - impl From for BehaviourOutEvent { - fn from(_event: libp2p_kad::Event) -> Self { - BehaviourOutEvent::Kad - } - } - - impl From> for BehaviourOutEvent { - fn from(_event: Either) -> Self { - BehaviourOutEvent::PingOrIdentify - } - } - - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour( - to_swarm = "BehaviourOutEvent", - prelude = "libp2p_swarm::derive_prelude" - )] - struct Foo { - kad: libp2p_kad::Behaviour, - ping_or_identify: Either, - } - - #[allow(dead_code)] - fn foo() { - require_net_behaviour::(); - } -} - -#[test] -fn generated_out_event_derive_debug() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - ping: ping::Behaviour, - } - - fn require_debug() - where - T: NetworkBehaviour, - ::ToSwarm: Debug, - { - } - - require_debug::(); -} - -#[test] -fn multiple_behaviour_attributes() { - #[allow(dead_code)] - #[derive(NetworkBehaviour)] - #[behaviour(to_swarm = "FooEvent")] - #[behaviour(prelude = "libp2p_swarm::derive_prelude")] - struct Foo { - ping: ping::Behaviour, - } - - require_net_behaviour::(); - - struct FooEvent; - - impl From for FooEvent { - fn from(_: ping::Event) -> Self { - unimplemented!() - } - } -} - -#[test] -fn custom_out_event_no_type_parameters() { - use libp2p_identity::PeerId; - use libp2p_swarm::{ConnectionId, ToSwarm}; - use std::task::Context; - use std::task::Poll; - - pub(crate) struct TemplatedBehaviour { - _data: T, - } - - impl NetworkBehaviour for TemplatedBehaviour { - type ConnectionHandler = dummy::ConnectionHandler; - type ToSwarm = void::Void; - - fn handle_established_inbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: &Multiaddr, - ) -> Result, ConnectionDenied> { - Ok(dummy::ConnectionHandler) - } - - fn handle_established_outbound_connection( - &mut self, - _: ConnectionId, - _: PeerId, - _: &Multiaddr, - _: Endpoint, - _: PortUse, - ) -> Result, ConnectionDenied> { - Ok(dummy::ConnectionHandler) - } - - fn on_connection_handler_event( - &mut self, - _peer: PeerId, - _connection: ConnectionId, - message: THandlerOutEvent, - ) { - void::unreachable(message); - } - - fn poll( - &mut self, - _: &mut Context<'_>, - ) -> Poll>> { - Poll::Pending - } - - fn on_swarm_event(&mut self, _event: FromSwarm) {} - } - - #[derive(NetworkBehaviour)] - #[behaviour(to_swarm = "OutEvent", prelude = "libp2p_swarm::derive_prelude")] - struct Behaviour { - custom: TemplatedBehaviour, - } - - #[derive(Debug)] - enum OutEvent { - None, - } - - impl From for OutEvent { - fn from(_e: void::Void) -> Self { - Self::None - } - } - - require_net_behaviour::>(); - require_net_behaviour::>(); -} - -#[test] -fn ui() { - let t = trybuild::TestCases::new(); - t.compile_fail("tests/ui/fail/*.rs"); -} diff --git a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.rs b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.rs deleted file mode 100644 index 727f2439ec0..00000000000 --- a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.rs +++ /dev/null @@ -1,11 +0,0 @@ -use libp2p_ping as ping; - -#[derive(libp2p_swarm::NetworkBehaviour)] -#[behaviour(prelude = libp2p_swarm::derive_prelude)] -struct Foo { - ping: ping::Behaviour, -} - -fn main() { - -} diff --git a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.stderr b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.stderr deleted file mode 100644 index 2c2a79805d9..00000000000 --- a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/prelude_not_string.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: expected a string literal - --> tests/ui/fail/prelude_not_string.rs:4:23 - | -4 | #[behaviour(prelude = libp2p_swarm::derive_prelude)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.rs b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.rs deleted file mode 100644 index e0ff56e41a7..00000000000 --- a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.rs +++ /dev/null @@ -1,19 +0,0 @@ -use libp2p_ping as ping; - -#[derive(libp2p_swarm::NetworkBehaviour)] -#[behaviour(out_event = FooEvent, prelude = "libp2p_swarm::derive_prelude")] -struct Foo { - ping: ping::Behaviour, -} - -struct FooEvent; - -impl From for FooEvent { - fn from(_: ping::Event) -> Self { - unimplemented!() - } -} - -fn main() { - -} diff --git a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.stderr b/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.stderr deleted file mode 100644 index f2fbba685cb..00000000000 --- a/third-party/libp2p-swarm-0.45.1/tests/ui/fail/to_swarm_not_string.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: expected a string literal - --> tests/ui/fail/to_swarm_not_string.rs:4:25 - | -4 | #[behaviour(out_event = FooEvent, prelude = "libp2p_swarm::derive_prelude")] - | ^^^^^^^^ From 463274508d24aeea6258ac75ced78fa30ce7a06f Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Wed, 10 Jun 2026 21:24:47 +0400 Subject: [PATCH 08/13] Fix stable2603 CI blockers --- Cargo.lock | 1 + ethexe/network/src/injected.rs | 20 +++- ethexe/network/src/lib.rs | 27 +++++ protocol/sandbox/env/src/lib.rs | 9 +- .../src/utils.rs | 7 +- .../src/wasm_project.rs | 3 +- vara/common/src/event.rs | 2 +- vara/common/src/gas_provider/node.rs | 2 +- vara/common/src/pallet_tests.rs | 1 + vara/node/cli/src/benchmarking.rs | 1 + vara/node/cli/src/command.rs | 11 ++- vara/node/testing/src/keyring.rs | 6 +- vara/pallets/gas/src/mock.rs | 1 + vara/pallets/gear-bank/src/mock.rs | 9 +- vara/pallets/gear-builtin/src/benchmarking.rs | 98 ++++++++++++------- vara/pallets/gear-builtin/src/mock.rs | 9 +- .../gear-builtin/src/tests/bad_builtin_ids.rs | 1 + vara/pallets/gear-builtin/src/tests/proxy.rs | 2 +- .../pallets/gear-builtin/src/tests/staking.rs | 18 +++- .../gear-eth-bridge/src/benchmarking.rs | 2 +- vara/pallets/gear-eth-bridge/src/lib.rs | 5 - vara/pallets/gear-eth-bridge/src/mock.rs | 5 +- vara/pallets/gear-eth-bridge/src/tests.rs | 63 +++++++----- vara/pallets/gear-messenger/src/mock.rs | 9 +- vara/pallets/gear-program/src/mock.rs | 2 + vara/pallets/gear-scheduler/src/mock.rs | 1 + vara/pallets/gear-voucher/src/lib.rs | 3 - vara/pallets/gear-voucher/src/mock.rs | 2 +- vara/pallets/gear/src/benchmarking/mod.rs | 5 +- vara/pallets/gear/src/benchmarking/tasks.rs | 5 + vara/pallets/gear/src/lib.rs | 5 - vara/pallets/gear/src/mock.rs | 2 +- vara/pallets/gear/src/pallet_tests.rs | 1 - vara/pallets/grandpa-signer/src/lib.rs | 2 - vara/pallets/grandpa-signer/src/tests.rs | 14 ++- vara/pallets/payment/src/lib.rs | 4 +- vara/pallets/payment/src/mock.rs | 1 - vara/pallets/payment/src/tests.rs | 4 +- vara/pallets/staking-rewards/src/extension.rs | 11 +-- vara/pallets/staking-rewards/src/lib.rs | 17 ++-- vara/pallets/staking-rewards/src/mock.rs | 14 +-- vara/runtime/common/src/apis.rs | 4 +- vara/runtime/interface/Cargo.toml | 3 + vara/runtime/vara/Cargo.toml | 1 + vara/runtime/vara/build.rs | 5 +- vara/runtime/vara/src/integration_tests.rs | 11 ++- vara/runtime/vara/src/lib.rs | 32 +++--- vara/runtime/vara/src/tests/mod.rs | 2 +- vara/sdk/gsdk/src/lib.rs | 2 +- vara/sdk/gsdk/src/signed/mod.rs | 3 +- vara/tools/gear-replay-cli/src/lib.rs | 5 +- vara/tools/gear-replay-cli/src/state.rs | 2 +- vara/tools/runtime-fuzzer/src/runtime/mod.rs | 1 + 53 files changed, 288 insertions(+), 188 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cafdcf63b96..78bb446996a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21028,6 +21028,7 @@ dependencies = [ "sp-inherents", "sp-io", "sp-keyring", + "sp-maybe-compressed-blob", "sp-offchain", "sp-runtime", "sp-session", diff --git a/ethexe/network/src/injected.rs b/ethexe/network/src/injected.rs index c755edd38ff..2c34cfcaa71 100644 --- a/ethexe/network/src/injected.rs +++ b/ethexe/network/src/injected.rs @@ -189,10 +189,6 @@ impl Behaviour { for (recipient, identity) in recipients { let peer_id = identity.peer_id(); - for address in identity.addresses() { - self.inner.add_address(&peer_id, address.clone()); - } - let id = self .inner .send_request(&peer_id, InnerRequest(transaction.clone())); @@ -466,6 +462,10 @@ mod tests { let transaction = signed_injected_tx(); let identities = [(bob_identity.address(), bob_identity)].into(); + crate::register_validator_addresses( + &mut alice, + crate::validator_peer_addresses(&identities), + ); alice .behaviour_mut() .broadcast_transaction(&identities, transaction.clone()) @@ -506,6 +506,10 @@ mod tests { ] .into(); + crate::register_validator_addresses( + &mut alice, + crate::validator_peer_addresses(&identities), + ); alice .behaviour_mut() .broadcast_transaction(&identities, transaction.clone()) @@ -552,6 +556,10 @@ mod tests { let transaction = signed_injected_tx(); let identities = [(bob_identity.address(), bob_identity)].into(); + crate::register_validator_addresses( + &mut alice, + crate::validator_peer_addresses(&identities), + ); alice .behaviour_mut() .broadcast_transaction(&identities, transaction.clone()) @@ -594,6 +602,10 @@ mod tests { let transaction = signed_injected_tx(); let identities = [(bob_identity.address(), bob_identity)].into(); + crate::register_validator_addresses( + &mut alice, + crate::validator_peer_addresses(&identities), + ); alice .behaviour_mut() .broadcast_transaction(&identities, transaction.clone()) diff --git a/ethexe/network/src/lib.rs b/ethexe/network/src/lib.rs index 10b1f5ec942..cf76a910192 100644 --- a/ethexe/network/src/lib.rs +++ b/ethexe/network/src/lib.rs @@ -85,6 +85,28 @@ const MAX_ESTABLISHED_OUTGOING_CONNECTIONS: u32 = 500; const MAX_PENDING_INCOMING_CONNECTIONS: u32 = 10; const MAX_PENDING_OUTGOING_CONNECTIONS: u32 = 10; +fn validator_peer_addresses( + identities: &validator::discovery::ValidatorIdentities, +) -> impl Iterator + '_ { + identities.values().flat_map(|identity| { + let peer_id = identity.peer_id(); + identity + .addresses() + .iter() + .cloned() + .map(move |address| (peer_id, address)) + }) +} + +fn register_validator_addresses( + swarm: &mut Swarm, + addresses: impl IntoIterator, +) { + for (peer_id, address) in addresses { + swarm.add_peer_address(peer_id, address); + } +} + /// High-level events produced by [`NetworkService`]. #[derive(derive_more::Debug)] pub enum NetworkEvent { @@ -636,6 +658,11 @@ impl NetworkService { &mut self, transaction: SignedInjectedTransaction, ) -> Result { + let addresses: Vec<_> = + validator_peer_addresses(self.swarm.behaviour().validator_discovery.identities()) + .collect(); + register_validator_addresses(&mut self.swarm, addresses); + let behaviour = self.swarm.behaviour_mut(); behaviour .injected diff --git a/protocol/sandbox/env/src/lib.rs b/protocol/sandbox/env/src/lib.rs index c65b364a429..7905001f0b7 100644 --- a/protocol/sandbox/env/src/lib.rs +++ b/protocol/sandbox/env/src/lib.rs @@ -9,7 +9,6 @@ extern crate alloc; use alloc::string::String; use parity_scale_codec::{Decode, Encode}; -use sp_debug_derive::RuntimeDebug; use sp_std::vec::Vec; use sp_wasm_interface_common::ReturnValue; @@ -25,11 +24,11 @@ pub enum Instantiate { } /// Error error that can be returned from host function. -#[derive(Encode, Decode, RuntimeDebug)] +#[derive(Encode, Decode, Debug)] pub struct HostError; /// Describes an entity to define or import into the environment. -#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] pub enum ExternEntity { /// Function that is specified by an index in a default table of /// a module that creates the sandbox. @@ -46,7 +45,7 @@ pub enum ExternEntity { /// /// Each entry has a two-level name and description of an entity /// being defined. -#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] pub struct Entry { /// Module name of which corresponding entity being defined. pub module_name: String, @@ -57,7 +56,7 @@ pub struct Entry { } /// Definition of runtime that could be used by sandboxed code. -#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] pub struct EnvironmentDefinition { /// Vector of all entries in the environment definition. pub entries: Vec, diff --git a/substrate/sp-runtime-interface-proc-macro/src/utils.rs b/substrate/sp-runtime-interface-proc-macro/src/utils.rs index 7a1c46dc3e1..e120848e76c 100644 --- a/substrate/sp-runtime-interface-proc-macro/src/utils.rs +++ b/substrate/sp-runtime-interface-proc-macro/src/utils.rs @@ -133,7 +133,7 @@ impl RuntimeInterfaceFunctionSet { .insert(version.version, RuntimeInterfaceFunction::new(trait_item)?); if self .latest_version_to_call - .map_or(true, |v| v < version.version) + .is_none_or(|v| v < version.version) && version.is_callable() { self.latest_version_to_call = Some(version.version); @@ -234,7 +234,7 @@ pub fn get_function_arguments(sig: &Signature) -> impl Iterator wild.span(), ); - res.pat = Box::new(parse_quote!( #ident )) + *res.pat = parse_quote!( #ident ) } res @@ -372,7 +372,8 @@ pub fn host_inner_arg_ty(ty: &syn::Type) -> syn::Type { } pub fn pat_ty_to_host_inner(mut pat: syn::PatType) -> syn::PatType { - pat.ty = Box::new(host_inner_arg_ty(&pat.ty)); + let ty = host_inner_arg_ty(&pat.ty); + *pat.ty = ty; pat } diff --git a/substrate/substrate-wasm-builder/src/wasm_project.rs b/substrate/substrate-wasm-builder/src/wasm_project.rs index 732ad8625fb..d1bbb08376e 100644 --- a/substrate/substrate-wasm-builder/src/wasm_project.rs +++ b/substrate/substrate-wasm-builder/src/wasm_project.rs @@ -1073,7 +1073,8 @@ fn try_compress_blob(compact_blob_path: &Path, out_name: &str) -> Option { +pub enum Reason { /// Runtime reason variant. /// /// This means that actor explicitly forced some action, diff --git a/vara/common/src/gas_provider/node.rs b/vara/common/src/gas_provider/node.rs index c33add01293..cfdbca28d5e 100644 --- a/vara/common/src/gas_provider/node.rs +++ b/vara/common/src/gas_provider/node.rs @@ -150,7 +150,7 @@ impl NodeLock { )] #[codec(crate = codec)] #[scale_info(crate = scale_info)] -pub enum GasNode { +pub enum GasNode { /// A root node for each gas tree. /// /// Usually created when a new gasful logic started (i.e., message sent). diff --git a/vara/common/src/pallet_tests.rs b/vara/common/src/pallet_tests.rs index ede154b7660..f31329ffa4c 100644 --- a/vara/common/src/pallet_tests.rs +++ b/vara/common/src/pallet_tests.rs @@ -209,6 +209,7 @@ macro_rules! impl_pallet_staking { BlockNumber, pallet_staking::Pallet, ConstU32<100>, + ConstU32<100>, ); #[allow(dead_code)] diff --git a/vara/node/cli/src/benchmarking.rs b/vara/node/cli/src/benchmarking.rs index 31e526dadf5..decb63ad2e7 100644 --- a/vara/node/cli/src/benchmarking.rs +++ b/vara/node/cli/src/benchmarking.rs @@ -91,6 +91,7 @@ macro_rules! with_signed_payload { $( $usage )* }, + Client::Unsupported => Err("unsupported runtime client"), } } } diff --git a/vara/node/cli/src/command.rs b/vara/node/cli/src/command.rs index f2ae568a677..abfa676e415 100644 --- a/vara/node/cli/src/command.rs +++ b/vara/node/cli/src/command.rs @@ -258,8 +258,12 @@ pub fn run() -> sc_cli::Result<()> { )?; let db = backend.expose_db(); let storage = backend.expose_storage(); + let shared_trie_cache = backend.expose_shared_trie_cache(); - unwrap_client!(client, cmd.run(config, client.clone(), db, storage)) + unwrap_client!( + client, + cmd.run(config, client.clone(), db, storage, shared_trie_cache) + ) } BenchmarkCmd::Overhead(cmd) => { let inherent_data = inherent_benchmark_data().map_err(|e| { @@ -276,11 +280,12 @@ pub fn run() -> sc_cli::Result<()> { unwrap_client!( client, cmd.run( - config, + config.chain_spec.name().into(), client.clone(), inherent_data, Vec::new(), - &ext_builder + &ext_builder, + false, ) ) } diff --git a/vara/node/testing/src/keyring.rs b/vara/node/testing/src/keyring.rs index 6ab103cbf6a..8c07f59f3a6 100644 --- a/vara/node/testing/src/keyring.rs +++ b/vara/node/testing/src/keyring.rs @@ -109,13 +109,11 @@ pub fn sign( signature, extra, ) - .into() } - ExtrinsicFormat::Bare => generic::UncheckedExtrinsic::new_bare(xt.function).into(), + ExtrinsicFormat::Bare => generic::UncheckedExtrinsic::new_bare(xt.function), ExtrinsicFormat::General(ext_version, extra) => generic::UncheckedExtrinsic::from_parts( xt.function, generic::Preamble::General(ext_version, extra), - ) - .into(), + ), } } diff --git a/vara/pallets/gas/src/mock.rs b/vara/pallets/gas/src/mock.rs index 397f1e12a3a..47601a7fb5f 100644 --- a/vara/pallets/gas/src/mock.rs +++ b/vara/pallets/gas/src/mock.rs @@ -57,6 +57,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { (BOB, 2_u128), (BLOCK_AUTHOR, 1_u128), ], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); diff --git a/vara/pallets/gear-bank/src/mock.rs b/vara/pallets/gear-bank/src/mock.rs index eae816e4801..52e84098589 100644 --- a/vara/pallets/gear-bank/src/mock.rs +++ b/vara/pallets/gear-bank/src/mock.rs @@ -87,9 +87,12 @@ pub fn new_test_ext() -> TestExternalities { (TREASURY, EXISTENTIAL_DEPOSIT), ]; - pallet_balances::GenesisConfig:: { balances } - .assimilate_storage(&mut storage) - .unwrap(); + pallet_balances::GenesisConfig:: { + balances, + dev_accounts: None, + } + .assimilate_storage(&mut storage) + .unwrap(); pallet_gear_bank::GenesisConfig:: { _config: Default::default(), diff --git a/vara/pallets/gear-builtin/src/benchmarking.rs b/vara/pallets/gear-builtin/src/benchmarking.rs index 5c31c583d44..baa6884cf3d 100644 --- a/vara/pallets/gear-builtin/src/benchmarking.rs +++ b/vara/pallets/gear-builtin/src/benchmarking.rs @@ -9,9 +9,13 @@ use crate::*; use ark_std::{UniformRand, ops::Mul}; use builtins_common::bls12_381::{ ark_bls12_381::{self, Bls12_381, G1Affine, G1Projective as G1, G2Affine, G2Projective as G2}, - ark_ec::{Group, ScalarMul, pairing::Pairing, short_weierstrass::SWCurveConfig}, + ark_ec::{ + AffineRepr, CurveGroup, Group, ScalarMul, pairing::Pairing, + short_weierstrass::SWCurveConfig, + }, ark_ff::biginteger::BigInt, - ark_scale::{self, hazmat::ArkScaleProjective}, + ark_scale::{self, ArkScaleMaxEncodedLen, MaxEncodedLen}, + ark_serialize::CanonicalSerialize, }; use common::Origin; use frame_benchmarking::benchmarks; @@ -23,6 +27,13 @@ type ScalarField = ::ScalarField; const MAX_BIG_INT: u32 = 100; +fn buffer_for() -> Vec +where + T: CanonicalSerialize + ArkScaleMaxEncodedLen, +{ + vec![0; ArkScale::::max_encoded_len()] +} + fn naive_var_base_msm(bases: &[G::MulBase], scalars: &[G::ScalarField]) -> G { let mut acc = G::zero(); @@ -100,14 +111,15 @@ benchmarks! { let pub_key: ArkScale::G2Affine>> = pub_keys.into(); let encoded_pub_key = pub_key.encode(); - let mut _result: Result, ()> = Err(()); + let mut _result = buffer_for::<::TargetField>(); }: { - _result = sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_multi_miller_loop( - encoded_message, - encoded_pub_key, - ); + sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_multi_miller_loop( + &encoded_message, + &encoded_pub_key, + &mut _result, + ).unwrap(); } verify { - assert!(_result.is_ok()); + assert!(!_result.is_empty()); } bls12_381_final_exponentiation { @@ -124,16 +136,18 @@ benchmarks! { let pub_key: ArkScale::G2Affine>> = vec![pub_key].into(); let encoded_pub_key = pub_key.encode(); - let miller_loop = sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_multi_miller_loop( - encoded_message, - encoded_pub_key, + let mut miller_loop = buffer_for::<::TargetField>(); + sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_multi_miller_loop( + &encoded_message, + &encoded_pub_key, + &mut miller_loop, ).unwrap(); - let mut _result: Result, ()> = Err(()); + let mut _result = miller_loop; }: { - _result = sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_final_exponentiation(miller_loop); + sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_final_exponentiation(&mut _result).unwrap(); } verify { - assert!(_result.is_ok()); + assert!(!_result.is_empty()); } bls12_381_msm_g1 { @@ -156,14 +170,17 @@ benchmarks! { let ark_bases: ArkScale> = bases.clone().into(); let encoded_bases = ark_bases.encode(); - let mut _result: Result, ()> = Err(()); + let mut _result = buffer_for::(); }: { - _result = sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_msm_g1(encoded_bases, encoded_scalars); + sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_msm_g1( + &encoded_bases, + &encoded_scalars, + &mut _result, + ).unwrap(); } verify { let naive = naive_var_base_msm::(bases.as_slice(), scalars.as_slice()); - let encoded = _result.unwrap(); - let fast = ArkScaleProjective::::decode(&mut &encoded[..]).unwrap(); - assert_eq!(naive, fast.0); + let fast = ArkScale::::decode(&mut &_result[..]).unwrap(); + assert_eq!(naive, fast.0.into_group()); } bls12_381_msm_g2 { @@ -186,14 +203,17 @@ benchmarks! { let ark_bases: ArkScale> = bases.clone().into(); let encoded_bases = ark_bases.encode(); - let mut _result: Result, ()> = Err(()); + let mut _result = buffer_for::(); }: { - _result = sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_msm_g2(encoded_bases, encoded_scalars); + sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_msm_g2( + &encoded_bases, + &encoded_scalars, + &mut _result, + ).unwrap(); } verify { let naive = naive_var_base_msm::(bases.as_slice(), scalars.as_slice()); - let encoded = _result.unwrap(); - let fast = ArkScaleProjective::::decode(&mut &encoded[..]).unwrap(); - assert_eq!(naive, fast.0); + let fast = ArkScale::::decode(&mut &_result[..]).unwrap(); + assert_eq!(naive, fast.0.into_group()); } bls12_381_mul_projective_g1 { @@ -207,17 +227,20 @@ benchmarks! { let encoded_bigint = ark_bigint.encode(); let base = G1::rand(&mut rng); - let ark_base: ArkScaleProjective = base.into(); + let ark_base: ArkScale = base.into_affine().into(); let encoded_base = ark_base.encode(); - let mut _result: Result, ()> = Err(()); + let mut _result = vec![0; encoded_base.len()]; }: { - _result = sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_mul_projective_g1(encoded_base, encoded_bigint); + sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_mul_g1( + &encoded_base, + &encoded_bigint, + &mut _result, + ).unwrap(); } verify { - let encoded = _result.unwrap(); - let result = ArkScaleProjective::::decode(&mut &encoded[..]).unwrap(); + let result = ArkScale::::decode(&mut &_result[..]).unwrap(); let standard = ::mul_projective(&base, &bigint); - assert_eq!(standard, result.0); + assert_eq!(standard, result.0.into_group()); } bls12_381_mul_projective_g2 { @@ -231,17 +254,20 @@ benchmarks! { let encoded_bigint = ark_bigint.encode(); let base = G2::rand(&mut rng); - let ark_base: ArkScaleProjective = base.into(); + let ark_base: ArkScale = base.into_affine().into(); let encoded_base = ark_base.encode(); - let mut _result: Result, ()> = Err(()); + let mut _result = vec![0; encoded_base.len()]; }: { - _result = sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_mul_projective_g2(encoded_base, encoded_bigint); + sp_crypto_ec_utils::bls12_381::host_calls::bls12_381_mul_g2( + &encoded_base, + &encoded_bigint, + &mut _result, + ).unwrap(); } verify { - let encoded = _result.unwrap(); - let result = ArkScaleProjective::::decode(&mut &encoded[..]).unwrap(); + let result = ArkScale::::decode(&mut &_result[..]).unwrap(); let standard = ::mul_projective(&base, &bigint); - assert_eq!(standard, result.0); + assert_eq!(standard, result.0.into_group()); } bls12_381_aggregate_g1 { diff --git a/vara/pallets/gear-builtin/src/mock.rs b/vara/pallets/gear-builtin/src/mock.rs index 7fa6569ad4d..e11b63f1311 100644 --- a/vara/pallets/gear-builtin/src/mock.rs +++ b/vara/pallets/gear-builtin/src/mock.rs @@ -18,10 +18,10 @@ use frame_support_test::TestRandomness; use frame_system::{self as system, limits::BlockWeights, pallet_prelude::BlockNumberFor}; use gbuiltin_proxy::ProxyType as BuiltinProxyType; use gear_core::{ids::ActorId, message::StoredDispatch}; -use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; use sp_core::H256; use sp_runtime::{ - BuildStorage, Perbill, Permill, RuntimeDebug, + BuildStorage, Perbill, Permill, traits::{BlakeTwo256, IdentityLookup}, }; use sp_std::convert::{TryFrom, TryInto}; @@ -96,8 +96,9 @@ parameter_types! { PartialOrd, Encode, Decode, - RuntimeDebug, + Debug, MaxEncodedLen, + DecodeWithMemTracking, scale_info::TypeInfo, )] pub enum ProxyType { @@ -179,6 +180,7 @@ impl pallet_proxy::Config for Test { type CallHasher = BlakeTwo256; type AnnouncementDepositBase = AnnouncementDepositBase; type AnnouncementDepositFactor = AnnouncementDepositBase; + type BlockNumberProvider = System; } parameter_types! { @@ -353,6 +355,7 @@ impl ExtBuilder { .iter() .map(|k| (*k, self.endowment)) .collect(), + dev_accounts: None, } .assimilate_storage(&mut storage) .unwrap(); diff --git a/vara/pallets/gear-builtin/src/tests/bad_builtin_ids.rs b/vara/pallets/gear-builtin/src/tests/bad_builtin_ids.rs index 206add957cd..c86f9b34a00 100644 --- a/vara/pallets/gear-builtin/src/tests/bad_builtin_ids.rs +++ b/vara/pallets/gear-builtin/src/tests/bad_builtin_ids.rs @@ -139,6 +139,7 @@ impl ExtBuilder { .iter() .map(|k| (*k, self.endowment)) .collect(), + dev_accounts: None, } .assimilate_storage(&mut storage) .unwrap(); diff --git a/vara/pallets/gear-builtin/src/tests/proxy.rs b/vara/pallets/gear-builtin/src/tests/proxy.rs index ef53d8b3ad3..7bc9c01b1f2 100644 --- a/vara/pallets/gear-builtin/src/tests/proxy.rs +++ b/vara/pallets/gear-builtin/src/tests/proxy.rs @@ -135,7 +135,7 @@ fn gas_allowance_respected() { delay: 0, } .get_dispatch_info() - .weight + .total_weight() .ref_time(); let broker_gas_allowance = 1; diff --git a/vara/pallets/gear-builtin/src/tests/staking.rs b/vara/pallets/gear-builtin/src/tests/staking.rs index ec28d76cd5f..ef561ae1862 100644 --- a/vara/pallets/gear-builtin/src/tests/staking.rs +++ b/vara/pallets/gear-builtin/src/tests/staking.rs @@ -600,7 +600,7 @@ fn gas_allowance_respected() { payee: pallet_staking::RewardDestination::None, } .get_dispatch_info() - .weight + .total_weight() .ref_time(); System::reset_events(); @@ -751,7 +751,7 @@ mod util { use sp_runtime::{ BuildStorage, KeyTypeId, Perbill, Permill, testing::UintAuthorityId, - traits::{BlakeTwo256, ConstU32, IdentityLookup, OpaqueKeys}, + traits::{BlakeTwo256, ConstBool, ConstU32, ConvertInto, IdentityLookup, OpaqueKeys}, }; use sp_std::convert::{TryFrom, TryInto}; @@ -818,8 +818,10 @@ mod util { type Solver = SequentialPhragmen; type DataProvider = Staking; type WeightInfo = (); - type MaxWinners = ConstU32<100>; + type MaxBackersPerWinner = ConstU32<100>; + type MaxWinnersPerPage = ConstU32<100>; type Bounds = ElectionBoundsOnChain; + type Sort = ConstBool; } common::impl_pallet_staking!( @@ -869,18 +871,23 @@ mod util { impl pallet_session::Config for Test { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; - type ValidatorIdOf = pallet_staking::StashOf; + type ValidatorIdOf = ConvertInto; type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; type SessionManager = pallet_session_historical::NoteHistoricalRoot; type SessionHandler = TestSessionHandler; type Keys = UintAuthorityId; type WeightInfo = (); + type DisablingStrategy = + pallet_session::disabling::UpToLimitWithReEnablingDisablingStrategy<1>; + type Currency = Balances; + type KeyDeposit = (); } impl pallet_session_historical::Config for Test { + type RuntimeEvent = RuntimeEvent; type FullIdentification = pallet_staking::Exposure; - type FullIdentificationOf = pallet_staking::ExposureOf; + type FullIdentificationOf = pallet_staking::DefaultExposureOf; } pallet_gear_bank::impl_config!(Test); @@ -940,6 +947,7 @@ mod util { .map(|x| (x.0, self.endowment)) .chain(self.endowed_accounts.iter().map(|k| (*k, self.endowment))) .collect(), + dev_accounts: None, } .assimilate_storage(&mut storage) .unwrap(); diff --git a/vara/pallets/gear-eth-bridge/src/benchmarking.rs b/vara/pallets/gear-eth-bridge/src/benchmarking.rs index 9a4fda93a7b..264eca20492 100644 --- a/vara/pallets/gear-eth-bridge/src/benchmarking.rs +++ b/vara/pallets/gear-eth-bridge/src/benchmarking.rs @@ -55,7 +55,7 @@ benchmarks! { let origin = benchmarking::account::("origin", 0, 0); let _ = crate::CurrencyOf::::deposit_creating(&origin, CurrencyOf::::minimum_balance()); - let destination = [42; 20].into(); + let destination = gprimitives::H160::from([42; 20]).into(); let payload = vec![42; T::MaxPayloadSize::get() as usize]; }: _(RawOrigin::Signed(origin), destination, payload) diff --git a/vara/pallets/gear-eth-bridge/src/lib.rs b/vara/pallets/gear-eth-bridge/src/lib.rs index f3a8ac40529..f6425aa47fe 100644 --- a/vara/pallets/gear-eth-bridge/src/lib.rs +++ b/vara/pallets/gear-eth-bridge/src/lib.rs @@ -77,11 +77,6 @@ pub mod pallet { pub trait Config: frame_system::Config + pallet_gear_bank::Config + pallet_grandpa::Config { - /// Type representing aggregated runtime event. - type RuntimeEvent: From> - + TryInto> - + IsType<::RuntimeEvent>; - /// The bridge' pallet id, used for deriving its sovereign account ID. #[pallet::constant] type PalletId: Get; diff --git a/vara/pallets/gear-eth-bridge/src/mock.rs b/vara/pallets/gear-eth-bridge/src/mock.rs index 5377e171f0d..a91d5409e32 100644 --- a/vara/pallets/gear-eth-bridge/src/mock.rs +++ b/vara/pallets/gear-eth-bridge/src/mock.rs @@ -287,6 +287,9 @@ impl pallet_session::Config for Test { type SessionManager = TestSessionManager; type SessionHandler = VaraSessionHandler; type Keys = SessionKeys; + type DisablingStrategy = pallet_session::disabling::UpToLimitDisablingStrategy; + type Currency = Balances; + type KeyDeposit = (); type WeightInfo = pallet_session::weights::SubstrateWeight; } @@ -309,7 +312,6 @@ impl pallet_gear_eth_bridge::Config for Test { type AdminOrigin = EnsureSignedBy; type PalletId = GearEthBridgePalletId; type BuiltinAddress = MockBridgeBuiltinAddress; - type RuntimeEvent = RuntimeEvent; type MaxPayloadSize = ConstU32<1024>; type QueueCapacity = ConstU32<32>; type BridgeAdmin = MockBridgeAdminAccount; @@ -346,6 +348,7 @@ impl ExtBuilder { .iter() .map(|k| (*k, self.endowment)) .collect(), + dev_accounts: None, } .assimilate_storage(&mut storage) .unwrap(); diff --git a/vara/pallets/gear-eth-bridge/src/tests.rs b/vara/pallets/gear-eth-bridge/src/tests.rs index 7c8d404d73b..fca15bda026 100644 --- a/vara/pallets/gear-eth-bridge/src/tests.rs +++ b/vara/pallets/gear-eth-bridge/src/tests.rs @@ -114,10 +114,10 @@ fn bridge_got_initialized() { [ SessionEvent::NewSession { session_index: 6 }.into(), Event::BridgeInitialized.into(), - Event::AuthoritySetHashChanged(authority_set_hash).into(), + Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], ); - assert_eq!(QueueMerkleRoot::get(), Some(H256::zero())); + assert_eq!(QueueMerkleRoot::get(), Some(H256::zero().into())); assert!(Initialized::get()); assert!(Paused::get()); @@ -192,7 +192,7 @@ fn bridge_send_eth_message_works() { assert_ok!(GearEthBridge::unpause(RuntimeOrigin::root())); assert_noop!( - GearEthBridge::send_eth_message(RuntimeOrigin::root(), H160::zero(), vec![]), + GearEthBridge::send_eth_message(RuntimeOrigin::root(), H160::zero().into(), vec![]), BadOrigin ); @@ -210,14 +210,14 @@ fn bridge_send_eth_message_works() { let fee = MockTransportFee::get(); let message = unsafe { - EthMessage::new_unchecked(0.into(), SIGNER.cast(), destination, payload.clone()) + EthMessage::new_unchecked(0.into(), SIGNER.cast(), destination.into(), payload.clone()) }; let hash = message.hash(); let mut queue = vec![hash]; assert_ok!(GearEthBridge::send_eth_message( RuntimeOrigin::signed(SIGNER), - destination, + destination.into(), payload )); @@ -236,7 +236,7 @@ fn bridge_send_eth_message_works() { let payload = H256::random().as_bytes().to_vec(); let message = unsafe { - EthMessage::new_unchecked(1.into(), SIGNER.cast(), destination, payload.clone()) + EthMessage::new_unchecked(1.into(), SIGNER.cast(), destination.into(), payload.clone()) }; let nonce = message.nonce(); let hash = message.hash(); @@ -265,7 +265,7 @@ fn bridge_send_eth_message_works() { response, Response::EthMessageQueued { block_number, - hash, + hash: hash.into(), nonce, queue_id } @@ -294,21 +294,23 @@ fn bridge_queue_root_changes() { for _ in 0..4 { assert_ok!(GearEthBridge::send_eth_message( RuntimeOrigin::signed(SIGNER), - H160::random(), + H160::random().into(), H256::random().as_bytes().to_vec() )); assert!(QueueChanged::get()); } - let expected_root = binary_merkle_tree::merkle_root_raw::(Queue::get()); + let expected_root = binary_merkle_tree::merkle_root_raw::( + Queue::get().into_iter().map(Into::::into), + ); on_finalize_gear_block(WHEN_INITIALIZED); System::assert_last_event( Event::QueueMerkleRootChanged { queue_id: 0, - root: expected_root, + root: expected_root.into(), } .into(), ); @@ -350,7 +352,7 @@ fn bridge_updates_authorities_and_clears() { assert_eq!( AuthoritySetHash::get().expect("infallible"), - authority_set_hash + authority_set_hash.into() ); assert_ok!(GearEthBridge::unpause(RuntimeOrigin::root())); @@ -358,7 +360,7 @@ fn bridge_updates_authorities_and_clears() { for _ in 0..5 { assert_ok!(GearEthBridge::send_eth_message( RuntimeOrigin::signed(SIGNER), - H160::zero(), + H160::zero().into(), vec![] )); } @@ -370,7 +372,10 @@ fn bridge_updates_authorities_and_clears() { System::events().last().expect("infallible").event, RuntimeEvent::GearEthBridge(Event::QueueMerkleRootChanged { .. }) )); - assert!(!QueueMerkleRoot::get().expect("infallible").is_zero()); + assert_ne!( + QueueMerkleRoot::get().expect("infallible"), + H256::zero().into() + ); on_initialize(ERA_BLOCKS + 3); do_events_assertion(6, 39, None::<[_; 0]>); @@ -401,20 +406,23 @@ fn bridge_updates_authorities_and_clears() { 67, [SessionEvent::NewSession { session_index: 11 }.into()], ); - assert!(!QueueMerkleRoot::get().expect("infallible").is_zero()); + assert_ne!( + QueueMerkleRoot::get().expect("infallible"), + H256::zero().into() + ); run_to_block(ERA_BLOCKS * 2 + 1); assert_eq!( AuthoritySetHash::get().expect("infallible"), - authority_set_hash + authority_set_hash.into() ); do_events_assertion( 12, 73, [ SessionEvent::NewSession { session_index: 12 }.into(), - Event::AuthoritySetHashChanged(authority_set_hash).into(), + Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], ); @@ -426,7 +434,10 @@ fn bridge_updates_authorities_and_clears() { on_initialize(ERA_BLOCKS * 2 + 2); do_events_assertion(12, 74, [Event::QueueReset.into()]); - assert!(QueueMerkleRoot::get().expect("infallible").is_zero()); + assert_eq!( + QueueMerkleRoot::get().expect("infallible"), + H256::zero().into() + ); run_to_block(ERA_BLOCKS * 2 + EPOCH_BLOCKS * 5); do_events_assertion( @@ -462,7 +473,7 @@ fn bridge_updates_authorities_and_clears() { 109, [ SessionEvent::NewSession { session_index: 18 }.into(), - Event::AuthoritySetHashChanged(authority_set_hash).into(), + Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), GrandpaEvent::NewAuthorities { authority_set }.into(), ], ); @@ -490,7 +501,7 @@ fn bridge_queues_governance_messages_when_over_capacity() { for _ in 0..queue_capacity { assert_ok!(GearEthBridge::send_eth_message( RuntimeOrigin::signed(SIGNER), - H160::zero(), + H160::zero().into(), vec![] )); } @@ -500,7 +511,7 @@ fn bridge_queues_governance_messages_when_over_capacity() { GearEthBridge::send_eth_message( RuntimeOrigin::signed(::BridgeAdmin::get()), - H160::zero(), + H160::zero().into(), vec![], ) .unwrap(); @@ -598,7 +609,7 @@ fn bridge_queue_capacity_exceeded_and_reset() { for _ in 0..::QueueCapacity::get() { assert_ok!(GearEthBridge::send_eth_message( RuntimeOrigin::signed(SIGNER), - H160::zero(), + H160::zero().into(), vec![] )); @@ -805,7 +816,7 @@ mod utils { } => { GearEthBridge::send_eth_message( RuntimeOrigin::signed(SIGNER), - destination, + destination.into(), payload, ) } @@ -1020,10 +1031,10 @@ fn rotate_keys() { [ SessionEvent::NewSession { session_index: 3 }.into(), Event::BridgeInitialized.into(), - Event::AuthoritySetHashChanged(authority_set_hash).into(), + Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], ); - assert_eq!(QueueMerkleRoot::get(), Some(H256::zero())); + assert_eq!(QueueMerkleRoot::get(), Some(H256::zero().into())); assert!(Initialized::get()); assert!(Paused::get()); @@ -1076,7 +1087,7 @@ fn rotate_keys() { 37, [ SessionEvent::NewSession { session_index: 6 }.into(), - Event::AuthoritySetHashChanged(authority_set_hash).into(), + Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], ); @@ -1148,7 +1159,7 @@ fn rotate_keys() { 49, [ SessionEvent::NewSession { session_index: 8 }.into(), - Event::AuthoritySetHashChanged(authority_set_hash).into(), + Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], ); diff --git a/vara/pallets/gear-messenger/src/mock.rs b/vara/pallets/gear-messenger/src/mock.rs index 92ab2d05f60..f7b45e69059 100644 --- a/vara/pallets/gear-messenger/src/mock.rs +++ b/vara/pallets/gear-messenger/src/mock.rs @@ -50,9 +50,12 @@ pub fn new_test_ext() -> sp_io::TestExternalities { .build_storage() .unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![] } - .assimilate_storage(&mut t) - .unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![], + dev_accounts: None, + } + .assimilate_storage(&mut t) + .unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); diff --git a/vara/pallets/gear-program/src/mock.rs b/vara/pallets/gear-program/src/mock.rs index b6d25aa1b5c..12ff2bda095 100644 --- a/vara/pallets/gear-program/src/mock.rs +++ b/vara/pallets/gear-program/src/mock.rs @@ -92,6 +92,7 @@ impl pallet_treasury::Config for Test { type Paymaster = PayFromAccount; type BalanceConverter = UnityAssetBalanceConversion; type PayoutPeriod = ConstU64<10>; + type BlockNumberProvider = System; } // Build genesis storage according to the mock runtime. @@ -108,6 +109,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { (LOW_BALANCE_USER, 1_000_000_u128), (BLOCK_AUTHOR, 500_000_u128), ], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); diff --git a/vara/pallets/gear-scheduler/src/mock.rs b/vara/pallets/gear-scheduler/src/mock.rs index 8ee3d93e9db..61c2ae1f861 100644 --- a/vara/pallets/gear-scheduler/src/mock.rs +++ b/vara/pallets/gear-scheduler/src/mock.rs @@ -96,6 +96,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { (BLOCK_AUTHOR, 500_000_u128), (GearBank::bank_address(), ExistentialDeposit::get()), ], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); diff --git a/vara/pallets/gear-voucher/src/lib.rs b/vara/pallets/gear-voucher/src/lib.rs index 1d5f69c9f79..dfaf31dae76 100644 --- a/vara/pallets/gear-voucher/src/lib.rs +++ b/vara/pallets/gear-voucher/src/lib.rs @@ -73,9 +73,6 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { - /// The overarching event type. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// Currency implementation type Currency: ReservableCurrency; diff --git a/vara/pallets/gear-voucher/src/mock.rs b/vara/pallets/gear-voucher/src/mock.rs index 8bfac901441..94e1c27d5b0 100644 --- a/vara/pallets/gear-voucher/src/mock.rs +++ b/vara/pallets/gear-voucher/src/mock.rs @@ -117,7 +117,6 @@ impl Mailbox for MailboxMock { } impl pallet_gear_voucher::Config for Test { - type RuntimeEvent = RuntimeEvent; type Currency = Balances; type PalletId = VoucherPalletId; type WeightInfo = (); @@ -136,6 +135,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { pallet_balances::GenesisConfig:: { balances: vec![(ALICE, 100_000_000_u128), (BOB, 100_u128)], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); diff --git a/vara/pallets/gear/src/benchmarking/mod.rs b/vara/pallets/gear/src/benchmarking/mod.rs index 7b36e1b750e..24131bfe490 100644 --- a/vara/pallets/gear/src/benchmarking/mod.rs +++ b/vara/pallets/gear/src/benchmarking/mod.rs @@ -185,14 +185,14 @@ where pub fn find_latest_event(mapping_filter: F) -> Option where T: Config, + ::RuntimeEvent: TryInto>, F: Fn(Event) -> Option, { SystemPallet::::events() .into_iter() .rev() .filter_map(|event_record| { - let event = <::RuntimeEvent as From<_>>::from(event_record.event); - let event: Result, _> = event.try_into(); + let event: Result, _> = event_record.event.try_into(); event.ok() }) @@ -279,6 +279,7 @@ benchmarks! { where_clause { where T::AccountId: Origin, + ::RuntimeEvent: TryInto>, T: pallet_gear_voucher::Config, } diff --git a/vara/pallets/gear/src/benchmarking/tasks.rs b/vara/pallets/gear/src/benchmarking/tasks.rs index 2ad4513f556..8b3f5c82bc7 100644 --- a/vara/pallets/gear/src/benchmarking/tasks.rs +++ b/vara/pallets/gear/src/benchmarking/tasks.rs @@ -10,6 +10,7 @@ const DEFAULT_GAS_LIMIT: u64 = 15_000_000_000; fn send_user_message_prepare(delay: u32) where T: Config, + ::RuntimeEvent: TryInto>, T::AccountId: Origin, { use demo_delayed_sender::WASM_BINARY; @@ -40,6 +41,7 @@ where pub(super) fn remove_gas_reservation() -> (ActorId, ReservationId) where T: Config, + ::RuntimeEvent: TryInto>, T::AccountId: Origin, { use demo_reserve_gas::{InitAction, WASM_BINARY}; @@ -85,6 +87,7 @@ where pub(super) fn send_user_message() -> MessageId where T: Config, + ::RuntimeEvent: TryInto>, T::AccountId: Origin, { let delay = 1u32; @@ -219,6 +222,7 @@ where pub(super) fn remove_from_waitlist() -> (ActorId, MessageId) where T: Config, + ::RuntimeEvent: TryInto>, T::AccountId: Origin, { use demo_waiter::{Command, WASM_BINARY, WaitSubcommand}; @@ -276,6 +280,7 @@ where pub(super) fn remove_from_mailbox() -> (ActorId, MessageId) where T: Config, + ::RuntimeEvent: TryInto>, T::AccountId: Origin, { send_user_message_prepare::(0u32); diff --git a/vara/pallets/gear/src/lib.rs b/vara/pallets/gear/src/lib.rs index 5d67f899000..171c69443d5 100644 --- a/vara/pallets/gear/src/lib.rs +++ b/vara/pallets/gear/src/lib.rs @@ -150,11 +150,6 @@ pub mod pallet { + pallet_timestamp::Config + pallet_gear_bank::Config { - /// Because this pallet emits events, it depends on the runtime's definition of an event. - type RuntimeEvent: From> - + TryInto> - + IsType<::RuntimeEvent>; - /// The generator used to supply randomness to programs through `seal_random` type Randomness: Randomness>; diff --git a/vara/pallets/gear/src/mock.rs b/vara/pallets/gear/src/mock.rs index a0bca0fc5d1..07a92428c82 100644 --- a/vara/pallets/gear/src/mock.rs +++ b/vara/pallets/gear/src/mock.rs @@ -156,7 +156,6 @@ parameter_types! { } impl pallet_gear_voucher::Config for Test { - type RuntimeEvent = RuntimeEvent; type Currency = Balances; type PalletId = VoucherPalletId; type WeightInfo = (); @@ -183,6 +182,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { (RENT_POOL, ExistentialDeposit::get()), (GearBank::bank_address(), ExistentialDeposit::get()), ], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); diff --git a/vara/pallets/gear/src/pallet_tests.rs b/vara/pallets/gear/src/pallet_tests.rs index 13a8a00a3e5..c7bdc2cfb25 100644 --- a/vara/pallets/gear/src/pallet_tests.rs +++ b/vara/pallets/gear/src/pallet_tests.rs @@ -26,7 +26,6 @@ macro_rules! impl_config { macro_rules! impl_config_inner { ($runtime:ty$(,)?) => { impl pallet_gear::Config for $runtime { - type RuntimeEvent = RuntimeEvent; type Randomness = TestRandomness; type WeightInfo = pallet_gear::weights::SubstrateWeight; type Schedule = GearConfigSchedule; diff --git a/vara/pallets/grandpa-signer/src/lib.rs b/vara/pallets/grandpa-signer/src/lib.rs index 58392299fdc..8f2db938fef 100644 --- a/vara/pallets/grandpa-signer/src/lib.rs +++ b/vara/pallets/grandpa-signer/src/lib.rs @@ -73,8 +73,6 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// GRANDPA public key type. type AuthorityId: Parameter + Member diff --git a/vara/pallets/grandpa-signer/src/tests.rs b/vara/pallets/grandpa-signer/src/tests.rs index 3a39c766d99..73fcd546555 100644 --- a/vara/pallets/grandpa-signer/src/tests.rs +++ b/vara/pallets/grandpa-signer/src/tests.rs @@ -9,7 +9,7 @@ use sp_core::{Pair, ed25519}; use sp_runtime::{BuildStorage, traits::IdentityLookup}; use std::sync::Mutex; -type Extrinsic = sp_runtime::testing::TestXt, ()>; +type Extrinsic = sp_runtime::testing::TestXt; type Block = frame_system::mocking::MockBlock; frame_support::construct_runtime!( @@ -75,15 +75,21 @@ impl frame_system::Config for Test { type PreInherents = (); type PostInherents = (); type PostTransactions = (); + type ExtensionsWeightInfo = (); } -impl frame_system::offchain::SendTransactionTypes> for Test { +impl frame_system::offchain::CreateTransactionBase> for Test { type Extrinsic = Extrinsic; - type OverarchingCall = Call; + type RuntimeCall = RuntimeCall; +} + +impl frame_system::offchain::CreateBare> for Test { + fn create_bare(call: Self::RuntimeCall) -> Self::Extrinsic { + Extrinsic::new_bare(call) + } } impl Config for Test { - type RuntimeEvent = RuntimeEvent; type AuthorityId = ed25519::Public; type AuthoritySignature = ed25519::Signature; type MaxPayloadLength = MaxPayloadLength; diff --git a/vara/pallets/payment/src/lib.rs b/vara/pallets/payment/src/lib.rs index bb6fbbf1ea4..7871dd8edb6 100644 --- a/vara/pallets/payment/src/lib.rs +++ b/vara/pallets/payment/src/lib.rs @@ -274,7 +274,7 @@ impl Pallet { pays_fee, } = ::get_dispatch_info(&unchecked_extrinsic); - let partial_fee = if unchecked_extrinsic.is_signed().unwrap_or(false) { + let partial_fee = if !unchecked_extrinsic.is_bare() { let call: CallOf = >>::extract_call(&unchecked_extrinsic); // If call is exempted from weight multiplication pre-divide it with the fee multiplier @@ -331,7 +331,7 @@ impl Pallet { let tip = 0u32.into(); - if unchecked_extrinsic.is_signed().unwrap_or(false) { + if !unchecked_extrinsic.is_bare() { let call: CallOf = >>::extract_call(&unchecked_extrinsic); let adjusted_call_weight = if !T::ExtraFeeCallFilter::contains(&call) { diff --git a/vara/pallets/payment/src/mock.rs b/vara/pallets/payment/src/mock.rs index 93e043dfd65..9ecc5685382 100644 --- a/vara/pallets/payment/src/mock.rs +++ b/vara/pallets/payment/src/mock.rs @@ -163,7 +163,6 @@ parameter_types! { } impl pallet_gear_voucher::Config for Test { - type RuntimeEvent = RuntimeEvent; type Currency = Balances; type PalletId = VoucherPalletId; type WeightInfo = (); diff --git a/vara/pallets/payment/src/tests.rs b/vara/pallets/payment/src/tests.rs index 42520278489..363ab4ed930 100644 --- a/vara/pallets/payment/src/tests.rs +++ b/vara/pallets/payment/src/tests.rs @@ -1335,13 +1335,13 @@ mod utils { TransactionValidityError, > { let extension = CustomChargeTransactionPayment::::from(0); - let implicit = extension.implicit()?; + extension.implicit()?; let (_, val, origin) = extension.validate( RuntimeOrigin::signed(*who), call, info, len, - implicit, + (), &TxBaseImplication(()), TransactionSource::External, )?; diff --git a/vara/pallets/staking-rewards/src/extension.rs b/vara/pallets/staking-rewards/src/extension.rs index 6630a0c4b0c..f93837c99cc 100644 --- a/vara/pallets/staking-rewards/src/extension.rs +++ b/vara/pallets/staking-rewards/src/extension.rs @@ -50,12 +50,11 @@ where _: &impl Implication, _: TransactionSource, ) -> Result<(ValidTransaction, Self::Val, T::RuntimeOrigin), TransactionValidityError> { - if T::BondCallFilter::contains(call) { - if let Ok(from) = frame_system::ensure_signed(origin.clone()) { - if T::AccountFilter::contains(&from) { - return Err(TransactionValidityError::Invalid(InvalidTransaction::Call)); - } - } + if T::BondCallFilter::contains(call) + && let Ok(from) = frame_system::ensure_signed(origin.clone()) + && T::AccountFilter::contains(&from) + { + return Err(TransactionValidityError::Invalid(InvalidTransaction::Call)); } Ok((Default::default(), (), origin)) } diff --git a/vara/pallets/staking-rewards/src/lib.rs b/vara/pallets/staking-rewards/src/lib.rs index b7d98555321..d6212eeba21 100644 --- a/vara/pallets/staking-rewards/src/lib.rs +++ b/vara/pallets/staking-rewards/src/lib.rs @@ -100,9 +100,6 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config + pallet_staking::Config { - /// The overarching event type. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// RuntimeCall filter that matches the `Staking::bond()` call type BondCallFilter: Contains<::RuntimeCall>; @@ -429,17 +426,17 @@ fn pay_rent_rewards_out(maybe_active_era_info: Option) let funds: u128 = pallet::Pallet::::rent_pool_balance().unique_saturated_into(); for (account_id, points) in reward_points.individual { let payout = funds.saturating_mul(u128::from(points)) / total; - if payout > 0 { - if let Err(e) = CurrencyOf::::transfer( + if payout > 0 + && let Err(e) = CurrencyOf::::transfer( &pallet::Pallet::::rent_pool_account_id(), &account_id, payout.unique_saturated_into(), Preservation::Preserve, - ) { - log::error!( - "Failed to transfer rent reward: {e:?}; account_id = {account_id:#?}, points = {points}, payout = {payout}" - ); - } + ) + { + log::error!( + "Failed to transfer rent reward: {e:?}; account_id = {account_id:#?}, points = {points}, payout = {payout}" + ); } } } diff --git a/vara/pallets/staking-rewards/src/mock.rs b/vara/pallets/staking-rewards/src/mock.rs index 5e3831117ba..343e560342e 100644 --- a/vara/pallets/staking-rewards/src/mock.rs +++ b/vara/pallets/staking-rewards/src/mock.rs @@ -33,14 +33,6 @@ type AccountId = u64; pub type BlockNumber = BlockNumberFor; type Balance = u128; -pub(crate) type Executive = frame_executive::Executive< - Test, - Block, - frame_system::ChainContext, - Test, - AllPalletsWithSystem, ->; - pub(crate) const SIGNER: AccountId = 1; pub(crate) const VAL_1_STASH: AccountId = 10; pub(crate) const BLOCK_AUTHOR: AccountId = VAL_1_STASH; @@ -160,7 +152,6 @@ parameter_types! { } impl pallet_gear_staking_rewards::Config for Test { - type RuntimeEvent = RuntimeEvent; type BondCallFilter = BondCallFilter; type AccountFilter = NonStakingAccountsFilter; type PalletId = StakingRewardsPalletId; @@ -196,7 +187,7 @@ impl pallet_session::Config for Test { impl pallet_session_historical::Config for Test { type RuntimeEvent = RuntimeEvent; type FullIdentification = pallet_staking::Exposure; - type FullIdentificationOf = pallet_staking::ExposureOf; + type FullIdentificationOf = pallet_staking::DefaultExposureOf; } type AuthorityId = AccountId; @@ -790,7 +781,7 @@ pub(crate) mod two_block_producers { impl pallet_session_historical::Config for Test { type RuntimeEvent = RuntimeEvent; type FullIdentification = pallet_staking::Exposure; - type FullIdentificationOf = pallet_staking::ExposureOf; + type FullIdentificationOf = pallet_staking::DefaultExposureOf; } parameter_types! { @@ -883,7 +874,6 @@ pub(crate) mod two_block_producers { } impl pallet_gear_staking_rewards::Config for Test { - type RuntimeEvent = RuntimeEvent; type BondCallFilter = (); type AccountFilter = NonStakingAccountsFilter; type PalletId = StakingRewardsPalletId; diff --git a/vara/runtime/common/src/apis.rs b/vara/runtime/common/src/apis.rs index 43f5e904ef0..d9b6131be8f 100644 --- a/vara/runtime/common/src/apis.rs +++ b/vara/runtime/common/src/apis.rs @@ -178,7 +178,7 @@ macro_rules! impl_runtime_apis_plus_common { } fn gear_run_extrinsic(max_gas: Option) -> ::Extrinsic { - UncheckedExtrinsic::new_unsigned( + UncheckedExtrinsic::new_bare( pallet_gear::Call::run { max_gas }.into() ).into() } @@ -224,7 +224,7 @@ macro_rules! impl_runtime_apis_plus_common { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig - ) -> Result, sp_runtime::RuntimeString> { + ) -> Result, alloc::string::String> { use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch}; use sp_storage::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; diff --git a/vara/runtime/interface/Cargo.toml b/vara/runtime/interface/Cargo.toml index 976a0a342b8..9360e8e43ea 100644 --- a/vara/runtime/interface/Cargo.toml +++ b/vara/runtime/interface/Cargo.toml @@ -9,6 +9,9 @@ license.workspace = true homepage.workspace = true repository.workspace = true +[lints] +workspace = true + [dependencies] builtins-common = { workspace = true, optional = true } gear-core.workspace = true diff --git a/vara/runtime/vara/Cargo.toml b/vara/runtime/vara/Cargo.toml index 5a49c577645..fb665ad2acf 100644 --- a/vara/runtime/vara/Cargo.toml +++ b/vara/runtime/vara/Cargo.toml @@ -129,6 +129,7 @@ substrate-wasm-builder = { workspace = true, optional = true } sc-executor.workspace = true sc-executor-common.workspace = true sp-io.workspace = true +sp-maybe-compressed-blob.workspace = true gear-runtime-interface = { workspace = true, features = ["std"] } parity-scale-codec.workspace = true diff --git a/vara/runtime/vara/build.rs b/vara/runtime/vara/build.rs index ba6bcb87bc3..54c9659a1dd 100644 --- a/vara/runtime/vara/build.rs +++ b/vara/runtime/vara/build.rs @@ -94,7 +94,10 @@ fn regenerate_gsdk_scale() { .build(); // 4. Extract last supported metadata version - let runtime_blob = RuntimeBlob::uncompress_if_needed(&code).unwrap(); + let code = + sp_maybe_compressed_blob::decompress(&code, sp_maybe_compressed_blob::CODE_BLOB_BOMB_LIMIT) + .unwrap(); + let runtime_blob = RuntimeBlob::new(&code).unwrap(); let mut externalities = sp_io::TestExternalities::default(); let versions = executor diff --git a/vara/runtime/vara/src/integration_tests.rs b/vara/runtime/vara/src/integration_tests.rs index 228818b609d..5f6d892b8bf 100644 --- a/vara/runtime/vara/src/integration_tests.rs +++ b/vara/runtime/vara/src/integration_tests.rs @@ -17,7 +17,7 @@ use sp_consensus_babe::{ digests::{PreDigest, SecondaryPlainPreDigest}, }; use sp_core::{Pair, ed25519, sr25519}; -use sp_keyring::AccountKeyring; +use sp_keyring::Sr25519Keyring as AccountKeyring; use sp_runtime::{BuildStorage, Digest, DigestItem}; const ENDOWMENT: u128 = 100_000 * UNITS; @@ -145,9 +145,12 @@ impl ExtBuilder { balances.push((GearBank::bank_address(), EXISTENTIAL_DEPOSIT)); - pallet_balances::GenesisConfig:: { balances } - .assimilate_storage(&mut storage) - .unwrap(); + pallet_balances::GenesisConfig:: { + balances, + dev_accounts: None, + } + .assimilate_storage(&mut storage) + .unwrap(); SessionConfig { keys: self diff --git a/vara/runtime/vara/src/lib.rs b/vara/runtime/vara/src/lib.rs index add459adff3..183b26193b3 100644 --- a/vara/runtime/vara/src/lib.rs +++ b/vara/runtime/vara/src/lib.rs @@ -50,8 +50,8 @@ use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_core::{ConstU8, ConstU64, H256, OpaqueMetadata, crypto::KeyTypeId, ed25519}; use sp_runtime::{ - ApplyExtrinsicResult, FixedU128, Perbill, Percent, Permill, Perquintill, create_runtime_str, - generic, impl_opaque_keys, + ApplyExtrinsicResult, FixedU128, Perbill, Percent, Permill, Perquintill, generic, + impl_opaque_keys, traits::{ AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, DispatchInfoOf, Dispatchable, IdentityLookup, Implication, NumberFor, One, @@ -158,8 +158,8 @@ static _WASM_BLOB_VERSION: [u8; const_str::to_byte_array!(env!("SUBSTRATE_CLI_IM #[cfg(not(feature = "dev"))] #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("vara"), - impl_name: create_runtime_str!("vara"), + spec_name: alloc::borrow::Cow::Borrowed("vara"), + impl_name: alloc::borrow::Cow::Borrowed("vara"), spec_version: 2_00_00, @@ -174,8 +174,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { #[cfg(feature = "dev")] #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("vara-testnet"), - impl_name: create_runtime_str!("vara-testnet"), + spec_name: alloc::borrow::Cow::Borrowed("vara-testnet"), + impl_name: alloc::borrow::Cow::Borrowed("vara-testnet"), spec_version: 2_00_00, @@ -210,8 +210,12 @@ parameter_types! { pub const Version: RuntimeVersion = VERSION; pub const SS58Prefix: u8 = VARA_SS58_PREFIX; pub RuntimeBlockWeights: BlockWeights = gear_runtime_common::block_weights_for(MAXIMUM_BLOCK_WEIGHT); - pub RuntimeBlockLength: BlockLength = - BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_LENGTH_RATIO); + pub RuntimeBlockLength: BlockLength = BlockLength::builder() + .max_length(5 * 1024 * 1024) + .modify_max_length_for_class(DispatchClass::Normal, |m| { + *m = NORMAL_DISPATCH_LENGTH_RATIO * *m + }) + .build(); } // Configure FRAME pallets to include in runtime. @@ -497,7 +501,7 @@ impl pallet_session::Config for Runtime { impl pallet_session_historical::Config for Runtime { type RuntimeEvent = RuntimeEvent; type FullIdentification = pallet_staking::Exposure; - type FullIdentificationOf = pallet_staking::ExposureOf; + type FullIdentificationOf = pallet_staking::DefaultExposureOf; } // Filter that matches `pallet_staking::Pallet::bond()` call @@ -551,7 +555,6 @@ parameter_types! { } impl pallet_gear_staking_rewards::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type BondCallFilter = BondCallFilter; type AccountFilter = NonStakingAccountsFilter; type PalletId = StakingRewardsPalletId; @@ -824,6 +827,7 @@ impl pallet_nomination_pools::Config for Runtime { type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; + #[allow(deprecated)] type StakeAdapter = pallet_nomination_pools::adapter::TransferStake; type PostUnbondingPoolsWindow = ConstU32<4>; type MaxMetadataLen = ConstU32<256>; @@ -1190,7 +1194,6 @@ impl pallet_gear_bank::Config for Runtime { } impl pallet_gear::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type Randomness = pallet_babe::RandomnessFromOneEpochAgo; type WeightInfo = pallet_gear::weights::SubstrateWeight; type Schedule = Schedule; @@ -1271,7 +1274,6 @@ impl SortedMembers for GearEthBridgeAdminAccounts { } impl pallet_gear_eth_bridge::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type PalletId = GearEthBridgePalletId; type BuiltinAddress = GearEthBridgeBuiltinAddress; type AdminOrigin = frame_system::EnsureSignedBy; @@ -1316,7 +1318,6 @@ impl pallet_grandpa_signer::AuthorityProvider for GrandpaAuthor } impl pallet_grandpa_signer::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type AuthorityId = ed25519::Public; type AuthoritySignature = ed25519::Signature; type MaxPayloadLength = GrandpaSignerMaxPayloadLength; @@ -1366,7 +1367,6 @@ parameter_types! { } impl pallet_gear_voucher::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type Currency = Balances; type PalletId = VoucherPalletId; type WeightInfo = pallet_gear_voucher::weights::SubstrateWeight; @@ -1382,7 +1382,7 @@ where RuntimeCall: From, { fn create_bare(call: RuntimeCall) -> UncheckedExtrinsic { - generic::UncheckedExtrinsic::new_bare(call).into() + generic::UncheckedExtrinsic::new_bare(call) } } @@ -1968,7 +1968,7 @@ impl_runtime_apis_plus_common! { } fn execute_block( - block: Block, + block: ::LazyBlock, state_root_check: bool, signature_check: bool, select: frame_try_runtime::TryStateSelect diff --git a/vara/runtime/vara/src/tests/mod.rs b/vara/runtime/vara/src/tests/mod.rs index f90e620f076..557faeda15d 100644 --- a/vara/runtime/vara/src/tests/mod.rs +++ b/vara/runtime/vara/src/tests/mod.rs @@ -106,7 +106,7 @@ fn payout_stakers_fits_in_block() { let dispatch_info = call.get_dispatch_info(); assert_eq!(dispatch_info.class, DispatchClass::Normal); - assert_eq!(dispatch_info.weight, expected_weight); + assert_eq!(dispatch_info.total_weight(), expected_weight); let block_weights = ::BlockWeights::get(); diff --git a/vara/sdk/gsdk/src/lib.rs b/vara/sdk/gsdk/src/lib.rs index c662097d155..632f22f1450 100644 --- a/vara/sdk/gsdk/src/lib.rs +++ b/vara/sdk/gsdk/src/lib.rs @@ -29,7 +29,7 @@ pub use crate::{ }, }; pub use gear_core::rpc::GasInfo; -pub use sp_keyring::AccountKeyring; +pub use sp_keyring::Sr25519Keyring as AccountKeyring; pub use subxt::dynamic::Value; use crate::gear::runtime_types::{ diff --git a/vara/sdk/gsdk/src/signed/mod.rs b/vara/sdk/gsdk/src/signed/mod.rs index 55295e6aac1..f9623366225 100644 --- a/vara/sdk/gsdk/src/signed/mod.rs +++ b/vara/sdk/gsdk/src/signed/mod.rs @@ -5,9 +5,8 @@ pub use self::{pair_signer::PairSigner, tx_output::TxOutput}; -use crate::{Api, backtrace::Backtrace, config::GearConfig, result::Result}; +use crate::{AccountKeyring, Api, backtrace::Backtrace, config::GearConfig, result::Result}; use sp_core::{Pair as PairT, sr25519::Pair}; -use sp_keyring::AccountKeyring; use sp_runtime::AccountId32; use std::sync::Arc; diff --git a/vara/tools/gear-replay-cli/src/lib.rs b/vara/tools/gear-replay-cli/src/lib.rs index 476ac00d29d..c90f0ef7c19 100644 --- a/vara/tools/gear-replay-cli/src/lib.rs +++ b/vara/tools/gear-replay-cli/src/lib.rs @@ -24,7 +24,8 @@ use sp_runtime::{ traits::{Block as BlockT, HashingFor, Header as HeaderT}, }; use sp_state_machine::{ - OverlayedChanges, StateMachine, TestExternalities, backend::BackendRuntimeCode, + OverlayedChanges, StateMachine, TestExternalities, + backend::{BackendRuntimeCode, TryPendingCode}, }; use std::{ fmt::{self, Debug}, @@ -190,7 +191,7 @@ pub(crate) fn state_machine_call( method, data, &mut extensions, - &BackendRuntimeCode::new(&ext.backend).runtime_code()?, + &BackendRuntimeCode::new(&ext.backend, TryPendingCode::No).runtime_code()?, CallContext::Offchain, ) .execute() diff --git a/vara/tools/gear-replay-cli/src/state.rs b/vara/tools/gear-replay-cli/src/state.rs index 163b39a742e..7c753cfb268 100644 --- a/vara/tools/gear-replay-cli/src/state.rs +++ b/vara/tools/gear-replay-cli/src/state.rs @@ -173,7 +173,7 @@ where .collect::, _>>()?; Builder::::new().mode(Mode::Online(OnlineConfig { at, - transport: uri.to_owned().into(), + transport_uris: vec![uri.to_owned()], state_snapshot, pallets: pallet.clone(), child_trie: *child_tree, diff --git a/vara/tools/runtime-fuzzer/src/runtime/mod.rs b/vara/tools/runtime-fuzzer/src/runtime/mod.rs index cec9b8b58b7..452b50f41e9 100644 --- a/vara/tools/runtime-fuzzer/src/runtime/mod.rs +++ b/vara/tools/runtime-fuzzer/src/runtime/mod.rs @@ -49,6 +49,7 @@ pub fn new_test_ext() -> TestExternalities { .map(|(acc, ..)| (acc, Balances::minimum_balance())), ) .collect(), + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); From 2a0e6a745e2e2d42ac25bb9d133a704352f95a0a Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Wed, 10 Jun 2026 23:18:46 +0400 Subject: [PATCH 09/13] Remove unused staking rewards dependency --- Cargo.lock | 1 - vara/pallets/staking-rewards/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 935f6a78eef..fb6294780b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13475,7 +13475,6 @@ version = "2.0.0" dependencies = [ "frame-benchmarking", "frame-election-provider-support", - "frame-executive", "frame-support", "frame-system", "gear-common", diff --git a/vara/pallets/staking-rewards/Cargo.toml b/vara/pallets/staking-rewards/Cargo.toml index d4a4cf3c660..28408ed9812 100644 --- a/vara/pallets/staking-rewards/Cargo.toml +++ b/vara/pallets/staking-rewards/Cargo.toml @@ -42,7 +42,6 @@ pallet-session = { workspace = true, features = ["std"] } pallet-sudo = { workspace = true, features = ["std"] } pallet-utility = { workspace = true, features = ["std"] } pallet-election-provider-multi-phase = { workspace = true, features = ["std"] } -frame-executive = { workspace = true, features = ["std"] } tracing-subscriber.workspace = true common = { workspace = true, features = ["std"] } From 13e570220ddf1b7b8cc7aa99acac0efafad633d4 Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Thu, 11 Jun 2026 18:09:44 +0400 Subject: [PATCH 10/13] Fix stable2603 CI failures --- .config/nextest.toml | 16 ++ .../actions/setup-compilation-env/action.yml | 11 +- Cargo.lock | 1 + utils/gear-workspace-hack/Cargo.toml | 24 +++ vara/pallets/gear-builtin/src/mock.rs | 2 +- .../pallets/gear-builtin/src/tests/staking.rs | 49 +++--- vara/pallets/gear-eth-bridge/src/tests.rs | 155 +++++++----------- vara/pallets/gear/src/benchmarking/mod.rs | 8 +- .../vara/src/genesis_config_presets.rs | 2 +- vara/runtime/vara/src/migrations.rs | 10 ++ vara/sdk/gcli/src/template.rs | 16 +- vara/sdk/gcli/tests/smoke.rs | 14 +- vara/sdk/gsdk/vara_runtime.scale | Bin 319296 -> 350499 bytes vara/sdk/node-wrapper/src/instance.rs | 6 +- vara/sdk/node-wrapper/src/log.rs | 13 +- vara/sdk/node-wrapper/src/node.rs | 87 +++++++++- 16 files changed, 270 insertions(+), 144 deletions(-) diff --git a/.config/nextest.toml b/.config/nextest.toml index 5b47a1d07c0..1bb9f9be580 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -15,11 +15,21 @@ slow-timeout = { period = "1m", terminate-after = 5 } # every test process compiling the Vara runtime WASM independently. authorship = { max-threads = 1 } +# These tests invoke nested builds or long runtime benchmarks. Running them +# together with a fully saturated workspace test set can exceed the timeout +# window even though they complete when isolated. +heavy-workspace = { max-threads = 1 } + [[profile.default.overrides]] filter = 'package(gear-authorship)' retries = 5 test-group = 'authorship' +[[profile.default.overrides]] +filter = '(package(cargo-gbuild) and test(test_program_tests)) or (package(gstd-codegen) and test(ui)) or (package(pallet-gear) and (test(bench_gr_create_program_per_kb) or test(bench_gr_create_program_wgas_per_kb)))' +test-group = 'heavy-workspace' +threads-required = 8 + # ethexe-service tests spawn Anvil child processes plus a malachite # engine with libp2p sockets and a RocksDB WAL. Graceful tear-down of # the whole stack can exceed the default 5s leak window; treat leaks @@ -28,6 +38,12 @@ test-group = 'authorship' filter = 'package(ethexe-service)' leak-timeout = { period = "10s", result = "pass" } +# These gsdk tests pass their assertions but can leave RPC/node client tasks alive +# just past the default leak window on local runs. +[[profile.default.overrides]] +filter = 'package(gsdk) and (test(timeout) or test(memory_dump) or test(memory_download))' +leak-timeout = { period = "10s", result = "pass" } + [profile.default.junit] path = "junit.xml" store-success-output = false diff --git a/.github/actions/setup-compilation-env/action.yml b/.github/actions/setup-compilation-env/action.yml index be224f6e942..2f447440640 100644 --- a/.github/actions/setup-compilation-env/action.yml +++ b/.github/actions/setup-compilation-env/action.yml @@ -25,7 +25,16 @@ runs: timeout_minutes: 15 max_attempts: 5 retry_wait_seconds: 10 - command: brew install protobuf binaryen + command: brew install protobuf binaryen llvm + + - name: "Install: macOS LLVM env" + if: runner.os == 'macOS' + run: | + LLVM_PREFIX="$(brew --prefix llvm)" + echo "LIBCLANG_PATH=${LLVM_PREFIX}/lib" >> "$GITHUB_ENV" + echo "${LLVM_PREFIX}/bin" >> "$GITHUB_PATH" + echo "DYLD_FALLBACK_LIBRARY_PATH=${LLVM_PREFIX}/lib:/usr/local/lib:/usr/lib" >> "$GITHUB_ENV" + shell: bash - name: "Install: Linux packages" if: runner.os == 'Linux' diff --git a/Cargo.lock b/Cargo.lock index fb6294780b3..55a1b9535f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8315,6 +8315,7 @@ dependencies = [ "pallet-referenda", "pallet-scheduler", "pallet-session", + "pallet-staking", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-sudo", diff --git a/utils/gear-workspace-hack/Cargo.toml b/utils/gear-workspace-hack/Cargo.toml index fa86c45f610..fe97eaed42c 100644 --- a/utils/gear-workspace-hack/Cargo.toml +++ b/utils/gear-workspace-hack/Cargo.toml @@ -17,6 +17,24 @@ publish = false # they have features like `runtime-benchmarks` and `try-runtime` # so we cannot, for example, run `cargo build -p gear-cli` without `--all-features` +[features] +runtime-benchmarks = [ + "pallet-bags-list/runtime-benchmarks", + "pallet-conviction-voting/runtime-benchmarks", + "pallet-ranked-collective/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", + "pallet-session/runtime-benchmarks", + "pallet-staking/runtime-benchmarks", +] +try-runtime = [ + "pallet-bags-list/try-runtime", + "pallet-conviction-voting/try-runtime", + "pallet-ranked-collective/try-runtime", + "pallet-referenda/try-runtime", + "pallet-session/try-runtime", + "pallet-staking/try-runtime", +] + [target.'cfg(not(target_arch = "wasm32"))'.dependencies.frame-executive] git = "https://github.com/paritytech/polkadot-sdk.git" rev = "e3737178ec726cffe506c907263aaaa417893fd0" @@ -159,6 +177,12 @@ rev = "e3737178ec726cffe506c907263aaaa417893fd0" default-features = false features = ["historical", "std"] +[target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-staking] +git = "https://github.com/paritytech/polkadot-sdk.git" +rev = "e3737178ec726cffe506c907263aaaa417893fd0" +default-features = false +features = ["std"] + [target.'cfg(not(target_arch = "wasm32"))'.dependencies.pallet-sudo] git = "https://github.com/paritytech/polkadot-sdk.git" rev = "e3737178ec726cffe506c907263aaaa417893fd0" diff --git a/vara/pallets/gear-builtin/src/mock.rs b/vara/pallets/gear-builtin/src/mock.rs index e11b63f1311..e701b2ee225 100644 --- a/vara/pallets/gear-builtin/src/mock.rs +++ b/vara/pallets/gear-builtin/src/mock.rs @@ -370,7 +370,7 @@ impl ExtBuilder { ( *x, *x, - self.endowment, + self.endowment.saturating_sub(EXISTENTIAL_DEPOSIT), pallet_staking::StakerStatus::::Validator, ) }) diff --git a/vara/pallets/gear-builtin/src/tests/staking.rs b/vara/pallets/gear-builtin/src/tests/staking.rs index ef561ae1862..cbbb82499db 100644 --- a/vara/pallets/gear-builtin/src/tests/staking.rs +++ b/vara/pallets/gear-builtin/src/tests/staking.rs @@ -6,6 +6,7 @@ use frame_support::assert_ok; use gbuiltin_staking::{ActiveEraInfo, Response}; use gprimitives::ActorId; use parity_scale_codec::Decode; +use sp_runtime::Perbill; use sp_staking::StakingAccount; use util::*; @@ -66,10 +67,9 @@ fn bonding_works() { signer_current_balance_at_blk_1 - 100 * UNITS - gas_price(gas_burned) ); - // The contract's account has 10 * UNITS of the ED and 100 * UNITS of the bonded funds - assert_eq!(contract_account_data.free, 110 * UNITS); - // and all of it is frozen as bonded or locked - assert_eq!(contract_account_data.frozen, 100 * UNITS); + // The contract keeps its ED free; staking tracks the bonded funds as holds. + assert_eq!(contract_account_data.free, EXISTENTIAL_DEPOSIT); + assert_eq!(contract_account_data.frozen, EXISTENTIAL_DEPOSIT); // Asserting the expected events are present assert_staking_events(contract_account_id, 100 * UNITS, EventType::Bonded); @@ -106,10 +106,10 @@ fn bonding_works() { Balances::free_balance(SIGNER), signer_current_balance_at_blk_2 - 100 * UNITS - gas_price(gas_burned) ); - // Another 50 * UNITS added to locked balance + // The contract account still exposes only its ED; staking holds the bonded funds. assert_eq!( System::account(contract_account_id).data.frozen, - 150 * UNITS + EXISTENTIAL_DEPOSIT ); // Asserting the expected events are present @@ -293,8 +293,8 @@ fn withdraw_unbonded_works() { let contract_account_data = System::account(contract_account_id).data; - // Locked 500 * UNITS as bonded on contracts's account - assert_eq!(contract_account_data.frozen, 500 * UNITS); + // The contract keeps its ED free; staking tracks the bonded funds as holds. + assert_eq!(contract_account_data.frozen, EXISTENTIAL_DEPOSIT); System::reset_events(); @@ -311,10 +311,10 @@ fn withdraw_unbonded_works() { run_to_next_block(); assert_staking_events(contract_account_id, 200 * UNITS, EventType::Unbonded); - // The funds are still locked + // The funds are still held by staking. assert_eq!( System::account(contract_account_id).data.frozen, - 500 * UNITS + EXISTENTIAL_DEPOSIT ); // Pretend we have run the chain for at least the `unbonding period` number of eras @@ -337,10 +337,10 @@ fn withdraw_unbonded_works() { run_to_next_block(); - // 200 * UNITS have been released, 300 * UNITS remain locked + // The staking ledger changed, while account data still exposes only the ED. assert_eq!( System::account(contract_account_id).data.frozen, - 300 * UNITS + EXISTENTIAL_DEPOSIT ); assert_staking_events(contract_account_id, 200 * UNITS, EventType::Withdrawn); let ledger = @@ -413,8 +413,8 @@ fn rebond_works() { let contract_account_data = System::account(contract_account_id).data; - // Locked 500 * UNITS as bonded on contracts's account - assert_eq!(contract_account_data.frozen, 500 * UNITS); + // The contract keeps its ED free; staking tracks the bonded funds as holds. + assert_eq!(contract_account_data.frozen, EXISTENTIAL_DEPOSIT); System::reset_events(); @@ -431,10 +431,10 @@ fn rebond_works() { run_to_next_block(); assert_staking_events(contract_account_id, 400 * UNITS, EventType::Unbonded); - // All the bonded funds are still locked + // All the bonded funds are still held by staking. assert_eq!( System::account(contract_account_id).data.frozen, - 500 * UNITS + EXISTENTIAL_DEPOSIT ); // However, the ledger has been updated @@ -456,10 +456,10 @@ fn rebond_works() { run_to_next_block(); - // All the bonded funds are still locked + // All bonded funds are still held by staking. assert_eq!( System::account(contract_account_id).data.frozen, - 500 * UNITS + EXISTENTIAL_DEPOSIT ); // However, the ledger has been updated again @@ -481,10 +481,10 @@ fn rebond_works() { run_to_next_block(); - // All the bonded funds are still locked + // All bonded funds are still held by staking. assert_eq!( System::account(contract_account_id).data.frozen, - 500 * UNITS + EXISTENTIAL_DEPOSIT ); // The ledger has been updated again, however, the rebonded amount was limited @@ -566,11 +566,14 @@ fn payout_stakers_works() { run_to_next_block(); - // Expecting the nominator to have received 1/5 of the rewards + // Expecting the nominator to receive rewards proportional to its exposure. let rewards_payee_final_balance = Balances::free_balance(REWARD_PAYEE); + let nominator_reward = + Perbill::from_rational(250 * UNITS, ENDOWMENT - EXISTENTIAL_DEPOSIT + 250 * UNITS) + * (100 * UNITS); assert_eq!( rewards_payee_final_balance, - rewards_payee_initial_balance + (100 * UNITS) / 5 + rewards_payee_initial_balance + nominator_reward ); }); } @@ -973,7 +976,7 @@ mod util { ( x.0, x.0, - self.endowment, + self.endowment.saturating_sub(EXISTENTIAL_DEPOSIT), pallet_staking::StakerStatus::::Validator, ) }) diff --git a/vara/pallets/gear-eth-bridge/src/tests.rs b/vara/pallets/gear-eth-bridge/src/tests.rs index fca15bda026..627cbb93919 100644 --- a/vara/pallets/gear-eth-bridge/src/tests.rs +++ b/vara/pallets/gear-eth-bridge/src/tests.rs @@ -53,47 +53,31 @@ fn bridge_got_initialized() { do_events_assertion(0, 6, []); run_to_block(EPOCH_BLOCKS + 1); - do_events_assertion(1, 7, [SessionEvent::NewSession { session_index: 1 }.into()]); + do_events_assertion(1, 7, new_session_events(1)); run_to_block(EPOCH_BLOCKS * 2); do_events_assertion(1, 12, []); run_to_block(EPOCH_BLOCKS * 2 + 1); - do_events_assertion( - 2, - 13, - [SessionEvent::NewSession { session_index: 2 }.into()], - ); + do_events_assertion(2, 13, new_session_events(2)); run_to_block(EPOCH_BLOCKS * 3); do_events_assertion(2, 18, []); run_to_block(EPOCH_BLOCKS * 3 + 1); - do_events_assertion( - 3, - 19, - [SessionEvent::NewSession { session_index: 3 }.into()], - ); + do_events_assertion(3, 19, new_session_events(3)); run_to_block(EPOCH_BLOCKS * 4); do_events_assertion(3, 24, []); run_to_block(EPOCH_BLOCKS * 4 + 1); - do_events_assertion( - 4, - 25, - [SessionEvent::NewSession { session_index: 4 }.into()], - ); + do_events_assertion(4, 25, new_session_events(4)); run_to_block(EPOCH_BLOCKS * 5); do_events_assertion(4, 30, []); run_to_block(EPOCH_BLOCKS * 5 + 1); - do_events_assertion( - 5, - 31, - [SessionEvent::NewSession { session_index: 5 }.into()], - ); + do_events_assertion(5, 31, queued_session_events(5)); run_to_block(ERA_BLOCKS); do_events_assertion(5, 36, []); @@ -112,7 +96,7 @@ fn bridge_got_initialized() { 6, 37, [ - SessionEvent::NewSession { session_index: 6 }.into(), + new_session_event(6), Event::BridgeInitialized.into(), Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], @@ -385,10 +369,10 @@ fn bridge_updates_authorities_and_clears() { 10, 66, [ - SessionEvent::NewSession { session_index: 7 }.into(), - SessionEvent::NewSession { session_index: 8 }.into(), - SessionEvent::NewSession { session_index: 9 }.into(), - SessionEvent::NewSession { session_index: 10 }.into(), + new_session_event(7), + new_session_event(8), + new_session_event(9), + new_session_event(10), ], ); @@ -401,11 +385,7 @@ fn bridge_updates_authorities_and_clears() { let authority_set_hash: H256 = Blake2_256::hash(&authority_set_ids_concat).into(); run_to_block(ERA_BLOCKS + EPOCH_BLOCKS * 5 + 1); - do_events_assertion( - 11, - 67, - [SessionEvent::NewSession { session_index: 11 }.into()], - ); + do_events_assertion(11, 67, queued_session_events(11)); assert_ne!( QueueMerkleRoot::get().expect("infallible"), H256::zero().into() @@ -421,7 +401,7 @@ fn bridge_updates_authorities_and_clears() { 12, 73, [ - SessionEvent::NewSession { session_index: 12 }.into(), + new_session_event(12), Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], ); @@ -444,10 +424,10 @@ fn bridge_updates_authorities_and_clears() { 16, 102, [ - SessionEvent::NewSession { session_index: 13 }.into(), - SessionEvent::NewSession { session_index: 14 }.into(), - SessionEvent::NewSession { session_index: 15 }.into(), - SessionEvent::NewSession { session_index: 16 }.into(), + new_session_event(13), + new_session_event(14), + new_session_event(15), + new_session_event(16), ], ); @@ -460,11 +440,7 @@ fn bridge_updates_authorities_and_clears() { let authority_set_hash: H256 = Blake2_256::hash(&authority_set_ids_concat).into(); run_to_block(ERA_BLOCKS * 2 + EPOCH_BLOCKS * 5 + 1); - do_events_assertion( - 17, - 103, - [SessionEvent::NewSession { session_index: 17 }.into()], - ); + do_events_assertion(17, 103, queued_session_events(17)); run_to_block(ERA_BLOCKS * 3 + 1); on_finalize_gear_block(ERA_BLOCKS * 3 + 1); @@ -472,7 +448,7 @@ fn bridge_updates_authorities_and_clears() { 18, 109, [ - SessionEvent::NewSession { session_index: 18 }.into(), + new_session_event(18), Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), GrandpaEvent::NewAuthorities { authority_set }.into(), ], @@ -918,6 +894,21 @@ mod utils { System::reset_events(); } + pub(crate) fn new_session_event(session_index: u32) -> RuntimeEvent { + SessionEvent::NewSession { session_index }.into() + } + + pub(crate) fn new_session_events(session_index: u32) -> [RuntimeEvent; 1] { + [new_session_event(session_index)] + } + + pub(crate) fn queued_session_events(session_index: u32) -> [RuntimeEvent; 2] { + [ + SessionEvent::NewQueued.into(), + new_session_event(session_index), + ] + } + pub(crate) fn balance_of(account: &AccountId) -> Value { Currency::free_balance(account) } @@ -966,7 +957,7 @@ fn rotate_keys() { do_events_assertion(0, 6, []); run_to_block(EPOCH_BLOCKS + 1); - do_events_assertion(1, 7, [SessionEvent::NewSession { session_index: 1 }.into()]); + do_events_assertion(1, 7, new_session_events(1)); let validators = era_validators(1, false); // emulate the situation if a validator rotates its keys (i.e. calls "author_rotateKeys" on @@ -979,15 +970,17 @@ fn rotate_keys() { // // To the sum "SessionKeys::generate" expands to the following - // https://github.com/gear-tech/polkadot-sdk/blob/e8fd208dd5dcc13d9d365aaad85f6aa406e66c0e/substrate/primitives/runtime/src/traits.rs#L2039 - let session_keys_new = SessionKeys { - grandpa: <::Public as sp_runtime::RuntimeAppPublic>::generate_pair(Some(b"//new_validator_keys".into())), - }; + let generated = SessionKeys::generate( + &validators[0].encode(), + Some(b"//new_validator_keys".to_vec()), + ); + let session_keys_new = generated.keys.clone(); // validator changes its keys assert_ok!(Session::set_keys( RuntimeOrigin::signed(validators[0]), session_keys_new.clone(), - vec![], + generated.proof.encode(), )); // session doesn't end @@ -996,11 +989,7 @@ fn rotate_keys() { // sessions ends. "Changed" validator set will be used on the next rotation of the session. run_to_block(EPOCH_BLOCKS * 2 + 1); - do_events_assertion( - 2, - 13, - [SessionEvent::NewSession { session_index: 2 }.into()], - ); + do_events_assertion(2, 13, new_session_events(2)); // session doesn't end run_to_block(EPOCH_BLOCKS * 3); @@ -1029,7 +1018,7 @@ fn rotate_keys() { 3, 19, [ - SessionEvent::NewSession { session_index: 3 }.into(), + new_session_event(3), Event::BridgeInitialized.into(), Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], @@ -1050,21 +1039,13 @@ fn rotate_keys() { do_events_assertion(3, 24, []); run_to_block(EPOCH_BLOCKS * 4 + 1); - do_events_assertion( - 4, - 25, - [SessionEvent::NewSession { session_index: 4 }.into()], - ); + do_events_assertion(4, 25, new_session_events(4)); run_to_block(EPOCH_BLOCKS * 5); do_events_assertion(4, 30, []); run_to_block(EPOCH_BLOCKS * 5 + 1); - do_events_assertion( - 5, - 31, - [SessionEvent::NewSession { session_index: 5 }.into()], - ); + do_events_assertion(5, 31, queued_session_events(5)); run_to_block(ERA_BLOCKS); do_events_assertion(5, 36, []); @@ -1086,7 +1067,7 @@ fn rotate_keys() { 6, 37, [ - SessionEvent::NewSession { session_index: 6 }.into(), + new_session_event(6), Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], ); @@ -1095,31 +1076,26 @@ fn rotate_keys() { do_events_assertion( 6, 37, - [GrandpaEvent::NewAuthorities { - authority_set, - } - .into()], + [GrandpaEvent::NewAuthorities { authority_set }.into()], ); run_to_block(ERA_BLOCKS + 2); - do_events_assertion( - 6, - 38, - [Event::QueueReset.into()], - ); + do_events_assertion(6, 38, [Event::QueueReset.into()]); System::reset_events(); let validators = era_validators(6, false); - let session_keys_new = SessionKeys { - grandpa: <::Public as sp_runtime::RuntimeAppPublic>::generate_pair(Some(b"//new_validator_keys2".into())), - }; + let generated = SessionKeys::generate( + &validators[1].encode(), + Some(b"//new_validator_keys2".to_vec()), + ); + let session_keys_new = generated.keys.clone(); // validator changes its keys assert_ok!(Session::set_keys( RuntimeOrigin::signed(validators[1]), session_keys_new.clone(), - vec![], + generated.proof.encode(), )); // session doesn't end @@ -1128,11 +1104,7 @@ fn rotate_keys() { // sessions ends. "Changed" validator set will be used on the next rotation of the session. run_to_block(ERA_BLOCKS + EPOCH_BLOCKS + 1); - do_events_assertion( - 7, - 43, - [SessionEvent::NewSession { session_index: 7 }.into()], - ); + do_events_assertion(7, 43, new_session_events(7)); // session doesn't end run_to_block(ERA_BLOCKS + 2 * EPOCH_BLOCKS); @@ -1146,7 +1118,11 @@ fn rotate_keys() { // the second validator changed its keys let authority_set = era_validators_authority_set(6); - let authority_set = vec![authority_set[0].clone(), (session_keys_new.grandpa, 1), authority_set[2].clone()]; + let authority_set = vec![ + authority_set[0].clone(), + (session_keys_new.grandpa, 1), + authority_set[2].clone(), + ]; let authority_set_ids_concat = authority_set .clone() .into_iter() @@ -1158,7 +1134,7 @@ fn rotate_keys() { 8, 49, [ - SessionEvent::NewSession { session_index: 8 }.into(), + new_session_event(8), Event::AuthoritySetHashChanged(authority_set_hash.into()).into(), ], ); @@ -1167,18 +1143,11 @@ fn rotate_keys() { do_events_assertion( 8, 49, - [GrandpaEvent::NewAuthorities { - authority_set, - } - .into()], + [GrandpaEvent::NewAuthorities { authority_set }.into()], ); // the queue should be cleared on the next block run_to_block(ERA_BLOCKS + 2 * EPOCH_BLOCKS + 2); - do_events_assertion( - 8, - 50, - [Event::QueueReset.into()], - ); + do_events_assertion(8, 50, [Event::QueueReset.into()]); }) } diff --git a/vara/pallets/gear/src/benchmarking/mod.rs b/vara/pallets/gear/src/benchmarking/mod.rs index 24131bfe490..9683764d036 100644 --- a/vara/pallets/gear/src/benchmarking/mod.rs +++ b/vara/pallets/gear/src/benchmarking/mod.rs @@ -124,13 +124,11 @@ where )], }; - let bn = previous - .unwrap_or_else(Zero::zero) - .checked_add(&One::one()) - .expect("overflow"); + let previous = previous.unwrap_or_else(SystemPallet::::block_number); + let bn = previous.checked_add(&One::one()).expect("overflow"); + SystemPallet::::set_block_number(previous); SystemPallet::::initialize(&bn, &SystemPallet::::parent_hash(), &pre_digest); - SystemPallet::::set_block_number(bn); SystemPallet::::on_initialize(bn); AuthorshipPallet::::on_initialize(bn); } diff --git a/vara/runtime/vara/src/genesis_config_presets.rs b/vara/runtime/vara/src/genesis_config_presets.rs index 23b082228a2..f7ebfc69614 100644 --- a/vara/runtime/vara/src/genesis_config_presets.rs +++ b/vara/runtime/vara/src/genesis_config_presets.rs @@ -79,7 +79,7 @@ pub fn testnet_genesis( ( x.0.clone(), x.1.clone(), - STASH, + STASH - EXISTENTIAL_DEPOSIT, StakerStatus::::Validator, ) }) diff --git a/vara/runtime/vara/src/migrations.rs b/vara/runtime/vara/src/migrations.rs index 75455e4d002..73a797443d9 100644 --- a/vara/runtime/vara/src/migrations.rs +++ b/vara/runtime/vara/src/migrations.rs @@ -13,6 +13,11 @@ parameter_types! { /// All migrations that will run on the next runtime upgrade for dev chain. #[cfg(feature = "dev")] pub type Migrations = ( + pallet_staking::migrations::v16::MigrateV15ToV16, + pallet_session::migrations::v1::MigrateV0ToV1< + Runtime, + pallet_staking::migrations::v17::MigrateDisabledToSession, + >, pallet_gear_eth_bridge::migrations::set_hash::Migration, // migrate to v3 of the Gear Scheduler with removal of program pause tasks pallet_gear_scheduler::migrations::v3_remove_program_pause_tasks::MigrateRemoveProgramPauseTasks, @@ -22,6 +27,11 @@ pub type Migrations = ( /// All migrations that will run on the next runtime upgrade for prod chain. #[cfg(not(feature = "dev"))] pub type Migrations = ( + pallet_staking::migrations::v16::MigrateV15ToV16, + pallet_session::migrations::v1::MigrateV0ToV1< + Runtime, + pallet_staking::migrations::v17::MigrateDisabledToSession, + >, pallet_gear_eth_bridge::migrations::set_hash::Migration, LockEdForBuiltin, // migrate to v3 of the Gear Scheduler with removal of program pause tasks diff --git a/vara/sdk/gcli/src/template.rs b/vara/sdk/gcli/src/template.rs index e13c020d068..bff51ade6e7 100644 --- a/vara/sdk/gcli/src/template.rs +++ b/vara/sdk/gcli/src/template.rs @@ -32,7 +32,11 @@ pub async fn list() -> Result> { rb = rb.bearer_auth(tk); } - let resp = rb.send().await.context("failed to get examples")?; + let resp = rb + .send() + .await + .and_then(|resp| resp.error_for_status()) + .context("failed to get examples")?; let repos = resp .json::>() @@ -110,7 +114,15 @@ fn process_manifest(manifest: &mut String) -> Result<()> { #[tokio::test] async fn list_examples() { - let ls = list().await.expect("Failed to get examples"); + let ls = match list().await { + Ok(ls) => ls, + Err(err) if env::var(GITHUB_TOKEN).is_err() => { + eprintln!("skipping unauthenticated live GitHub template list check: {err:#}"); + return; + } + Err(err) => panic!("Failed to get examples: {err:#}"), + }; + // TODO: #2914 assert!( ls.contains(&"dapp-template".to_string()), diff --git a/vara/sdk/gcli/tests/smoke.rs b/vara/sdk/gcli/tests/smoke.rs index 39c9c6bf156..0b31b1b5482 100644 --- a/vara/sdk/gcli/tests/smoke.rs +++ b/vara/sdk/gcli/tests/smoke.rs @@ -26,11 +26,15 @@ async fn smoke_test() -> Result<()> { " )); gcli().args(["wallet", "dev"]).assert().success(); - gcli().args(["info", "balance"]).assert().stdout_eq(indoc!( - " - Free balance: 1000000000000000000000 - " - )); + gcli() + .args(["info", "balance"]) + .assert() + .success() + .stdout_eq(indoc!( + " + Free balance: 1000000000000000000000 + " + )); Ok(()) } diff --git a/vara/sdk/gsdk/vara_runtime.scale b/vara/sdk/gsdk/vara_runtime.scale index 2537de001cf0db1249b3faa4a9decdc8f1e1bb2e..779d986ca8eaaff1c58bf6c056eb1d703d9ccc4d 100644 GIT binary patch delta 86618 zcmd443wTu3*)P7=nmr+b009!1Kmr2;B%?Q{NuiWISv#fokr;f^}8a}(V?+xd>eZbNuyKOir6vp_{Oc~J*JHfv2W4>5E7n(Op#X4h9=rr*HW>$37K zYloXZ0pI{*rz}9Jev6&;jkVMCgDSDr+_BEjj>uB~gr{TjX-7k$zLm41^3yjO3VDPB zt4mE|{XD&!vkxWwZ|mprhzIay^RpX@Sf}~mhR^9cJ?usK_V$ehlN#!~JCc!eJ7TRn z>Lc6Zp=2Z$P3YPYkHT{HnO>Lrtv+6=`L&#l-Qk$7J?}w3?&2@f&!y(!Cfz*PI9Y$w z!=6V~TTNe6vHq5a9hdbUZYt&@b@QPODr4!UnLJ-5%U2IGAKR46ip0bB@;vjkO_P}K z<_ov6Vzc$a3z^US)`hkBmtFJ>D>Z+3Q4Om!M{Qm{#>cWRFnTmrkm%mF!{|u_dz&|p zV92=R;zm|&K6UZ8Sat6emmC79cjDInW>bqXsWP-uOr&zH98)XP=hG^Y@@YZ5@oLrP z7Cv#*fEl^moY@>;D|?%oTRp>8Vj>o6tIfx^t!8V?mT-`D^)7AoGbeF-_z#RFd#`T0 zf?%wD?&bz88rH7mFn_GA&A>{Ew=;k=mXqj+B|BKoM*L{3ye$$>B%9lf5OOpy-)i}w zvC4$e8jFU9ywDoVo7(5p26I-2675(ath6f>H=-y3>1tL^;Hs*1-N~+Ql}uWYeegV+C}CIe3E&D=Sx?uBvM2-qsOm)wB+Dc;Et2fHNloTlIeiZ^U-70=|Hcx`I5lrwh<20td~%|>W$XwVJ0m=3 z?7nEGl9T7!Z7fZO;@idqyD-KJaB1 z?=Xz6W+1i8c%t{+o=ZG{uira`^_x5QcCn|#&QmP6_iuZvt^8(vDvLd0UYI(-zHk09 zRfy-zs|5Z%d{sVsqWAHuo?`irV8Qom{n#3ZX;0u^O?wK?W?PRQ1LaN0>WkfmRLNpJrZrH@{4_5 zR$xALjW5+iaN5QJZEQFEQDe71p_Z(l!2V12RjCJaBeJ3qDwf0tbSDo3o%kJI1& zDj|Ve{Pb0Kmp>Af`7LrGP(#&8L{)t$zf2%cDCywm#|-p`T3dkzRWIv{M|NTBbSi9- zCvI=ecWV_l)0-A1!~x3xIYWm73tRfAub_}gM}e`jnV+7pT5xl=A= ze`s5*J4rQG`z_4WyFhVQHx`F1T4Vm+P1oMc#P`0zRt#1|aP}*+W&gC^17B$1{?}OJxv@Rfm>3PnWF!;ol?xR zZ76qJsC9<|)MaeRV=E(xF2dIza^FfEtqEZ4!qz2+QkEoNwS^)ba)gaNMr(J{2$&OZ z3Z!0ZY>y=TZQapUqK^D>kMoC;IO)2QGI!XniY7)271!dY@&Yf_waFUNU_b_Slq#@| zc8ebs$P$xAIFQF8>NE8^g=XP(qFc_tw(gFO9=~0q5mqIsK1zVN@NbJH+hy&E8H^SO zrfqj;cL(Nb*pEF5|NB+bK~N-tY9zXSP%jwqIHn@13>#gsL?lHxX}_vd>qdP`E6nXy zYErkg4tKZ5It*FAYH9oK2=Jkfv2l!J8OEbjrd)fnyVO#52Lg+1n_;z5wA{zNE3n*w z5&o>j*BOfUplxzQklP-xCA6HKZdJwFNwM}mK0ZYoKx+s)$DqMd=mxZv)2I8Lxw9s= zJ<>{OS_7%}D?+1%Xr`7@)!kH-M4md>u1*bt+@LJ%!v5Xp&2}v4J$`?vtE;1jIzJTc z@muA#MLLp3JQ1inQ;pFWHYBT7s&K$Jgc6k)!6;Mb(IiM~An;n_mmQOm>qO1ZL_jM= zYn#v+E6^jGQR~K7r{V7gfVwE*@1&)N9@`b`*kxb}Zo|ozlt}wqt_A>za|j!hz@4PU7&>wb#t%TW7I1%bkY47${9xS)c>fS4FUuqxQhYw}3_j^y>aSZ|1@69)_I+UR(08_p) zPu(%M_ZNr0Otj?QyC$$;?=5$A>Buqco`py(y{CY&_suOw=9l-EO72f_1RyQ5nUA4SljWkoZsQSFZuP^uw(3S4TDe`J9>W;J%;U4B z^`3LAnS)BZGwZIdr)2_-;#R8<*!A`nJ^U=DROtGzYZvemrm8*}QH zutrQiFk^{!ES?_P{94;1I4i?`>nyyrL55${oUWN8NGk`Zia3VkmiUVM44`0{)6c#{!2etj#|v$JUel8 z31fcAKFy!ER2$iAFe>~kYuzAN`{40n| z^X{Jp8$eMXMU7_tpu=mryxruwW2K?rQrwV)L{r0mATnxF8u$QD&JK1C6&m{EjtI3C&!8Z92{wEBgXO+foTt**|Qyrqtj?@4@D!1 z&e^jA+9SkM<=*^Erg_Kj#}sRoIO!W8D1~qrBt{m|NlszSvPCWaGJm7F?1xk3D99QE zA0Qi6oP32I#3QZS-R%*K49z>I2=po@oT3q_y+kg6OCw6AWne$pW#LG{>Q7?j5ZOwF zsqsw4QmVP7n7CaeImTcS|K+!OPf;!B8ttK7kyu=__D&il%mBQ2yVu*!~x zaptR{32Jp#D~NGa(q#Z?mG`O?NMp=;92H@I%SI}ArO{@@S9UA;XbTXKE2+~6MH5x) zU1DuuZ-hFqM8ekCp{Q*jSpDrd{jgJ~H6D{!VMv4vI=Ivi8ZnZ%6AY`{CbSi-aLgYH zha*Ju;t;^f0nUL>tR7v5{^?HGv&Y7OWK-z~lw#>34|P&Ff->Vq8)n~X|KQFH5N+K^ z!{nlct`1YzP*0(GXX-3!QUYUwW*YdRJ~pD5Ax7BTx$QhUevZuzU~Bx<+_H%SlnN00 zuZ=|wlKkWFT3;S0&QDuGtUwY4M)(Pa(>m6nY59<}WfU^4keSoUXXe<)|5Sjvrp+*K z{?n|{*(|dgGTst`1+_Bs@jsUq^|NeL6zc-bmc7wP>RLb38zHvysr{8cu84aruIO!%u;wdJj6`bHv^njkl~ zYg}(;y*;bEAM!_=Hgai1I++{O_CI`xUS7|%&1UHBYW9ez>EPqU7drVU^UHh2_x|i{ z(7%nnKYb^~C+D!0mVls!D5VP`(J<&NpCWS}F}wa+gb8xXU(58ZjCF|zuklRql=|y> zPyDq&2LbYrznuV?+xyDj=Mc4{f3Sn`txSC5E>96@U`_-lnxhsC18wRDDf5dDCvt`LAM3dA=RIk7)Nf5;dOqUYXh(;NEf_=$MR_c`>z4fn}(H3qC@z<5$qpI&jxjxPP=DE zLp}Xw%i<}OL!j>GtRS=v+ixVAmIo6*LdZ-Rt*XUbfI3d=lzl2b&S94o?;J3vP7aw; z;FvH8x|ujIhAn5WiKDYv5$h2@p2bS^YZ<#<{Bss7q_OPt6|+xa6#KqCj$KT@f0@lD z;a7|(Wsl(JsZ#a_{M=i{zJva64=|8Z!M-`=Y!+qOJBdx^`&r+iN$hUMdze^W$i|xw z)Q&IrLkznYYs|Ms5=h|BlrXtywWAgRt5z57h(xha_A&FlTL0u~miC%uySxN?WG@q; zC44&Hr&dXBwpt`Uca2;ttFPJ;WSN;Y*iHuXN?L9W5$i)zF7{ z^m(SS;aE2W$w!wK7vXF9xi6~#ve#w^bR?_RH*6-ml<@=q|BmG?OpKq;ma%HFX+A5* z&voh)xD^D#+DMO^^lz_uApD8Jkq(mV- z!J)a^=t!X^Md8cs!={vEjgs1elv)-!3k1@3FjJv`wt&?sI!ubWq^M5eMqiau-I7dF zd;ld~YB?6$0TFpJ1Y%nuFdI_Lpp9p8&|-R)qv&(@*$Eo5_8 zrug|nw&LtP|JWjSUhaUxb0uqgmeMcgcVjI!@M&VyVwPzg@yrJbD-sKnCN0;K5!@^S z)og0t*2QceFVf1Gq~D~>clK<>n<(BCqAw{xONjDnR#FwH#&OgPiDkS;H68@SpvD)_ z+lY}+q=j4W$;vz|r?P5xlox0tRfV9}X%0wwYd6?@Q245%34wB8fqA9s!Zt-?rP?)B zj9kWQ(R&-0v8(4F8n8v&J@gd68~X_U=ts{C2DKwh^`3*q5gtWl9YSwwtuaOEo?FiP~sF$#*f^&;U`olJ#dDMGd@K zJBC%Yl1*bRA_vNOYdfl`WzX`5Szq=lwwzT|oAY0etOIp?#9?2*1r=d)SZbNa4a z!@|th$buV;?O;*kp}56RXMPcrP!Pgc6qnRk~d#HhZ z38%7X*ns^_6Axd`@`qp64X&^g%txKLaRZxyE_h@EJHoA9Gv35T;aRHOGNAqqJ<0m+ zzK}t5G5{uicM*Ha`s9ht>}~oS`|r#|cUxOzkIyxMVa3GUDaEX{WsS}if7-$>f&gIU zR<<%ljIxyh8%P}^E)HxF%@v66rL4!En51Y-l7tpaVy7V$37A!KCSwK>?;~?MQuppI zw7>}e2zCL;Pplu!I$|<+$0N{RQ61x@fPg4-oAHslC-L@HHpx$_<{>RA3Mpx3vPTYs z2wci)hvl$r>#*=$>|mJQ4@C)E1Xs^lmqjOGo~>(ZLyIF(M-T^cDTro3jcIp_P34cN z6fa-OR!!N=AYN!0m`7?+uwJ1O5tEylFXbSS-oK$;&{oI|E*Yz3;QOMGRY*&N-I0W$ z)G1Eu)J{nf4eB)*QTVYvhAhR1lp}+8q^XO|Mlp{?_Rs`0_E6udW;UF$&0>8EyPs|D z`=~`Fv$nD3R5he^*wmZt4|L|>yP31nCToa^($CA@%s>o6PC~cs;UOPO_c4dkf{(bSaFRtPBwL%hdI0{06$2O4i= zlL8|pn{e6>nM8!xU6O%O9@z%4<0St`lO9#>fGEQ0iZiq9#1;ttg+z=UZaRCnvCU28;IK`)$y}1r zrDd+}+TPU+V+jlb(2gdTh@3E+G}-;2Ac@vv6*&+M7!cDt^)ZVLUCdn)`!RXAJ;|PA z+LKItC(|=QJRD{dQpW*jTF!>h?h0Ldn$9PgfZ^e@NI;-~H}hevMxV<>rLKj^qJds4 z(6txwB10w?>e|al43mjPy7np(nKBX7wG&8W$;4t^JB7q>Etl#{mFwE;NRCiR;P56= z*(wDj-a=}mN&$=0NR3h{pz$73qg4us{2i$rl>#OoA~i;(fC>W_GFGL4ix;VJDz!MJ zYgtI<%H%vCQvlJ4N&uIUcr{+7fXf)9Ca4r}$wSJgQoto2seF|JE`>-%8;5YQ}cmK1yWN~3dk%#%CAyDCR5X=`Z}X@ET=`osCmZA zM;bEE1o=qgC#dGaNghRQQhKGHaOCdo${BM&A9^3ni#3gsh>j%Tubq@nRl zk&lb<$RA_c5}qz#Dj33-qByjtW*lX&G(~qrW4og$ zy=!=R;~)k77~HdY+kPNfVS7st)Ab(o z+s~})V_I%)Yd8^tfQz%`20d0)x#e&zyEfS_UtVOrRMXGRf;rR#lsq-EuQqeJU!6f9 zu$7B-m-0OEafA&YT}oC_dwQ~24ur!UL_PUL_)0d0g~YBa*<_0Y?Ys6e_5~)1OP|Pz zvJuP>H+GSf2>i_WzV;4w<0rk%?OPpXpJr^U_+gAK7^c)T&9`>38`8_j8>SfBlYQUq zV(nxkMu=E7H6+=D9NVzR*DmdE8d0%N+>~U)KuaG?vbVAxYO%@|*LQ=4ZW0f4vw3!X z;$$}~1ni@3c21#{4+cv{OTga{k8K0}1!-}4OCXDhwY%7YQ3JBniqGz1i=3j4?_#-Z zz4+NKRy6=7igvSx3Gdq!GH6fOEjUPBvm0!^r1z(RzCX2_{g`NakpGl?>2m5KC;6!> z*h7?*Ms{Z%m;Ni+S6QmOE4IV1Rk+%4e;sQ8z(3bt6TS>;PWzZuIxR_n(4d1!lvD$$ z!eC4!84yq_Ftm``vsS5JOOi^Z+eic~mNA{ECj|nr10_*qcVy|sdO+TgNFUTlgh(Ay z-dieSv-~TIE&}%hItAQSG+`OcoKX?x&<0AmOq7)3Ltv@%`C1r$!02VAvc77U_gshe#z%S<8?|mQQ4F z08#@fNQiSX<=>DG1sg6qALVgM0##s8~{*x{i%2KtplDY-jnPO;^BCQb+*a2-b6JxGsWqqH&o_)siiK9^>_I{oX zFM_;A`g4%)1}p9i?XhHW?(p#2)bK3E@W}ph^qx`_wYGLs?S>(p3;iE#^lSqNdvFE} z=X!?KN>Vf$h`OYbtk@ixJD^Y;Lv_}gOhKP}hEXi_x3~jAb_(x+!J(nDsbd;iGQ3mc zM6FFwAO1tuy33yGB6rtIA%utZ#OBg{+g_%s_mvefVF zIsvaZ{V6tc9&KrM)9{$yy0h%?vpWau@USQvtX|xyc6bcRT)|38rFViN8V0F8Y#o?o znAOd*#oZA;LrgC43=$!c; z9Aei%4{;ZJhd>qio|)q4VV1LWFQ_&K`=X9+Qiks3#5%%$rWKo8orhJ{c94=k7Trhy zypS#pmPAh5%f;Ugv*Oe~YK@QdZHaj|xX<(NcAqPcxz7t8bDtMJ?LIGh(R~h{aGw{y zNzVnc{EG7T(h?O61SLyZujY-Ul$DsDpO&bck(O9ck(OAv1PP5Az^~;R{y>E{?&li* zw2YG)wT2(y8vY>EZM=m8ev8bspC9BJ{hHVYhp0L4t>LLCl*YHR0kJJ0(^j=r*pQiWEat(j<{&{-; zJO?);Su+&yB4v1)YxtuKuTq9r@htf@yr=Hvr?`ecdjC4Tf1TbF6NmS2()+i#hCh0L zn%Oc@r_dtxl{o(7)Rcr^Uc`&xQmOYe!>#QQoihRzEQPyFYdj(iBYb^xzsg3F3S#-a?7#8zP!u+JU*0ppD^(5R zvZL%EYwYuWoo)2s?ZwB~EBN_m2QTc~@BnKi1w!A0?9a$@`t|cZh;{eX%C114rup?Umt@8>Fs;jSay?G{}3z4v>F=_Yrh6jH-7+<_jLXU zMm=tW2X@==>etSG=t{PbPzAvyyW47cs3V}gYqii-df5C?beiIil$ofjMcWE?2KwC_jh%^WZku9YQu@Rsqlu;E? zakhDyjmzBbXguW*8J5lB8ms@~#E~fNPXHE6jf1EMR6`b%P~MVN<0qk@W(&kDes}~x z=K~c-Kzkyco0}G~*tt(GgbcOxPEU5DsCmGXC*a_-aKhjPVA%tSu3lEae0?|cG7l}J z)5qBq{0v-eeQ$n~t);c7-u7Mm7`r(wIr<59((AmHi;yga`c{3HK`P{Y_4xPMRcXns zKVX-7_)d>FRqgSM6VI{ynS<@ISwR;p#o#p=WWEMG!EI7oUMmWI$jXaIcn&%j#9lGz zHpwj8c5N1e4!fxP-)99Ev}}d1mTh0!X^=-PEh-vnD&8J5+4E_{@0Fe~I$VP~Dy z_oW}gkcfAC`o{g3?YE^c-+U3=?jwEAyvVNbPH|CXtKs#itWmKdn&I6PO$7T|f6fls zqM(VdvT@L=23}=%cqR;Kd=B}JXyVkbKwc|x&s8wkk&hGlmY#qD^FR6q<{@@(iu+Eo z2PULpS`4;ZInE{|2Y+j-7V{S~HVodSmGn2DsFeo>^@ZG}(1jqe$t_L_MwIs(R9r1k ze34Ca9WlFY&``Dbi;ckcKxr*&=^`F2Sw^Q9a^QGLr)bH8X*!c7+$Y6(tdA~>8_y)@tO>f}P zvlFQ|*hnP$@a8f$*8Obc%B~gUY#=KB%*G4s7W*eDp_F3NhoH zKe6-0u0OH*x<^PLV{z|Np_ev_(HQ!g&S0|Ap>7H+ryg%M_F%m?%MB9RZndOoh2#&D zZ?HVgKeMM9zriCeew)3|bg}U->@Njw53(S2ymb7PzU2oz;tQYR)B3J@hpk`(@{w@F z%~#0!etnvGS$AJm*SX8ZAOFfGd0_M`&Uu$jTtmkV^yIK6 zNi<6}HyqF98Q&3#C=+;^+nB;`tpQkOT4$Erut?GewYk4VtYBwwV|a( z9e>5Bw!}t5ia{(q66Lc&#I&~J9jGFBj-(AXjjxTb)=y3~YMY^Lh=w&1O+;Gdl%FKU zB%q23Yqy)E>_c?E%Y4%?p_Jo|Y#ch+%@ycxq_^VmyKKT3r9h^>1ooF3@tAn|U7UZx zzW3f`jQiYSgsYd+$A>(9qyC1C+uDh%uv3vK3B05FF8K#LL3WOdKVUy+I3~oYkFlud ze8h6c!pgUF6^?$3U?eTd`j428_gI;(`H0QM7Nfp+@MAV|M*m<-Tih~~x3~qo0eB1g(K8E~u3_y^ zO}F&&>Dx#o0e6l)&Gs2wm~Kg4L_09f|4`2$d4+apK&^KVt@UnI>)lqX8W^96-C;N5 zlT!n1*@4*+PxeZ6UNt)|CkdZ|jPO zEZ<0XG?;J3CKmi1hg(}x!oKJC>$Rv`nF4_jIgIKN{2QQ+s z$;2c8qw$SOcpN2`nxA}?B+x?uVdHt+@cptUGh=)e}Y)0OXv)%V#0C049lx`$dX zAM>z_tnq;Ie?|I`Ag;;?RYP+q30w4I*LVt2%(wXr<3w1gI?pm(bN|ICS=1H!i=>pW zZ7Y+epHL=Hq!XfbE@??^G&Kz==kWlnfKLlKiL@|A);_SYljOBBQ=|^1U^og>v1|d)Om%g1(`-(h~U!ID!%&gJ)$xPRwrV=zxv?*wBstnA-S{c`}D?>ebH1q&9_2pZaAFd(yq8 zA?D8X)j%M<3!Vp$BEFA$ro1y_@oM!=ssCJ3=qm4Q?Dg>SNOrgGprh_#k2E+)4fQ~H z^h{VGj2l(;FHnN~e4xeq;4LpW;0S`DW{P4+(PoNmV(|I-*nn<)cxX31th({ZGaj-xF9MmX(7E`?4F#$Fy}Z(9e)Ax-mN80iSNVj)8!C?~~M#!4;3;S&z5 zt8MQ%YsxA)N$mmL@rsXi_k+Q&}=bAH^TJ?k-dy;a1Y_lU1CKF8Kh|8K^l z*0USIr0)Rd6D%@M9QPoHv^Xea{ysPuBXQa>YF~Czc+l&%O2)if#6pv6xsi96<6m$ zsy_Zz3=QTU?3xj!s^I@S!vD+1S9*LWJglf5qzRlI{x8dm7Vr-kKjG=?n9Mgb^tbrI z6uyoEmCL{6fnS6?q_-H1dJ;I(KdbC)~pT&#Dr2(LoL!2~SGt1+v_*))v z$?d!Vo?3hoDB3^H;u8yo%qJofafWp!PJ4vEn3s;Tt+bgxZ28Jc|BJpvG2i6L`w&C7 zDF&ZzLrw)5`v(m09KHZ9k7D&)UdTW6^vy5hxlr86^pruL1j*sO8TMl!Y}zATHR77N ze75qUFJWHs>Rc3+B}SL?Y2*P&R9D}+az4pR<#sHe(muzgyCjAco5)&I$4<8@zhDI_C7y&G)q0e6t4Rdt!*z<_XDIjnuO*GLH`* zFTNY(Z;l%S50%vw3(M0N^tTuDPoq<6s`y@@@SQ5&%g5;A#V>iLpRe+whY=uUW!j2? ziwPA1a3(fnYaKOHM45#1NkLk$P%U2^I)~TJPu~ZvKzOI1-?cVy3@IH0tXP?9Cmb5Q zP|U057s3JQuCMS3lQUV6LQB|=478iL4hnaQr>gl~yiljrwTw^I#q*!>VN?(lH5+h92ZHCorFCulCb4fnPHHNq}NWuQWnV!I|-9qB!}5a*yJLaX(wTmi)5DO zuTRN}D`1ujz;FOm8iu(@k8sioGsIZ6-Ye8bI%$R5C?~Cu8||bOb~#R3p*KeJr>p`M zf@7Tw3d3=BnrxVXP_C0!2%gHDPa15g-NIce2}=h*3m z3c+e8tq@$|q!oe)hN~v^LWSTmC#?`%?xcYrt^XPapfEhwNvkeg;iMIUE1k4Lu+~m5 zQV6bc(h9-zoU}r4wUeH&lcl&;=KvIj=R0ZDg%>z!h2R<|tq`nt(h9+~PFf+j&Q1pv zf(=f(0-g#$V7&uS7;bRVstY$dX@y{;lU4{eIcbI9CMT^BywFK21TS*ZDTU!?8?abm zc(IdKU3iI;RtRo!(h9+?PFf*&sgqU+HalsBV2hnjEmjzYY`|iL;Wj6&5Ny?otevu4 zVHkD+3Pr;OC>+~dfI@P+3s6|LYen|{TdweoxLFjUm$?9i=nfa4Fzs*w3e`>rU>z$_ z7obp$xqy_ywabMlTz9$vg=^deC{zve7xh3oY$K%u(d1t?TM>jD(2pK}1#sq=XkpisTR z2Baz~6|Ohhkcvu$>la*r!u2K>pin*F0u-t@y8wl%=>in0UvvQq)zmEx#5#X&bpZ-j z;Q|z@x48g?>OmKvP`%v+C{*uo0SeVSEkLTHVu8Z-kefx}`Xv{jaJ|a`SSQh87obqR z+XX08zw81Os$X#d64jJ;j|)+_9&rH**RQ$&h3eN_fI{_N7obo*>Hw@W>FX{)p?aSJ zq(U7PixjT+yIB;j$6SEw)(2dGLiIrxpiq6t1t?S>b^!|2Z@2(L73Y7i1F?>$M_hoy z^-&j~Q2nM0P^k8~0EKG53s9&&<^mL|k4r!bWPe3a;rcB%i^BB@7ofWJNe5t^Q{Q$0 z3f1qp0EOyPEeDVjq55AgK%x2r8!*p0u%2-N z3e{%`kdk~)xx)21H;cmchb};M>yKQ3LiKqUpiup>3s9*3#04l+UvL4775(#~1F=r5 z|K$P{u0M4F3e}fffI{_U7obr6nF~;;{@ev9R9^u=@n7>Q6t1tjSro3nZ~>}Yf9U|M z1M62VK%siV1t?U1?E)04zi|PTivBw3LKLp2T!6y$w=O`T`a2h(P<_n>C{$l}0M>!^ zdl#Tk{ewe)%%eL&Fcsf$vnX8ObOEYc|L6h~s(*3;3e`Wm0EOyXE%@A;1t?rky8wmif4cyM>R(-eLiJr2piq6!1t?Viw?lu-t5mrD&CQ~4ecuJBZvDFh zunw$$xB!LfKV5)A^#d26Q2o#W6fRJ>e&j$FC|o}VW2B24Z}ZF?jaXigk3iyx0I=E; zOQLb&Hjkgz=;GtsJd5Bht82BoSbESi#Z#+iisOeolY}_v@sAs9e5Tdu;<X%=@Fi{#EeU`6Gxs;Z?>>ebGrFc3dAB_nh#0{rfE zv)o(6U)0SeZ-Bq7i>|MG^2~$YAb(XC-=XI}cqfiNomMFHz~)sMx#r^+jO2gU&5Deo z#$sC&6zYI8yw2_!h=8TrBqi$*Tt;il-EeLQo(AxZr7g2+TAf~c6}DKg*Bgr>o3`m$#7tzL6^ zRwWO4#j*!H6V02lrs;+kmsmXfI4)9nK5N|SPq>(;)61?IVns5f)qeY0o}FIv&8%6x z+iQ*;Ucuk=inky1_)TN@WPaK!0uOn7=Aq$!_MZ9e;njLp2K%Bod=Bp288;%A@6_oI zo(bl%5n0S{){U4trW>+bJ21K&akG0w{k(lTt8}0gI9_9wPQY!t$YAJaZ;fa|IKLIy zEAj93*;Nw;hqkq1w3)AFpNH#vrjEo#6y`Z2i&9r@FfM~~+6dQ0rG2R-x&Mn^Qn;&v-e_q zgu@>83jipn_y;3{e6M<}A2oi;KHMYY-Xbx$dQxA&wFE^S96fE671~O5 zW7vFl^enz#H&2i5=P2guIcuqyzvnDX-J)lwVOK6UUsx)`*3L*Pmj#zw0|+aeq_Kgl zk~M90T@*%jF#b&%w6Bv_G`9SPO=K@ngS*GGaFg8ZC^; zPB!em$kHn1$Mp!g8%kESwnLU)?c&-18^kt<)61!iDi5+`Yo!W%g*-fbu+av`EaQiC zbI+J>jXOm9`rW#QKbW%JRIFhG{;1n$zQ1_XygdcA(JcK2D;1OfR ztu$X6yB_Q8bnXOP0kd@67xISW&rHVb_x~7IiM(@j^N_bTcd_%G$ldHbXXS;@TE^{p zQ~6Qdd?N3N^U3AoX~8QL-WcEJJa3&XW;yaKMKktFQiLedkxAM?1X z%Jx?pp`Vm@6u@E{ndAbsnyNzbAV97%fF&!HMv9hRmq>I|Y_)*zTzT(ArVLXh@fkg^ z>}<2nR}v{!*;X3cJ_(1B`i~?IVPuhkl4Qi8Fnp1^P`Be7AZzzK)fa8-meHnY@F-B$ znJ^e-9`#+Q`eYDpqs>|QRZzPP42Pa$#`9+n$~nfoFF!O0HrAXp(H+9FNmI=SCXPR2 zJ-OzeCYGG>O`dtqq*-TtGv3@ksdC!DzGT@ji5>`=VE$%OSy|3%#AU-qNWKuU=rNr& zV010oVKoAYZ;)`!?V|9&QhfSVvh%G`moq?`9m*gIcCgl9<*7*{#ZkU!07|-F-2!rl;l2c<4IurFg zR^vFPkPTXkS|2U2D^oGk<;-hQB`X7JDh#m&U};6xA~N1npxQ>ZCK^5)wyCtiI1{=q zwu2@mE2W*4x&v!;V4qIXvsfdUkEP{kae5ebgJ~mq0qV!4ILh2iHN@KT0wD2WiUzyA z|70Ew>dylGrXlkvZWXHrSk0v-7&}sMaJtIlNrW4A(-fvyE7TtX3DNCjnoIGpVNkXU zvApFCL)7^=0k?1GMqIGld6DO+o-1k!S>COW^K7%BU?xANi`>UJl)?oYVc7zUOid!zvaAP?CamGmGZOcm{u1m$!N4 z7pGOn^cGLJwtQ~taa z4eIqOn8MOkU1ai39e{WtFu%uMab^nr8rm-G3l31u!nw~wRxCuKUmJ4VLOs=z$Pj0kZHASpo1^P`je%N?X z8BW|@rwgsiFkozJRbx$Sn@TIgTpYYfV$Y!RXonm$navxgJ~`y1=jN7a=Mw{si*_cN z|5%)D{&-prmcwtR<&7zpk{Twiqyla>~5m%?~m~MdC#uYoOaQU0B=yrZW zH+ze2$UQ-H<|zcQlXRy3I%3x$$oh<_i*?&fiS?5>L3+MCk|qerh5=T3+9y4y5^w6} z+cV}4f0K%R3&HMmbN0+RmFb09bPr3rIe2IsdF`~^VWz72CztS=0@%+`tT6aaLnvae z-5<;>9BPwRM2^@ra`FC~XMNo_q}y}oB$0RC%m$JB=ULm)Pl___C{E(}RB^s3Yud|zKRH3{Ur}LAEjph&3XR9oYl_rJ9BOwTDNtRi}|I}FCydovdGAs0S!7@ zRsgq=ffOE7cgql4xE&l(4w>G=nzh`rbt33eEnA0c0dDtDS82c=cLzjXSk~4hS8;@J zv8?C2(2KB?rcz|MRLgK2{=-;~{;tp{3MU!D2g=jQ{GhBLe+WtlVP>=?a4AE1U<>-= zhQKQP`%<8izo(m7bJroUdG5T_a+n&+D{PcGG%dO_UuDCB%J`nV$G+g?@5avxzrpaSmb)B!%UaK=;tB0mUKfmS0fa zQFF}LY1EFdly89eNnG^`?&ry=D8XE*s@M)cy-F~3@Mi#9K?ewA3nA)cn7!e01M~Tc zObqPLDr%9vVBSXj+cj?|{{8K|jT47{YV$YpTe=t_8z0B!Ur0uDRN61*XXD#H%x^`9 zUQn5zkBhKyKGfJZBsdo&pq9TDU8qiva}nc-f(+qyJQ%?3qN4y8(8M}}tRc;id=>1= z<-G(jc~eGm(s=t!SSl{Fco)VH;z;5hWGfqxkZrbaqX1pe0HRe<(`J2e!oN{y z>R%S>(YN4;g#WaAEUNgv;c^IGji#uIOlKbg13L+qipsk%2K9`l<9MfG>ZrpK$Jjt9 zj;QW5CE(uX+|!||wIcIMUrXmmv2|sQ;ZjPp37O7Xdsd>L$)-K>@3oLbz0 z{RtIJ6ECdh!+4fgtX;*gMlQB&rOZ1=oO>S6g{A8HIzEryFFBtF#rMvGS#wZKT}^oh zyfT;9EE@z8Pu6j)-1Kah4NL|_?gjkZPi)Kk7x3lkWrn&mL+n_?FBt;K7h~)BI^amF zLAOi!SUh8g)bxV0MdUDTF ze(o6r#NaP?oD?rE<(GWo%N5JeS-QA;8Alv`y7$F5#>v&luiigSq)C6vF zhkjs&m*q%3fx~4DR;_5zLg5ONNd*pfTU@l!zC;AK1j&0i=ltI`kxVV{hu_?#E`Z?n1uF zP5t0PzSd1Gx(MF|#myJ-nltQb#ML-ecsBEOq2(L9w^_(Q`~Y;Y-O5~pce0@Jp>2+} zHRB53gcb3Ql|n*m2eBPYb7$&L)I`OYjr#Z$i8d5*r9!9T2HlPwC4tp$?L8YHK0q8& z9PKE7$VPfbq_Xs>U|F_9P8Owmh083_9>qLLB<#@iRO&P-zO*9IlAkDriom&H#LFVm zM>W|a)^Fw$&)Q{U2DfjxxNkGR^gsJ%gs8iiiy@qOwm5w;UpfRlQY^m&?nwHrTY3JN z!52D=5{ED0(6!J@#LW83C2-r3u2O8Y@NePaA*JPrTek4aKB2TRV)j;Cb#~^e#)@xl z<-1bVP1b!9O>l7rU8FPTmVm*?jnlhooR=;!hZ_~>!+=xL26>U_*-FZFO1c;$=@wep^o}#(M3*cmdTxoAf^7R)f#|xFPoTZ*`b+t`LLc~N1RoeO zClyKeP7C_o5IN0!X0{#gIumZJv|o;|29K zKodEt=_0L`6;>@=zq1C{iGX8)l5|gxoZ{3LFtqjzS6>H;YOH9{5Psx9c-5hc2b%f# zvLP*U!A#SB3w2ONI5#>=1{m3gInot1*6|D;`N=oVHlbv3Hl8BjLV*rA&& z)=;|0Q=ikW25)(aLF>liCRsg&t_vfSH^p!>_f4Czw8ooR?#RqBSOd|^EPz0ON&}%# zX^$28>Vw+VG}wVG+XrvB&xZJjiMgeaD%XSbpis~dWvRG%B*PaEhIsxNdYZxps7STq zwGdxhIHb#p$QiyX2DPaQiCc2^LcX|-Z~Zq4sTf+1iwVPB@oI8G0HH`JEVk{f{NjJ3 z-*1(l21@&G8;Ix9!u7I^e zH(lmv#itd&YvVu1qWji%UJfGS&)eZ2?xa57&Xbwzy{v^yy2O~jvOL&iBx3_0VrhgA z1O2cn!Y?9hWLVt)itx33y_KlGjE@)=WI5Tma7mns@bNnCH}Hz~%Xs04CXly!<`Y3} zvsc`7886TM5I4W573il)mgtBjed49d_%C3)Bu-C*(GrBv`Q^cLv3`<0N-CBn*Aai& z!K)FQY+#s7d9k__Z-KWKM>=>Deh_7I5}G=plh-5lQ5XDll?2R^iHSQq`5L@=vy(5y zPjQrkNfw<^;$11S-~@d9OjLe6J|=Toz)!{a+=fB($&E!h7&qFruq%WJ7OixDw`Z`) z4T{=05hyY>CoOQ5PesfdQnl|g>_WJWS3DVq*g$=k9v2Uhju47I*)K{G{5txNbLJk{+0_h)7<@$01ncjhL9FX!E`HnoFHvTQ;=?P}b# zYh^#WoL`Y1C9uF!FdmR0;i&;_jhAg$TxM(*Z zB*&o7wXym$pe`uNrW&hR3Gs!!e0r+7-iod0RNw@sbVtEQhuF~NJx<@F$^`FWhiH@p znYHT&RyUx+wJLTXl=Jn79|gr8VPS_7g{cHtLwrI7xtXM$u|nZlF$hVQVX-_a;3$qC zD~FVMTklHbu3>!xvLyWic&L{zvf^2a+fK33sfIK>V{sYMQEEEVF+D4ydAbZ{NBN19 zZl$1*s5BBl@GjgvZe610wji+Pybj#u(jl*vPo%8A_p!=OXmn{mKwReNQ2plMh?hh5 z5?DI#X(lWZ&~y!q+fque)YuPx>Csq&IQ$2eJKX(Btoc1FyfA`e*VdOA@oi|;Qf<7> zn8F@fFXw7RTpiKf0jq0_j@?Xju|x$U;mDDd(SjJ6Lb$}p0Fh7O&FWYbf8XOrx%IzNu?|@dQI*4M>5_@3B zMI&tk2_4e98NH$!>o>PNm5r!gBqG6eFqH$a(RlWj!3}MbRxSbU4LKGV4g_f6XqYnJ!`=5d4;ee%OBk%j@kv->AA4N@H7_Ml7nXf<;U9kF7jQsGM#a zq{h>-X}P2YHu7ze?NwDy$qB@T>wx+$;E_y}({#Bp+J)IylcXdx)B*N1?A(!q5mXj4 zxJ5D+(>t93(;|Fid}j<}6u}VRT(xx;r09w@EyOSWwSP`A)AWPVq_-eQizg zn4(fAh}QrE#hiZ?zr%X9OuTy)-vp-+v1T8ij|f;|-#%V}JiYrMut&72f9&JSc#l_{ z^J)H1zSk>)SMy>kpwgtiy;t*U3Y#Uqbqz0NclW(<4KG2AS~2!B{33Qt?D!1-I)Be2 zCR~T`Imp$29S^W4`~Gkp&tmLZar%00BB1TH`=Q;W*LQpt`iYmtv!CU!^Ors1q0b?n z(<$-G&+(rSBKLnDAHUxB%g^&V2EA<8tx#1gzLC!^92f^jkmc!nl+jse>MW!hYzM5LPz|4>&mK#5&=2v0rJH_KO?8 zz~>eXY#OdcgTKNJURES4TS3kX+705=7kI_A16~FpJfb`%67r>GIgNNZ(z5{m9HR0j z1f)Gc*(Zwbo1ovgMLj=r6GWv4#hW+rGS49|6XiGaLb31wM)IJ_aQOj#2Ro#m@$wFK zx9a_qH}esJBVK(YJBo%BSf`t=9q}@K1DfRckm0qC%Xbj>R()7z@>+IOJzrYs}XZo(@J4Zh~rffIS3^P%$w-jr^RDmfz-}H;@gDA9LtUL(W%v)mr zK}a6n5B)1{?93VHa;Jhus&oxzdQ+?(PxmN7ICnk)vj zdNU{z+QQ0n{FPe~0Sw-^@&ct|Eh|HO=^Q>;1i!*(L*j;=0`|rU#6Y9U5l1=_E*5*f zfVx8iukaE+GDH0HE3m!@ilTe?oZ(|o6O^)AUWV9w4{TW)#esYH z)CKt&Y~_mB?&?`2PKmTqMCmv-!Tbz88(>m@7iIu!{DV7z@sAf*9%YDM+(SxMa_Spl z2Mg3@WQeI>#r>#jj_`s~_s&2j*+5CCr30b(YnHY`B^lz2NB9h0lHs_~E-uT^96#E! zj3JJ+76=7fp0o;}l}QYOm!;KHNsOkW0V?q_JMgKxa1!C=Bzn>~_DpXT?P$O3B%-1aUAy3Gv^X{~~| zjg@I_afaCOH9o^hoKv~|PoH?N`J(8%&5Nqz`Q_i!$4=T4xy9DKvsMWaBt(K-6{(;toW^7%C zhCezlSWv6a=z}-wQ4e3AAx_@qDOuT2RBLPZSW^bfFmTN+b$J8xt(Ffme4wTOOKinR@^{}Vnd`$*$XZ|8dh9sfa!%a20R0AB;2`wM6!h@z47wS{> z8G4CcrdQ~T^(A_ZUZ-nY31OfS%AklwCWXIjpklp#~=&PX>%>B$&EeDok6&bpoqQE?2WW_vS)aSVIpwHe}uV|)(Z zpCKMU21gFS@qUu{?_-EB8Wg?<_~bbqEN3IM0&w`<6^CVkycQBo-QOh8=u4PFM>ZW@T5L8BfKPkn=z%n0VL zp_rE-1X+2)Hsg_&xM`n=QN1{vkBS++eAXCj21OR}xfXNqXxeirKKLdn(kTovp zM@ZGQ8ntJsz^5~`=T(6dUbG5)Ijz7KGaQGiiHnX6^f*AV@G(TlXdH&NKdI9m?PV(c z#SHCLtMn6A>2Ic$ej=^(z^M%TV;kvHSW}-+`YEycaU6HAi+zuSKYKkx>0W;FIG;ZJ zO{(}rhW1tl`Syye>7G%2)4s*$d)R5Q>DzpEwi6}dy$ma`#@D{h{i(mxcOPbG_``(M zf21+oamc;HH2eV&%o?U;4U=BjIF`v`z97~Hf3#Mk8ahAv-3YHVZ1_F2vp`r`0NFeV zL^W-sEMUwqpEhP#HjEc=O-K8xs%~7Ez6-MgdEYP5A$i04#(alw z!^JVf$Zbe`{wWwZ6^i3;B1|rAW0PJ|vvTS%cUDd%oL|yrP_BxC_f>|HvC1)_(A#H1onEHKC)JjuRTC^>+y&2}EMtp#KjMBEI zgS5r6)CuCw@AGl^8ih>s600W*@(tIP5H`hH%`o!4nKe8!2W|sN95utlw5NIXQr{XF z6_f9n{>lo+!9eK_z|}{=v6X^HZw=v|0g{Ps0h| z|1|e5;89iQ-uT*ktt2x^fFKD>Ab|k_Odtsf1RO9x0^t%(AV7jpz+{q4!bomp5+Eua zX|-xwZ27FNQl)~HwptOfrHK|)T4}{wwWm}$6_wN4YAdJVJ9=7sy!?OfT6@pzNwAmm zedl}rJhqv=?$>v{_cvXB`;>Xb7`t8A(^ROvInU2?Rux;?DKF`jTkTl6)il268c=_AtY5?V-b~NH9rGcm|smN|Ke&m zk@`RLwj_rC2pss?9{e!(Cb7Lq^22A%8RgDVro-4UW*g`Z*VOaE({K|7?rpHl%-KqM|229+SB%gfFoC|Z8oVAEhSD~$Bd=&kG1g~A) zemUZKbAm5^JK_AfqYG@LVufXO1ynU`=zi5&rtEm$%os+mM3%C~3c}!K@AGE*aOW5f zCXr=os>S@EU^=(+^w#ETFU(dLe$HHz$| zVszCn>uGPH&=d8_emh*?10w=BCm9>Fi6k}DE*>-!($3Lptq@v)>I!vg$qX2X)HUEe zg$O}+6z@t0A@PRFwEc`NZVZK=w#q8LBNhe@*}=g_bT2(CkaBR+PV2Be1hEhJ&qXh>QOB>MgXkx_R){Ssj0u>8rd%;}rb z3YFcHWi@Q{=PizDIvB#qsxbUH;Ng)57Q#fNff46}LMf%B`aPrv!I#e zY%|_?O74Ee%$zfbB?96aly6V?Xp*tX>TxY;7L-K0#{oVnfBuS@Qv{7SytFF97;bG& zS$B7^trNQp%p`7c%_bs=!Xm za>JFi1XmabOt2T^+SkC$drR(n4Z$j2kk8}KOza3fXF5;`?ZKs50b-fHoh(6Kmigz* z72sQ4{|3x&&da;sFmu2bBYePjCP_agXC2Sl88r!i&|qir%f#n7n$1|5|2lXE1Q>L? z4tQW>H3m9EF!6AtvGaNjzV^E5$@AMU17UJ7;BZcWF=wr}bge(XZf4Z{jg^BVvZxkI z>})(K;N&I5GqZVV@1#2-bIu_%CT8uaQ*+p6le7&#M z;*Q~$yZf$q)BHR)K9DE>!<-d(v)JO#u7dx8P`mM4PZb!>?cIi7)2qGFQ5rDW!HMcM z+zGK!8luEDE+}hiqSx9uhzCAvReK9wD;$K6WbJ!q4~QPCT`+lEa^&yKX(s-@{FXU& ztij-_LAy^%#S(v7Ir)|M&EcQk&g@UmnkwsmXQm8~H4R4PM>P9P`L+Kv$3^}pmVo8q z_3nZR`k6rbnEp0eDd4ktXhlUV>aoa5=dN7~Eh{hT&4& z1b1AyVMEIebHN1@*bc+gfHGzAJ7!jjpRTczDf{Kdcg(SspmyzucMjkJs5&yP{fwdQ zXXtUz9}q=gUS`VONxW!YwoAj7iD3BHG;+2s)Q=Yz*9l)!=x?rz;Xl-VGvCGX^}4Mr zRNHMyd{SfZBX+M=f;C2r&m1y!YYS$B4NOT)haYT0ydsJ+so}aj`e$<#EZFUKn1Oia zK|JiiI#4YzbM(s-e=x^J97n_tuz@I8ZFYg!;i)E_o9O8pnqNryTH_e5XR**rdcd7z zMjoYGW_Yn=R^&=8wUnOa>EDAPmeWpUYf zF_GT#uIalBQFc;8sKMr8_YzXs0#_gGJYVEynTxFQ3bWoc($>Iw5L`mNy@FNfAK((I zLy|Ex*wboP%qr0>zwxR$tZ&vu^LEp$RR^P};lBZ9GX5DzyTK*by=Qj+4LJD!3e=8> zokoCKj7tHO|1PZkyNmGuGgzDP55rnxvpP(p50bbJNZLpTM=4;R$)Kz6b03;tL-0aX zcww6bo_ZYM326?K!fiug-8LLwfYNO)`Gt?o$)zs)ZFk}`hQC;2jA0uUa6a=uT!>(3 z2trh}TK?fnb2>>#;!^})Ci!Bcm;WV68wQXDUoycaYm zOm+GVo(=0;Qgb3i+7fkPPo`H~xW@W>80wuB;}-|&@1Kj7*}wNzJW+tkq}A!aX?blLR{$CV;% zONCN%Hc!+%_)o#EGcGueuzr_VWH&IcGpdtKa4DvXIodN)7{s0hKPt8Ym>F%kW31prL0+j_K_l2*yA`i5SO8{`C9du6eJSSF zRu2KZYjCX9B75vpp%ih!F7j$wY_8%9rJPqc^etCEgQNpDG~*rXDqe70#dqX?j^HyQ zA_pgDrxGR@K{Nh|!aW0X^RBNM2;7B)Eyb5H99+%O8#6z9I)lA_is*Q3xnp26lM| zxVI3u!Qhlk+P9g;dbzp*(&F57o>J(%S`KTTIEv1)I7BPM+_EVhQS0y*0_VaZO!tv) zWw+S(hjcDXb~r%pmM3~(ce`#3_l+T&N-g^+ zCY5RHO%C^cb__piK(hgIUvZcu2! zCJWNb+YcG;lw7xQ+#0>S`;g&HwI+jc=IU{d4{|+Dhzg?P%*QxQ47Nz^woh&x%RQR} zLVse_NQ!98aiePwF#@~7^W0jsBASam%+egQ@KZV~x?<=TRq3Vhg_77j>IUBn^iZak zSxdImv1Dbccm?*aC>~kFNmv?PPYY#zGW0#3bHk2V^W0?K&;c?t! z_L}mUaeNXy?M4ZBR%JEbH$IDJ3Ujqv&hzqual)&luQ*`_yzRLRNC+T|#pii=81wSc z;+MIZl4fAn4@zyG(d%TZf`7B~V=^pISD<$uSv{ z%aQetHM`+p7FZnb&2HnX^4_T&ZtUIi_KAG@$Uz)uNQC`-1-!84$&^F4HX?zMcv1l5ffIq9J@u@4~mNMSp^dH+R zkX75a`_0+>xQ?k z-39RA(w~cfB)tj*WXM0|@~I2`5Rmq3sI&{fMMe3Aj&aFVdERxnSi9Wu@>EqEFr2u5 zY_}T8SlKom#M;en`PJ#%8})tav4`{2bUxbLS zU(e&CCkcS6PkZmvNR72jUPL+Da23BvLjr#?INNJARF=g6qh4)6W>IP?AT*?bPK zhxBLCSm;~A1RSs+UPFN0X*Ez$z{iZ==QfIg{{m*va*+Cwq0B@Dz{A>YVYVNZt zyk5XF^9DEPke&?c2i28c9PRHK+OT~VtUq{(4L*2@4c_O*4j%$YRsUx`;AZ%bSi{IT zj4_pPuTyaR_3wBKd6Ie5-8boSes=;K7slkWQ-JnZFVa6GmsQ4tmypU17Rui6=|WjS zc2!yidsGefl{v@Uf6JPXoasUX7b+>Xum+QTyGFir-b_b`3~lk_)#h7ah=jaVi>n}_ zhC7lDE!$C@MILjz$}J|a7F*+S3>Q{4v{i&H84#dP>V_bYQs!FO0R}_*+U}mltwhqD zh&#+D-9tDMC$RzGNSwS>A9?7bx+|jX5eefh2Ow8KF***LgHo!QP0@7AMv@tuhE#$6 zL9jEL-#RqE4Vt&AjOG_b2pK2=rwLHw)TM@*gJIIO@4*6qM_{epV{T*68qv$3Oe;^g zqXG>zL!C+&1&se@FuTLWP>}=zN&o9f@-IZsr`_`L1-un<)@cj*Jopj`EX4hMS>C#k zXX6hN$IGV|^65+L6)8lJpg>(%qqcUUzeQQ<4o)scq>WZYEU^m9qD8pKcAY|Ul@-mi zcy4E8^CG@rq+KQpP8SI=KP!K*i2EQDKDP(}<{kOrBAz$*BAmU0i0$s`A^wr#MA*x9 z*1n``b^P^nbV1M41wALPDdktX>9>j0x8%`MKB>s+kG&IjtS$^aRu}ZKx*-3xoR4$c z)h^%Y~Pp9mhs7J(TcLE1b+X46U4x2Dyda|V2|Fi zUAf=}OrkpMBboyJpJ^mB{0A6w!Ht}RWLdhH=R!~!HOpY`WVvH8_mQE~!Nojtq|+t| zLqYa)i}}n#KXe#~>uPa*!icAW_#QNPi-}kWduT+3A|G<0ox_sl^d(T%7?~_rE#cYe zXMmWK)ey-jNo%S*I5An?xP(u{VmQ%A$l{Xa_fa#~YL<;mj(;dmC18>n$(Up&=EX9S zR05j8Fxt!cLNWq-xE#306v|3H z%ZDZBCbQgR`Rj5%HrcM9kIqnNLQ%3&NN$c7_cU9?R}rdl$nTkt%}JIeOZlVbykt4B zl>76QMbUy};M>Y;av(XXJ9`xoiVBfhkZg!`2yd1wYnSm^kiiG8;+ffH$wsmEQ(Fb8 zH~IrjLUz=_o!zy`@`+`@{>zf(tIPPzzinm~ac(JG258%|f5^;iX|l22()6{)5HmDe zn(RarDw2o5)(R{NU~7euEWbjgUoS1^V~yM7AD8oSW2$Iw%3989kV;lr1utL0Gp1h3 z0&R7&;nTIW3EJvp8Q2RU`=bzp=wkSEY5n=kj`?9u2=nB zK%?8Ge(t89yOZU#s{rlwdCVAk9@)*weP6kX?+~fCsapO$$!t%uysVl}$rrA*PsoX@4NJRXU{<#29Xf+Zac{D0 zSk0d^?@T7kz2fNt%2CG21e?Y-eCg1dYYH3vM!J`{7T{2}dP$8+$d}jhOmknde0MFM zHVRz$DAk)rs!99d^RI^Itd7edN9G3sR8(LmU>Jz)1jk)?AHX#Q#v9e6uxWog0T2F? zo^EJv{X_jew3g?9fO3wnB5oLZd`3A1r>ewQOQIZia{BhShbTAI@QDRv0!h22aDMwk z!?;WIq*fw7F5~ZZ^I;92oMpEh*Nt;|(;SULa~ZqQQOl=z`csz&!iEo`vvp)n3+^7i zArO!c)$*~axZL<8K!i)K`KUx6-kO9&nY<31hJ#kd>UDfv6hq1DX;)T7G{sr;=sfW<1TOljXY2d^V7;FK*^@hsEr}*kRrJZ#LsC*lfs;HuEu8 zMIS$Ut6S|6!EtuLb}(X>u%B$wG!DOsH?s(qf<6lwgVC2?)?LFhs_f!<&3 zBO`HQ+jQHntdVCuFwSBQROjS1JPTGcuV2GGQ5buarZEpHCR!fph3W*I{pdTMg#@yP zwhLs1X3uhdQw8O8-7erofw%;iAQGF^&QI%_9BQ^dTn%07=Z0B$j~lw`VmV%XspYVX zuCNnGwFQbU5Leh)X|xjdN3mKK63cW^uX1EPco%+IRL@68XPKk+rw&Sab}cIf`Xz%> zx`RPG#b=?=j%s$2qn_VF#w_Z>uI#}&MH*YLi+#_Y759mC?~c!nedeHYXGdpaOhr8h zs~n#~9R#<Nprzxz+iJrlX}%7)?7rDL1Ze+~?e4 z#I|!zDee>3uqV>s%m&PeeaxteG>e%r~cN|s+(Mi!AkN;Nr(UDpCj_b5ErGBjrxZCo&{2uy$*%;t z*BFqG1o=4pc|OQJOB@x7Q9*Gj0&P$@aAf2lLtC&r61_-NBuRhaUiE|2d#`;)uLwK*}}(MvQ%eJc*}r1pi7->;h7l7uUo*%7?6L} ze=@i5Y4|GJ!l!I<^i!fH2R|SXB(%Yp(~(s@C`%6|7Wq}@N6}xb5tkQ(5e=_ zt`$s#0r|gL`AjFW_?Si(f7=Ra$ABE!#wX!VahqzOp$)XbfV`y*qLu-9xQ!R$&+BbG zv&b>1QiQVw7FMS$(}=(4$Rk&XbuC>TI|kqyRh@>V?R>Jc`xCnRFCllSqoO|=rx~mp z9RJt>%hQlUaqJw)Sr#padx)l-J)G1%%;?~wXE-Y0S)f4!VN<&r>p(jl7?7;!d18Zua1DRyz3@tXV}TFueg8(tmF2v*PbZWq5g zG4rg=Nwb)p0(8w&V49PQesnbh!5mm*31Um?KkU%{TbvUYmJY2*G>f z7NVP4y0_SgqH(8u=o=8@g%ag6-{5m$J@Lsm_$53CWTeQMck|pU?210c3aulT$+qhP zXf}~h8Uh8oP@b)N1sz$dgG^}sK{p*QT|3y0;29}x|CT+8hWz;vGjn=oij(h`oic>? zm5s@Qh|W%tQ}5w3hkG2JWhSQFvF)QAb4m)u(wro}cMl&wt=|H0#sI_@o*hbc$#KH% z$mH@*_wejEQ_Ebdm6H8DBb`o6F`{m?_E6~3I_N~^r^w)bK4q@s46*#Uu@?;;dyyV{ zk!pJ0q<&KSp(xoLbLIaka{UBYd0;ev@ZaUw}_} za2&Svz{Zwr-Hp_)j?mylwjgeVWkW|;rbk$oLhgWOMPi3tyRmp5{AH5c&;06V<$UE;hq%0P{ENXH zMe%qsd=tM{r;rPjv5}n0z;(UKuEu5gJTd+`uPC)CMm0@%Rc8RY(BQ@CXbF&y)KXU) zQrLzRXSn+Kg6W|~+)T(evXrpPk7}D!u|?ewO|hWo*P+La=2y`SgK+LaP7YdHt01XO>M&~ zOOe01AIQXUnf5K7p5p-bB>D~arauq=-E< zwl77yr2u3Dn8>r-u)-uMv_&7F<*?{grqNcIJ{@rw!keuKJ?uCNme&|Z3fmudI1V}v z$3)A=-a)&P45Ng^j;V;y%*%1@A9b; z8)ilwY}pB(1{Iv${)8W`-a6P;zziiW-9uP^jI+;PjvIr=v5DBY_&q#>qPa1^T;eEO zGPvy7lsmG;n9JxoGUIDew}@4VGVcK}miH&hbq@f^JuG)W0Ogwt@+kh88A$8 zwn1C?VO}B*yN!F~(Z}J(U)-E*d`<4X3YuWEk3h~1anbrCyx2UHEN?%;XTYE0 z<42Sr_rejr2#N^#kMLsXHZ?rL=b9fS-|=MfIC<<5?iIsQ(9D4=pg#TYkMMMFzqLb# z^|v}|F<}T()CxKAD8GFa^G9E~C8U(cm|vbe%4cP;QXAZcp@<0Y(M<+BE|VVR`6HRe zyfrCluz-+D9)%)2%TWun7OWDqB3SApFmiykI<#`G3wq%P1c88nLFd}agcd(pd-*M3 z&v=z7Dmkf!Ha=BRPA3p!NqH|*E^WaT_kxwHUuF2+);%iyb|XO~_)Bh-MMt?;y1vhS z8LT)uHF_}&0|h*?{QJCS4D(o4{micdY{StB;kh=?cNcvZIP@c#LVji1EK&aUF+Oz+E4NH%t_wCr zXD~5QdLIYc$?BsUrOygAG6rBI^Kc4hEv!mOu!iGgV9*nrZYz6tIc3kC-G` zX<3#+q|z4H4v{VC1;M}t3#8Tu%cDd`hZ zZ9T}hd@iYuNdyJi8hKj|Z0|sr;3jZTLa>{HGbTg`*3}A_k;9B_Ktc=EWz_2#o|5>M z@#6!(Z)Qm>?a(jZ9`%X!Z&KiNCQC4q`WM|HZ+V=LPgV)|P8lJOJkDoue9Lo>^D8D; zcfL}QlSPTJM)u)-sMh}z-<8`oicGokM||W+=2tz_#Zd>!FFSt3H>Wahd4nDe+%>-P zBfc($0Zr~A%n2SEFF(%D8i+)9f^Qtgd~4Uv@mE6v8ru1$+=up$N1<4NZk9_SQSH>vd4XbhssM4EjZdbu5$^PeT|@%g_nH25%2_^dLEg0OH8R zV)pHbKm*$gch)#E(2ovi!?glsAX6f~uEv2tFyJiOAgi8ckFBovB4DrD&w?x~X_tX8 zfvO5_2$iuckGwF0Yk|jw?k#P(Fr=ak;xQ;guLur#7oA+38*SvYxE1`oS-Axl5W=+Fnf5xYEkpv#3&3^X+4)+^C! z7Y<*YRR$~Hf%8a)vT*y2+Rw-Cr;1Oeo%1vhwDOXuI|O?$FEIegJx_Zu2o3gvJWCyw z;PwXLiePy3lbVLxap%^koq?}$y(b7ff*!ljEh0iFM$JserUDdV5rbWbroJVFJ4e^5 z$@YoV)Da}V=q(6+4ry38w}8-}oEnM~)h#=o;2A*wZ+?Q$9?o*gLx5ozF?_cim#3cK zZ)Jcs2KHTC1r4#b9tsWvR|menC!XZh#vCRrUkW}tD$qaFiwF3Gg~8ba@qoR?+*DVA zwocq(CP$p)lNN*S7foIbIq7H(dNFB)z`<4>lN2%5u%qKfeaxWfi z3;K40GlK^^QQmu!Pe@~VM4*I2VR9E~uvYovN#2gsC0aApPObbgG{%{OjbkvEerNmc z{xScRfzfVz8X}l(dHd6RGaiAJ0LU?>Pqefge~M>juoB81Jf5pg@vM;yfzw+^uhJU5 zzi-DWel@lK;!pW#?r%$!zyB$}64N21J_N^KcuhcxCd#s(@!L`C=Rf145&!jfKjUv> zz-l4ZlD?9`4jO&up5blAFy^hq#t}1$p5=AV^1q-tRdR_67y-I6QC{;LZ?OhCIP2_l z{7a))u@$C5<)Wp%iGACj=l^2hAgsW46sz=dn>{8szsO%rXXQ(G;LgD}*?FZ0>MSQaY7XB1KplK0)0xeq7E zKD)$XrSqTj3w~!h9V~oXR5*0V6MX)@=YPSIO`LYex*MRK-})t=n#qhCnXwNj?2wI_ zc!rO^^v2|{_1G?FM@ym7feYvJLO)LZ^URaR9^vUbbp}KUHuCT#HZsGxH-Bd%KU5H3 z@A?1y4uZP%DkU!Y$*&+j>zCtS;qw%oKunYE!HRIWhvJ|Z(1F_e3SXDT;wX*{qVMOg z@DLxy(kls5B?MR;mF2(Y@1~JYB_-I^sVC*4*Z6)ET!BcLI_U-Z_G{cbf@Lj(s_=Dy zVpRLA9DR;Y%Vx$S%s2$IkrhjK!jB~Y2w;O{q21qi^*R2saTz1yO4YAFjr=U6y(f#_ zgeGS78~phUmWNDx1Uf%;nA$42;!S=xFcRcj9sA{<-sJVmm~kPIrIoMIuQH8ujq)RV zScq=5D-`J_(1n0g0Pcv;(S*xKer5}76~2Da>aCFrUgeqjP-j$=*DeLfU;8;Db&G1H zqCEC+*jh>@q8<*=c!vLpZ%A<<1v(VL-KCzp5RV6Yjqp?6P_or2|#g zh!urYYU)CuSa0`EFF4(x-@1YYY>wfrg}cytJG-uXCo=1GWF=tH%9BQ6i=9kZZX?Bk z(7pkIUWH-Ks<4qpVyWSIHckpAPn?H@J+<#uXxj4W7&;ikS=K!_>>pkqH1sq81FU`u zkLnGw^dqRXKKK?-iNOr})sd&(;!^;MR`&#Zf=wC{DdP9P-r~CeigY^h@(f6czVJJK zJIJ^4P?+e8CTCAZlAQ5-ejcZrR-Gyk=n>D$thf1$k<4p@a7rDPB;?g^^W~uRmRc&H ztrU+tS}P6byU6fbh!KJ_ZGq7qfq6$LYjSQ_Z_U1fFr8+22dD?iXtfAjr+Z7TGGW4k z&LihqkU`OlOQ)1Dy~c=E6YaurZ6;=GBgpVBZ)ad{~aSx>_!lx`J~xvb`}jcCTg(&(JflY#aLnN>C%wVU`7&C8l3uk zRBUdd3tUFNCy89dZBhe|J%I&j=sNto093~?bt7^un-_ta$)rv#*rBNz00T7V1R7LNQ!()#YJMy9MWlS7y4p!wUR+hO za-m0>TF@&;m^V4h!;D=(l+1U)9m`IFlQKSScmyJ#NN7W#+3IPU3Igh}$H-2KodqWk z@+U1~WQ6EffJT744yf4!T3OCZFh6w#o8jfNV+R2{08gBEay$zMxMaFa?6hK(Zx7N~ zuyFHN8{Q&a&F0SZkZlc7$g$PUk4-1gWd!eNn>!}r9QRVgJ4-jB_myfZI7-Wc8AHrY z!wI(sI>TGwqoqYll}O}dq1~vU`A1k)fSF)Zo8g^ZKpt&qpj25q&IMPa+Y2?x?g+8( zV#9*ohh`t+%%RqI*VJ~@e!4Xp( z6L|nIi~S1j+yd|5wC!LL;0Oh}yOk4+JjHDZ;wVrbaEyX835PyG+#URL+$YLb*92S@ zRW^DguypFB>VWxVBmBQmBx0-u3*q`9;B`m)v~G=#sA6IA`L0k9Z$A7S!+%bobw?nA zSF<^&;Ir=|A8?oqDVXI zX(nIG*u}13zJ`%%XUOpqJv#BXu7KeZl+pVLxPmvQz7PmUM*{`u)Vr@WKJ?PntC#6g z!|_HIczwB7)aMdUl%C#jv0C9~sHhf4W>+A`|t z`@ZQ>+Zh(hZ$?Fu=MnF6c)3@HPjg7T^{NCQ51_EO1)W4WQ3VVKf}gPH|d- zO>ieg?9*PK{OZU2L?bgc;J`$w``(JCmn>E-rU&ptWLAu}A`sQny+t*EaIQo|Xy@Y~ zBJ_{%`lG15x{q}IwtvD4#PbRC50jB84Fh7li(XilZJ4$$|vc$VNogi*OqtR(<#4ecB*N`Y?2<-Hp zWHAO>bA-u_X8v`du5QE*P_ydNWz+iJO&0r!FL+z3py={cRQDHaHQL{WRB;QaHj6Q| zv@1Y^_}nn@^%3w|u2xK?wIxa4aPed|tHEa&-F0uzSgs8$IG&Hd{gUqiai|61xO8XKkkVS9F>`R(MQ* zzg#|6+?}a=bOdHVc}!?mlKksfaSKZC9w$ao>AS{>gC)!hw7M~fP7L-wF`;W93Ij|9 zmTCTo}s5l}j_#Md%e`wwA_gX7pTQ5=9^oeVHrqwg^-&4e8Bv4Z`c!h%(Y#lrD7ltVyCRDDNd>MlSFNJ{GTxGwk%oU{>Y=s(6IZ^Ae ztOL2?%xFb)f#=)-yd_Adj3o2^zAsJ}-#5xxiSu@X(cn*en}Zax*pGpRFu9Hj;z8L- zA`RMlAjJS;F-kZrcNdFv#7`n^lmd0#Yn3-6EZ&kWJ?&e={=U_D;y(=#yaxe`OY{|N z?6oXG`{8!PdnJiE>5ZwkbEDoswG8hHpte9?l`IJl4X|5~PGAlZmJYInerp*N5Dt2r zx;u)!^~*qDl|VIdA%w5P*k%S{Hn?v+UA-VMtY2Bh!1k~E>3Sthqpu?d6SQa zSzGJYKvPF|ezp+_83#1y=XR?3^^O){RHyHJkuJbR^oujvkZaVhz{Va22QBx2i%0}AVON<&= z`3F!n$aAcbUydylxll7$44`mKRuqb=6c&x`@t8bNDAq1xasD6uY2d*y&;R{{J^P+I;Rvxre~V_Qd4YiBQn%;BzHQawTpf&)Y) zSm?3F*gOj{`2bJEx{F#@13xDTv4cU2jR6fpkzW+( z1D;RY9%Cs*Z~!%^D{uyX5n}U@wuz@hP{+cDwWz-V%mqc#ljJIf)}t7X0io#8_VxJ& zLvc8CLG()o@=%VLC8n7ElXC7Xu^FOOVi^KG(9%4J>F%E;7A-eEA}NDdu?(=V!otRJ z#(*NcC4i(;vOOwNa6vk~KXmf9+xTPw8^PpTvqW*isif0MuhQDjl{K@)tx)>{>J$!F zf_V}K8bdF&ct;M*7N^HC0|<>_Brq3AgUCN4n2<_<4wD;_2K~NRJPbiC3XpsG?Iss{J3x?90V0pt@j&Hf~i? z0~*YmnJyW)T>KmZEw_RvXjnvfemQ@c@LvXj6Jl_Kb_=X(R&AB^?eUA521d|>86-fS zb8?;-1sU9#c_NU?axfh&mhj86`J&Xr%4$&6Nu7Lhwtesho>brM()YJ%!tnKg`oULi87bx=0i zp%OWA%|cN;7GYiR{Hoo+C<)61n_Lg$?u9fANB&ko-PmyC2go1S6mG+-Ue_I>Kzq?4 z(vN4PQ6)yfTa@sRZE6TXRyDK?hVsB7>P5GrU~+sjl9y6GTycbY+UkZDfU_vdr}l?t zVifX+I=?G~uzH1?h{Mh76U7g^|=1VA?1iEZr z5|6r8FH2V!uwOi{9@IwC&B29>(d66deilG#2=Wh1r)vpQYzVZ{mKNynFzy6VsVb8m zK(Af7fQ@p@pEP?FaAv9B@}SBG2Z|mb zJZgg)p!|hdoHbc+Vn_o_mq0X6yqI7HfyJu;ild+|k-)IMxZQ($pn`W*p_9aD6GO|X z0!gf?4agxKsUiPV0avtzq2*KoH=r45!+^pX(he2)e||#)@i#OQy`ld9gBzOhDK~T! zIBcu5MABNnbjEV7wjUTH=W4mHN@SOnK){6Cb0>~&HeI7296dR}2-HCTmf)0SF!|Fe zk-Hk&=;A%E;(L27q@4uNmKGp*#&}qo0svYqU<5)aZu^srX#)d4Rb>?0B;=CDO0j+< zL&RXE;zL*dpn-@Xp_QVFSZf^}TNNNkZ~^CedZqX-xb*uli6Y=0q}4?l@6MF>Ozetg97QMxsn~i$xC6do$#0 zG-P|IT8dY%^zP~{kqCq_mP{<5l=7@sv)=A*RdYQ+Kqms~LVcK+>lOz;)I1Pv8~l&3 z{J2((m|*urynYl$Iu0$Q4i?!cGuDZPF1u;Dah;ekmX%skBRiR1L34w7*420KI&fO^ z9`SC(;(`Z7M$Kx;H~TCp@SybiT>0|V;;IN+0k60qLGTm~Y7`eO4Om1pRq;3+_sm{= zObr*103cD8Si?3o7vK^~R!oa(3$L-^%QiWO z71widy?7#vHC-a#8h{)Y5T~#;Af^8a4J=~B>JTqMGp&~7-Nb>Rm#LF7t{`3r88Tp% zm41pkdz7Od4LX>}A;?b(Jg}#zuL!Fa>7c?!B-9E_vH;xh8e~FYrkiLSD;XyjnINd~ zJVv+Mk~OPWpB@ZQTQm^rA8IPZe5UJ8!gi(mQc+dCYE4bq%9{D!dPoWa5vYLR)lmeM zs;Nc3gpF3!uC4JdUaE#kL!GWv9OxdA0C9V8x&|TzE|2?_&oAq`Zut9O9&zA`Blk~! z?o|4%XQz+-&Zz78lgEaCIHnxRZ;e~YQ;H>e47<|QcoF#~f|apC-y8>CwuDL&%?a&A zhf-XZgJ+A_>!Z5?R{7v@j7fi_epkbh7;?o7U%r!W07qn0m0= zg$<~~xK=~2#>`SGSHQi^xG_L?%j@VsjRC=08i?(tFcEEG;wVzUGMW5UK;(!7x7#g0 z4v5?_%n0FnEKLB>>pY)*S2T!)2;mIQkJ4MQ59O_m;+O?E)fI&t8muW<)g%@}O?)KW zF#i)s?^y5%9%&K?u-YW10JNTI5+BZsYQ`(WJcF%H0Pa=dwWOlnPGAx^D}K#HvcrbJ z0?{p9&7vJTf@>}HBSt|`KHn^U3JF&^j7PxTt5MN_K?xzqX^S`lS+!l*=3>DeuN=Qc z+z)tva*Ke=#=h6L2u`BW^Vf>8<^p%$N7q6Ona!#Reo>SfJ8Wzi{-}YkB={@beFs`a ztr3&A*FwEs=@_jg-5tg%nB_?V39wq z^d8ua7a3mpr++g?N1zm^o?Vdoc6D4%OFjrN7uUQMf~J7It&tD_CT-=V-)a(0#s))_ zR}V3i!16^wrFBP|hkmsWSTcHTuZ6S}dzgb=jHbse^z2dZuI?Xy^B-6HnbOV(cA=)? zHdP0^=x>)lO&tPje`%w1ye7R+AaJVOXnh>?%Xf>^>*rObJQ@wyeJH<6X_;mqo_J&2IP`<=ZW}f%dqeaGRmJXnX)Qa&(axv25 zCw3r`NjIxOjZ$ObWSM}+lpa06XF|@^sZvCMdhBqL$mR_evPAAcbx%nZNo~&3iHzdu zz4|rN^g2k!F0`w)X4Ok(^{TW(Nf{mzT%80nT_OkS3rN+89x7^_-o3bSM#51QDzs}) z&3bslq%T0)qiCUCu^3kN5Qhu2^ZfZ$W$U5lr5Ypp7E=RCpwUbq5RkOMkPW8AdHtH) zA+(QrrwgK*prUJ(HH(cEN3It) zLpBklOOwr{>jp7Cl2xiaQ0rc7X{!dkAe)^scJjCZbl<|A>b2p$avczB0jsC2Ou&@@ z#twRMYcSYJ>jfPu5)z@hVj+jILv#cqkV}J_2|yBnT{H=`%nD#AwYiX6esY7z&1JA(v2&qk5^jXyJ^|P8x+2Be zK4=guNzF9~m`sg$72_LANv6HzIG_3lLD!-qC|VIvkho zY|zd{)!)|@DotJ5QV=xZ5R6X>SoONXnvQivj;1P_G#or=2$oKAOmqeMUhO`u6+YGY z>`NPhY*h7OD`l(3@uJkPD^%vm`ikwqcM;e$)H8M5W*{mj&4Nl%8x4SvK=KJ~CpQ*x zeW3yv?3O||dqH7Aoq%h4# zc8hI5L9HZPz5^6=_UFVG#^c%7WvvWAF{-IFI9z4&^3REh^3R_W8=li3&1~Y#9aZXlZfVWix>wD%UIQD0jxNU7wlHjmZ5IR@YXLc zyH#9)vru&_PLY64+^ynw^m&``0?VNq_&RW#$lziRm;JYirRg{&IAcN3Ob&gK;a?Q_ zc#za?;*5uDIxOw6)V@_;6#GqRX&_Gr=^}1{{Ogy+)u8VWgJvq$t78rNVq)QU)y-5o z=nB&SN}(v>=LhY@fys#ZmJ8kM{Bp#TzUf;v{^D%sS4&ew3TJTLk3<#`QebEVw z%%883Ka>D%2(Va>dC)Egcf!E}nZCgGrx%_NV8#L%8}78dSInQk3^A*kYT>>N#!t}| z1}_GKQ81NQc|cCd?}R0c2H%GE1K1smZ=hGhx;sfH;7>p8$_7m-1j`Tr$<=0ah7?w1^$%z!6?m_W{T+Aq9A0EHpO8D8??r z2MA3xqIjw(irNM2xK~@mVcHr~BV+-q)866WGUHIAGO;cTnAg@OBEWT$Lj;)i0~`#^ zf5C~vDJO|QGt`87v7_X$2TK$kNVp(E9(Od3V%>0(lK@ZIN*WKiLmlc71i#fL7-E(6 z*p$MlHl&D2SE6=%AcW~)(tD02?k?~yC&SHl#kC`vI06=Y4^9Gxr|hZFCgukn9BrSb z(&~_emmt&#jLJ9!z}JSymE0F#&9Jw?tO>0&SeiCwZ6lc>kdRj8fQL>N5!sMb(wlFu zG!A*0x22;a0;4go`M~9iU0xlt0);IYF?a)%0-^;Upyj0qFAPPW^s1$mZrGeOV48X^ z%G}G6Dqw1$Yi!#fV*5qNYz>FJp0JV@GRmlfIzTsOT58kDiX_*QgaiZoOThMTPBIiV z+fY=an&_v@GeTZA{?Uno(GYDpU&nX!V!r?QY==%ZV$Ie#2DB$F#hdw!7w0s+bl1wf zsw?mQR_JS0$3MBY_58P9dh~{l=gnVK`mHE?2-HXNS@xJ)eAjE64iPN0^3^Is;~9G& zJFYOU8PxnWCw4?yk8ZwuZ^5)ZRrw944ialv#p*)@!!&H8-L##IodVb(>n@eagGvAzJe=+uGN0Enkxc^0Jjdx<%^H5Msg} zuxTOBi;+JB@Tr74F;Gv(L!{WmsvPeB;6+(>Tm|>X+vXDbn z662yJdZF<@07Sd5q1*akrSCvT=B-OljC=H(KlN@tXT`l`r`)gyx3^S{s-tZQnt>%U z@#~$32Jj%1uf%4tO$FNN#Tg~Xgobucm(T5=9ziYPpK&vd zJ;>w@UlCW#RAcwn1j1Vh(^1XbmaMd7Akiybqdkd4ncaT*+pmyDN}=8F5?HMI=~H8Ywc6LkHK0H2RAPncVfy72`(W?I zW1+CC1WUPBvaunTheJ;IATkPbLg zTZ42%*TQWJ7XL!u4flvNEJNusC3g%qS#o@6$()r3_KRPG5_<5?Zmfb6+x|s*a%$ijd7i7o1A|o08 zdk9oFH(!u@?iIz@<#ROCYhfUIugHOmwLjb|0+%uGx(-k>q+Lgs?R@fEa?=6Pf^l8I zxGpBJG{?Apc|a`3@}e7DLntk@h0EHA!cCP02Spj3@=$xsGU|qd;!1V$cgE8G1!)+` zJ2aB5P$j-kjGrtns8gG_IMBYetO+{9$Q>*C z=>n9jYF`HJSMpD$*sCy%DOJ`1^4Ir?WaBaUyZc1VNLGv^A9KWmxN=wCFLEb9Zbf)L zjFqf@qrFD03`Wau-!IZz5XiiVu@!dlnw`sndXsgAaginj(4!8~;vVd_rI!8ANE6$b z{P+7|nQ&ZYeM>YBW1ec#Cau&fy z-v_egJE9)xq;%UwD(;|D02{sXng_+0zCV2je1^+#BC&6H5O56$?ig@5`hfU6T>hx` z9j<*gJ}Ab@7akDXVb!YgRso?W6C21P!F~;*ZHY2_P!&4z2+@ZK!B}mwc>2qO0-jHe zVFK0xP=|1w%$?s8)sQS&D{t?neD!-`DURS`rJ!9#y7EF!e@HCD1=4A1g}a3O>_cL? zmI?y`P_Ptbz$ec z@Ea*~Ms@5{QU;+*mSDP5?xAEq2^5u%h$7k@3~D??nV6%ST<;G{f%Zgn!z-Fxa6Yws zP1(xw>N0Ok0WyF%xV~)MT8Sq#TcpXOU*Mxc6Ga+i4bUN23oVRwnw>jE_+fyFw3?k(O0MuD zCMHsr!-xQ+f4(TuCE(>1>|HEkktp%066(0j6KQ$sON$m4h_rfHx{rG@%S2ka%CPYk zI_(u=wU8e_EHWt&N9GYRWelsdFz7nS`Vol(*nL+woGjKJ5wp`-aa<vC(9mvg`*UYqTp(h2bc)bcH}%g_^cx%GZ7+mi0aIh`5Wy z>dU?_7H3qJU=!+;HX;T2>1fVQnV8b|&F@3vjw1cXM4{{nR!xS%}f0feXNkWW6+FQ7KuFXk9> z_2VK#zR@rIQ(1W@Ugd6titebh_%5!jPSnBV{T`jy-!DrZ6N}K#^^b{hBm6nAldDq_ z_WpkHpfx0g-?py za)xM#m<#kR>FEl`^5>)g_Tv8HqAH&YB$S@tv)XJkzi;2T5UR{@3Dft;B_5Jl}akmMGt!vehGI5wyrN~1+ z6Yn7s#elc0x`KE?#HE0~Ar!*F)uXXY)MT0Ma~J%lC6J7yX5mdBQ4xc~;@>?Zrp{rA zE2+3ob&9GI>FUqwlr(_Dr8-9uirO=X%EX>5IxRAJH6nv-I;{}MBd5hxp7a>cJvC}e z!zgUXvtr6bR@sKDM)qI`7F1^qL)hc-2UBG2v*N`JRvs;8l?k(4dHHkV8tmM`=UVQE{<_B+6p(=V3tXl4SUSv&Xl_4wKM$DCUSYWM)T!o@R%4WE6 zeqOAZ%t{&wsv`W0&I!As%RmF}O+jRjt6mW6F@*bH5Ot;p?#Esfb29d%xVm@NCi>K} z)ItAfOUd4pzRDNH6Lfi!UlQxgR3__R!r7`$lefPlipP^T+!|2kz#o-5q<2S07kn^4 zFCbKanVow{Odjdd(WE?SVX&=F^L;7balb66MfWdol|B2V?-!y0pI`h1KoKf^`xiKI z`$gX~zYuLyOhL|@21CvVqL9-D!yXsHz>;v(7YB&HdbkgO_*oO{YD0Kk48BPF&I+Hw z`rbGzo;7H05B!<{hF|{6uaz_;;Wg-Z;I2-4O-#$LO|(ESW91s^IstBK55l(V61j*f zp*yusg!76RtGBx^WRaY^yli}Tmeq-kLQsB1pG%)ut&IX zq#-1n=ciNHU9XF5ah}&E%89Rw6_c0`IB}EWkOfnrL8uUYEPiZ4cHNgTjQd{~lXGHO zS)V6gDFV}&@YP=S&6+{Uf+J7Y1HRn8^xA`kjq8Dei$2a+cx>gnbQ{k}GsTf}v zV;EgCz~F3cHXkvH=2p+w=aWjbbXr@JH{{zGN781C2aTlp)?&=eCwi?$THKuP44D3_!;tDGQZ8+ z-0W+w5BWkNbl{jVwW4$l<6uF%zuDj3scZN1ACIO5LFQ+5O z>wM$oK>msEyPOvA5C6jYlaKko|H5+k zO=r>vbiTBjmeYMYzq6W_(E~a^R82?FgF63nH7%xxbnYI5-@`heIfmBIBRbzYhEAr( zb^i7kI)t9k`M<}|N_tY~qpqN1^;0^zpRc(*E`xvj3YwbeoY&D9(6!S#|KJKbl%CPK zb1W^_y>Y0+nFN}}myf0S#LsUTORH&19Pc{MviPyF)J-?U@n_GoOrAE5rjo^c=s4;o z*?j6an%`$BDVyvMwRzhcn)nUl&=5`h$T*r8gFioxE+878HJ(n!&)wtc82tQlJWVH+ z{M2}Q6@E&tq#4A`uey>JlL3ewT&#gMntvaT3shD)GnbEgSYh4-8#0*^L z^RH@Z_Yl`2`GA4Z(CiI`mXk`8!ASzv2ukV<)vxsV8i{i@9yM*bER%1aK&wcjdj9hS zIskP^s-fAWiVv+p-!}8bHFP#<<3AF}cK%8YM!|aiNe!JxwPt?pL^`OigE%^>#Fz{Q z1Hq~Mn-l3!WO#BS{RuL(PNFlB;kik4JceIoExi)Mp`(^Q)9+@C^xL%CFkKzDmua_$ zpDWLFyJmN+X!bX#X+GB1STSl;dG(kvCiYw5_bOcc+9|Ye+T!fm*2cg(U!#L$dzIwY z_=YJohq(BCQ|KJD_RV#4AfULb=$+{rDVslLOjN{c#L*szQXIO9Ru1e%p#&>Wo{Fgw zCB1GcU1CA6Po<4tUbJ@_hSy#EwrO;im2KkHa%>pgXcl6+OyH;g8hOF{wS9 zqAx#NM~C&G?Z=1Bq~0D#C;#5eXan^~OXZofXwju#d>OyqN<*I|&!YMK=q#FcY4SAg zm`y7O#Wn&-ZuPB;MWyrWX44XW`5D;>XXnwW^zLNdR)Kl{_XV^#r)Ncp$J@}};cXTZ z#l!J;t95NB z76L7~Hi*@sNz;fX5Lg_3$OkQ@gNTDax|C)N@5Q>iqjfD-Ke6nW8RKHsO1T>F&z91I zy*icf=a$i{$)jOsQwG0kE$w@`1DeSS@2XY4#$+|rdd?Zlh(Jpjabx7o6PlBpMPFMbNp8}%VUR>ohuj{2}#T*!oQon4QG=t+K4J^dc}33n~0Tga2)n%eTgIvE=Z z_L%TLfsA-odsfH@?FH=xeqcGxuhL9ihq%Pr*dA#2Hos_7fRY32TJ5ka0Erq5y~2N! z%SNQU2ra{5k_vY<(Dtle4enkU#OTHPeT=&svCcU8=tlYoeoi#f$E?gdee~}Z^yEr9 z)q>Jj(R*FJ3Qh~PdqYhc|Jf>fH)t0(QGbdfrmn9w(d@3C`I7bT&c{lI%&XD*L!p+g z^9CD3Zg0@%Ugc|V_qVRXs^o7hoxIT7?3bG2?4WODXr8a#L5z3y9D!+Vg5q6L6`Ms% z(Z9=I@S`eDo_IZ-f}h#f(@OFO{`KqWEI_}xo>r*I`eyid`$~xx?)yYZhGy?&ra7Ur z`@~E;#_&p4; zW7;41$<=f&`BQk`eiyH6#+Y~U&SvzYlb>vs>(cpV$PtaFx6oRoUE4zE;pg!dx&}Y_ zt#n?dlT^+Q2HFB4Z}T)Url9JXosDP&fw2BNLe7XQ7o(y0Gb@J5LY5x>7k8gdOKj^FXwks5`YJ|=W&NzAg8YnP3`4wwuHvelIEsjB51L)p05S<_MlN)I!FB#1e`Lwk(xx`s8+1Kn_ z<%O)mZmLHY_eAg)LUeH|Iwh8lU(rsl$}uNvkG0*oHqh?-jOTaIyjrR^*0j0}4FRf^ zx7`gD+ASy=ix=YGxxSVFHcS7xs4S*0uaOy5F)Mt&Rt##Ho0mUWov!dx$MQz@!rJ6pws!?4mEXRZ zqnh?t`SSkqRq90;wrF4NAAH|T$Xzsj9=e3wPK$Zz*J(Vt!0%s+@kqkCX9w`ib+kdH zmSGe;zK&jjvDA7yt>k&@<+MV+*p!e(m%Eu>|HVa*xq}wb%{u?Z4fIw;HJsmgBSwy7 zW;lQ0Ml7=iW3x8UctQKww`diA=bLnyN%ZrZ=;BKdt-A!SieK?HI{lIf-}*MKxMafc zJLyD~5L?Mg-tR6t!N?Nt#K>u?(_+`usnSYA^RoC z-7Jr8R`|>GTzZdqyov5snB=%TeV<8rN1R*VZvsj2dGwGXy33gmzAN6PUo_Jk2_8L; zlDA~}cO?|*snp;n!%+f`!h8E(7ao_G6y6IkpN4a`ZEl?3V910^q!vG9|e}k7MMbOgRSNJTnToKBW-oyHdWX6P>&v({JpX zZEg)m>9U>f?dPJ^;_+sEj!urMIyj5;1v)t-fs9lS?a;$pQ?3i|NF7EusK?=#Wzj?u zzUs0vQWai**$Pq?{_SOp@I11AE&lE7{|ZeZ;fZNASdhcFrA0M&h$>(3-J1qvW`pc?+51yxmP=>k!uWsvZz znWdz-`}52OCVIOucPeC1cu#H>9Yw;ep4@Idj}i;jJ;D6}Vbz%MeTNR{zH*RHrtKO$ zVtFBPOlu@11go4ouyUo?K?F;PKx)JpY7VrQ6XKkQUkKrq{$QxRzRBkWO(7w!sq#r9 zl_4KYU5&j{v_cXtDHuM`>6|LG2-wJq+n@rpq7X5g!hwQ;t|AmPv!i8&F9^dBWLvwh z9@e4u%J2gPZZyhs1q0K@lBjtHdk8Jwsg+h@;Qfgy4aZHugJ;SX2`hE4S0cc|AwdaSp)15YrL)q@MYQj$tmW9U5qvJ@p zbZB;74IyPU&COz0Dq0KMZcQ5}yREEDt0Cc)L)*n%{O!=``ZPjb2|u1YAbh2#6y4R` z>d7R%kgpg077Z^Ko7+PR&7FVwLwdmXS2* zP@?n7d}})VYXc3^E>}m$)LI)nc51PECX7XOMoCYPNbN66B93e*Vq%5VwK*hwVnn;{ zBV=p%cOxc-?=2gOy>-}GQE<)e`a-gR=<^6R#Aw1GG}XrXR@sY20~5Eu5giQ!((P(6 zrODCbMQ?i+7Q5#aLH$s}#)i@skno!F+%mIL#qHi8)I~K~AW$*X42*i0ljt)wZ3%(> zz*Dvib&OgK=J{8(dfPj&Ptlg47uW;{TZiVA9kM`h?XxQ4|DRN(rFTVaD9um8n=9N` z{C5>;k?i>edus^H9TRB>32&`;B^aBK?ujFth>3HGy+Uky_)nGhn#pFC2S@c4S@_0k zlF?_i&(~HDg?p{f-TlVsYndX>NHA2(aNU?Tx{-80H)ghc&A$4KM6r_-R^}JO8f||xg7{Wsp zWxBS37)cdn%Y=U4i8hYk2{Z;pnj91x@rdPh6Oo4R@U2&tiN*2BD=XYv2+78N7cv{u z8QTvSt!)-!tsopXVN7_!gd550;Wb}R3%h^q2%nnZ>e4C)4|Y!qw6rz*)?@rHAtmnR zvpnTR%S+ug(!}6y2!z_*jXt5KhuncyY4uYh8Zy|8Rex1`lXzNgynW0VEEkyFAy3hA z_qry3LzCMda=YCt{p)>=rJlA9%#wPsqF~y;(p@oeE9uF^xF{2Df2-Si7c#k}iT%Ij z?Yr(TSSK10;chzC(gwZ;*jfBaJLEQtU%w+v8K&+RK#*!sc;z)So#X;S7 zPiv-h8|fx9f|Nc$!XGWnr7~%7_^FxSL5j@2dR7Ki=s|qkABcl^!h7eO34gR`O42ql zGUAAayyF)Sr8^+S7Z<~r7Y;8T3`iPI!@pcSpj0Et&be5$ghnSMkFV!AhLn^WOpLQ# zq}#pZp9Jbw_lj%F%<0_yqd0bsSED)TnjImU4&)OHOW? za}vgkE)KG8!ZyAYdp6VP6KhO^2=I3Le9}JCy);ly$&203uF0X7z1YL*MrVXS3Vk;h zlXp@_5b91t=a?}q{#JiWM@zl2|ML`uceD@x&P@xuu}D$$)CcRfGV*Tth8sU6hr{FV z&guTfO#>NuvwM5jLLHXV@ZWF6RtgEquebwuWoBH0?| z5puHou^;>tPhR>{r>JS?V7sI z-`><1^scMNMjzTM>`@RO_=P$eYgN$Pt`wrywvZIaf>_w8nthF{d_nh$PPbW>zx7_SX=VAb%3>QE%+Bu;AGAsi1iiMpU_-d1TSH4dGM@qTZkNJ4g$=Wi89 z*?w4Lg-MBrg&6H1+L7?dCx$xJiIH|xAe|Zp zmzaZL&yy*_ZUQM8XoD0@h7zl5E_u4F!Bj2`En<;=%SMhlA4?8x5Odg0e%vA-dW7_( z2c~C+6IO=8V?F7Q^&&q>_>Oc|c7>+T6NbW#&Op=M#P~a_UYLFkDyw+odD|P$g_rCfTJFMLz!YDm ztz1oXY_zP2hMZ{sb40rs-n)M+c~RIAGm8NF67w!pRFc>;;lch0vbo7_P>O%S8O3Fy2#DfF)wSGgvj2h0mFMD~vPA+u6@@j}8 z-`Lk&=0eo`S|u5jLdks9?qlWgr#J^Gc265W9vU2sp0Lh?gS777{L&St@ZrUg*_5u>7DsQ>iewWrQyrA1d^X^Pd$EVPPxM z(hWAPUgBdZ^sO(jZN?DB@ zn#{eMVCTxciY0{WJ}}2c__hzWt2WCBkN?w7v)MoY(^x}u$q3K>(1AW#^5O4M4eyx& zI@U{f_ri~o#LDD71G8WEjc0aR3WC^N;9RqVbk}^^0h7f4KkZjY`Np~Erduuyfq`N7 zg);p6&V>s6n{qK5j1Ie)1toCG#W6}PydEY@erK3wgya7u4*!IG{GM?nm6p(ZW|J!H zpf~<2%g`Xh&;P5$AoqP69zwMrv$#A0I^A|GdKd{B$B;=~JnBvpCVvu}!`TQ4@RKY)k zFTI-%8kimQ3EN1>IP!PF=f@vtR3*g2duIum$Ft)}USu638)@}eVUQ46I_qT(lY7`w>%I@sInF zBXDYoM4V(5A#X(TE+dC&4y1I|T;D3JwLx#tP>Ql!yz9lW^oviWlcAVO5zj!j7J6&W7$-HDbrkv8pBN>@wkP!2HY!=BNWs!whAd>DT&>H1STnW;dt&T<}4MN-YK=RuLlNZcfOAE*+My`w@ z(lu_qZLf{PdDzyJEz6ix{ha)cp=2>x!rvcCCd0Vown&PFGSWGXgdkg*8{NWQfemx0 z!{_$E$0i8N7;Go*wSKRAl~4;?#lR|pN`}U9FZVV!)(hQCjM{o{M|)Esh+X`0s8P+$ z{8Z_B2C|)%t?^{G_9qQ;D7#L1!%p&Zyu=Y16C}}g6DQpvFtz6mAgj1d9<^*bc z0slo2nZg#3`Mi7>aXDMTS+oscN{Ad8hT#tF_s!wtQF1!6u~>oMDk1e<%hlObeWSN^ z6%H6yMJoguU@~@^lHvtMJ%z78x?=%RnwFuQiUv@_T57PNHtda{iAs&oJX8}ZvAZ=8 zHTIRdYuEcjWD%8=cTN{s>#DFG%3SC;Snn;ElqHmmaZT$^8nHYC;sggATYBZP_}}q^e*iHz#IjlX$}I)mC#5q za|lqLg22pSKyC$r8EEDC8cZG7B+g$KfXk^w4T4Rl$!kJ`wSwush6e9y6H%ZQBYA!k zY@`a+rD=tlCI$f$TE0UL0fq$!k8%JY1&^ZpnV^7KT0FwP7LTI4S-gA{oy`*Dqv&cT z&T}2IqgkSS6rIeHz5)OOcPFXIWqQD7uyPlaHcLnNvQB4rQtG zQS>IeOg@U9Wc}r%=s1=xA4RXR0rF9F85<}cMSn4uhWa~XZ?O!C7G1?M<)i2)mL(rW zAF*utC_0Gc$VbsTELT2?u3>rd@dzI2G^!nqS=nLP?YT=5R$T%X-w+wzq8k2$_fQ?x zj`Q!2BE>k@eti@Xj)8v~MP?VBh$-)6Z%yGO@}tO;+&h}&rX*+ADyKwYQsUnnP4aO@ z&G(EZd4;Danc!<^40+)lWtyPl8rf#A^NI|DH}#$yuH{gBZ5UL6NhUlRL#yDhzIe$vOV-aj20}!y>O&ldWHrw(kmZ zD%7_{Xkm^#$SWOVaqnNu)ntI*H_vYJS5caz#4K)jlj>@NZe+ zUD4d>US77m^ke?`7?RFEm_*zOD!quOPbQZuV)r_@ZJ>38xdjIAQM_p~8N+u^CXLQ_ zqbpHU05*^1yZ~pfq5?uy;eD?riO^4Ot|hMt6D_gF$3vb?}2nq4Wx5?&n(hL&hy;a=sG8#IGYr~j>ns4lT2d=5!pSPyoU`j zcS6GxX*=ga#k$CUK9`glBs^;#Nlvyo{@%}LFD1Nq@3fU-RSiM~#ecrmK*y>ksR^~Z z8x5CbkuDeA$b<9AK6-TynK^5I?HKoh)@EVJY8Qqp{0S;7k+2bY+tBQAfh%@*20CB> zYi@@B7P=PeHtb>ER;=Rzv94$EU5m(+2=uWCyCm~PeG0^4FOTwcUb2)7wAFyFmo$GVEeZ#}d{{;t)u1A#@o3%k`vaxIBqfv!uti z+_XL@4^iAB;bnW^p4yp7`|z&S;31Lm?W?h!JP|p*nqcE~l0VW)J|L$e-wu$Y#7G_y z`PLe88&pj)LD@US&On^j21BsA6dM{Pd{ANTm~2rf{kK6d1SfuTsh8q9yQH+9=*VNzT9g)SG8Er)t%xwTb5s5w#f#RZxuk7kyP=3EotO# z8&J9528=pn14bVOpot35bf)1C%SRE(U>g3k_zRk-4$Ws8{;>5cB83bIg_10T6)_Ee zT6}y7(@M~r9i*_!5S^N+I~~O|{K<^fB4afG2FV~w5Dh|Wn1(+|P%8*(1p)pO1frE_ z9nFNV3Q!&%ryK7f-bT}P;3ztLTLfT zRzYzO)9@#Y*d_?J2?C+YfZzc^u!Cv%lLWg2!7f1{6dVxj76f~khCfNLPY~=A1VZZp z!G1w-fN2NVHHzY(pg1Tfgfaw*LxSQk)9@#YI3fs+2m+xZf#9ehc!O#9lLT)Gg0}>L zP@F(;oPT>Ase~qRavkZ9gDV{E$kPRhC>-b_V{x@g`s169`q~L|rcGQ=1}(tuTsezp z8?)0yXeXK7*obM@Q_VRJJ|J{X2_8=~4Szz*Im5IwJhGm6&`huaOV?<{9>2JrBZ@NNypKDh#$@GadRHguL#iV8 zcanZoEd7t(Nd7E-AG(PQ6zl8REd;h={^m_&8_eMU=>*k?O=JKJF;g~?_rgD$G=*Mdy!aND%je!fMu_x%H?wrS z<-2#_WmS>=cMv9DlDZ9I6v?s7MEZW4%#_R;>5&b0k?+JH%EIKmIFZvV!OmvmHZmuM z`ZxEHn`02`9wgT>NXlfs@ofx<&vp;%?d4C4BV5q^u9@I<29V zxG&>tdL#7bBUw$xU%kE%;+lxSWywkC6vVeTJ{zOZo%XwU^w-Ts;php?2Z~ zTj@xHR3Eu`^OM9Oo@+jJMYcQ%HSfR62HzEaCW13{C;wZ7Jm#{RgLt4+D97&*l$>XN zLhfBPjmV>{M(I_8`r|&7@EVu37rKK`HAG982XpFzRIzZNSmA5(Hm?*e6J}Gn#Yrws z)r`h1)m($!GldK8GESa`@_6ObBqJW~z-xW~;Pp?Fx&3XtiSxmBU!op)@o939zyZwc zMB)}VNX7lkDt_;?WH(LG#o6dE<2Q3S?me!r7d;h9)k!7JFIM_j&1xH~7UW`)*y0ne zZb;@&93(?1e&0C=qh7imVb76g$N>Axgn3+aN`}t=^*qVspF9uCngWIxzZsD$Um$aE zQWfPfWdgtd5cwYe^Io!?&-@V?PRA_a*Z+)M&AWd_W_BGLh66*T1Nwr}9U5k@08XdH zZB4hZj^Ty)r`cz3&C>r}ebZl#-@1zY*1v;D+Fi7PJZ2Cco`pyJavS`kt|!bVi?+B z`>Dr$RbP>~FG#-5hVqL)CkHOGsM69Jad_l!;b+6Ff7ty>3IFt2(wD#gDj7Hn8yARm z*pHSG>+M2m7WWz40a&)gJcbbwgHH@taYMz86DB_v(oFi@&Sy>uUF=N}&>@ZXLkzeWg+nMAO`8}%>I`RcE;3cl!da?+Hrv){n%HG#HY z6LC%#nfVrZn+OrI=2n)$C%jG4ie1D}JO%a(W2F)YuhFAJ7*^)0%Nt_JNi?!;dmEA% zgI|_WdW?Lf!&{7Xi~cK|-lp5>zrtxOW`h zLcQ0bTL?7^Eg*h$$1zPSGIGCqoD7DGii4Di>21pFW1PH0(#Q1J1ZX8OZz=En7TBc3 zTgr{X{qK+=82fj% zq}jy}d_=N{JMz{?oqjXV{x!Jhly^5bpz{MyRALgKi=1@?+0xlkKnCJhd zyQzym=Ags+m|d;6mhtx;w4lEYp+G0MmSQvooicgLRIdJ`vZ>PX-8uQ{G zPFyYU>5=#Q(llzoc|EdJ3Ez==Tnogi+vIOM#Zx}R(RN)b{OYCWP!Vb2n^RHV8vcAL z9b|epME;#hv*JYI*#ptjGnT~k!Lr^ncbS^G%XHm6aXy5p@L+-GM~$!{dyyvpp#Xh4 z|C);y_lp?}eu>QGZ@cg^7yraXv%hRE3^6;w=srtc$GF?_Ycpv6mrsqaTGB5w(5qGa zqYRoiwbn}v%;dXDtX*{TzdU~sN+Mcrq55lteBz!G+kq`bTg%VeF@ zi%l;;(MA@bY@;ZsZPWj6xYY*Uzw)g%(EjIJZHg%NR-2iz*R3`)q1UZ8GvR;Rtu_&* z1MV_e^1?HJa4W7GRq|)IB0fYV|9C5{NUxMm^74WYaY2cN;dO`3M}CJ+DBl4AVBK@y zrQ@Re9!Lv$(|wnaiN;m;JxX5eLdSlNf%DvV;0m-GQ|CK0t52gDv;v676KDb5qw~@* zEg6Xda1$A}3fy}^OpINS8!|SAdHddqgMsVxfgs$L5oRQe1+1W8p5Zkuu4h_qHsS=t z$$yWs@gq(+6r%WUT534K6q5a%+(QQ>sA_KK+wVr`5aonoq``qm=IsOdWjf68vG>p^ zv1DodxqEQ39g{VUUwJQW?1}r`y>w+y+(u5f_rxvxF1^yJm&s5fuoxh0PU(Il*oVZ5aqq%9VGEt+v)iJJq1@E{Wd;l zJG6lV+i50Vf8E10BekbnL^A)^c4$p16)HpB4jBSMj1Q`%@UQKljlJI2m;Yr4z5a_z z?8k3^n0mh`)ydPoPuI#Y5h4K2=AG1?ktQyKukWl~?`!D5-DT+4<^cTJPC6?GfuO{h zSyOaP%PL{d zz#<^#xr!}8`GrShtd;kEAY0FPkL@^;YK%Ye1577$_7~BlYq~zWMyQ4B#etI8218-v z&fS>lhjpGe8^i97-Ly}pvv{U&U7a}93Hetc+=4op!af{VmUqk1BiJN5|HE!Nvv+il zf_7}c+X8U-P=`Gt7>SYL?jO-*Up+%Q^ft30aI|4|MAMJyHDA3DuvzdZ9nDwngrqy7 zi?g7)IY)8-#XMjU*N4#6cmceR5S~i;yYt8%+86t*m-gT$1wE?s4UePd$2otTzK!|> z_Trwli*MhHXd_W*!amxb_=ZlF%kWX+p2dJZ?SU9XdV+C~!$03g7qg?faUyiX6Lcnf z!-PJ20zn3x{K6A7m%fEiDBXxM^%exT?r=M`<2s+*P0P}@z)4317jTOP7k4kK`0d^F z9TBW)d?&cO=}Fo*qqu6KG%sUV3u7}zwBek~zyBm1i?_V@q>R6E?n#IrCttE3L35nK zdYr?5v7gR>4Ww8VU?>bO>=a>ok>L@U(HY3_z*C4k6;OFW`qRM_kOVzYHsSA6vn@>3aspsVN2jq;u@c^y1Aj!)o2V^ON;EP#meHzh| zH2%$}qqHdHuTP_CPuWby3CU?vbjy1vQ+eAnsK3S^dR}ty;4@MJ3CM1zbSWFBi~s8x zIuP5|0ngG2My41tvvF>DmR@C~*I33b5_PTaA#sUI&KGE>v65I_8;J})NN*IIF2Pmt ze^VTP|9N@=ZSdX;blgB&Min(inO=G2Avz_d63TF@@hyjFK5<1JKZMC{Tmwl$6{I8! zs%Zl05H)E^%(gV!YogWV2Y*I83T-L!I*iRp-f9`X=tX*y-4LAJpiFc5%IwIK4kLtz zX?5hChiUVFHaZS{iLU$)*1Wf0q6_Rz@wt~cpO z7*F_jj-4Oe@dE+&Qi!Q&LdSm#&2gWVOVK6(eiKv0`nyb#khBaGRuCQ~$IfsZJ zl!mA^9gyeQjW|K@H-|3jWVUf!KiAjR+&NjHaWr>ccNVM?{*dC(9e3zj{5UF` zjk_?;Fsjsf+Z_6IQmf5A5jlv zM$AP|w2hZv{}C2X1Sk4PhK2d)BN?jb%8%*gK(6~3X+Hk!$5`5YJn;;jMSXEHfD&&% zL!F6+l}hvTEoTt?Pvb|=Acm0qar3HAaD&2!UEZhgy!pl_Qp`O2i6}zi@_Ff})Cc0b zKc&+R+;B)GnD4d#d*5etW;A!7vvjuJ5@*_xI?h5OR7Q55rT-)_>uvuFhHxc+g2Yxo5T`|>#6EywinAAcm{4E@1@t=XqG@@C#!=e_s4Kbqv^zMlnRE3VjKoxg(BW{W%?sKyt}AhS?QI z<|BYtOdL#g2&?T<{Ec#2?5TT$cJ36$Vot)^?l|86pR~{wwY{#x#Q>i<#`nbW+5e

CCf#)!!5-7AIahCt;VVS3dlmUz32k@xOQZ`vv#BbP$-w-6a_EwBwKHgg} z9|s*o?D04eX{Camh~uf04PmF^2=8JzxSU5>DmxA6GsXtSVc`aah{?hqq^uCr;ZeqN zi>=r-m1~0{;II)CZ56H)|~NsPA!O#j=|5V+YIE-8^Y4t9~!R2x}( zdc2~`iMI&TxicA>*i(JjfXO1-BW}pG;6mCAT<}(ws+E2bG{_8$XFCId<;@$yjpdAZ zg41jHh^qvmxG_mN@O7i<@mjuoeOY>;@#Z4in+w&O_a!s;loo29g(Ku7rjTS}vQh|e z)F`g3d=Vd7k$6{OyjG&#HK5#h*Erj|%HuhLlMdotDXi~^QSm)rHY#3)&*@!DZB#tJ zVm=+zSBERL&)51{fDU2S%*%W$`>vfpf%{FJtapuPDG5ui+1JNyEzTmrpJ6Ra#3tuj|ip`%Wd< zGFrP>Z`Z^}I{UK~IQ5PfaYHir-_qE8+G!hVxm$(K1QE8u)&v{GYqkE)NWDiliD8q;4UO=(SQtRdB1G7m>xjqXQTD-EACXKI~7j|SrNTDe=wdO&t}7Q zT>E@7yzd7YJU@pGc027GbB{PCgXs;XBU4M^bCTIeSQBO6+Hc|?j^{tlVV)r|1qc_f zVEZ)P@|hl83DI>Vo}bTQ#aS*5$4y2}%^3-g5)oXMPsn9i9&?5Dh zKrlway)GC!%k$jKQ-MaV5|?3X%#SC)>D)BLS;AO5BY8OH($2~AA{ zdpavmyTquD;|Gh`u&$kDH6j43;c7(?ln2)-#CIUP!A>GBpV>n66u^og?%5(h-%iL! zk3E!Yfh;CAjw>Q$*~*5(y}~LRka!bcS;EAw@5U0AAx)On`@{|e#W`MNY;5|E zl&}KCc>M%W`cAbBX|5>{O1?&MxhW+=37N~e}1AG8Zveu4@WalV`l81J&0zjvG9q*_{iiPK%@U2hzt zJF+Kvg;i#it`+jS3RX+T@o)tc$3mmrlND^>h#n!33T9ubENB{O@^V2DA3Bmv#bv3s zkt~l?^Sef(If`Tl4=qVhf~Gvdl3OLRF3!)iay(E#qvX5YytI-HC>DcOm1`R>B)b8s zI}X=vIIY@X`Ho7KQ|vUwkI+6KmFyz~h7;RBA7^AcQ^_*Nd`Sx;3S-m+YGuc#BxI~T zjn|A~E)o3V+EFaCN9Ai&pfn)K{z4Y4e5a0oknE$HZ9k1h+;-dLy{z@5-Ll zx(Ww87y=7;-5Ay(ysuTc2m+YEYo@cI6u)FT8~FuE-YZz;7bgwjpHF8gUzUE&Sk?zY z;LW!}DPJJ#J+kZnlPYV)Sfmj6d-Vkz!HZvMMo2le#LlJNS7Ghe#3Z{*558{%?}#vK*DwQQM@d{Zm|P9 zJVeRY@|Qt z4K2Oj(4yWTexN(S>H<>}gnxC1F+DnM)1yNXxwK9^P(T~R@5TfTf5?4dQ-Zchaav!X zx)Lr84r>-fCx})cT!vbFuq2cX87c&}zX2ZcShA%5X``>fFPxK2{bYhb2%|zh92f(L z66N9#OkkO#twBo0MoEl_9?|hjs*F~tH&XbS36O+No>GJT;pPOAHmL(28^Y3pcB?l$ zmn^il*=YOaHEeLfF^4GS-U48 zg1A1fF}f{5c{XjC!UkmH2x~6iu?Yrk&63dz5i!Y@jq7i|BzI?=POG^I1vdsF`(QCC$Y(9(K%oawSx%} zcwOC1$RSBQ{;(lbj@pC@aJCp@M|w-BBN&j7l}8fzrul5}Qr%o#?Xr(JD`#VcMTCy% zYHVL=p)I)8MN)qw;%=3hb{>czsQb{Ep{gThhYW%Qt5eZq6`(l9Rz_s4qAi9xqI)OjFn2E?zuP$c!^bA(n#jJ3s`5suIMPS2AzwH#5nn!c^q9ts^MC=fz zSl!(X=SD>nefOXH5A?JiG~dd5zdye8Ho31u5TJ~3KzZ_L|3wB1XB)a zCAcQe5T%J|H8a9q9Il*V-91jVL_AS|DGvL5fFoB=-Ql#lhMy{Py3!qpd84clmoOV- zsHAZ@#;Xf$uLjOG@$xY=dxY!D#~aX~`TQH#v9hHx%6Rs)#wmVZb0f^<7+l8nG-zbe zQHilAK0#z_92X3X&5fZlV&=s)6j9|I2aY}$)w7bZu6g2Pg6l~MK2nHnoCHenq|jPy z_#{tFG>(v_m8fc7A}mEY-?JPWo~FpJmb0cf&NA7cj5I|3l9FM*))_x=!W@8|g5CYA=fvz=7aYD87XIkZ~& z?rC`UG~?ZM#=Ga(-d)E_{LHgllM&}hrM)N_^VaZmvp2UDm_Qu+!M_bV;Y;4(*X9UT z>JZVz5!vr&Q)!Ue!PbD^*F2=X&zK)k-t@3s?bDV z8p>a&#evUd{cQ~^Ov375#0}tMf-H03rM%m;7FCCVr5v0mY}11wTvDDago2#_Z#VB%U&2hKAv;WTTG^p^tyA+8TULRb^=L3q$lHBTDFFZt|#_RFAE|- ztr>Iyfgpa>!3OoU5olZF+eSpn*D|M0w>tQw8(8T~&5gie;*NQcJd1gc3!4ghmP8XU zh=N$Zf})+!5YnOsmk)`6MeQC@F~=5sQevBfzi8`%)L$H7N$WTX1^ zXbOJAMx1VHeEUY(5HDrPu*$ zhvbVh_-}86HTJNB|NA!PcA6@W>34`g0Bit#!@;lG#PU-UaTQElrk^J~1T_trzgO}JMpL5tx5i{;!eaPKED7=Fu(DRPS(5>vgIBCLX=VR#Z z;4DHfI{1R`F_;f|&3y_^pgG z3@4iV*nk;k8oo8MqS+TsG;)lE)*=jNJ@IAY%0&;PmdMHdY+R~YVm7|12GJWz;j`{% z9yrFWzn|s8r7x7b4`T6_V)rsO6AGpPl_KXME zpmL*lEhjNXElun-vh$Hos-+J-z_Owy`$EBFrg--x+<{l^f}84%a?|1D6%R5`9|I5l zxrqB7WP|6SDCx8f4WJ~^Hu({3S$u`K#H@nhv6r8S0VMKh<)R+qA37>g!yne4{6wTw zC-UDu$cp;nO)lI3#$h5n?GpKA4`IB*k8|upEF;zKZV6V9yz(J70{#y!A~u*tfY4BV zJMLeK9g|s`GB^+8Th!v7kbiwmB0u~P8%%2x`G*g&oHYA&Wfl2hK_buE&hpV1F-wPr zoHMtx!9_-~T5XR?j*CMjr-@3|iAqib`6F<=+qa$NjwwUK3Y(NVcr+PF-et|#(2J6RgnzmHLy$}ju?lD8v~kN-Z)$ljb7^=C!ci*_7+&%-Tl*a$RG z$Xws}KEvn8bm>vMz}}O@?qnB}@Lze<3ajwG<8 z+FfwbbMhk|-eyF{MD#f6CDd&A=ZcIQWyVbYtDP);$ff*hHznd5jKbHbSvl5jO5}IG z4_|~K@R(JOvlYWO$8fo&HqP8PZI6{}3JysXfG5@c6Oxu;n z7yN*gOi<={aS$&Z>_~Jr2&dcKl9d`ATY;Zq&tp&1t56kX_T)KzhhOy3X+yhk!zdQC|S#|TL_prQzm;&HATxoM9 z#&HeQ(Zh-S;vV)YJ%Um40X~&}`Z1P1OcP&atBy0(L{gSEMSSf65g5`CVHeuG2+k** zku=`C7t`=42LE0*6qobOEU>AFv)wn)jeFs}ckMpbFE&+tP4%rregfGGqsKRP#}gxk-Rz+_dLofK zU&S@~cYneL4myc11kb?T0P&@{86wJIutVxF_3E?mp;L)G{Q&%IPABpS2QVzpV68j= z^Wxb=zWD%#>$yb!L-Bh)k-vNZOYFr&e)a$x3EipiX*N2=6aB2bcG7t5*Pdpsu3i?; z>{ZPO<-*vV{4&C+LB_F(f(6YQ#+ErW(elr6sR88*1f zq;}(I2C^CfNoP5r6EInFj4^ZoZ@ckHFY0{?&`ZX2=wrtSo%GPL0ry;Wi ziTX9;3ztTHMEk{nBDKRv?IJ4KgaMAOTos!+1{A3_;*k|GAc_`o8dS^6lI@^Kjmg{W z>$1Tp+D?t4?Vw1t5sOqCIJy!6w(KvC0WsY=R@hUcAU;$sYK-8p_GB9<=5nKdZM0I^ zXw6tyrbk&Z(rxhQN*r0m74Cw5V4sEYoAyM!F3~wF2$7@=&c9Sf*!1c^5ALfeC9^ zr=+OedWhwuTB{FnijPlv`16NY`WPE}hCm~Tn+WA5tGpo( z@B35i{XKlxPhouV@acduZRC|8$7N*^JPKbS@bH^|ilxq$UVwCUG028=11Wb$Hr!Mb zSMOa5KRIDPu%%{;Vz9#XK*3qP(T17;DxkU=WyMx>w%h58k?3n(ix&q&wmf5jR$s_d z2N$*^!IDan7qZ*EEp4_`Q8Tn+W1z)`lpM?#w-QaS5nH0H1f-=6CFnyyU5eo{Gi{yh zhYx?o+~u~c(PZp{+b@N0>j*V@_!Te8ep~t?%Ru+7eUat5ZNxJ~C9E5Ik{1tu@Wp|>9*XW(`9ZC zf9EjE?m385!K$jxmv8~Y!|{_=C~9%3))C#Q^0Ws$eDzB#Bg^(OF^c7#m1cZ`6+Ofs z0s)FV@Dldl9)3*y{QV_a&%Bqh>G1HXmsw7ptqjrqs&51f{#Ha4@bLDR*^r*KYV@t> zSmoi5zYNz;5B~*9yTVqC=ymZmQyWS&1-{#{);>H1**Y)Cc-|{)z|}TtF~vkmeMeh8 z>KauqiORCtUdm+9iqNO{6m**k7v|wzufQ6O{&)or@~HYNvTZ+qg;fA5Il@NRHCE`l zQkHZb!F?SMfAk3a+dTZ2M`Q^XkKj<#!w3BwyG9S6`g2y+WaFkvC~i`k;M*zfUR%n9 zjywUn*|6HcOq#(@{s#L(dobYY527JU5*E*~#xiBW1xgz^dus={*o+NJ4=JEsYNhfyG zTSpiUOpD>DB>v%htaLzG^n2(YB~cpdz1Rhb2m<}!79s2D3jwE2igGA2ic@uXc*u(+ zwhQ;wvb~+KN+(6|`aZaADKMVeq-jZYNpq4GBrQquCi#;5NgYXAEk_^a@-=ygC^#*N zzn2H|-(z{SjMhnDGM!@}uXNL)bb$eEbc1|}0X*lXL;5UBBFVS`0SD$J{;8Xe?t%@M zXxVi*MesJ`lQjUT3E~4f0GSEm3pxOG6T~NU0LGahzHI|A-URUx9e@cYh)?7eJE6$RmuwpGG3M=0FMq$NVzbLG@b4FpsUaIEq zGG3?{yevwfIP7o2;QCM*}I0`EU3!<=MurLZM z28Tpp#o$mAu2c+qqOfAHt0;<491e@Zio@YiSTR@}g%yJ(QCKlp8if^uBciZkuq+Bo z2D`L!6ERA0SP_L4ha;n~Vz4p_D+WhJVa4F+D6AN~JPIoYtD>-A5Fan%0*q z24|UYm11yq6fVcd#lXOvC_-^KHwvpJoEL=^gY%=XVsJqeRtzqT!ivE~QCKm!I0|OSTR^1g%yL#O}MLCap*M>)r!LvQCKn9 zpcNRBvP^N&7D92_Y#|h@ zEm4HAth8DP#cIGpbSYljER5oHjfGIW1}%hQHDn5Q^0e7DBQ5wJ4&iLh;%a#Z)L>Z?+JM*Nstx zvDVyTArz~(S_sAJZ5BeYy2(N)R=;k&cckL=8y1P;^>z!PSlw(P6svbw2*v6*qX=Ww z`Id!HtZp$8UFDUE*KeDc@=C?)ofbmzdY6SztZuasiq-E}2*qmHLMT@6wh)Tdu6v>w zWBs|;LMUFjg;1=1*Fq>(w^<0q>h~;!V)Z@?p;*1&Ky)>ik5aroV38-2*v6l3jtPz{_#@_qj>$9g;2b{Xdx7148Y;D#{hF$1M`Y>pK=g zHS2Gq2xGx|*Fq>(Pgscmr?antkFvP>eP;K}X0!QvLN;UrN!UOFiG;9$1vU^cf$$Lw z5J~t@p%9XVMDj&8QSb}()>_}{+oIypzD0{dE4|u^m2R~~rLAr8ij}rjd977yQBkO( zqN1YrKl42M5%B)*?_Pc_vges+W}cZdXU?2C=YOoO{v$!Ky82pz5VZ8K*Ao=0uSXLE ztFQk|5Uj4gksw%I{a1oub@f=BU~gD&CJ0tn--_!WlO|hzeLGRa>g(|Y!5Y?g5(KNO z?);*>c?^YV^YxS>nDjKR$o6&5UgQ66DQak)@KQV)z!}v1gooGBnVbl&&CObQ>?yz z8K+FK`uY_@a$!2Da*QJ5ZZ+ik5nr!AijuibD` zij}il*M;Zy^|p1uc@8{J+rag!(6rSlfgc`jVHzy<}Q;4L1$`(Mt9Q$k6Ibhiz8 z7XS|D1S##(Z*KFXbKfMy&nEgm;&Z4D0pM|R?$`IP&vm8p2Y?xjR__j8IuRccs zz`-*Ez8(Xet+=ch624??AJW3ljyZF^%5)e+9Cp{Bj!ni3_jvf_W6siPNybFuo*^Hw z{I^<0|ryrsK9-*4X|M{kKR913JJ3Vebkpj@6qi;G3n!-|4 zG==*&4FWA18BgI8*5BKCF45RMq<4GH@7*4&cY8d1^t59P_r2xJ%8pw+6}EQo`f3Mn zd&^n0HO@`AP+5;#n)dMK7|B$m*lWhaXmqK@*mncJZ5IIb5eRMp>SH?Ltp%)mr0RxS z8JJ@4kRGan=Wu{sZlCbnao~3)p2yK)2Wa~}+cTWyBTGdIT+M(G80l;i2RxWEghjO? z+N4x$U*gOi{*1@Me~A}@v*!WN_N$z8s|GEg0k~F{#6i}Om&&V(whGuy0cDEbKBF2$ z%?CYv>}_X*gUv=EWe|^_kKIwSOYHvF}cRSz{9K!dWM9caw$0?72|G{?OjkufB9-er@ zSy3Igy;rQqy;Ij3BnU(@wpel;pZ*y+=0SjDk4o{|GoYfK02XU^YTpUx)WF#xLm<+U z$3Or{D8?T4AP9csxN|hmJc--H0Ixdf^aGcl?>*_vOH)?^D$puo5sLBr>66aUTVowE zWLmOZN=-YDwNlX@SWx}Pk&$NLfB4`~x68;*bC)HcD3P+Z6#x?2ZB7}hlV?76NE_K` zqy8NJ&9)lJN5RCRC{*7avZuZfC1Rfqjzf_%_@#vfK=!rRxWz-7C{1pn z^t>iY`J3-KL-6b0|DH2%RC$`HRpDvNa2;lQrDCC!<1L^g8x#1$_nhMqrZDP#TxKNu zq8q*i*q6F+zXSL8ruUuRtwVi{4T;sYRNZ82FJouSYgsw+isWok=eQ%ov9W5%*Gx(N znknaf&6Kos3y+xJct1&0>3ntYuV{}6D&M-n{+`6o8pJKHLEtiyU<{%A)GcrVw#%p< z(w9)u+$jlR3p8u$W};|WVxogdWdYVOv}_$ec*lh7ayJqz|k`wz-fJli^ViYE|32ZcUXH}+@yY7 z^&yl9fJ@yl4aN3+h+?@Zymy+z%m4i$0N57smmfN(JGQ6r^p6lYwFg*9Ax9D4^^voY z9#0V;am`20Q7liRt^EiYKMhZ7706zVny)#H$`EpWpc<7uj31(k52}L85Y=?rS>Xt~ zdF;oCZbDSxw&{*?zWrmou-nZ)``8(D>~-_8kDWDi+KuFfo2JQpp7n_{JJoC+Z0{ul zAu{}lv(kYmfIobKuX!91DxadCa6+E>Dc(Mk%8^gOkEwj$r_M=~?GX?0$rNY@?|+JW z&_W(|#u)@o_xv-?sbT_OcLtv}6Sr|^oa2ihvxgc{$6J8X(Y*kP+%zzn5QG5mI;2OcN!gzWr+skQUSsE0%->M)E5w!XFqq2^9JJ$Dlx1dhq(F+ zXN$+Tcu*zy6!@6Czi=+hENenC_MQPyw*ux2f%=@ zaMGkH0?6wteE~fd*2qV;%VT2QB3~Eo3(ehseLLqX`_Jt8H|HB7CGh(P_yS2qp4ji( zNAXfgZckR&SH~KffetLS867^1An?xmNk^FXQ57@^ZjM zv(x#WY~k$jztmU{}8!^Ie%0vO)cTyz9}%#WwgW$9(j%~L{f5J23|7hLS7cbx)) z;JP$YTi%W|nw(Km-`T#b56&LIn)dTQ(&(61AQue<7r`Z|d$1ddU}tZ8Ao_ATHK{1N z)tNLJ?(NrSQgMO9FqPsi^xySmT7kE)$&3IW05Io;6|oFrfV2?C0SU(J@&h$T@q{07 zxNRMN8~=9zB`PcC1EVd{8EM9GLKszoi?gW5tgv5*Q&F{dggSEgdo;IICLLkWb;YQ~ z(f6|GZ=!Imovk$Ka4|<`K*dFt;D2V*>S3Y9SO|$TkX^xO9vDVGZ;g6*&PVXhVN_rS zn!_73I-Sy1!KTsYhtUd=U%yNRB;yzpcS+aF1CYQMdTF6q(Evv;91`FL*N#X>$=~EdX*ixgYzuHkaPcvc?r*pZ#h~9MRBl>K5t#MogJHv#AyGXdZoPRwR8RR4vKB z^3evL{(y6yz>qhApYl-wugIs3!-CBlJNx>=?Yb1|J0+tp=F?w<7b%ntGpNb+_K_^W z`$y8tIrVcl1DqNAnC8?LpxFnadkScdFheTT-%cBcDK+_QA(dw-e2m4hG`k>vXAIT& z#aRFs7tB}wcYUoQ_KyOuj&K!lAz3$y%Cm#^492ES@{Un7HM2}j%)DNJm17){wrUhj zPA|ZlfN}u=iKRySsmu(-SSPGd1i_V;`DuF&rVc-wF?d)pI26l(8Kq+KII@QFYbqCw zp|QioTp_MWKkvgLOK_bJ2@S0L8MeJ$mSgKYM z-@*@Vh(rckVKxwkk0WDgxjAGH@nZR554kWpVjPt@)4h#|Z_%<4agj?dpc7esCa}p$#`H{cnju&3a<#mR#@aTyW+FW?Tp=Xb?I5rjZ%`|C zB>l?h03j@BnM?BRRaEA8*XyYahjn%%wc}y?xWrX!80|m)`7d72;8&_>glDyjP>Hyc z*7AuUA!Tp$sY%4nF>v9qCsM@zQBVeb+D@)5;4{S6OroX?E~p1>e?g zF_+$H-d#Y)? z=?BF^mH-vVy*#g)=I4uBgt*%fn_TcWS%wof@PiDoT|i&Ccn0MH2xr3#f?a0NeEeJxwzGilpk&t8TlC<%P6;^~B3w-@lY>NJsgdKh*`JhMo zdDTi;i-Z{`g?|Nw$9D2ImO_jRdltt784VfkLt0K0HapZ(z{lZM?a0Xm-KYi@CEiRZAA>L z&S}|k`)XR5t#)wa(Xta{3*%)zyPDcEeU0Jv4aye|TIoJuO@D((UG}@8 z*S6AlO0F_dB*rkgq2-dcT*vA1=H5|zd~l-@x% zXO`JpgLW@7`Th>NI}=zMD)L&BfScUVNlz8D;8z6A_Yc@|Mhg(t5!2+-%jpAegd-yM_A*HS#aUNS zuG4%GpxIZ@&AA~}S|1uLMpB>X~nD|7kO+oWE~wrtLngLL|0R zhaUZg-lL>>%*A(Zp($Bq*1}QU6vj=Gk8Ghw`PQrS5TA7Mo~tOrg;!I)^I?~dtFNZj zxj|ixl4^aBcba=nx%i>0Y22_9MbeLzf_Bt(8ZhwC8#(0~x*@;CW{#$=Rz#4;R0YLX z_g_Ol-1>jm3gB!wDE#1$&bDwwjm{PE#ejVFtpolJxQoYNYT5xFs3A=u}*EB!jD9=Tf4$mam)&;Kn^Q-iv#dqRkuaIwGpv^eq|{0Pw@Bl zbZr4drWRm;h*ns4{*67oSE7D^wLlHWaO#$q0nZefIyAfkDn|b=TWjrkY5-xm90+gN zvUat;0{XZ}h{}da$eAzb>iMS9Wx^b#z-efWv9ZWZG#aTiy7|HoExxb=$rJnf!&h|n4o14RY)%X_ zZ0vx0S_k3Nk8wa|skV;FkiwejitjdxQI}myUwXv>AzttW7GReGU;BU^N(?WUfjUZ#C z0x4)#A)nDd{tx=O@GAMatOwDDYOk5oG1#*)Vn*M)i9SZ~?HL!`N0C^&6)$dqCT0K2 zr&430HWh0RBLX;7Z*a)taSL7GRS0DIp=N#atlBYo!heuItD-)v`3`fc_nOuJK})hr z;uu}fzEf1$?(firnPtribR||l|LQvw@cJ~(s#dC^FZi4J@OLPezxy46-h3;0bHrI8 z-u71LlGZWOP^>2f z+vyb&i&D(H?jn^w-KcJPFi1XEAW=(55 zHv7Bor4oK}2aQcnGfD<5hDFKX4rvHd*jK59%aTi3b4CbaW`hbV`C zc^`$)XIg?c|m`5P!1fpz_zP^PS&a?MU^%tY9> zCiS(d_z%8+C(Uxu>-^69pHkq_fv0H z!6Ka(+}gPSzkAICG=5k~1FT!N76PSqM~cZ$JOD#RiKgKZ0s%k=94}w6i=w6vJPURO z(E$y38}SFbsA^2mqRzqnTF+pg=CR#a$c89%h}*~zds2q+;@vcJC_@9X_iGt?-~TT| zj}XNUaSweRNAoWqq}KB|Ip=FQnYSQA*4J}!ew>RBrNPXGP_y%>x^S&8)giHg0JU!UNn_e-arLA($cza3g;HVVafg ziWf>IdvN0G22j6h55;P;Vl^cZXPK!6qQ%fn?0)g0aVDDle`TV_Qvfw?f!P9_5P!V< z$j@*X4enC2Tj~%yFuVIxa=G9UD$j?l*znb1$+cT{+yhFO0}rHuNA0Cze)16tm`Ea| z4H$|^svH2V{pt}~go8wH??%lzl3;JSY%e`HT$DS+USu|a^ijq`%SKto1&`9|;Y}dM z4wvnao!WGSWJ{0IYb0Jw8O}R@PGg)wfY*+AjLLkqc5XOmlt{_|;f&T@LEy@&rwtVl z37snEkNqG&<&CKJRo2Vi{sss`wZ?vv)yR>|a`{O5;ol-|-kdn_192h{>}= zt??p1x{n^q0D9=U$ddJXPsrwhU(i#TxP93Gsn?I_Q-QFf*-<(?qETIJDM<1ps~5T| z4dhSwCCx6Zx32+~tdA8`!w4u=GQ8b<(=Tb^0!#0MmtE_+cnl8==qHYU0{N z*VlqG`YQbEpuBYsD0pIj4{V{G>$&c6Dgac8GT;ns;cFhJS%4Fx|%P4nnt)y^ZFd80cGR*J(R}}JWUg`YjlMQ1=g~wn;bbn<8tajj(u$G!A}p+ zS`t-mA3yXP8tE{m@WJ2EUT-j#5L{VxmBCCRjOn|-rP_RP(jg9zuNK`ySG)P6XQ|vP&N##~lnyN}(V1xQf6*+F z1(ib6?2hn_&(S_@m9;z(09UQ7vI`E;Y^T6YTHkcwCm%TkW2DJn9ilI$#Z0F9QbZVs z3G$#OZnN)$njNkTS*k@0>(ekg-5mTA^lOCwDPZX zGjR3KEfRtAfm(v*E$--_UqnvR{1)3zvJ7X7L8Z1dtL(DKug7&S(cMKtI>kW>wag9! zAGY7BE`B(8nLmGtt};Ua8*S@o?d-vwGh%a1{?^O17i@=5QQ(To8G-RWT=UOUx1y+2D^gNulr5w6k`pp8aE4S*XlPcl5PZ=Y3x^=vn{Y! zFO zsbgJern$$>V~*135eqaG>pjxe-wDiMTmHdDFjwKf(Kr^A21mW zhV3Qe<8g1&MDGH1(`z@RHgC;y8{ecZeWF#H{Zeg%hzZ$~Z_-U9cDoDt>bIzh)Z7oJN&YHdQ^B@_y!V8pgkVo2KUlhZNRY zZM>Og;p@-W;G%sv72D9r4YH^9PPH~j@ zniDhIOU9X2f2DJ1r~i}=EmG!;49uQ*B7 zBC7)9x)6DKVs_l8{!P;@TP;pV17VvSO?!_*xa9-$E6`UhHk;n3O~cj3sVK37fx7H> zH&|Ue@jmqwwhS$Rxl+Zk+)=L1DtGHC>JW{*?J0p>6lS=L59qy|isV|==C{wy=7+Qp zwlKx#+Mu6QBxYmHsj!T4>XEfRfNlH4hg6jOUQ&_7dzNTRy!WD;Lm$x-$?qijP+FXafDNg?8s_!o$&AZEB^eq9}vr$XGp1we{1^5V-E@g?r?4`S0u1iu|)dTzyovH2Ixz$$gQ?n&LD-mcMl1Ud)dt*ms0;Rn@hh61J;)-YS} zl3js+1w5ye(LvX+C-q@fLon7VjtL66p3t$qvHm+BPYv^}DRRbe^#T5t*2qRRyZZh8 zsk?|@OOeAdpC6~lMVWzE^>cb70|8#@mXp=JrUsX=NO!p9r0g2&o>T997WpN&EFV@I z>xa5+P0&d^le(VgrphsO0o4Vd;>B*vT-EZR>S#%wGK5&Sz5&1S+|~E}RF6JfF!Tut zuV|pV06&x}7ng`5sT&M)KFpXx|D9fAxv_*}UPH=_V~j_BI6N7=6*HoRt@$AT@C)Y! zydq8BFf62ML6WS79^H^(?25jdCKrogqM9JQ3jDFt+N-J2#ToKWXI^m0;DF9Crh9}c z(SK;LyyOtXa(1@7kT1@bIjOoWq6zkcZ)VG2o=Ql)zPGk^IIdV~+NcD68h7g~G?NzDpdK5d^<&~3> zoqf7jR_4~@G-TZ+f!UU-ITS{iuk%WOZaw_+FI6 z47b~7865sH_(-mNC0krfqE&j6miZrt%S*5&!V=X9SY@njWiP%2y$bNOJXwuJ--!WV z-=!HS%vxIp*-3ke)xtWIh-FTlm~Mx zVYVpTzp*R46t+_P>0=(RW%o6pf!2(*O>ubagr~?!qM`3BbzjJ338?* z?HEEknpFZgEnaZ|^~*fY7$YNQ0LET`Z$f*42 z_^1z-$hj~8Xwzq%vi%zT#}YX&GhmVQK=vD4SSsh|X${6gr_`4prcnziQp&HE$^yQ- zR90qLP8oAr`&w~j1Qq#jrE(LA37#Hq8Y?GGv_zQ!Z)TiEE`HW_o%J8ia@bQAeGptX3_3$b{KlFvK=ukD2S)wO~$1 zxNRfG`OEm$6}Gk#BCC2E%2bwK6n><;B2BOwl~`{PcSr5 z6RenYeA6YKV40@qX>9fEs?fizQ&QNoYb`fTa`;AedUn-YFWQ#@it7eF`>5N)>18rs zh53vtlcjl$ZI(~n8k~RHIuv$N|A6wJYb%qJbAm%28aH_8cYLx;j^RUPGBdNR2c9d| zdw9g}l*!9PA2&^q1^I4MIoVZ-K&$Q01qku>3F0PC^r~|Cii4L|$l1e-MGdS}Yc#-) z!mH|Ce~affPxRpmIl{qztds%%tWuUZu6410qHN&HC(3)-6OdJ@(n>nD&BJp7av9$f zkcBbYc7!qo$lBf}LNll1*GSNsdf6WBC<)^btQjN%|1~BTLKb0pqGRC%|*9v2sAT z3;IwiKG`hk317KJpU!PHMqNG} z6szU@vQ_G~R?V++Hn4!Y+O!l;#{)B-Ps!v%)$(En!WVGoGtTV3PV6n>Kxh3tLMmzhWlgZgmm0pTX%8>B6XggBTM~_F$y4**4Rx^ ztWEQeA`@EP6s?MdiaUC^2T8yT(0Xa(dwd6 zDtPfch{lccWDy5Kh@ z$XUD`p9pEQq)HY#O`pNrmdgp{!DO)aU<_a@R08C$HC+mUI$!~G`}nJs63|)sX?LxV zk`5NZG$ z@s}&)g5ok56A;9ya>b;VK`P@ysT-r4=zr|h>NLJ_r5sa|cv7&wM=!jPd1Y&)I|P4{ p4TDOb#)?(V`5UM@%?RrH6<;fsawj*TOQko^OoY-%(NdRY{BQP~pCkYP diff --git a/vara/sdk/node-wrapper/src/instance.rs b/vara/sdk/node-wrapper/src/instance.rs index 0694fd9201f..82b56d1cc46 100644 --- a/vara/sdk/node-wrapper/src/instance.rs +++ b/vara/sdk/node-wrapper/src/instance.rs @@ -37,6 +37,10 @@ impl NodeInstance { impl Drop for NodeInstance { fn drop(&mut self) { - self.process.kill().expect("Unable to kill node process.") + if matches!(self.process.try_wait(), Ok(None)) { + let _ = self.process.kill(); + } + + let _ = self.process.wait(); } } diff --git a/vara/sdk/node-wrapper/src/log.rs b/vara/sdk/node-wrapper/src/log.rs index e75f5326bdc..5665786ab37 100644 --- a/vara/sdk/node-wrapper/src/log.rs +++ b/vara/sdk/node-wrapper/src/log.rs @@ -5,7 +5,7 @@ use anyhow::{Result, anyhow}; use smallvec::SmallVec; use std::{ - io::{BufRead, BufReader, Read}, + io::{BufRead, BufReader}, process::Child, sync::{Arc, RwLock}, thread, @@ -13,7 +13,6 @@ use std::{ }; const DEFAULT_LOGS_LIMIT: usize = 256; -const BLOCK_INITIALIZATION: &str = "Imported #1"; /// Log filter for the node #[derive(Default)] @@ -52,15 +51,7 @@ impl Log { return Err(anyhow!("Not stderr found")); }; - // Blocking after initialization. - let mut reader = BufReader::new(stderr); - for line in reader.by_ref().lines().map_while(|result| result.ok()) { - if line.contains(BLOCK_INITIALIZATION) { - break; - } - } - - // Mapping logs to memory + let reader = BufReader::new(stderr); let logs = Arc::clone(&self.logs); let handle = thread::spawn(move || { for line in reader.lines().map_while(|result| result.ok()) { diff --git a/vara/sdk/node-wrapper/src/node.rs b/vara/sdk/node-wrapper/src/node.rs index a8aff4fff7c..1c0f861c032 100644 --- a/vara/sdk/node-wrapper/src/node.rs +++ b/vara/sdk/node-wrapper/src/node.rs @@ -3,15 +3,22 @@ //! Gear protocol node wrapper use crate::{Log, NodeInstance, utils}; -use anyhow::Result; +use anyhow::{Result, anyhow}; use std::{ env, + net::{SocketAddrV4, TcpStream}, path::Path, process::{Command, Stdio}, + thread, + time::{Duration, Instant}, }; const GEAR_BINARY: &str = "gear"; const DEFAULT_ARGS: [&str; 4] = ["--dev", "--tmp", "--no-hardware-benchmarks", "--rpc-port"]; +const RPC_READY_TIMEOUT: Duration = Duration::from_secs(30); +const RPC_READY_POLL_INTERVAL: Duration = Duration::from_millis(100); +const FIRST_BLOCK_TIMEOUT: Duration = Duration::from_secs(30); +const FIRST_BLOCK_POLL_INTERVAL: Duration = Duration::from_millis(100); /// Gear protocol node wrapper pub struct Node { @@ -92,6 +99,8 @@ impl Node { let address = format!("{}:{port}", utils::LOCALHOST).parse()?; let mut log = Log::new(self.logs); log.spawn(&mut process)?; + wait_for_rpc(&mut process, &log, address)?; + wait_for_first_block(&mut process, &log, address)?; Ok(NodeInstance { address, log, @@ -99,3 +108,79 @@ impl Node { }) } } + +fn wait_for_rpc(process: &mut std::process::Child, log: &Log, address: SocketAddrV4) -> Result<()> { + let deadline = Instant::now() + RPC_READY_TIMEOUT; + + loop { + if TcpStream::connect_timeout(&address.into(), RPC_READY_POLL_INTERVAL).is_ok() { + return Ok(()); + } + + if let Some(status) = process.try_wait()? { + return Err(anyhow!( + "node exited before RPC became reachable at {address} with status {status}.\n{}", + startup_logs(log) + )); + } + + if Instant::now() >= deadline { + let _ = process.kill(); + let _ = process.wait(); + return Err(anyhow!( + "node RPC at {address} did not become reachable within {:?}.\n{}", + RPC_READY_TIMEOUT, + startup_logs(log) + )); + } + + thread::sleep(RPC_READY_POLL_INTERVAL); + } +} + +fn wait_for_first_block( + process: &mut std::process::Child, + log: &Log, + address: SocketAddrV4, +) -> Result<()> { + let deadline = Instant::now() + FIRST_BLOCK_TIMEOUT; + + loop { + if logs_contain(log, "Imported #1") { + return Ok(()); + } + + if let Some(status) = process.try_wait()? { + return Err(anyhow!( + "node exited before importing first block after RPC became reachable at {address} with status {status}.\n{}", + startup_logs(log) + )); + } + + if Instant::now() >= deadline { + let _ = process.kill(); + let _ = process.wait(); + return Err(anyhow!( + "node at {address} did not import first block within {:?} after RPC became reachable.\n{}", + FIRST_BLOCK_TIMEOUT, + startup_logs(log) + )); + } + + thread::sleep(FIRST_BLOCK_POLL_INTERVAL); + } +} + +fn logs_contain(log: &Log, needle: &str) -> bool { + log.logs + .read() + .is_ok_and(|logs| logs.iter().any(|line| line.contains(needle))) +} + +fn startup_logs(log: &Log) -> String { + match log.logs.read() { + Ok(logs) if logs.is_empty() => "no startup logs captured".to_string(), + Ok(logs) => format!("startup logs:\n{}", logs.join("\n")), + Err(_) => "failed to read startup logs".to_string(), + } +} From 66bc34332f47edb91dbadc565bc47885bcd39337 Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Fri, 12 Jun 2026 00:24:29 +0400 Subject: [PATCH 11/13] Stabilize stable2603 CI follow-up --- .github/actions/setup-compilation-env/action.yml | 10 ++++++++-- .github/workflows/build.yml | 12 +++++++++++- vara/sdk/gsdk/build.rs | 6 ++++++ vara/sdk/gsdk/src/lib.rs | 2 ++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-compilation-env/action.yml b/.github/actions/setup-compilation-env/action.yml index 2f447440640..2456d6bbf88 100644 --- a/.github/actions/setup-compilation-env/action.yml +++ b/.github/actions/setup-compilation-env/action.yml @@ -25,15 +25,21 @@ runs: timeout_minutes: 15 max_attempts: 5 retry_wait_seconds: 10 - command: brew install protobuf binaryen llvm + command: brew install protobuf binaryen llvm openssl@3 - - name: "Install: macOS LLVM env" + - name: "Install: macOS package env" if: runner.os == 'macOS' run: | LLVM_PREFIX="$(brew --prefix llvm)" + OPENSSL_PREFIX="$(brew --prefix openssl@3)" echo "LIBCLANG_PATH=${LLVM_PREFIX}/lib" >> "$GITHUB_ENV" echo "${LLVM_PREFIX}/bin" >> "$GITHUB_PATH" echo "DYLD_FALLBACK_LIBRARY_PATH=${LLVM_PREFIX}/lib:/usr/local/lib:/usr/lib" >> "$GITHUB_ENV" + echo "OPENSSL_DIR=${OPENSSL_PREFIX}" >> "$GITHUB_ENV" + OPENSSL_DIR_VAR="$(echo "${{ inputs.target }}_OPENSSL_DIR" | tr '[:lower:]-' '[:upper:]_')" + echo "${OPENSSL_DIR_VAR}=${OPENSSL_PREFIX}" >> "$GITHUB_ENV" + echo "PKG_CONFIG_ALLOW_CROSS=1" >> "$GITHUB_ENV" + echo "PKG_CONFIG_PATH=${OPENSSL_PREFIX}/lib/pkgconfig:${PKG_CONFIG_PATH}" >> "$GITHUB_ENV" shell: bash - name: "Install: Linux packages" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index db017859625..5ebefba7791 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -455,7 +455,17 @@ jobs: run: cargo build -p vara-runtime -F std,try-runtime --locked ${{ matrix.profiles.flags }} - name: "Test: Download Vara Mainnet snapshot" - run: curl -o vara_ci.snap -L https://snapshots.vara.network/vara-mainnet.snap + run: >- + curl + --fail + --location + --retry 5 + --retry-all-errors + --retry-delay 10 + --continue-at - + --http1.1 + -o vara_ci.snap + https://snapshots.vara.network/vara-mainnet.snap - name: "Test: on-runtime-upgrade" run: >- diff --git a/vara/sdk/gsdk/build.rs b/vara/sdk/gsdk/build.rs index 7cb10fcaee1..db94673b0a6 100644 --- a/vara/sdk/gsdk/build.rs +++ b/vara/sdk/gsdk/build.rs @@ -4,4 +4,10 @@ fn main() { // force subxt proc macro to use updated metadata println!("cargo:rerun-if-changed=vara_runtime.scale"); + + let metadata = std::fs::read("vara_runtime.scale").expect("failed to read Vara metadata"); + let fingerprint = metadata.iter().fold(0xcbf29ce484222325u64, |hash, byte| { + (hash ^ u64::from(*byte)).wrapping_mul(0x100000001b3) + }); + println!("cargo:rustc-env=GSDK_METADATA_FINGERPRINT={fingerprint:016x}"); } diff --git a/vara/sdk/gsdk/src/lib.rs b/vara/sdk/gsdk/src/lib.rs index 632f22f1450..bc6d0fe7243 100644 --- a/vara/sdk/gsdk/src/lib.rs +++ b/vara/sdk/gsdk/src/lib.rs @@ -16,6 +16,8 @@ // // TODO: update docs after merging with `gclient`. +const _: &str = env!("GSDK_METADATA_FINGERPRINT"); + pub use crate::{ api::{Api, ApiBuilder}, config::GearConfig, From d9a0499c19dab70fdb8698d5104d76de19b1abbf Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Fri, 12 Jun 2026 01:08:19 +0400 Subject: [PATCH 12/13] Allow stable2603 BLS runtime imports --- sdk/wasm-proc/src/main.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sdk/wasm-proc/src/main.rs b/sdk/wasm-proc/src/main.rs index 1eb50a58118..fe170e1f7a3 100644 --- a/sdk/wasm-proc/src/main.rs +++ b/sdk/wasm-proc/src/main.rs @@ -11,7 +11,7 @@ use std::{collections::HashSet, fs, path::PathBuf}; use tracing_subscriber::EnvFilter; use wasmparser::{Parser as WasmParser, Payload, TypeRef}; -const RT_ALLOWED_IMPORTS: [&str; 78] = [ +const RT_ALLOWED_IMPORTS: &[&str] = &[ // From `Allocator` (substrate/primitives/io/src/lib.rs) "ext_allocator_free_version_1", "ext_allocator_malloc_version_1", @@ -97,6 +97,8 @@ const RT_ALLOWED_IMPORTS: [&str; 78] = [ "ext_host_calls_bls12_381_final_exponentiation_version_1", "ext_host_calls_bls12_381_msm_g1_version_1", "ext_host_calls_bls12_381_msm_g2_version_1", + "ext_host_calls_bls12_381_mul_g1_version_1", + "ext_host_calls_bls12_381_mul_g2_version_1", "ext_host_calls_bls12_381_mul_projective_g1_version_1", "ext_host_calls_bls12_381_mul_projective_g2_version_1", "ext_host_calls_bls12_381_multi_miller_loop_version_1", @@ -218,7 +220,7 @@ fn main() -> Result<(), Box> { .with_env_filter(env_filter.from_env_lossy()) .init(); - let rt_allowed_imports: HashSet<&str> = RT_ALLOWED_IMPORTS.into(); + let rt_allowed_imports: HashSet<&str> = RT_ALLOWED_IMPORTS.iter().copied().collect(); for file in &wasm_files { if !file.ends_with(".wasm") || file.ends_with(".opt.wasm") { From c962668b552c3074a44bfe664638e3719f4b2fe3 Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Mon, 15 Jun 2026 16:09:05 +0400 Subject: [PATCH 13/13] Fix stable2603 crates-io CI --- .github/workflows/check.yml | 2 +- utils/crates-io/src/handler.rs | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 21ee0226d14..5c8b78225cd 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -19,7 +19,7 @@ jobs: steps: - uses: actions/checkout@v6 - uses: cargo-bins/cargo-binstall@main - - run: cargo binstall --no-confirm cargo-shear + - run: cargo binstall --no-confirm --locked cargo-shear - run: cargo shear --exclude=gear-workspace-hack fmt: diff --git a/utils/crates-io/src/handler.rs b/utils/crates-io/src/handler.rs index dea7ef7adbb..b1afe733c9f 100644 --- a/utils/crates-io/src/handler.rs +++ b/utils/crates-io/src/handler.rs @@ -9,6 +9,8 @@ use cargo_metadata::Package; /// The working version of sp-wasm-interface. pub const GP_RUNTIME_INTERFACE_VERSION: &str = "18.0.0"; +const SANDBOX_INTERFACE_RUNTIME_INTERFACE_VERSION: &str = "34.0.0"; +const SANDBOX_INTERFACE_WASM_INTERFACE_VERSION: &str = "24.0.0"; /// Get the crates-io name of the provided package. pub fn crates_io_name(pkg: &str) -> &str { @@ -228,7 +230,9 @@ mod sandbox { /// sandbox interface handler mod sandbox_interface { - use super::GP_RUNTIME_INTERFACE_VERSION; + use super::{ + SANDBOX_INTERFACE_RUNTIME_INTERFACE_VERSION, SANDBOX_INTERFACE_WASM_INTERFACE_VERSION, + }; use toml_edit::DocumentMut; /// Patch the manifest of runtime-interface. @@ -260,18 +264,21 @@ mod sandbox_interface { let Some(wi) = manifest["dependencies"]["sp-runtime-interface"].as_table_like_mut() else { return; }; - wi.insert("version", toml_edit::value(GP_RUNTIME_INTERFACE_VERSION)); - wi.insert("package", toml_edit::value("gp-runtime-interface")); + wi.insert( + "version", + toml_edit::value(SANDBOX_INTERFACE_RUNTIME_INTERFACE_VERSION), + ); + wi.remove("package"); wi.remove("workspace"); let Some(wi) = manifest["dependencies"]["sp-wasm-interface"].as_table_like_mut() else { return; }; - // The copied stable2409 executor crates use upstream `sp-wasm-interface` - // 21.0.1, but `gear-sandbox-interface` still pairs with the old - // Gear-published runtime-interface stack. - wi.insert("version", toml_edit::value("15.0.0")); - wi.insert("package", toml_edit::value("gp-wasm-interface")); + wi.insert( + "version", + toml_edit::value(SANDBOX_INTERFACE_WASM_INTERFACE_VERSION), + ); + wi.remove("package"); wi.remove("workspace"); } }