From 584bc52933ce28d4a16a442fd66227410594c178 Mon Sep 17 00:00:00 2001 From: Guantong <04637@163.com> Date: Fri, 30 Sep 2022 15:42:27 +0800 Subject: [PATCH] Prepare polkadot v0.9.27 for darwinia-parachain (#188) * Update market after order is created or comfirmed (#94) * Update order capacity * FIX CI * Update comment * Redesign fee market payment (#169) * Add basic solution * Refactor Slash Report * Refactor Slash Report 2 * Add other changes * Add tests * Self review * Rename to `message_and_confirm_reward` * Rename to `previous_relayers` * Rename to AssignedRelayer * Add more comments * Add more comments * Add new reward implementation * Rename and clean the code, needs more test * Add more docs here * Prepare for tests * Fix broken tests * Refactor * Rename * Remove RewardBook * Self review * Save one storage * Try fix ci * Handle Zero `CollateralPerOrder` (#176) * Companion 189 for darwinia-parachain (#194) * Update fee-market terminology (#192) (#199) * Support pangolin <> pangolin parachain alpha bridge (#190) * Cherry-pick #201 to `darwinia-parachain` (#203) * Del useless related to fee calculation (#201) * Delete estimate_delivery_transaction * Delete transaction_payment * Delete MessageTransaction * Code clean * Fix compile * Anchor polkadot-v0.9.27 * remove unused import * Fix test problem (#172) * fix ci * Add necessary reward event (#89) * Refactor the total reward cal * Code Clean * Fix test * Add OrderCreated event * Self review * Update comment * Update OrderCreate event to include relayers * Fix review * Enhance dispatch module (#121) * rm shift session manager pallet and clean useless imports (#128) * `Pre-dispatch` validate for main branch (#130) * Adjust the traits * Try fix compile * Fix tests * Code clean * Avoid duplicate evm transact fees (#136) * cherry pick #137 (#140) * cherry pick #137 * pick #141 Co-authored-by: bear * Drop error in `pre_dispatch` (#152) (#153) * Migrate to new s2s bridge (#149) * Add client-darwinia/client-crab/client-crab-parachain * Update CI * rever substrate commit * fix compile * remove transactional * Fix * Bump finality-grandpa to v0.16.0 * fix wrong import * make change follow https://github.com/paritytech/substrate/pull/11415 * Add runtime-common to workspace and try fix test * Make changes follow https://github.com/paritytech/substrate/pull/10242 * Code clean * More ci check * Remove integrity Co-authored-by: bear * Companion for #155 (#157) * Update market after order is created or comfirmed (#94) * Update order capacity * FIX CI * Update comment * Redesign fee market payment (#169) * Add basic solution * Refactor Slash Report * Refactor Slash Report 2 * Add other changes * Add tests * Self review * Rename to `message_and_confirm_reward` * Rename to `previous_relayers` * Rename to AssignedRelayer * Add more comments * Add more comments * Add new reward implementation * Rename and clean the code, needs more test * Add more docs here * Prepare for tests * Fix broken tests * Refactor * Rename * Remove RewardBook * Self review * Save one storage * Try fix ci * Handle Zero `CollateralPerOrder` (#176) * Update Fee market docs (#178) * Update doc * Update example * Move to `dev-dependencies` (#182) * Sync part.1 (#184) * Remove fee relates (#186) * Sync missing changes from different branches (#191) * Support pangolin <> pangolin parachain alpha bridge (#190) * Integrate `fee-market` to `FromThisChainMessageVerifier` (#189) * Run ignored crate * Fix tests * Add features * Fix compile * Update fee-market terminology (#192) * Del useless related to fee calculation (#201) * Delete estimate_delivery_transaction * Delete transaction_payment * Delete MessageTransaction * Code clean * master > polkadot-v0.9.27 * roll back bp-parachain Co-authored-by: bear Co-authored-by: Xavier Lau Co-authored-by: Aki Wu Co-authored-by: HackFisher Co-authored-by: HackFisher Co-authored-by: fewensa <37804932+fewensa@users.noreply.github.com> --- .github/workflows/ci.yml | 8 +- .gitlab-ci.yml | 2 +- Cargo.lock | 5162 +++-------------- Cargo.toml | 2 +- bin/runtime-common/Cargo.toml | 32 +- bin/runtime-common/src/integrity.rs | 331 -- bin/runtime-common/src/lanes.rs | 3 + bin/runtime-common/src/lib.rs | 4 - bin/runtime-common/src/messages.rs | 592 +- bin/runtime-common/src/messages_api.rs | 51 - modules/dispatch/Cargo.toml | 12 +- modules/dispatch/src/lib.rs | 18 +- modules/fee-market/Cargo.toml | 23 +- modules/fee-market/README.md | 160 +- modules/fee-market/src/lib.rs | 33 +- modules/fee-market/src/s2s/callbacks.rs | 9 + modules/fee-market/src/s2s/payment.rs | 304 +- modules/fee-market/src/tests.rs | 353 +- modules/fee-market/src/types.rs | 67 +- modules/grandpa/Cargo.toml | 18 +- modules/messages/Cargo.toml | 16 +- modules/messages/src/lib.rs | 35 - modules/parachains/Cargo.toml | 16 +- modules/parachains/src/lib.rs | 79 +- modules/parachains/src/mock.rs | 2 + primitives/chain-crab-parachain/Cargo.toml | 10 +- primitives/chain-crab-parachain/src/lib.rs | 2 +- primitives/chain-crab/Cargo.toml | 10 +- primitives/chain-crab/src/lib.rs | 92 - primitives/chain-darwinia/Cargo.toml | 34 + primitives/chain-darwinia/src/lib.rs | 34 + primitives/chain-kusama/Cargo.toml | 16 +- primitives/chain-kusama/src/lib.rs | 115 - .../chain-pangolin-parachain/Cargo.toml | 10 +- .../chain-pangolin-parachain/src/lib.rs | 2 +- primitives/chain-pangolin/Cargo.toml | 10 +- primitives/chain-pangolin/src/lib.rs | 2 +- primitives/chain-pangoro/Cargo.toml | 10 +- primitives/chain-pangoro/src/lib.rs | 2 +- primitives/chain-polkadot/Cargo.toml | 10 +- primitives/chain-polkadot/src/lib.rs | 119 +- primitives/chain-rococo/Cargo.toml | 10 +- primitives/chain-rococo/src/lib.rs | 111 - primitives/chain-wococo/Cargo.toml | 34 - primitives/chain-wococo/src/lib.rs | 101 - primitives/darwinia-core/Cargo.toml | 10 +- primitives/header-chain/Cargo.toml | 10 +- .../tests/implementation_match.rs | 43 +- primitives/message-dispatch/Cargo.toml | 6 +- primitives/messages/Cargo.toml | 8 +- primitives/parachains/Cargo.toml | 34 + primitives/parachains/src/lib.rs | 86 + primitives/polkadot-core/Cargo.toml | 14 +- primitives/polkadot-core/src/parachains.rs | 9 + primitives/runtime/Cargo.toml | 14 +- primitives/runtime/src/lib.rs | 3 + primitives/test-utils/Cargo.toml | 8 +- relays/client-kusama/Cargo.toml | 30 - relays/client-kusama/src/lib.rs | 151 - relays/client-kusama/src/runtime.rs | 166 - relays/client-polkadot/Cargo.toml | 30 - relays/client-polkadot/src/lib.rs | 152 - relays/client-polkadot/src/runtime.rs | 166 - relays/client-rococo/Cargo.toml | 31 - relays/client-rococo/src/lib.rs | 151 - relays/client-rococo/src/runtime.rs | 145 - relays/client-substrate/Cargo.toml | 48 - relays/client-substrate/src/chain.rs | 217 - relays/client-substrate/src/client.rs | 787 --- relays/client-substrate/src/error.rs | 86 - relays/client-substrate/src/guard.rs | 415 -- relays/client-substrate/src/lib.rs | 114 - .../src/metrics/float_storage_value.rs | 133 - relays/client-substrate/src/metrics/mod.rs | 23 - .../src/metrics/storage_proof_overhead.rs | 97 - relays/client-substrate/src/rpc.rs | 76 - relays/client-substrate/src/sync_header.rs | 59 - relays/finality/Cargo.toml | 20 - relays/finality/src/finality_loop.rs | 689 --- relays/finality/src/finality_loop_tests.rs | 548 -- relays/finality/src/lib.rs | 59 - relays/finality/src/sync_loop_metrics.rs | 86 - relays/messages/Cargo.toml | 24 - relays/messages/src/lib.rs | 37 - relays/messages/src/message_lane.rs | 71 - relays/messages/src/message_lane_loop.rs | 966 --- relays/messages/src/message_race_delivery.rs | 1071 ---- relays/messages/src/message_race_loop.rs | 631 -- relays/messages/src/message_race_receiving.rs | 227 - relays/messages/src/message_race_strategy.rs | 517 -- relays/messages/src/metrics.rs | 139 - .../src/relay_strategy/altruistic_strategy.rs | 45 - .../relay_strategy/enforcement_strategy.rs | 219 - .../src/relay_strategy/mix_strategy.rs | 58 - relays/messages/src/relay_strategy/mod.rs | 123 - .../src/relay_strategy/rational_strategy.rs | 121 - relays/utils/Cargo.toml | 32 - relays/utils/src/error.rs | 46 - relays/utils/src/initialize.rs | 136 - relays/utils/src/lib.rs | 273 - relays/utils/src/metrics.rs | 164 - relays/utils/src/metrics/float_json_value.rs | 147 - relays/utils/src/metrics/global.rs | 118 - relays/utils/src/relay_loop.rs | 268 - 104 files changed, 1926 insertions(+), 16297 deletions(-) delete mode 100644 bin/runtime-common/src/integrity.rs delete mode 100644 bin/runtime-common/src/messages_api.rs create mode 100644 primitives/chain-darwinia/Cargo.toml create mode 100644 primitives/chain-darwinia/src/lib.rs delete mode 100644 primitives/chain-wococo/Cargo.toml delete mode 100644 primitives/chain-wococo/src/lib.rs create mode 100644 primitives/parachains/Cargo.toml create mode 100644 primitives/parachains/src/lib.rs delete mode 100644 relays/client-kusama/Cargo.toml delete mode 100644 relays/client-kusama/src/lib.rs delete mode 100644 relays/client-kusama/src/runtime.rs delete mode 100644 relays/client-polkadot/Cargo.toml delete mode 100644 relays/client-polkadot/src/lib.rs delete mode 100644 relays/client-polkadot/src/runtime.rs delete mode 100644 relays/client-rococo/Cargo.toml delete mode 100644 relays/client-rococo/src/lib.rs delete mode 100644 relays/client-rococo/src/runtime.rs delete mode 100644 relays/client-substrate/Cargo.toml delete mode 100644 relays/client-substrate/src/chain.rs delete mode 100644 relays/client-substrate/src/client.rs delete mode 100644 relays/client-substrate/src/error.rs delete mode 100644 relays/client-substrate/src/guard.rs delete mode 100644 relays/client-substrate/src/lib.rs delete mode 100644 relays/client-substrate/src/metrics/float_storage_value.rs delete mode 100644 relays/client-substrate/src/metrics/mod.rs delete mode 100644 relays/client-substrate/src/metrics/storage_proof_overhead.rs delete mode 100644 relays/client-substrate/src/rpc.rs delete mode 100644 relays/client-substrate/src/sync_header.rs delete mode 100644 relays/finality/Cargo.toml delete mode 100644 relays/finality/src/finality_loop.rs delete mode 100644 relays/finality/src/finality_loop_tests.rs delete mode 100644 relays/finality/src/lib.rs delete mode 100644 relays/finality/src/sync_loop_metrics.rs delete mode 100644 relays/messages/Cargo.toml delete mode 100644 relays/messages/src/lib.rs delete mode 100644 relays/messages/src/message_lane.rs delete mode 100644 relays/messages/src/message_lane_loop.rs delete mode 100644 relays/messages/src/message_race_delivery.rs delete mode 100644 relays/messages/src/message_race_loop.rs delete mode 100644 relays/messages/src/message_race_receiving.rs delete mode 100644 relays/messages/src/message_race_strategy.rs delete mode 100644 relays/messages/src/metrics.rs delete mode 100644 relays/messages/src/relay_strategy/altruistic_strategy.rs delete mode 100644 relays/messages/src/relay_strategy/enforcement_strategy.rs delete mode 100644 relays/messages/src/relay_strategy/mix_strategy.rs delete mode 100644 relays/messages/src/relay_strategy/mod.rs delete mode 100644 relays/messages/src/relay_strategy/rational_strategy.rs delete mode 100644 relays/utils/Cargo.toml delete mode 100644 relays/utils/src/error.rs delete mode 100644 relays/utils/src/initialize.rs delete mode 100644 relays/utils/src/lib.rs delete mode 100644 relays/utils/src/metrics.rs delete mode 100644 relays/utils/src/metrics/float_json_value.rs delete mode 100644 relays/utils/src/metrics/global.rs delete mode 100644 relays/utils/src/relay_loop.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b48a56ec..a1e0cb0a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,11 +18,17 @@ jobs: - pallet-fee-market - pallet-bridge-grandpa - pallet-bridge-messages + - pallet-bridge-parachains + - bp-crab + - bp-crab-parachain + - bp-darwinia + - bp-kusama - bp-pangolin - - bp-pangoro - bp-pangolin-parachain + - bp-pangoro - bp-rococo - bp-darwinia-core + - bridge-runtime-common steps: - uses: actions/checkout@v2 - name: Check ${{ matrix.package }} diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7d3bf6fd8..6e476d3de 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,7 +66,7 @@ default: - if: $CI_PIPELINE_SOURCE == "pipeline" - if: $CI_PIPELINE_SOURCE == "web" - if: $CI_PIPELINE_SOURCE == "schedule" - - if: $CI_COMMIT_REF_NAME == "master" + - if: $CI_COMMIT_REF_NAME == "polkadot-v0.9.27" - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 diff --git a/Cargo.lock b/Cargo.lock index a8a767eda..82ea451df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,48 +27,13 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aead" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" -dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", - "opaque-debug 0.3.0", -] - -[[package]] -name = "aes-gcm" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - [[package]] name = "ahash" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", "once_cell", "version_check", ] @@ -93,9 +58,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" +checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" [[package]] name = "approx" @@ -106,12 +71,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "array_tool" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" - [[package]] name = "arrayref" version = "0.3.6" @@ -139,163 +98,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" -[[package]] -name = "asn1_der" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22d1f4b888c298a027c99dc9048015fac177587de20fc30232a057dfbe24a21" - [[package]] name = "assert_matches" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" -[[package]] -name = "async-attributes" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "async-channel" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8b508d585e01084059b60f06ade4cb7415cd2e4084b71dd1cb44e7d3fb9880" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" -dependencies = [ - "concurrent-queue", - "futures-lite", - "libc", - "log", - "once_cell", - "parking", - "polling", - "slab", - "socket2", - "waker-fn", - "winapi", -] - -[[package]] -name = "async-lock" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-process" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2c06e30a24e8c78a3987d07f0930edf76ef35e027e7bdb063fccafdad1f60c" -dependencies = [ - "async-io", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "libc", - "once_cell", - "signal-hook", - "winapi", -] - -[[package]] -name = "async-std" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52580991739c5cdb36cde8b2a516371c0a3b70dda36d916cc08b82372916808c" -dependencies = [ - "async-attributes", - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "num_cpus", - "once_cell", - "pin-project-lite 0.2.9", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-std-resolver" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2f8a4a203be3325981310ab243a28e6e4ea55b6519bffce05d41ab60e09ad8" -dependencies = [ - "async-std", - "async-trait", - "futures-io", - "futures-util", - "pin-utils", - "socket2", - "trust-dns-resolver", -] - -[[package]] -name = "async-task" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" - [[package]] name = "async-trait" version = "0.1.56" @@ -307,52 +115,12 @@ dependencies = [ "syn", ] -[[package]] -name = "asynchronous-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690" -dependencies = [ - "bytes", - "futures-sink", - "futures-util", - "memchr", - "pin-project-lite 0.2.9", -] - -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "backoff" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721c249ab59cbc483ad4294c9ee2671835c1e43e9ffc277e6b4ecfef733cfdc5" -dependencies = [ - "instant", - "rand 0.7.3", -] - [[package]] name = "backtrace" version = "0.3.65" @@ -368,12 +136,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base-x" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc19a4937b4fbd3fe3379793130e42060d10627a360f2127802b10b87e7baf74" - [[package]] name = "base16ct" version = "0.1.1" @@ -392,21 +154,6 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" -dependencies = [ - "serde", -] - -[[package]] -name = "bimap" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0455254eb5c6964c4545d8bac815e1a1be4f3afe0ae695ea539c12d728d44b" - [[package]] name = "bitflags" version = "1.3.2" @@ -444,48 +191,13 @@ dependencies = [ "constant_time_eq", ] -[[package]] -name = "blake2b_simd" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" -dependencies = [ - "arrayref", - "arrayvec 0.7.2", - "constant_time_eq", -] - -[[package]] -name = "blake2s_simd" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db539cc2b5f6003621f1cd9ef92d7ded8ea5232c7de0f9faa2de251cd98730d4" -dependencies = [ - "arrayref", - "arrayvec 0.7.2", - "constant_time_eq", -] - -[[package]] -name = "blake3" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" -dependencies = [ - "arrayref", - "arrayvec 0.7.2", - "cc", - "cfg-if", - "constant_time_eq", -] - [[package]] name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ - "block-padding 0.1.5", + "block-padding", "byte-tools", "byteorder", "generic-array 0.12.4", @@ -497,7 +209,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1", "generic-array 0.14.5", ] @@ -520,27 +231,21 @@ dependencies = [ ] [[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "blocking" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +name = "bp-crab" +version = "0.1.0" dependencies = [ - "async-channel", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "once_cell", + "bp-darwinia-core", + "bp-messages", + "bp-runtime", + "frame-support", + "sp-api", + "sp-runtime", + "sp-std", + "sp-version", ] [[package]] -name = "bp-crab" +name = "bp-crab-parachain" version = "0.1.0" dependencies = [ "bp-darwinia-core", @@ -554,7 +259,7 @@ dependencies = [ ] [[package]] -name = "bp-crab-parachain" +name = "bp-darwinia" version = "0.1.0" dependencies = [ "bp-darwinia-core", @@ -689,6 +394,19 @@ dependencies = [ "sp-version", ] +[[package]] +name = "bp-parachains" +version = "0.1.0" +dependencies = [ + "bp-polkadot-core", + "bp-runtime", + "frame-support", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", +] + [[package]] name = "bp-polkadot" version = "0.1.0" @@ -772,26 +490,13 @@ dependencies = [ "sp-std", ] -[[package]] -name = "bp-wococo" -version = "0.1.0" -dependencies = [ - "bp-messages", - "bp-polkadot-core", - "bp-rococo", - "bp-runtime", - "parity-scale-codec", - "sp-api", - "sp-runtime", - "sp-std", -] - [[package]] name = "bridge-runtime-common" version = "0.1.0" dependencies = [ "bp-message-dispatch", "bp-messages", + "bp-polkadot-core", "bp-runtime", "ed25519-dalek", "frame-support", @@ -801,6 +506,8 @@ dependencies = [ "pallet-bridge-dispatch", "pallet-bridge-grandpa", "pallet-bridge-messages", + "pallet-bridge-parachains", + "pallet-fee-market", "pallet-transaction-payment", "parity-scale-codec", "scale-info", @@ -811,22 +518,6 @@ dependencies = [ "sp-std", "sp-trie", "sp-version", - "static_assertions", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "memchr", ] [[package]] @@ -859,26 +550,11 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" -[[package]] -name = "cache-padded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" - -[[package]] -name = "castaway" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" - [[package]] name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" -dependencies = [ - "jobserver", -] [[package]] name = "cfg-if" @@ -887,81 +563,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "chacha20" -version = "0.8.1" +name = "chrono" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", - "zeroize", -] - -[[package]] -name = "chacha20poly1305" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "time 0.1.44", - "winapi", -] - -[[package]] -name = "cid" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc949bff6704880faf064c42a4854032ab07bfcf3a4fcb82a57470acededb69c" -dependencies = [ - "core2", - "multibase", - "multihash", - "serde", - "unsigned-varint", -] - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "cmake" -version = "0.1.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" -dependencies = [ - "cc", -] - -[[package]] -name = "concurrent-queue" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" -dependencies = [ - "cache-padded", + "libc", + "num-integer", + "num-traits", + "winapi", ] [[package]] @@ -976,31 +586,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - [[package]] name = "cpufeatures" version = "0.2.2" @@ -1010,60 +595,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" -dependencies = [ - "cfg-if", - "lazy_static", -] - [[package]] name = "crunchy" version = "0.2.2" @@ -1112,67 +643,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "ctor" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher", -] - -[[package]] -name = "cuckoofilter" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b810a8449931679f64cd7eef1bbd0fa315801b6d5d9cdc1ace2804d6529eee18" -dependencies = [ - "byteorder", - "fnv", - "rand 0.7.3", -] - -[[package]] -name = "curl" -version = "0.4.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d855aeef205b43f65a5001e0997d81f8efca7badad4fad7d897aa7f0d0651f" -dependencies = [ - "curl-sys", - "libc", - "openssl-probe", - "openssl-sys", - "schannel", - "socket2", - "winapi", -] - -[[package]] -name = "curl-sys" -version = "0.4.55+curl-7.83.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23734ec77368ec583c2e61dd3f0b0e5c98b93abe6d2a004ca06b91dd7e3e2762" -dependencies = [ - "cc", - "libc", - "libnghttp2-sys", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", - "winapi", -] - [[package]] name = "curve25519-dalek" version = "2.1.3" @@ -1199,45 +669,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "curve25519-dalek" -version = "4.0.0-pre.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4033478fbf70d6acf2655ac70da91ee65852d69daf7a67bf7a2f518fb47aafcf" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - -[[package]] -name = "data-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" - -[[package]] -name = "data-encoding-macro" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86927b7cd2fe88fa698b87404b287ab98d1a0063a34071d92e575b72d3029aca" -dependencies = [ - "data-encoding", - "data-encoding-macro-internal", -] - -[[package]] -name = "data-encoding-macro-internal" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5bbed42daaa95e780b60a50546aa345b8413a1e46f9a40a12907d3598f038db" -dependencies = [ - "data-encoding", - "syn", -] - [[package]] name = "der" version = "0.5.1" @@ -1287,34 +718,12 @@ dependencies = [ "subtle", ] -[[package]] -name = "dns-parser" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" -dependencies = [ - "byteorder", - "quick-error", -] - -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - [[package]] name = "downcast-rs" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" -[[package]] -name = "dtoa" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5caaa75cbd2b960ff1e5392d2cfb1f44717fffe12fc1f32b7b5d1267f99732a6" - [[package]] name = "dyn-clonable" version = "0.9.0" @@ -1338,9 +747,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" +checksum = "140206b78fb2bc3edbcfc9b5ccbd0b30699cfe8d348b8b31b330e47df5291a5a" [[package]] name = "ecdsa" @@ -1401,53 +810,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "encoding_rs" -version = "0.8.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enum-as-inner" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime 1.3.0", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "atty", - "humantime 2.1.0", - "log", - "regex", - "termcolor", -] - [[package]] name = "environmental" version = "1.1.3" @@ -1481,27 +843,12 @@ dependencies = [ "uint", ] -[[package]] -name = "event-listener" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" - [[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -[[package]] -name = "fastrand" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" -dependencies = [ - "instant", -] - [[package]] name = "ff" version = "0.11.1" @@ -1524,25 +871,10 @@ dependencies = [ "log", "num-traits", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot", "scale-info", ] -[[package]] -name = "finality-relay" -version = "0.1.0" -dependencies = [ - "async-std", - "async-trait", - "backoff", - "bp-header-chain", - "futures", - "log", - "num-traits", - "parking_lot 0.11.2", - "relay-utils", -] - [[package]] name = "fixed-hash" version = "0.7.0" @@ -1555,51 +887,10 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "fixedbitset" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" - -[[package]] -name = "flate2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" -dependencies = [ - "crc32fast", - "libz-sys", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "fork-tree" -version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "form_urlencoded" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" -dependencies = [ - "matches", - "percent-encoding", -] - [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "frame-support", "frame-system", @@ -1633,7 +924,7 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "bitflags", "frame-metadata", @@ -1663,7 +954,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "Inflector", "frame-support-procedural-tools", @@ -1675,7 +966,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", @@ -1687,7 +978,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "proc-macro2", "quote", @@ -1697,7 +988,7 @@ dependencies = [ [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "frame-support", "log", @@ -1766,21 +1057,6 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite 0.2.9", - "waker-fn", -] - [[package]] name = "futures-macro" version = "0.3.21" @@ -1792,17 +1068,6 @@ dependencies = [ "syn", ] -[[package]] -name = "futures-rustls" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01fe9932a224b72b45336d96040aa86386d674a31d0af27d800ea7bc8ca97fe" -dependencies = [ - "futures-io", - "rustls", - "webpki", -] - [[package]] name = "futures-sink" version = "0.3.21" @@ -1834,7 +1099,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite", "pin-utils", "slab", ] @@ -1873,23 +1138,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi 0.10.0+wasi-snapshot-preview1", -] - -[[package]] -name = "ghash" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" -dependencies = [ - "opaque-debug 0.3.0", - "polyval", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -1898,31 +1153,6 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" -[[package]] -name = "globset" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" -dependencies = [ - "aho-corasick", - "bstr", - "fnv", - "log", - "regex", -] - -[[package]] -name = "gloo-timers" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "group" version = "0.11.0" @@ -1934,25 +1164,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "h2" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util 0.7.3", - "tracing", -] - [[package]] name = "hash-db" version = "0.15.2" @@ -1986,12 +1197,6 @@ dependencies = [ "ahash", ] -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - [[package]] name = "hermit-abi" version = "0.1.19" @@ -2013,12 +1218,6 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" -[[package]] -name = "hex_fmt" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" - [[package]] name = "hmac" version = "0.8.1" @@ -2051,3105 +1250,929 @@ dependencies = [ ] [[package]] -name = "hostname" -version = "0.3.1" +name = "impl-codec" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" dependencies = [ - "libc", - "match_cfg", - "winapi", + "parity-scale-codec", ] [[package]] -name = "http" -version = "0.2.8" +name = "impl-rlp" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" dependencies = [ - "bytes", - "fnv", - "itoa 1.0.2", + "rlp", ] [[package]] -name = "http-body" -version = "0.4.5" +name = "impl-serde" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" dependencies = [ - "bytes", - "http", - "pin-project-lite 0.2.9", + "serde", ] [[package]] -name = "httparse" -version = "1.7.1" +name = "impl-trait-for-tuples" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "httpdate" -version = "1.0.2" +name = "integer-sqrt" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] [[package]] -name = "humantime" -version = "1.3.0" +name = "itoa" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] -name = "humantime" -version = "2.1.0" +name = "itoa" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] -name = "hyper" -version = "0.14.19" +name = "js-sys" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa 1.0.2", - "pin-project-lite 0.2.9", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", + "wasm-bindgen", ] [[package]] -name = "idna" -version = "0.2.3" +name = "k256" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "cfg-if", + "ecdsa", + "elliptic-curve", + "sec1", ] [[package]] -name = "if-addrs" -version = "0.7.0" +name = "keccak" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" -dependencies = [ - "libc", - "winapi", -] +checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" [[package]] -name = "if-watch" -version = "1.1.1" +name = "lazy_static" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "015a7df1eb6dda30df37f34b63ada9b7b352984b0e84de2a20ed526345000791" -dependencies = [ - "async-io", - "core-foundation", - "fnv", - "futures", - "if-addrs", - "ipnet", - "log", - "rtnetlink", - "system-configuration", - "windows", -] +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] -name = "impl-codec" -version = "0.6.0" +name = "libc" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] -name = "impl-rlp" -version = "0.3.0" +name = "libm" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] +checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" [[package]] -name = "impl-serde" -version = "0.3.2" +name = "libsecp256k1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", "serde", + "sha2 0.9.9", + "typenum", ] [[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" +name = "libsecp256k1-core" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" dependencies = [ - "proc-macro2", - "quote", - "syn", + "crunchy", + "digest 0.9.0", + "subtle", ] [[package]] -name = "indexmap" -version = "1.8.2" +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" dependencies = [ - "autocfg", - "hashbrown 0.11.2", + "libsecp256k1-core", ] [[package]] -name = "instant" -version = "0.1.12" +name = "libsecp256k1-gen-genmult" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" dependencies = [ - "cfg-if", + "libsecp256k1-core", ] [[package]] -name = "integer-sqrt" -version = "0.1.5" +name = "linregress" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +checksum = "d6c601a85f5ecd1aba625247bca0031585fb1c446461b142878a16f8245ddeb8" dependencies = [ - "num-traits", + "nalgebra", + "statrs", ] [[package]] -name = "ip_network" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" - -[[package]] -name = "ipconfig" -version = "0.3.0" +name = "lock_api" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723519edce41262b05d4143ceb95050e4c614f483e78e9fd9e39a8275a84ad98" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ - "socket2", - "widestring", - "winapi", - "winreg", + "autocfg", + "scopeguard", ] [[package]] -name = "ipnet" -version = "2.5.0" +name = "log" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] [[package]] -name = "isahc" -version = "1.7.2" +name = "lru" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" +checksum = "c84e6fe5655adc6ce00787cf7dcaf8dc4f998a0565d23eafc207a8b08ca3349a" dependencies = [ - "async-channel", - "castaway", - "crossbeam-utils", - "curl", - "curl-sys", - "encoding_rs", - "event-listener", - "futures-lite", - "http", - "log", - "mime", - "once_cell", - "polling", - "slab", - "sluice", - "tracing", - "tracing-futures", - "url", - "waker-fn", + "hashbrown 0.11.2", ] [[package]] -name = "itertools" -version = "0.10.3" +name = "matchers" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" dependencies = [ - "either", + "regex-automata", ] [[package]] -name = "itoa" -version = "0.4.8" +name = "matrixmultiply" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84" +dependencies = [ + "rawpointer", +] [[package]] -name = "itoa" -version = "1.0.2" +name = "memchr" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] -name = "jobserver" -version = "0.1.24" +name = "memory-db" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "6566c70c1016f525ced45d7b7f97730a2bafb037c788211d0c186ef5b2189f0a" dependencies = [ - "libc", + "hash-db", + "hashbrown 0.12.1", + "parity-util-mem", ] [[package]] -name = "js-sys" -version = "0.3.57" +name = "memory_units" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" -dependencies = [ - "wasm-bindgen", -] +checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" [[package]] -name = "jsonpath_lib" -version = "0.2.6" +name = "merlin" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61352ec23883402b7d30b3313c16cbabefb8907361c4eb669d990cbb87ceee5a" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" dependencies = [ - "array_tool", - "env_logger 0.7.1", - "log", - "serde", - "serde_json", -] - -[[package]] -name = "jsonrpsee" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05fd8cd6c6b1bbd06881d2cf88f1fc83cc36c98f2219090f839115fb4a956cb9" -dependencies = [ - "jsonrpsee-core 0.8.0", - "jsonrpsee-proc-macros 0.8.0", - "jsonrpsee-types 0.8.0", - "jsonrpsee-ws-client", -] - -[[package]] -name = "jsonrpsee" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11e017217fcd18da0a25296d3693153dd19c8a6aadab330b3595285d075385d1" -dependencies = [ - "jsonrpsee-core 0.14.0", - "jsonrpsee-http-server", - "jsonrpsee-proc-macros 0.14.0", - "jsonrpsee-types 0.14.0", - "jsonrpsee-ws-server", - "tracing", -] - -[[package]] -name = "jsonrpsee-client-transport" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3303cdf246e6ab76e2866fb3d9acb6c76a068b1b28bd923a1b7a8122257ad7b5" -dependencies = [ - "futures", - "http", - "jsonrpsee-core 0.8.0", - "jsonrpsee-types 0.8.0", - "pin-project", - "rustls-native-certs", - "soketto", - "thiserror", - "tokio", - "tokio-rustls", - "tokio-util 0.6.10", - "tracing", - "webpki-roots", -] - -[[package]] -name = "jsonrpsee-core" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f220b5a238dc7992b90f1144fbf6eaa585872c9376afe6fe6863ffead6191bf3" -dependencies = [ - "anyhow", - "arrayvec 0.7.2", - "async-trait", - "beef", - "futures-channel", - "futures-util", - "hyper", - "jsonrpsee-types 0.8.0", - "rustc-hash", - "serde", - "serde_json", - "soketto", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "jsonrpsee-core" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16efcd4477de857d4a2195a45769b2fe9ebb54f3ef5a4221d3b014a4fe33ec0b" -dependencies = [ - "anyhow", - "arrayvec 0.7.2", - "async-trait", - "beef", - "futures-channel", - "futures-util", - "globset", - "hyper", - "jsonrpsee-types 0.14.0", - "lazy_static", - "parking_lot 0.12.1", - "rand 0.8.5", - "rustc-hash", - "serde", - "serde_json", - "soketto", - "thiserror", - "tokio", - "tracing", - "unicase", -] - -[[package]] -name = "jsonrpsee-http-server" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd69efeb3ce2cba767f126872f4eeb4624038a29098e75d77608b2b4345ad03" -dependencies = [ - "futures-channel", - "futures-util", - "hyper", - "jsonrpsee-core 0.14.0", - "jsonrpsee-types 0.14.0", - "serde", - "serde_json", - "tokio", - "tracing", -] - -[[package]] -name = "jsonrpsee-proc-macros" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4299ebf790ea9de1cb72e73ff2ae44c723ef264299e5e2d5ef46a371eb3ac3d8" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "jsonrpsee-proc-macros" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874cf3f6a027cebf36cae767feca9aa2e8a8f799880e49eb5540819fcbd8eada" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "jsonrpsee-types" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b3f601bbbe45cd63f5407b6f7d7950e08a7d4f82aa699ff41a4a5e9e54df58" -dependencies = [ - "anyhow", - "beef", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "jsonrpsee-types" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcf76cd316f5d3ad48138085af1f45e2c58c98e02f0779783dbb034d43f7c86" -dependencies = [ - "anyhow", - "beef", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "jsonrpsee-ws-client" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aff425cee7c779e33920913bc695447416078ee6d119f443f3060feffa4e86b5" -dependencies = [ - "jsonrpsee-client-transport", - "jsonrpsee-core 0.8.0", - "jsonrpsee-types 0.8.0", -] - -[[package]] -name = "jsonrpsee-ws-server" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd2e4d266774a671f8def3794255b28eddd09b18d76e0b913fa439f34588c0a" -dependencies = [ - "futures-channel", - "futures-util", - "jsonrpsee-core 0.14.0", - "jsonrpsee-types 0.14.0", - "serde_json", - "soketto", - "tokio", - "tokio-stream", - "tokio-util 0.7.3", - "tracing", -] - -[[package]] -name = "k256" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "sec1", -] - -[[package]] -name = "keccak" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" - -[[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.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a301d8ecb7989d4a6e2c57a49baca77d353bdbf879909debe3f375fe25d61f86" -dependencies = [ - "parity-util-mem", - "smallvec", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "libm" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" - -[[package]] -name = "libnghttp2-sys" -version = "0.1.7+1.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ed28aba195b38d5ff02b9170cbff627e336a20925e43b4945390401c5dc93f" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "libp2p" -version = "0.46.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81327106887e42d004fbdab1fef93675be2e2e07c1b95fce45e2cc813485611d" -dependencies = [ - "bytes", - "futures", - "futures-timer", - "getrandom 0.2.6", - "instant", - "lazy_static", - "libp2p-autonat", - "libp2p-core", - "libp2p-deflate", - "libp2p-dns", - "libp2p-floodsub", - "libp2p-gossipsub", - "libp2p-identify", - "libp2p-kad", - "libp2p-mdns", - "libp2p-metrics", - "libp2p-mplex", - "libp2p-noise", - "libp2p-ping", - "libp2p-plaintext", - "libp2p-pnet", - "libp2p-relay", - "libp2p-rendezvous", - "libp2p-request-response", - "libp2p-swarm", - "libp2p-swarm-derive", - "libp2p-tcp", - "libp2p-uds", - "libp2p-wasm-ext", - "libp2p-websocket", - "libp2p-yamux", - "multiaddr", - "parking_lot 0.12.1", - "pin-project", - "rand 0.7.3", - "smallvec", -] - -[[package]] -name = "libp2p-autonat" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4decc51f3573653a9f4ecacb31b1b922dd20c25a6322bb15318ec04287ec46f9" -dependencies = [ - "async-trait", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-request-response", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.8.5", -] - -[[package]] -name = "libp2p-core" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf9b94cefab7599b2d3dff2f93bee218c6621d68590b23ede4485813cbcece6" -dependencies = [ - "asn1_der", - "bs58", - "ed25519-dalek", - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "lazy_static", - "libsecp256k1", - "log", - "multiaddr", - "multihash", - "multistream-select", - "parking_lot 0.12.1", - "pin-project", - "prost", - "prost-build", - "rand 0.8.5", - "ring", - "rw-stream-sink", - "sha2 0.10.2", - "smallvec", - "thiserror", - "unsigned-varint", - "void", - "zeroize", -] - -[[package]] -name = "libp2p-deflate" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0183dc2a3da1fbbf85e5b6cf51217f55b14f5daea0c455a9536eef646bfec71" -dependencies = [ - "flate2", - "futures", - "libp2p-core", -] - -[[package]] -name = "libp2p-dns" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbf54723250fa5d521383be789bf60efdabe6bacfb443f87da261019a49b4b5" -dependencies = [ - "async-std-resolver", - "futures", - "libp2p-core", - "log", - "parking_lot 0.12.1", - "smallvec", - "trust-dns-resolver", -] - -[[package]] -name = "libp2p-floodsub" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98a4b6ffd53e355775d24b76f583fdda54b3284806f678499b57913adb94f231" -dependencies = [ - "cuckoofilter", - "fnv", - "futures", - "libp2p-core", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.7.3", - "smallvec", -] - -[[package]] -name = "libp2p-gossipsub" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b4b888cfbeb1f5551acd3aa1366e01bf88ede26cc3c4645d0d2d004d5ca7b0" -dependencies = [ - "asynchronous-codec", - "base64", "byteorder", - "bytes", - "fnv", - "futures", - "hex_fmt", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "prometheus-client", - "prost", - "prost-build", - "rand 0.7.3", - "regex", - "sha2 0.10.2", - "smallvec", - "unsigned-varint", - "wasm-timer", -] - -[[package]] -name = "libp2p-identify" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50b585518f8efd06f93ac2f976bd672e17cdac794644b3117edd078e96bda06" -dependencies = [ - "asynchronous-codec", - "futures", - "futures-timer", - "libp2p-core", - "libp2p-swarm", - "log", - "lru", - "prost", - "prost-build", - "prost-codec", - "smallvec", - "thiserror", - "void", -] - -[[package]] -name = "libp2p-kad" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740862893bb5f06ac24acc9d49bdeadc3a5e52e51818a30a25c1f3519da2c851" -dependencies = [ - "arrayvec 0.7.2", - "asynchronous-codec", - "bytes", - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.7.3", - "sha2 0.10.2", - "smallvec", - "thiserror", - "uint", - "unsigned-varint", - "void", -] - -[[package]] -name = "libp2p-mdns" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66e5e5919509603281033fd16306c61df7a4428ce274b67af5e14b07de5cdcb2" -dependencies = [ - "async-io", - "data-encoding", - "dns-parser", - "futures", - "if-watch", - "lazy_static", - "libp2p-core", - "libp2p-swarm", - "log", - "rand 0.8.5", - "smallvec", - "socket2", - "void", -] - -[[package]] -name = "libp2p-metrics" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8aff4a1abef42328fbb30b17c853fff9be986dc39af17ee39f9c5f755c5e0c" -dependencies = [ - "libp2p-core", - "libp2p-gossipsub", - "libp2p-identify", - "libp2p-kad", - "libp2p-ping", - "libp2p-relay", - "libp2p-swarm", - "prometheus-client", -] - -[[package]] -name = "libp2p-mplex" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61fd1b20638ec209c5075dfb2e8ce6a7ea4ec3cd3ad7b77f7a477c06d53322e2" -dependencies = [ - "asynchronous-codec", - "bytes", - "futures", - "libp2p-core", - "log", - "nohash-hasher", - "parking_lot 0.12.1", - "rand 0.7.3", - "smallvec", - "unsigned-varint", -] - -[[package]] -name = "libp2p-noise" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "762408cb5d84b49a600422d7f9a42c18012d8da6ebcd570f9a4a4290ba41fb6f" -dependencies = [ - "bytes", - "curve25519-dalek 3.2.0", - "futures", - "lazy_static", - "libp2p-core", - "log", - "prost", - "prost-build", - "rand 0.8.5", - "sha2 0.10.2", - "snow", - "static_assertions", - "x25519-dalek", - "zeroize", -] - -[[package]] -name = "libp2p-ping" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "100a6934ae1dbf8a693a4e7dd1d730fd60b774dafc45688ed63b554497c6c925" -dependencies = [ - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "rand 0.7.3", - "void", -] - -[[package]] -name = "libp2p-plaintext" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be27bf0820a6238a4e06365b096d428271cce85a129cf16f2fe9eb1610c4df86" -dependencies = [ - "asynchronous-codec", - "bytes", - "futures", - "libp2p-core", - "log", - "prost", - "prost-build", - "unsigned-varint", - "void", -] - -[[package]] -name = "libp2p-pnet" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" -dependencies = [ - "futures", - "log", - "pin-project", - "rand 0.7.3", - "salsa20", - "sha3 0.9.1", -] - -[[package]] -name = "libp2p-relay" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4931547ee0cce03971ccc1733ff05bb0c4349fd89120a39e9861e2bbe18843c3" -dependencies = [ - "asynchronous-codec", - "bytes", - "either", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "pin-project", - "prost", - "prost-build", - "prost-codec", - "rand 0.8.5", - "smallvec", - "static_assertions", - "thiserror", - "void", -] - -[[package]] -name = "libp2p-rendezvous" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9511c9672ba33284838e349623319c8cad2d18cfad243ae46c6b7e8a2982ea4e" -dependencies = [ - "asynchronous-codec", - "bimap", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "prost", - "prost-build", - "rand 0.8.5", - "sha2 0.10.2", - "thiserror", - "unsigned-varint", - "void", -] - -[[package]] -name = "libp2p-request-response" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "508a189e2795d892c8f5c1fa1e9e0b1845d32d7b0b249dbf7b05b18811361843" -dependencies = [ - "async-trait", - "bytes", - "futures", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "rand 0.7.3", - "smallvec", - "unsigned-varint", -] - -[[package]] -name = "libp2p-swarm" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ac5be6c2de2d1ff3f7693fda6faf8a827b1f3e808202277783fea9f527d114" -dependencies = [ - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "log", - "pin-project", - "rand 0.7.3", - "smallvec", - "thiserror", - "void", -] - -[[package]] -name = "libp2p-swarm-derive" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f54a64b6957249e0ce782f8abf41d97f69330d02bf229f0672d864f0650cc76" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "libp2p-tcp" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a6771dc19aa3c65d6af9a8c65222bfc8fcd446630ddca487acd161fa6096f3b" -dependencies = [ - "async-io", - "futures", - "futures-timer", - "if-watch", - "ipnet", - "libc", - "libp2p-core", - "log", - "socket2", -] - -[[package]] -name = "libp2p-uds" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d125e3e5f0d58f3c6ac21815b20cf4b6a88b8db9dc26368ea821838f4161fd4d" -dependencies = [ - "async-std", - "futures", - "libp2p-core", - "log", -] - -[[package]] -name = "libp2p-wasm-ext" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec894790eec3c1608f8d1a8a0bdf0dbeb79ed4de2dce964222011c2896dfa05a" -dependencies = [ - "futures", - "js-sys", - "libp2p-core", - "parity-send-wrapper", - "wasm-bindgen", - "wasm-bindgen-futures", -] - -[[package]] -name = "libp2p-websocket" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9808e57e81be76ff841c106b4c5974fb4d41a233a7bdd2afbf1687ac6def3818" -dependencies = [ - "either", - "futures", - "futures-rustls", - "libp2p-core", - "log", - "parking_lot 0.12.1", - "quicksink", - "rw-stream-sink", - "soketto", - "url", - "webpki-roots", -] - -[[package]] -name = "libp2p-yamux" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6dea686217a06072033dc025631932810e2f6ad784e4fafa42e27d311c7a81c" -dependencies = [ - "futures", - "libp2p-core", - "parking_lot 0.12.1", - "thiserror", - "yamux", -] - -[[package]] -name = "libsecp256k1" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" -dependencies = [ - "arrayref", - "base64", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", - "rand 0.8.5", - "serde", - "sha2 0.9.9", - "typenum", -] - -[[package]] -name = "libsecp256k1-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" -dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", -] - -[[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libsecp256k1-gen-genmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libz-sys" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "linked_hash_set" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "linregress" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c601a85f5ecd1aba625247bca0031585fb1c446461b142878a16f8245ddeb8" -dependencies = [ - "nalgebra", - "statrs", -] - -[[package]] -name = "lock_api" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", - "value-bag", -] - -[[package]] -name = "lru" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8015d95cb7b2ddd3c0d32ca38283ceb1eea09b4713ee380bceb942d85a244228" -dependencies = [ - "hashbrown 0.11.2", -] - -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - -[[package]] -name = "matchers" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - -[[package]] -name = "matrixmultiply" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84" -dependencies = [ - "rawpointer", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memmap2" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5172b50c23043ff43dd53e51392f36519d9b35a8f3a410d30ece5d1aedd58ae" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memory-db" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6566c70c1016f525ced45d7b7f97730a2bafb037c788211d0c186ef5b2189f0a" -dependencies = [ - "hash-db", - "hashbrown 0.12.1", - "parity-util-mem", -] - -[[package]] -name = "memory_units" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" - -[[package]] -name = "merlin" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" -dependencies = [ - "byteorder", - "keccak", - "rand_core 0.5.1", - "zeroize", -] - -[[package]] -name = "messages-relay" -version = "0.1.0" -dependencies = [ - "async-std", - "async-trait", - "bp-messages", - "bp-runtime", - "finality-relay", - "futures", - "hex", - "log", - "num-traits", - "parking_lot 0.11.2", - "relay-utils", - "sp-arithmetic", -] - -[[package]] -name = "mime" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - -[[package]] -name = "miniz_oxide" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", -] - -[[package]] -name = "multiaddr" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" -dependencies = [ - "arrayref", - "bs58", - "byteorder", - "data-encoding", - "multihash", - "percent-encoding", - "serde", - "static_assertions", - "unsigned-varint", - "url", -] - -[[package]] -name = "multibase" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" -dependencies = [ - "base-x", - "data-encoding", - "data-encoding-macro", -] - -[[package]] -name = "multihash" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3db354f401db558759dfc1e568d010a5d4146f4d3f637be1275ec4a3cf09689" -dependencies = [ - "blake2b_simd", - "blake2s_simd", - "blake3", - "core2", - "digest 0.10.3", - "multihash-derive", - "sha2 0.10.2", - "sha3 0.10.1", - "unsigned-varint", -] - -[[package]] -name = "multihash-derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" -dependencies = [ - "proc-macro-crate", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "multistream-select" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363a84be6453a70e63513660f4894ef815daf88e3356bffcda9ca27d810ce83b" -dependencies = [ - "bytes", - "futures", - "log", - "pin-project", - "smallvec", - "unsigned-varint", -] - -[[package]] -name = "nalgebra" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462fffe4002f4f2e1f6a9dcf12cc1a6fc0e15989014efc02a941d3e0f5dc2120" -dependencies = [ - "approx", - "matrixmultiply", - "nalgebra-macros", - "num-complex", - "num-rational 0.4.0", - "num-traits", - "rand 0.8.5", - "rand_distr", - "simba", - "typenum", -] - -[[package]] -name = "nalgebra-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "netlink-packet-core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" -dependencies = [ - "anyhow", - "byteorder", - "libc", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-route" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" -dependencies = [ - "anyhow", - "bitflags", - "byteorder", - "libc", - "netlink-packet-core", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-utils" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25af9cf0dc55498b7bd94a1508af7a78706aa0ab715a73c5169273e03c84845e" -dependencies = [ - "anyhow", - "byteorder", - "paste", - "thiserror", -] - -[[package]] -name = "netlink-proto" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" -dependencies = [ - "bytes", - "futures", - "log", - "netlink-packet-core", - "netlink-sys", - "thiserror", - "tokio", -] - -[[package]] -name = "netlink-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b654097027250401127914afb37cb1f311df6610a9891ff07a757e94199027" -dependencies = [ - "async-io", - "bytes", - "futures", - "libc", - "log", -] - -[[package]] -name = "nix" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-format" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" -dependencies = [ - "arrayvec 0.4.12", - "itoa 0.4.8", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", -] - -[[package]] -name = "object" -version = "0.28.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "owning_ref" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" -dependencies = [ - "stable_deref_trait", -] - -[[package]] -name = "pallet-balances" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "parity-scale-codec", - "scale-info", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-bridge-dispatch" -version = "0.1.0" -dependencies = [ - "bp-message-dispatch", - "bp-runtime", - "frame-support", - "frame-system", - "log", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-bridge-grandpa" -version = "0.1.0" -dependencies = [ - "bp-header-chain", - "bp-runtime", - "bp-test-utils", - "finality-grandpa", - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "num-traits", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-finality-grandpa", - "sp-io", - "sp-runtime", - "sp-std", - "sp-trie", -] - -[[package]] -name = "pallet-bridge-messages" -version = "0.1.0" -dependencies = [ - "bitvec", - "bp-message-dispatch", - "bp-messages", - "bp-runtime", - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "num-traits", - "pallet-balances", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-bridge-parachains" -version = "0.1.0" -dependencies = [ - "bp-header-chain", - "bp-polkadot-core", - "bp-runtime", - "bp-test-utils", - "frame-support", - "frame-system", - "log", - "pallet-bridge-grandpa", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-trie", -] - -[[package]] -name = "pallet-fee-market" -version = "0.1.0" -dependencies = [ - "bitvec", - "bp-messages", - "bp-runtime", - "frame-benchmarking", - "frame-support", - "frame-system", - "pallet-balances", - "pallet-bridge-messages", - "pallet-timestamp", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-timestamp" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "parity-scale-codec", - "scale-info", - "sp-inherents", - "sp-runtime", - "sp-std", - "sp-timestamp", -] - -[[package]] -name = "pallet-transaction-payment" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-transaction-payment-rpc-runtime-api" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "pallet-transaction-payment", - "parity-scale-codec", - "sp-api", - "sp-runtime", -] - -[[package]] -name = "parity-scale-codec" -version = "3.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b44461635bbb1a0300f100a841e571e7d919c81c73075ef5d152ffdb521066" -dependencies = [ - "arrayvec 0.7.2", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "parity-send-wrapper" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" - -[[package]] -name = "parity-util-mem" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c32561d248d352148124f036cac253a644685a21dc9fea383eb4907d7bd35a8f" -dependencies = [ - "cfg-if", - "ethereum-types", - "hashbrown 0.12.1", - "impl-trait-for-tuples", - "lru", - "parity-util-mem-derive", - "parking_lot 0.12.1", - "primitive-types", - "smallvec", - "winapi", -] - -[[package]] -name = "parity-util-mem-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" -dependencies = [ - "proc-macro2", - "syn", - "synstructure", -] - -[[package]] -name = "parity-wasm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.5", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.3", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - -[[package]] -name = "paste" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" - -[[package]] -name = "pbkdf2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" -dependencies = [ - "crypto-mac 0.8.0", -] - -[[package]] -name = "pbkdf2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" -dependencies = [ - "crypto-mac 0.11.1", -] - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "petgraph" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "pin-project" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" - -[[package]] -name = "polling" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" -dependencies = [ - "cfg-if", - "libc", - "log", - "wepoll-ffi", - "winapi", -] - -[[package]] -name = "poly1305" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" -dependencies = [ - "cpufeatures", - "opaque-debug 0.3.0", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug 0.3.0", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "primitive-types" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" -dependencies = [ - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prometheus" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cface98dfa6d645ea4c789839f176e4b072265d085bfcc48eaa8d137f58d3c39" -dependencies = [ - "cfg-if", - "fnv", - "lazy_static", - "memchr", - "parking_lot 0.12.1", - "thiserror", -] - -[[package]] -name = "prometheus-client" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1abe0255c04d15f571427a2d1e00099016506cf3297b53853acd2b7eb87825" -dependencies = [ - "dtoa", - "itoa 1.0.2", - "owning_ref", - "prometheus-client-derive-text-encode", -] - -[[package]] -name = "prometheus-client-derive-text-encode" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e12d01b9d66ad9eb4529c57666b6263fc1993cb30261d83ead658fdd932652" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "prost" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae5a4388762d5815a9fc0dea33c56b021cdc8dde0c55e0c9ca57197254b0cab" -dependencies = [ - "bytes", - "cfg-if", - "cmake", - "heck", - "itertools", - "lazy_static", - "log", - "multimap", - "petgraph", - "prost", - "prost-types", - "regex", - "tempfile", - "which", -] - -[[package]] -name = "prost-codec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00af1e92c33b4813cc79fda3f2dbf56af5169709be0202df730e9ebc3e4cd007" -dependencies = [ - "asynchronous-codec", - "bytes", - "prost", - "thiserror", - "unsigned-varint", -] - -[[package]] -name = "prost-derive" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "prost-types" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" -dependencies = [ - "bytes", - "prost", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quicksink" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" -dependencies = [ - "futures-core", - "futures-sink", - "pin-project-lite 0.1.12", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", - "rand_pcg", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.3", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", + "keccak", "rand_core 0.5.1", + "zeroize", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "miniz_oxide" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ - "ppv-lite86", - "rand_core 0.6.3", + "adler", ] [[package]] -name = "rand_core" -version = "0.5.1" +name = "nalgebra" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "462fffe4002f4f2e1f6a9dcf12cc1a6fc0e15989014efc02a941d3e0f5dc2120" dependencies = [ - "getrandom 0.1.16", + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational 0.4.1", + "num-traits", + "rand 0.8.5", + "rand_distr", + "simba", + "typenum", ] [[package]] -name = "rand_core" -version = "0.6.3" +name = "nalgebra-macros" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218" dependencies = [ - "getrandom 0.2.6", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "rand_distr" -version = "0.4.3" +name = "nodrop" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" -dependencies = [ - "num-traits", - "rand 0.8.5", -] +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] -name = "rand_hc" -version = "0.2.0" +name = "num-bigint" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "rand_core 0.5.1", + "autocfg", + "num-integer", + "num-traits", ] [[package]] -name = "rand_pcg" -version = "0.2.1" +name = "num-complex" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" dependencies = [ - "rand_core 0.5.1", + "num-traits", ] [[package]] -name = "rawpointer" -version = "0.2.1" +name = "num-format" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" +checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" +dependencies = [ + "arrayvec 0.4.12", + "itoa 0.4.8", +] [[package]] -name = "rayon" -version = "1.5.3" +name = "num-integer" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", - "crossbeam-deque", - "either", - "rayon-core", + "num-traits", ] [[package]] -name = "rayon-core" -version = "1.9.3" +name = "num-rational" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", + "autocfg", + "num-bigint", + "num-integer", + "num-traits", ] [[package]] -name = "redox_syscall" -version = "0.2.13" +name = "num-rational" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ - "bitflags", + "autocfg", + "num-integer", + "num-traits", ] [[package]] -name = "ref-cast" -version = "1.0.7" +name = "num-traits" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685d58625b6c2b83e4cc88a27c4bf65adb7b6b16dbdc413e515c9405b47432ab" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "ref-cast-impl", + "autocfg", + "libm", ] [[package]] -name = "ref-cast-impl" -version = "1.0.7" +name = "num_cpus" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a043824e29c94169374ac5183ac0ed43f5724dc4556b19568007486bd840fa1f" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "proc-macro2", - "quote", - "syn", + "hermit-abi", + "libc", ] [[package]] -name = "regex" -version = "1.5.6" +name = "object" +version = "0.28.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" dependencies = [ - "aho-corasick", "memchr", - "regex-syntax", ] [[package]] -name = "regex-automata" -version = "0.1.10" +name = "once_cell" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax", -] +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" [[package]] -name = "regex-syntax" -version = "0.6.26" +name = "opaque-debug" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] -name = "relay-kusama-client" +name = "pallet-balances" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-bridge-dispatch" version = "0.1.0" dependencies = [ - "bp-header-chain", - "bp-kusama", "bp-message-dispatch", - "bp-messages", - "bp-polkadot", - "bp-polkadot-core", "bp-runtime", - "bridge-runtime-common", "frame-support", - "pallet-bridge-dispatch", + "frame-system", + "log", "parity-scale-codec", - "relay-substrate-client", - "relay-utils", "scale-info", "sp-core", + "sp-io", "sp-runtime", + "sp-std", ] [[package]] -name = "relay-polkadot-client" +name = "pallet-bridge-grandpa" version = "0.1.0" dependencies = [ "bp-header-chain", - "bp-kusama", + "bp-runtime", + "bp-test-utils", + "finality-grandpa", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-finality-grandpa", + "sp-io", + "sp-runtime", + "sp-std", + "sp-trie", +] + +[[package]] +name = "pallet-bridge-messages" +version = "0.1.0" +dependencies = [ + "bitvec", "bp-message-dispatch", "bp-messages", - "bp-polkadot", - "bp-polkadot-core", "bp-runtime", - "bridge-runtime-common", + "frame-benchmarking", "frame-support", - "pallet-bridge-dispatch", + "frame-system", + "log", + "num-traits", + "pallet-balances", "parity-scale-codec", - "relay-substrate-client", - "relay-utils", "scale-info", + "serde", "sp-core", + "sp-io", "sp-runtime", + "sp-std", ] [[package]] -name = "relay-rococo-client" +name = "pallet-bridge-parachains" version = "0.1.0" dependencies = [ "bp-header-chain", - "bp-message-dispatch", - "bp-messages", + "bp-parachains", "bp-polkadot-core", - "bp-rococo", "bp-runtime", - "bp-wococo", - "bridge-runtime-common", + "bp-test-utils", "frame-support", - "pallet-bridge-dispatch", - "pallet-bridge-messages", + "frame-system", + "log", + "pallet-bridge-grandpa", "parity-scale-codec", - "relay-substrate-client", - "relay-utils", "scale-info", + "serde", "sp-core", + "sp-io", "sp-runtime", + "sp-std", + "sp-trie", ] [[package]] -name = "relay-substrate-client" +name = "pallet-fee-market" version = "0.1.0" dependencies = [ - "async-std", - "async-trait", - "bp-header-chain", + "bitvec", "bp-messages", "bp-runtime", - "finality-relay", + "frame-benchmarking", "frame-support", "frame-system", - "futures", - "jsonrpsee 0.8.0", - "log", - "num-traits", "pallet-balances", "pallet-bridge-messages", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", + "pallet-timestamp", "parity-scale-codec", - "rand 0.7.3", - "relay-utils", - "sc-chain-spec", - "sc-rpc-api", - "sc-transaction-pool-api", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-timestamp" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-inherents", + "sp-runtime", + "sp-std", + "sp-timestamp", +] + +[[package]] +name = "pallet-transaction-payment" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", "serde", "sp-core", - "sp-finality-grandpa", - "sp-rpc", + "sp-io", "sp-runtime", - "sp-storage", - "sp-trie", - "sp-version", - "thiserror", - "tokio", + "sp-std", ] [[package]] -name = "relay-utils" -version = "0.1.0" +name = "parity-scale-codec" +version = "3.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9182e4a71cae089267ab03e67c99368db7cd877baf50f931e5d6d4b71e195ac0" dependencies = [ - "ansi_term", - "anyhow", - "async-std", - "async-trait", - "backoff", - "bp-runtime", - "env_logger 0.8.4", - "futures", - "isahc", - "jsonpath_lib", - "log", - "num-traits", - "serde_json", - "substrate-prometheus-endpoint", - "sysinfo", - "thiserror", - "time 0.3.9", - "tokio", + "arrayvec 0.7.2", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", ] [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "parity-scale-codec-derive" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +checksum = "9299338969a3d2f491d65f140b00ddec470858402f888af98e8642fb5e8965cd" dependencies = [ - "winapi", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "resolv-conf" -version = "0.7.0" +name = "parity-util-mem" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +checksum = "c32561d248d352148124f036cac253a644685a21dc9fea383eb4907d7bd35a8f" dependencies = [ - "hostname", - "quick-error", + "cfg-if", + "ethereum-types", + "hashbrown 0.12.1", + "impl-trait-for-tuples", + "lru", + "parity-util-mem-derive", + "parking_lot", + "primitive-types", + "smallvec", + "winapi", ] [[package]] -name = "rfc6979" +name = "parity-util-mem-derive" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ - "crypto-bigint", - "hmac 0.11.0", - "zeroize", + "proc-macro2", + "syn", + "synstructure", ] [[package]] -name = "ring" -version = "0.16.20" +name = "parity-wasm" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] +checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" [[package]] -name = "rlp" -version = "0.5.1" +name = "parking_lot" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999508abb0ae792aabed2460c45b89106d97fe4adac593bdaef433c2605847b5" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "bytes", - "rustc-hex", + "lock_api", + "parking_lot_core", ] [[package]] -name = "rtnetlink" -version = "0.10.1" +name = "parking_lot_core" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ - "async-global-executor", - "futures", - "log", - "netlink-packet-route", - "netlink-proto", - "nix", - "thiserror", + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", ] [[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hex" -version = "2.1.0" +name = "paste" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" [[package]] -name = "rustc_version" +name = "pbkdf2" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" dependencies = [ - "semver", + "crypto-mac 0.8.0", ] [[package]] -name = "rustls" -version = "0.20.6" +name = "pbkdf2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" dependencies = [ - "log", - "ring", - "sct", - "webpki", + "crypto-mac 0.11.1", ] [[package]] -name = "rustls-native-certs" -version = "0.6.2" +name = "pin-project-lite" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "schannel", - "security-framework", -] +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] -name = "rustls-pemfile" -version = "1.0.0" +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" -dependencies = [ - "base64", -] +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "rw-stream-sink" -version = "0.3.0" +name = "ppv-lite86" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26338f5e09bb721b85b135ea05af7767c90b52f6de4f087d4f4a3a9d64e7dc04" -dependencies = [ - "futures", - "pin-project", - "static_assertions", -] +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] -name = "ryu" -version = "1.0.10" +name = "primitive-types" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "uint", +] [[package]] -name = "salsa20" -version = "0.9.0" +name = "proc-macro-crate" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ - "cipher", + "thiserror", + "toml", ] [[package]] -name = "sc-allocator" -version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "proc-macro2" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ - "log", - "sp-core", - "sp-wasm-interface", - "thiserror", + "unicode-ident", ] [[package]] -name = "sc-block-builder" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "quote" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" dependencies = [ - "parity-scale-codec", - "sc-client-api", - "sp-api", - "sp-block-builder", - "sp-blockchain", - "sp-core", - "sp-inherents", - "sp-runtime", - "sp-state-machine", + "proc-macro2", ] [[package]] -name = "sc-chain-spec" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "impl-trait-for-tuples", - "memmap2", - "parity-scale-codec", - "sc-chain-spec-derive", - "sc-network", - "sc-telemetry", - "serde", - "serde_json", - "sp-core", - "sp-runtime", + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", ] [[package]] -name = "sc-chain-spec-derive" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", ] [[package]] -name = "sc-client-api" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ - "fnv", - "futures", - "hash-db", - "log", - "parity-scale-codec", - "parking_lot 0.12.1", - "sc-executor", - "sc-transaction-pool-api", - "sc-utils", - "sp-api", - "sp-blockchain", - "sp-consensus", - "sp-core", - "sp-database", - "sp-externalities", - "sp-keystore", - "sp-runtime", - "sp-state-machine", - "sp-storage", - "sp-trie", - "substrate-prometheus-endpoint", + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] -name = "sc-consensus" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "async-trait", - "futures", - "futures-timer", - "libp2p", - "log", - "parking_lot 0.12.1", - "sc-client-api", - "sc-utils", - "serde", - "sp-api", - "sp-blockchain", - "sp-consensus", - "sp-core", - "sp-runtime", - "sp-state-machine", - "substrate-prometheus-endpoint", - "thiserror", + "ppv-lite86", + "rand_core 0.6.3", ] [[package]] -name = "sc-executor" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "lazy_static", - "lru", - "parity-scale-codec", - "parking_lot 0.12.1", - "sc-executor-common", - "sc-executor-wasmi", - "sp-api", - "sp-core", - "sp-core-hashing-proc-macro", - "sp-externalities", - "sp-io", - "sp-panic-handler", - "sp-runtime-interface", - "sp-tasks", - "sp-trie", - "sp-version", - "sp-wasm-interface", - "tracing", - "wasmi", +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] -name = "sc-executor-common" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "environmental", - "parity-scale-codec", - "sc-allocator", - "sp-maybe-compressed-blob", - "sp-sandbox", - "sp-serializer", - "sp-wasm-interface", - "thiserror", - "wasm-instrument", - "wasmi", + "getrandom 0.2.7", ] [[package]] -name = "sc-executor-wasmi" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ - "log", - "parity-scale-codec", - "sc-allocator", - "sc-executor-common", - "sp-runtime-interface", - "sp-sandbox", - "sp-wasm-interface", - "wasmi", + "num-traits", + "rand 0.8.5", ] [[package]] -name = "sc-network" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "async-trait", - "asynchronous-codec", - "bitflags", - "bytes", - "cid", - "either", - "fnv", - "fork-tree", - "futures", - "futures-timer", - "hex", - "ip_network", - "libp2p", - "linked-hash-map", - "linked_hash_set", - "log", - "lru", - "parity-scale-codec", - "parking_lot 0.12.1", - "pin-project", - "prost", - "prost-build", - "rand 0.7.3", - "sc-block-builder", - "sc-client-api", - "sc-consensus", - "sc-network-common", - "sc-network-light", - "sc-network-sync", - "sc-peerset", - "sc-utils", - "serde", - "serde_json", - "smallvec", - "sp-arithmetic", - "sp-blockchain", - "sp-consensus", - "sp-core", - "sp-finality-grandpa", - "sp-runtime", - "substrate-prometheus-endpoint", - "thiserror", - "unsigned-varint", - "void", - "zeroize", + "rand_core 0.5.1", ] [[package]] -name = "sc-network-common" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" dependencies = [ - "futures", - "libp2p", - "parity-scale-codec", - "prost-build", - "sc-peerset", - "smallvec", + "rand_core 0.5.1", ] [[package]] -name = "sc-network-light" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ - "futures", - "libp2p", - "log", - "parity-scale-codec", - "prost", - "prost-build", - "sc-client-api", - "sc-network-common", - "sc-peerset", - "sp-blockchain", - "sp-core", - "sp-runtime", - "thiserror", + "bitflags", ] [[package]] -name = "sc-network-sync" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "ref-cast" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685d58625b6c2b83e4cc88a27c4bf65adb7b6b16dbdc413e515c9405b47432ab" dependencies = [ - "bitflags", - "either", - "fork-tree", - "futures", - "libp2p", - "log", - "lru", - "parity-scale-codec", - "prost", - "prost-build", - "sc-client-api", - "sc-consensus", - "sc-network-common", - "sc-peerset", - "smallvec", - "sp-arithmetic", - "sp-blockchain", - "sp-consensus", - "sp-core", - "sp-finality-grandpa", - "sp-runtime", - "thiserror", + "ref-cast-impl", ] [[package]] -name = "sc-peerset" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "ref-cast-impl" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a043824e29c94169374ac5183ac0ed43f5724dc4556b19568007486bd840fa1f" dependencies = [ - "futures", - "libp2p", - "log", - "sc-utils", - "serde_json", - "wasm-timer", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "sc-rpc-api" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "regex" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" dependencies = [ - "futures", - "jsonrpsee 0.14.0", - "log", - "parity-scale-codec", - "parking_lot 0.12.1", - "sc-chain-spec", - "sc-transaction-pool-api", - "scale-info", - "serde", - "serde_json", - "sp-core", - "sp-rpc", - "sp-runtime", - "sp-tracing", - "sp-version", - "thiserror", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] -name = "sc-telemetry" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "chrono", - "futures", - "libp2p", - "log", - "parking_lot 0.12.1", - "pin-project", - "rand 0.7.3", - "serde", - "serde_json", - "thiserror", - "wasm-timer", + "regex-syntax", ] [[package]] -name = "sc-transaction-pool-api" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "regex-syntax" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" + +[[package]] +name = "rfc6979" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" dependencies = [ - "futures", - "log", - "serde", - "sp-blockchain", - "sp-runtime", - "thiserror", + "crypto-bigint", + "hmac 0.11.0", + "zeroize", ] [[package]] -name = "sc-utils" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +name = "rlp" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "999508abb0ae792aabed2460c45b89106d97fe4adac593bdaef433c2605847b5" dependencies = [ - "futures", - "futures-timer", - "lazy_static", - "log", - "parking_lot 0.12.1", - "prometheus", + "bytes", + "rustc-hex", ] +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "ryu" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + [[package]] name = "scale-info" version = "2.1.2" @@ -5176,16 +2199,6 @@ dependencies = [ "syn", ] -[[package]] -name = "schannel" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" -dependencies = [ - "lazy_static", - "windows-sys", -] - [[package]] name = "schnorrkel" version = "0.9.1" @@ -5210,16 +2223,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sec1" version = "0.2.1" @@ -5234,18 +2237,18 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.21.3" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c42e6f1735c5f00f51e43e28d6634141f2bcad10931b2609ddd74a86d751260" +checksum = "b7649a0b3ffb32636e60c7ce0d70511eda9c52c658cd0634e194d5a19943aeff" dependencies = [ "secp256k1-sys", ] [[package]] name = "secp256k1-sys" -version = "0.4.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957da2573cde917463ece3570eab4a0b3f19de6f1646cde62e6fd3868f566036" +checksum = "7058dc8eaf3f2810d7828680320acda0b25a288f6d288e19278e249bbf74226b" dependencies = [ "cc", ] @@ -5259,35 +2262,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" - [[package]] name = "serde" version = "1.0.137" @@ -5314,25 +2288,11 @@ version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ - "indexmap", "itoa 1.0.2", "ryu", "serde", ] -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug 0.3.0", -] - [[package]] name = "sha2" version = "0.8.2" @@ -5369,18 +2329,6 @@ dependencies = [ "digest 0.10.3", ] -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug 0.3.0", -] - [[package]] name = "sha3" version = "0.10.1" @@ -5392,31 +2340,12 @@ dependencies = [ ] [[package]] -name = "sharded-slab" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" +name = "sharded-slab" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" dependencies = [ - "libc", + "lazy_static", ] [[package]] @@ -5447,70 +2376,16 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" -[[package]] -name = "sluice" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" -dependencies = [ - "async-channel", - "futures-core", - "futures-io", -] - [[package]] name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "snow" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774d05a3edae07ce6d68ea6984f3c05e9bba8927e3dd591e3b479e5b03213d0d" -dependencies = [ - "aes-gcm", - "blake2", - "chacha20poly1305", - "curve25519-dalek 4.0.0-pre.1", - "rand_core 0.6.3", - "ring", - "rustc_version", - "sha2 0.10.2", - "subtle", -] - -[[package]] -name = "socket2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "soketto" -version = "0.7.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" -dependencies = [ - "base64", - "bytes", - "flate2", - "futures", - "httparse", - "log", - "rand 0.8.5", - "sha-1", -] +checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "hash-db", "log", @@ -5527,7 +2402,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "blake2", "proc-macro-crate", @@ -5539,7 +2414,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "parity-scale-codec", "scale-info", @@ -5552,7 +2427,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "integer-sqrt", "num-traits", @@ -5564,59 +2439,10 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "sp-block-builder" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "parity-scale-codec", - "sp-api", - "sp-inherents", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "sp-blockchain" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "futures", - "log", - "lru", - "parity-scale-codec", - "parking_lot 0.12.1", - "sp-api", - "sp-consensus", - "sp-database", - "sp-runtime", - "sp-state-machine", - "thiserror", -] - -[[package]] -name = "sp-consensus" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "async-trait", - "futures", - "futures-timer", - "log", - "parity-scale-codec", - "sp-core", - "sp-inherents", - "sp-runtime", - "sp-state-machine", - "sp-std", - "sp-version", - "thiserror", -] - [[package]] name = "sp-core" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "base58", "bitflags", @@ -5636,7 +2462,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.12.1", + "parking_lot", "primitive-types", "rand 0.7.3", "regex", @@ -5662,13 +2488,13 @@ dependencies = [ [[package]] name = "sp-core-hashing" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "blake2", "byteorder", "digest 0.10.3", "sha2 0.10.2", - "sha3 0.10.1", + "sha3", "sp-std", "twox-hash", ] @@ -5676,7 +2502,7 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "proc-macro2", "quote", @@ -5684,19 +2510,10 @@ dependencies = [ "syn", ] -[[package]] -name = "sp-database" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "kvdb", - "parking_lot 0.12.1", -] - [[package]] name = "sp-debug-derive" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "proc-macro2", "quote", @@ -5706,7 +2523,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.12.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "environmental", "parity-scale-codec", @@ -5717,7 +2534,7 @@ dependencies = [ [[package]] name = "sp-finality-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "finality-grandpa", "log", @@ -5735,7 +2552,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -5749,14 +2566,14 @@ dependencies = [ [[package]] name = "sp-io" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "futures", "hash-db", "libsecp256k1", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot", "secp256k1", "sp-core", "sp-externalities", @@ -5774,52 +2591,33 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.12.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "async-trait", "futures", "merlin", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot", "schnorrkel", "sp-core", "sp-externalities", "thiserror", ] -[[package]] -name = "sp-maybe-compressed-blob" -version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "thiserror", - "zstd", -] - [[package]] name = "sp-panic-handler" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "backtrace", "lazy_static", "regex", ] -[[package]] -name = "sp-rpc" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "rustc-hash", - "serde", - "sp-core", -] - [[package]] name = "sp-runtime" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "either", "hash256-std-hasher", @@ -5841,7 +2639,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -5858,7 +2656,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "Inflector", "proc-macro-crate", @@ -5867,33 +2665,10 @@ dependencies = [ "syn", ] -[[package]] -name = "sp-sandbox" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "log", - "parity-scale-codec", - "sp-core", - "sp-io", - "sp-std", - "sp-wasm-interface", - "wasmi", -] - -[[package]] -name = "sp-serializer" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "parity-scale-codec", "scale-info", @@ -5904,13 +2679,13 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.12.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "hash-db", "log", "num-traits", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot", "rand 0.7.3", "smallvec", "sp-core", @@ -5926,12 +2701,12 @@ dependencies = [ [[package]] name = "sp-std" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" [[package]] name = "sp-storage" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "impl-serde", "parity-scale-codec", @@ -5941,23 +2716,10 @@ dependencies = [ "sp-std", ] -[[package]] -name = "sp-tasks" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "log", - "sp-core", - "sp-externalities", - "sp-io", - "sp-runtime-interface", - "sp-std", -] - [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "async-trait", "futures-timer", @@ -5973,7 +2735,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "parity-scale-codec", "sp-std", @@ -5985,7 +2747,7 @@ dependencies = [ [[package]] name = "sp-trie" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "hash-db", "memory-db", @@ -6001,7 +2763,7 @@ dependencies = [ [[package]] name = "sp-version" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "impl-serde", "parity-scale-codec", @@ -6018,7 +2780,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -6029,7 +2791,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#5bfdbab8ba28523ef10e365627fed64ef2b77cbf" dependencies = [ "impl-trait-for-tuples", "log", @@ -6038,17 +2800,11 @@ dependencies = [ "wasmi", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "ss58-registry" -version = "1.22.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d804c8d48aeab838be31570866fce1130d275b563d49af08b4927a0bd561e7c" +checksum = "77ef98aedad3dc52e10995e7ed15f1279e11d4da35795f5dac7305742d0feb66" dependencies = [ "Inflector", "num-format", @@ -6059,12 +2815,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "static_assertions" version = "1.1.0" @@ -6097,19 +2847,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "substrate-prometheus-endpoint" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.26#e8a7d161f39db70cb27fdad6c6e215cf493ebc3b" -dependencies = [ - "futures-util", - "hyper", - "log", - "prometheus", - "thiserror", - "tokio", -] - [[package]] name = "subtle" version = "2.4.1" @@ -6139,73 +2876,12 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "sysinfo" -version = "0.15.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de94457a09609f33fec5e7fceaf907488967c6c7c75d64da6a7ce6ffdb8b5abd" -dependencies = [ - "cc", - "cfg-if", - "core-foundation-sys", - "doc-comment", - "libc", - "ntapi", - "once_cell", - "rayon", - "winapi", -] - -[[package]] -name = "system-configuration" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75182f12f490e953596550b65ee31bda7c8e043d9386174b353bda50838c3fd" -dependencies = [ - "bitflags", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if", - "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", -] - -[[package]] -name = "termcolor" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.31" @@ -6235,28 +2911,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" -dependencies = [ - "itoa 1.0.2", - "libc", - "num_threads", -] - [[package]] name = "tiny-bip39" version = "0.8.2" @@ -6289,99 +2943,17 @@ dependencies = [ name = "tinyvec" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "tokio" -version = "1.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" -dependencies = [ - "bytes", - "libc", - "memchr", - "mio", - "num_cpus", - "once_cell", - "parking_lot 0.12.1", - "pin-project-lite 0.2.9", - "socket2", - "tokio-macros", - "winapi", -] - -[[package]] -name = "tokio-macros" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-stream" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" -dependencies = [ - "futures-core", - "pin-project-lite 0.2.9", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" -dependencies = [ - "bytes", - "futures-core", - "futures-io", - "futures-sink", - "log", - "pin-project-lite 0.2.9", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" -dependencies = [ - "bytes", - "futures-core", - "futures-io", - "futures-sink", - "pin-project-lite 0.2.9", - "tokio", - "tracing", +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", ] +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + [[package]] name = "toml" version = "0.5.9" @@ -6391,12 +2963,6 @@ dependencies = [ "serde", ] -[[package]] -name = "tower-service" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" - [[package]] name = "tracing" version = "0.1.35" @@ -6404,8 +2970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ "cfg-if", - "log", - "pin-project-lite 0.2.9", + "pin-project-lite", "tracing-attributes", "tracing-core", ] @@ -6423,24 +2988,14 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921" +checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.1.3" @@ -6506,55 +3061,6 @@ dependencies = [ "hash-db", ] -[[package]] -name = "trust-dns-proto" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c31f240f59877c3d4bb3b3ea0ec5a6a0cff07323580ff8c7a605cd7d08b255d" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna", - "ipnet", - "lazy_static", - "log", - "rand 0.8.5", - "smallvec", - "thiserror", - "tinyvec", - "url", -] - -[[package]] -name = "trust-dns-resolver" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ba72c2ea84515690c9fcef4c6c660bb9df3036ed1051686de84605b74fd558" -dependencies = [ - "cfg-if", - "futures-util", - "ipconfig", - "lazy_static", - "log", - "lru-cache", - "parking_lot 0.12.1", - "resolv-conf", - "smallvec", - "thiserror", - "trust-dns-proto", -] - -[[package]] -name = "try-lock" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - [[package]] name = "tt-call" version = "1.0.8" @@ -6591,32 +3097,17 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" - [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "81dee68f85cab8cf68dec42158baf3a79a1cdc065a8b103025965d6ccb7f6cbd" dependencies = [ "tinyvec", ] @@ -6627,108 +3118,24 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" -[[package]] -name = "universal-hash" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" -dependencies = [ - "generic-array 0.14.5", - "subtle", -] - -[[package]] -name = "unsigned-varint" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" -dependencies = [ - "asynchronous-codec", - "bytes", - "futures-io", - "futures-util", -] - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" -dependencies = [ - "form_urlencoded", - "idna", - "matches", - "percent-encoding", -] - [[package]] name = "valuable" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "value-bag" -version = "1.0.0-alpha.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" -dependencies = [ - "ctor", - "version_check", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -6737,9 +3144,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -6747,9 +3154,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" dependencies = [ "bumpalo", "lazy_static", @@ -6760,23 +3167,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6784,9 +3179,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ "proc-macro2", "quote", @@ -6797,33 +3192,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" - -[[package]] -name = "wasm-instrument" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962e5b0401bbb6c887f54e69b8c496ea36f704df65db73e81fd5ff8dc3e63a9f" -dependencies = [ - "parity-wasm", -] - -[[package]] -name = "wasm-timer" -version = "0.2.5" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" [[package]] name = "wasmi" @@ -6833,7 +3204,6 @@ checksum = "ca00c5147c319a8ec91ec1a0edbec31e566ce2c9cc93b3f9bb86a9efd0eb795d" dependencies = [ "downcast-rs", "libc", - "libm", "memory_units", "num-rational 0.2.4", "num-traits", @@ -6850,61 +3220,6 @@ dependencies = [ "parity-wasm", ] -[[package]] -name = "web-sys" -version = "0.3.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d8de8415c823c8abd270ad483c6feeac771fad964890779f9a8cb24fbbc1bf" -dependencies = [ - "webpki", -] - -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - -[[package]] -name = "which" -version = "4.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" -dependencies = [ - "either", - "lazy_static", - "libc", -] - -[[package]] -name = "widestring" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" - [[package]] name = "winapi" version = "0.3.9" @@ -6921,116 +3236,55 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" -dependencies = [ - "windows_aarch64_msvc 0.34.0", - "windows_i686_gnu 0.34.0", - "windows_i686_msvc 0.34.0", - "windows_x86_64_gnu 0.34.0", - "windows_x86_64_msvc 0.34.0", -] - [[package]] name = "windows-sys" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" - [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" -[[package]] -name = "windows_i686_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" - [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" -[[package]] -name = "windows_i686_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" - [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" -[[package]] -name = "windows_x86_64_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" - [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" -[[package]] -name = "windows_x86_64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" - [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" -[[package]] -name = "winreg" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" -dependencies = [ - "winapi", -] - [[package]] name = "wyz" version = "0.5.0" @@ -7040,36 +3294,11 @@ dependencies = [ "tap", ] -[[package]] -name = "x25519-dalek" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" -dependencies = [ - "curve25519-dalek 3.2.0", - "rand_core 0.5.1", - "zeroize", -] - -[[package]] -name = "yamux" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0608f53c1dc0bad505d03a34bbd49fbf2ad7b51eb036123e896365532745a1" -dependencies = [ - "futures", - "log", - "nohash-hasher", - "parking_lot 0.12.1", - "rand 0.8.5", - "static_assertions", -] - [[package]] name = "zeroize" -version = "1.4.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" dependencies = [ "zeroize_derive", ] @@ -7085,32 +3314,3 @@ dependencies = [ "syn", "synstructure", ] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" -dependencies = [ - "cc", - "libc", -] diff --git a/Cargo.toml b/Cargo.toml index d57157f3a..8f69798e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ resolver = "2" members = [ + "bin/runtime-common", "modules/*", "primitives/*", - "relays/*", ] diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 30cb88b49..11bdd02d9 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -12,36 +12,39 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } -static_assertions = { version = "1.1", optional = true } # Bridge dependencies bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-dispatch = { path = "../../modules/dispatch", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } +pallet-bridge-parachains = { path = "../../modules/parachains", default-features = false } +pallet-fee-market = { path = "../../modules/fee-market", default-features = false } # Substrate dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false, optional = true } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false, optional = true } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false, optional = true } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false, optional = true } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false, optional = true } [features] default = ["std"] std = [ "bp-message-dispatch/std", "bp-messages/std", + "bp-polkadot-core/std", "bp-runtime/std", "codec/std", "frame-support/std", @@ -50,6 +53,8 @@ std = [ "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", + "pallet-bridge-parachains/std", + "pallet-fee-market/std", "pallet-transaction-payment/std", "scale-info/std", "sp-api/std", @@ -67,6 +72,3 @@ runtime-benchmarks = [ "sp-state-machine", "sp-version", ] -integrity-test = [ - "static_assertions", -] diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs deleted file mode 100644 index ab517566a..000000000 --- a/bin/runtime-common/src/integrity.rs +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Integrity tests for chain constants and pallets configuration. -//! -//! Most of the tests in this module assume that the bridge is using standard (see `crate::messages` -//! module for details) configuration. - -use crate::messages::MessageBridge; - -use bp_messages::MessageNonce; -use bp_runtime::{Chain, ChainId}; -use codec::Encode; -use frame_support::{storage::generator::StorageValue, traits::Get}; -use frame_system::limits; - -/// Macro that ensures that the runtime configuration and chain primitives crate are sharing -/// the same types (index, block number, hash, hasher, account id and header). -#[macro_export] -macro_rules! assert_chain_types( - ( runtime: $r:path, this_chain: $this:path ) => { - { - // if one of asserts fail, then either bridge isn't configured properly (or alternatively - non-standard - // configuration is used), or something has broke existing configuration (meaning that all bridged chains - // and relays will stop functioning) - use frame_system::Config as SystemConfig; - use static_assertions::assert_type_eq_all; - - assert_type_eq_all!(<$r as SystemConfig>::Index, bp_runtime::IndexOf<$this>); - assert_type_eq_all!(<$r as SystemConfig>::BlockNumber, bp_runtime::BlockNumberOf<$this>); - assert_type_eq_all!(<$r as SystemConfig>::Hash, bp_runtime::HashOf<$this>); - assert_type_eq_all!(<$r as SystemConfig>::Hashing, bp_runtime::HasherOf<$this>); - assert_type_eq_all!(<$r as SystemConfig>::AccountId, bp_runtime::AccountIdOf<$this>); - assert_type_eq_all!(<$r as SystemConfig>::Header, bp_runtime::HeaderOf<$this>); - } - } -); - -/// Macro that ensures that the bridge configuration and chain primitives crates are sharing -/// the same types (hash, account id, ...). -#[macro_export] -macro_rules! assert_bridge_types( - ( bridge: $bridge:path, this_chain: $this:path, bridged_chain: $bridged:path ) => { - { - // if one of this asserts fail, then all chains, bridged with this chain and bridge relays are now broken - // - // `frame_support::weights::Weight` is used here directly, because all chains we know are using this - // primitive (may be changed in the future) - use $crate::messages::{ - AccountIdOf, BalanceOf, BridgedChain, HashOf, SignatureOf, SignerOf, ThisChain, WeightOf, - }; - use static_assertions::assert_type_eq_all; - - assert_type_eq_all!(HashOf>, bp_runtime::HashOf<$this>); - assert_type_eq_all!(AccountIdOf>, bp_runtime::AccountIdOf<$this>); - assert_type_eq_all!(SignerOf>, bp_runtime::AccountPublicOf<$this>); - assert_type_eq_all!(SignatureOf>, bp_runtime::SignatureOf<$this>); - assert_type_eq_all!(WeightOf>, frame_support::weights::Weight); - assert_type_eq_all!(BalanceOf>, bp_runtime::BalanceOf<$this>); - - assert_type_eq_all!(HashOf>, bp_runtime::HashOf<$bridged>); - assert_type_eq_all!(AccountIdOf>, bp_runtime::AccountIdOf<$bridged>); - assert_type_eq_all!(SignerOf>, bp_runtime::AccountPublicOf<$bridged>); - assert_type_eq_all!(SignatureOf>, bp_runtime::SignatureOf<$bridged>); - assert_type_eq_all!(WeightOf>, frame_support::weights::Weight); - assert_type_eq_all!(BalanceOf>, bp_runtime::BalanceOf<$bridged>); - } - } -); - -/// Macro that ensures that the bridge GRANDPA pallet is configured properly to bridge with given -/// chain. -#[macro_export] -macro_rules! assert_bridge_grandpa_pallet_types( - ( runtime: $r:path, with_bridged_chain_grandpa_instance: $i:path, bridged_chain: $bridged:path ) => { - { - // if one of asserts fail, then either bridge isn't configured properly (or alternatively - non-standard - // configuration is used), or something has broke existing configuration (meaning that all bridged chains - // and relays will stop functioning) - use pallet_bridge_grandpa::Config as GrandpaConfig; - use static_assertions::assert_type_eq_all; - - assert_type_eq_all!(<$r as GrandpaConfig<$i>>::BridgedChain, $bridged); - } - } -); - -/// Macro that ensures that the bridge messages pallet is configured properly to bridge using given -/// configuration. -#[macro_export] -macro_rules! assert_bridge_messages_pallet_types( - ( - runtime: $r:path, - with_bridged_chain_messages_instance: $i:path, - bridge: $bridge:path, - this_chain_account_id_converter: $this_converter:path - ) => { - { - // if one of asserts fail, then either bridge isn't configured properly (or alternatively - non-standard - // configuration is used), or something has broke existing configuration (meaning that all bridged chains - // and relays will stop functioning) - use $crate::messages::{ - source::FromThisChainMessagePayload, - target::FromBridgedChainMessagePayload, - AccountIdOf, BalanceOf, BridgedChain, ThisChain, WeightOf, - }; - use pallet_bridge_messages::Config as MessagesConfig; - use static_assertions::assert_type_eq_all; - - assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundPayload, FromThisChainMessagePayload<$bridge>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundMessageFee, BalanceOf>); - - assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundPayload, FromBridgedChainMessagePayload<$bridge>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundMessageFee, BalanceOf>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundRelayer, AccountIdOf>); - - assert_type_eq_all!(<$r as MessagesConfig<$i>>::AccountIdConverter, $this_converter); - - assert_type_eq_all!(<$r as MessagesConfig<$i>>::TargetHeaderChain, BridgedChain<$bridge>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::SourceHeaderChain, BridgedChain<$bridge>); - } - } -); - -/// Macro that combines four other macro calls - `assert_chain_types`, `assert_bridge_types`, -/// `assert_bridge_grandpa_pallet_types` and `assert_bridge_messages_pallet_types`. It may be used -/// at the chain that is implemeting complete standard messages bridge (i.e. with bridge GRANDPA and -/// messages pallets deployed). -#[macro_export] -macro_rules! assert_complete_bridge_types( - ( - runtime: $r:path, - with_bridged_chain_grandpa_instance: $gi:path, - with_bridged_chain_messages_instance: $mi:path, - bridge: $bridge:path, - this_chain: $this:path, - bridged_chain: $bridged:path, - this_chain_account_id_converter: $this_converter:path - ) => { - $crate::assert_chain_types!(runtime: $r, this_chain: $this); - $crate::assert_bridge_types!(bridge: $bridge, this_chain: $this, bridged_chain: $bridged); - $crate::assert_bridge_grandpa_pallet_types!( - runtime: $r, - with_bridged_chain_grandpa_instance: $gi, - bridged_chain: $bridged - ); - $crate::assert_bridge_messages_pallet_types!( - runtime: $r, - with_bridged_chain_messages_instance: $mi, - bridge: $bridge, - this_chain_account_id_converter: $this_converter - ); - } -); - -/// Parameters for asserting chain-related constants. -#[derive(Debug)] -pub struct AssertChainConstants { - /// Block length limits of the chain. - pub block_length: limits::BlockLength, - /// Block weight limits of the chain. - pub block_weights: limits::BlockWeights, -} - -/// Test that our hardcoded, chain-related constants, are matching chain runtime configuration. -/// -/// In particular, this test ensures that: -/// -/// 1) block weight limits are matching; -/// 2) block size limits are matching. -pub fn assert_chain_constants(params: AssertChainConstants) -where - R: frame_system::Config, - C: Chain, -{ - // we don't check runtime version here, because in our case we'll be building relay from one - // repo and runtime will live in another repo, along with outdated relay version. To avoid - // unneeded commits, let's not raise an error in case of version mismatch. - - // if one of following assert fails, it means that we may need to upgrade bridged chain and - // relay to use updated constants. If constants are now smaller than before, it may lead to - // undeliverable messages. - - // `BlockLength` struct is not implementing `PartialEq`, so we compare encoded values here. - assert_eq!( - R::BlockLength::get().encode(), - params.block_length.encode(), - "BlockLength from runtime ({:?}) differ from hardcoded: {:?}", - R::BlockLength::get(), - params.block_length, - ); - // `BlockWeights` struct is not implementing `PartialEq`, so we compare encoded values here - assert_eq!( - R::BlockWeights::get().encode(), - params.block_weights.encode(), - "BlockWeights from runtime ({:?}) differ from hardcoded: {:?}", - R::BlockWeights::get(), - params.block_weights, - ); -} - -/// Test that the constants, used in GRANDPA pallet configuration are valid. -pub fn assert_bridge_grandpa_pallet_constants() -where - R: pallet_bridge_grandpa::Config, - GI: 'static, -{ - assert!( - R::MaxRequests::get() > 0, - "MaxRequests ({}) must be larger than zero", - R::MaxRequests::get(), - ); -} - -/// Parameters for asserting messages pallet constants. -#[derive(Debug)] -pub struct AssertBridgeMessagesPalletConstants { - /// Maximal number of unrewarded relayer entries in a confirmation transaction at the bridged - /// chain. - pub max_unrewarded_relayers_in_bridged_confirmation_tx: MessageNonce, - /// Maximal number of unconfirmed messages in a confirmation transaction at the bridged chain. - pub max_unconfirmed_messages_in_bridged_confirmation_tx: MessageNonce, - /// Identifier of the bridged chain. - pub bridged_chain_id: ChainId, -} - -/// Test that the constants, used in messages pallet configuration are valid. -pub fn assert_bridge_messages_pallet_constants(params: AssertBridgeMessagesPalletConstants) -where - R: pallet_bridge_messages::Config, - MI: 'static, -{ - assert!( - R::MaxMessagesToPruneAtOnce::get() > 0, - "MaxMessagesToPruneAtOnce ({}) must be larger than zero", - R::MaxMessagesToPruneAtOnce::get(), - ); - assert!( - R::MaxUnrewardedRelayerEntriesAtInboundLane::get() <= params.max_unrewarded_relayers_in_bridged_confirmation_tx, - "MaxUnrewardedRelayerEntriesAtInboundLane ({}) must be <= than the hardcoded value for bridged chain: {}", - R::MaxUnrewardedRelayerEntriesAtInboundLane::get(), - params.max_unrewarded_relayers_in_bridged_confirmation_tx, - ); - assert!( - R::MaxUnconfirmedMessagesAtInboundLane::get() <= params.max_unconfirmed_messages_in_bridged_confirmation_tx, - "MaxUnrewardedRelayerEntriesAtInboundLane ({}) must be <= than the hardcoded value for bridged chain: {}", - R::MaxUnconfirmedMessagesAtInboundLane::get(), - params.max_unconfirmed_messages_in_bridged_confirmation_tx, - ); - assert_eq!(R::BridgedChainId::get(), params.bridged_chain_id); -} - -/// Parameters for asserting bridge pallet names. -#[derive(Debug)] -pub struct AssertBridgePalletNames<'a> { - /// Name of the messages pallet, deployed at the bridged chain and used to bridge with this - /// chain. - pub with_this_chain_messages_pallet_name: &'a str, - /// Name of the GRANDPA pallet, deployed at this chain and used to bridge with the bridged - /// chain. - pub with_bridged_chain_grandpa_pallet_name: &'a str, - /// Name of the messages pallet, deployed at this chain and used to bridge with the bridged - /// chain. - pub with_bridged_chain_messages_pallet_name: &'a str, -} - -/// Tests that bridge pallet names used in `construct_runtime!()` macro call are matching constants -/// from chain primitives crates. -pub fn assert_bridge_pallet_names(params: AssertBridgePalletNames) -where - B: MessageBridge, - R: pallet_bridge_grandpa::Config + pallet_bridge_messages::Config, - GI: 'static, - MI: 'static, -{ - assert_eq!(B::BRIDGED_MESSAGES_PALLET_NAME, params.with_this_chain_messages_pallet_name); - assert_eq!( - pallet_bridge_grandpa::PalletOwner::::storage_value_final_key().to_vec(), - bp_runtime::storage_value_key(params.with_bridged_chain_grandpa_pallet_name, "PalletOwner",).0, - ); - assert_eq!( - pallet_bridge_messages::PalletOwner::::storage_value_final_key().to_vec(), - bp_runtime::storage_value_key( - params.with_bridged_chain_messages_pallet_name, - "PalletOwner", - ) - .0, - ); -} - -/// Parameters for asserting complete standard messages bridge. -#[derive(Debug)] -pub struct AssertCompleteBridgeConstants<'a> { - /// Parameters to assert this chain constants. - pub this_chain_constants: AssertChainConstants, - /// Parameters to assert messages pallet constants. - pub messages_pallet_constants: AssertBridgeMessagesPalletConstants, - /// Parameters to assert pallet names constants. - pub pallet_names: AssertBridgePalletNames<'a>, -} - -/// All bridge-related constants tests for the complete standard messages bridge (i.e. with bridge -/// GRANDPA and messages pallets deployed). -pub fn assert_complete_bridge_constants(params: AssertCompleteBridgeConstants) -where - R: frame_system::Config - + pallet_bridge_grandpa::Config - + pallet_bridge_messages::Config, - GI: 'static, - MI: 'static, - B: MessageBridge, - This: Chain, -{ - assert_chain_constants::(params.this_chain_constants); - assert_bridge_grandpa_pallet_constants::(); - assert_bridge_messages_pallet_constants::(params.messages_pallet_constants); - assert_bridge_pallet_names::(params.pallet_names); -} diff --git a/bin/runtime-common/src/lanes.rs b/bin/runtime-common/src/lanes.rs index 901950b69..8b08a74ef 100644 --- a/bin/runtime-common/src/lanes.rs +++ b/bin/runtime-common/src/lanes.rs @@ -9,5 +9,8 @@ pub const PANGORO_PANGOLIN_LANE: LaneId = *b"roli"; /// Identifier of bridge between Pangolin and Pangolin Parachain. pub const PANGOLIN_PANGOLIN_PARACHAIN_LANE: LaneId = *b"pali"; +/// Identifier of bridge between Pangolin and Pangolin Parachain Alpha. +pub const PANGOLIN_PANGOLIN_PARACHAIN_ALPHA_LANE: LaneId = *b"plpa"; + /// Identifier of bridge between Crab and Crab Parachain. pub const CRAB_CRAB_PARACHAIN_LANE: LaneId = *b"pacr"; diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 2c0fa93cd..66d8c391f 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -20,8 +20,4 @@ pub mod lanes; pub mod messages; -pub mod messages_api; pub mod messages_benchmarking; - -#[cfg(feature = "integrity-test")] -pub mod integrity; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 6be8fc6e8..c8b7cebfb 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -26,10 +26,8 @@ use bp_messages::{ target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; -use bp_runtime::{ - messages::{DispatchFeePayment, MessageDispatchResult}, - ChainId, Size, StorageProofChecker, -}; +use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaId}; +use bp_runtime::{messages::MessageDispatchResult, ChainId, Size, StorageProofChecker}; use codec::{Decode, DecodeLimit, Encode}; use frame_support::{ traits::{Currency, ExistenceRequirement}, @@ -39,8 +37,8 @@ use frame_support::{ use hash_db::Hasher; use scale_info::TypeInfo; use sp_runtime::{ - traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating, Zero}, - FixedPointNumber, FixedPointOperand, FixedU128, + traits::{CheckedAdd, CheckedDiv, CheckedMul, Header as HeaderT, Saturating, Zero}, + FixedPointNumber, FixedPointOperand, }; use sp_std::{ cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, @@ -66,12 +64,6 @@ pub trait MessageBridge { type ThisChain: ThisChainWithMessages; /// Bridged chain in context of message bridge. type BridgedChain: BridgedChainWithMessages; - - /// Convert Bridged chain balance into This chain balance. - fn bridged_balance_to_this_balance( - bridged_balance: BalanceOf>, - bridged_to_this_conversion_rate_override: Option, - ) -> BalanceOf>; } /// Chain that has `pallet-bridge-messages` and `dispatch` modules. @@ -100,15 +92,6 @@ pub trait ChainWithMessages { + Copy; } -/// Message related transaction parameters estimation. -#[derive(RuntimeDebug)] -pub struct MessageTransaction { - /// The estimated dispatch weight of the transaction. - pub dispatch_weight: Weight, - /// The estimated size of the encoded transaction. - pub size: u32, -} - /// This chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ThisChainWithMessages: ChainWithMessages { /// Call origin on the chain. @@ -123,12 +106,6 @@ pub trait ThisChainWithMessages: ChainWithMessages { /// /// Any messages over this limit, will be rejected. fn maximal_pending_messages_at_outbound_lane() -> MessageNonce; - - /// Estimate size and weight of single message delivery confirmation transaction at This chain. - fn estimate_delivery_confirmation_transaction() -> MessageTransaction>; - - /// Returns minimal transaction fee that must be paid for given transaction at This chain. - fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; } /// Bridged chain that has `pallet-bridge-messages` and `dispatch` modules. @@ -146,17 +123,6 @@ pub trait BridgedChainWithMessages: ChainWithMessages { /// already accounted by the `weight_of_delivery_transaction`. So this function should /// return pure call dispatch weights range. fn message_weight_limits(message_payload: &[u8]) -> RangeInclusive; - - /// Estimate size and weight of single message delivery transaction at the Bridged chain. - fn estimate_delivery_transaction( - message_payload: &[u8], - include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: WeightOf, - ) -> MessageTransaction>; - - /// Returns minimal transaction fee that must be paid for given transaction at the Bridged - /// chain. - fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; } /// This chain in context of message bridge. @@ -183,33 +149,6 @@ pub type CallOf = ::Call; /// Raw storage proof type (just raw trie nodes). pub type RawStorageProof = Vec>; -/// Compute fee of transaction at runtime where regular transaction payment pallet is being used. -/// -/// The value of `multiplier` parameter is the expected value of -/// `pallet_transaction_payment::NextFeeMultiplier` at the moment when transaction is submitted. If -/// you're charging this payment in advance (and that's what happens with delivery and confirmation -/// transaction in this crate), then there's a chance that the actual fee will be larger than what -/// is paid in advance. So the value must be chosen carefully. -pub fn transaction_payment( - base_extrinsic_weight: Weight, - per_byte_fee: Balance, - multiplier: FixedU128, - weight_to_fee: impl Fn(Weight) -> Balance, - transaction: MessageTransaction, -) -> Balance { - // base fee is charged for every tx - let base_fee = weight_to_fee(base_extrinsic_weight); - - // non-adjustable per-byte fee - let len_fee = per_byte_fee.saturating_mul(Balance::from(transaction.size)); - - // the adjustable part of the fee - let unadjusted_weight_fee = weight_to_fee(transaction.dispatch_weight); - let adjusted_weight_fee = multiplier.saturating_mul_int(unadjusted_weight_fee); - - base_fee.saturating_add(len_fee).saturating_add(adjusted_weight_fee) -} - /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { use super::*; @@ -269,7 +208,7 @@ pub mod source { /// dispatch origin; /// - check that the sender has paid enough funds for both message delivery and dispatch. #[derive(RuntimeDebug)] - pub struct FromThisChainMessageVerifier(PhantomData); + pub struct FromThisChainMessageVerifier(PhantomData<(B, F, I)>); /// The error message returned from LaneMessageVerifier when outbound lane is disabled. pub const MESSAGE_REJECTED_BY_OUTBOUND_LANE: &str = @@ -282,23 +221,27 @@ pub mod source { /// The error message returned from LaneMessageVerifier when the message fee is too low. pub const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane."; - impl + impl LaneMessageVerifier< OriginOf>, AccountIdOf>, FromThisChainMessagePayload, BalanceOf>, - > for FromThisChainMessageVerifier + > for FromThisChainMessageVerifier where B: MessageBridge, + F: pallet_fee_market::Config, + I: 'static, // matches requirements from the `frame_system::Config::Origin` OriginOf>: Clone + Into>>, OriginOf>>>, AccountIdOf>: PartialEq + Clone, + pallet_fee_market::BalanceOf: From>>, { type Error = &'static str; #[allow(clippy::single_match)] + #[cfg(not(feature = "runtime-benchmarks"))] fn verify_message( submitter: &OriginOf>, delivery_and_dispatch_fee: &BalanceOf>, @@ -338,19 +281,35 @@ pub mod source { // is valid, or not. }; - let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( - payload, - B::RELAYER_FEE_PERCENT, - None, - )?; + // Do the delivery_and_dispatch_fee. We assume that the delivery and dispatch fee always + // greater than the fee market provided fee. + if let Some(market_fee) = pallet_fee_market::Pallet::::market_fee() { + let message_fee: pallet_fee_market::BalanceOf = + (*delivery_and_dispatch_fee).into(); + + // compare with actual fee paid + if message_fee < market_fee { + return Err(TOO_LOW_FEE); + } + } else { + const NO_MARKET_FEE: &str = "The fee market are not ready for accepting messages."; - // compare with actual fee paid - if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { - return Err(TOO_LOW_FEE); + return Err(NO_MARKET_FEE); } Ok(()) } + + #[cfg(feature = "runtime-benchmarks")] + fn verify_message( + _submitter: &OriginOf>, + _delivery_and_dispatch_fee: &BalanceOf>, + _lane: &LaneId, + _lane_outbound_data: &OutboundLaneData, + _payload: &FromThisChainMessagePayload, + ) -> Result<(), Self::Error> { + Ok(()) + } } /// Return maximal message size of This -> Bridged chain message. @@ -388,55 +347,10 @@ pub mod source { Ok(()) } - /// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged - /// chain. - /// - /// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional - /// conversions. Returns `None` if overflow has happened. - pub fn estimate_message_dispatch_and_delivery_fee( - payload: &FromThisChainMessagePayload, - relayer_fee_percent: u32, - bridged_to_this_conversion_rate: Option, - ) -> Result>, &'static str> { - // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain - // - // if we're going to pay dispatch fee at the target chain, then we don't include weight - // of the message dispatch in the delivery transaction cost - let pay_dispatch_fee_at_target_chain = - payload.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; - let delivery_transaction = BridgedChain::::estimate_delivery_transaction( - &payload.encode(), - pay_dispatch_fee_at_target_chain, - if pay_dispatch_fee_at_target_chain { 0.into() } else { payload.weight.into() }, - ); - let delivery_transaction_fee = BridgedChain::::transaction_payment(delivery_transaction); - - // the fee (in This tokens) of all transactions that are made on This chain - let confirmation_transaction = ThisChain::::estimate_delivery_confirmation_transaction(); - let confirmation_transaction_fee = - ThisChain::::transaction_payment(confirmation_transaction); - - // minimal fee (in This tokens) is a sum of all required fees - let minimal_fee = B::bridged_balance_to_this_balance( - delivery_transaction_fee, - bridged_to_this_conversion_rate, - ) - .checked_add(&confirmation_transaction_fee); - - // before returning, add extra fee that is paid to the relayer (relayer interest) - minimal_fee - .and_then(|fee| - // having message with fee that is near the `Balance::MAX_VALUE` of the chain is - // unlikely and should be treated as an error - // => let's do multiplication first - fee - .checked_mul(&relayer_fee_percent.into()) - .and_then(|interest| interest.checked_div(&100u32.into())) - .and_then(|interest| fee.checked_add(&interest))) - .ok_or("Overflow when computing minimal required message delivery and dispatch fee") - } - /// Verify proof of This -> Bridged chain messages delivery. + /// + /// This function is used when Bridged chain is directly using GRANDPA finality. For Bridged + /// parachains, please use the `verify_messages_delivery_proof_from_parachain`. pub fn verify_messages_delivery_proof( proof: FromBridgedChainMessagesDeliveryProof>>, ) -> Result, &'static str> @@ -453,23 +367,70 @@ pub mod source { pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(storage_proof), - |storage| { - // Messages delivery proof is just proof of single storage key read => any error - // is fatal. - let storage_inbound_lane_data_key = - bp_messages::storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane); - let raw_inbound_lane_data = storage - .read_value(storage_inbound_lane_data_key.0.as_ref()) - .map_err(|_| "Failed to read inbound lane state from storage proof")? - .ok_or("Inbound lane state is missing from the messages proof")?; - let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..]) - .map_err(|_| "Failed to decode inbound lane state from the proof")?; - - Ok((lane, inbound_lane_data)) - }, + |storage| do_verify_messages_delivery_proof::< + B, + bp_runtime::HasherOf< + >::BridgedChain, + >, + >(lane, storage), ) .map_err(<&'static str>::from)? } + + /// Verify proof of This -> Bridged chain messages delivery. + /// + /// This function is used when Bridged chain is using parachain finality. For Bridged + /// chains with direct GRANDPA finality, please use the `verify_messages_delivery_proof`. + /// + /// This function currently only supports parachains, which are using header type that + /// implements `sp_runtime::traits::Header` trait. + pub fn verify_messages_delivery_proof_from_parachain< + B, + BridgedHeader, + ThisRuntime, + ParachainsInstance: 'static, + >( + bridged_parachain: ParaId, + proof: FromBridgedChainMessagesDeliveryProof>>, + ) -> Result, &'static str> + where + B: MessageBridge, + B::BridgedChain: ChainWithMessages, + BridgedHeader: HeaderT>>, + ThisRuntime: pallet_bridge_parachains::Config, + { + let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } = + proof; + pallet_bridge_parachains::Pallet::::parse_finalized_storage_proof( + bridged_parachain, + bridged_header_hash, + StorageProof::new(storage_proof), + |para_head| BridgedHeader::decode(&mut ¶_head.0[..]).ok().map(|h| *h.state_root()), + |storage| do_verify_messages_delivery_proof::(lane, storage), + ) + .map_err(<&'static str>::from)? + } + + /// The essense of This -> Bridged chain messages delivery proof verification. + fn do_verify_messages_delivery_proof( + lane: LaneId, + storage: bp_runtime::StorageProofChecker, + ) -> Result, &'static str> { + // Messages delivery proof is just proof of single storage key read => any error + // is fatal. + let storage_inbound_lane_data_key = bp_messages::storage_keys::inbound_lane_data_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + &lane, + ); + let raw_inbound_lane_data = storage + .read_value(storage_inbound_lane_data_key.0.as_ref()) + .map_err(|_| "Failed to read inbound lane state from storage proof")? + .ok_or("Inbound lane state is missing from the messages proof")?; + let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..]) + .map_err(|_| "Failed to decode inbound lane state from the proof")?; + + Ok((lane, inbound_lane_data)) + } } /// Sub-module that is declaring types required for processing Bridged -> This chain messages. @@ -641,6 +602,9 @@ pub mod target { /// Verify proof of Bridged -> This chain messages. /// + /// This function is used when Bridged chain is directly using GRANDPA finality. For Bridged + /// parachains, please use the `verify_messages_proof_from_parachain`. + /// /// The `messages_count` argument verification (sane limits) is supposed to be made /// outside of this function. This function only verifies that the proof declares exactly /// `messages_count` messages. @@ -675,6 +639,54 @@ pub mod target { .map_err(Into::into) } + /// Verify proof of Bridged -> This chain messages. + /// + /// This function is used when Bridged chain is using parachain finality. For Bridged + /// chains with direct GRANDPA finality, please use the `verify_messages_proof`. + /// + /// The `messages_count` argument verification (sane limits) is supposed to be made + /// outside of this function. This function only verifies that the proof declares exactly + /// `messages_count` messages. + /// + /// This function currently only supports parachains, which are using header type that + /// implements `sp_runtime::traits::Header` trait. + pub fn verify_messages_proof_from_parachain< + B, + BridgedHeader, + ThisRuntime, + ParachainsInstance: 'static, + >( + bridged_parachain: ParaId, + proof: FromBridgedChainMessagesProof>>, + messages_count: u32, + ) -> Result>>>, &'static str> + where + B: MessageBridge, + B::BridgedChain: ChainWithMessages, + BridgedHeader: HeaderT>>, + ThisRuntime: pallet_bridge_parachains::Config, + { + verify_messages_proof_with_parser::( + proof, + messages_count, + |bridged_header_hash, bridged_storage_proof| { + pallet_bridge_parachains::Pallet::::parse_finalized_storage_proof( + bridged_parachain, + bridged_header_hash, + StorageProof::new(bridged_storage_proof), + |para_head| BridgedHeader::decode(&mut ¶_head.0[..]).ok().map(|h| *h.state_root()), + |storage_adapter| storage_adapter, + ) + .map(|storage| StorageProofCheckerAdapter::<_, B> { + storage, + _dummy: Default::default(), + }) + .map_err(|err| MessageProofError::Custom(err.into())) + }, + ) + .map_err(Into::into) + } + #[derive(Debug, PartialEq)] pub(crate) enum MessageProofError { Empty, @@ -813,15 +825,11 @@ pub mod target { #[cfg(test)] mod tests { use super::*; + use bp_runtime::messages::DispatchFeePayment; use codec::{Decode, Encode}; use frame_support::weights::Weight; use std::ops::RangeInclusive; - const DELIVERY_TRANSACTION_WEIGHT: Weight = 100; - const DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; - const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2; - const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4; - const BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE: u32 = 6; const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: Weight = 2048; const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; @@ -838,16 +846,6 @@ mod tests { const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = *b"this"; - - fn bridged_balance_to_this_balance( - bridged_balance: BridgedChainBalance, - bridged_to_this_conversion_rate_override: Option, - ) -> ThisChainBalance { - let conversion_rate = bridged_to_this_conversion_rate_override - .map(|r| r.to_float() as u32) - .unwrap_or(BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE); - ThisChainBalance(bridged_balance.0 * conversion_rate) - } } /// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from @@ -863,13 +861,6 @@ mod tests { const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; const RELAYER_FEE_PERCENT: u32 = 20; const THIS_CHAIN_ID: ChainId = *b"brdg"; - - fn bridged_balance_to_this_balance( - _this_balance: ThisChainBalance, - _bridged_to_this_conversion_rate_override: Option, - ) -> BridgedChainBalance { - unreachable!() - } } #[derive(Debug, PartialEq, Decode, Encode, Clone)] @@ -1005,19 +996,6 @@ mod tests { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE } - - fn estimate_delivery_confirmation_transaction() -> MessageTransaction> { - MessageTransaction { - dispatch_weight: DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT, - size: 0, - } - } - - fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf { - ThisChainBalance( - transaction.dispatch_weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32, - ) - } } impl BridgedChainWithMessages for ThisChain { @@ -1028,20 +1006,6 @@ mod tests { fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { unreachable!() } - - fn estimate_delivery_transaction( - _message_payload: &[u8], - _include_pay_dispatch_fee_cost: bool, - _message_dispatch_weight: WeightOf, - ) -> MessageTransaction> { - unreachable!() - } - - fn transaction_payment( - _transaction: MessageTransaction>, - ) -> BalanceOf { - unreachable!() - } } struct BridgedChain; @@ -1066,16 +1030,6 @@ mod tests { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { unreachable!() } - - fn estimate_delivery_confirmation_transaction() -> MessageTransaction> { - unreachable!() - } - - fn transaction_payment( - _transaction: MessageTransaction>, - ) -> BalanceOf { - unreachable!() - } } impl BridgedChainWithMessages for BridgedChain { @@ -1088,27 +1042,6 @@ mod tests { std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight); begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT } - - fn estimate_delivery_transaction( - _message_payload: &[u8], - _include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: WeightOf, - ) -> MessageTransaction> { - MessageTransaction { - dispatch_weight: DELIVERY_TRANSACTION_WEIGHT + message_dispatch_weight, - size: 0, - } - } - - fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf { - BridgedChainBalance( - transaction.dispatch_weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32, - ) - } - } - - fn test_lane_outbound_data() -> OutboundLaneData { - OutboundLaneData::default() } #[test] @@ -1148,180 +1081,6 @@ mod tests { const TEST_LANE_ID: &LaneId = b"test"; const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; - fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload - { - source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![42], - } - } - - #[test] - fn message_fee_is_checked_by_verifier() { - const EXPECTED_MINIMAL_FEE: u32 = 5500; - - // payload of the This -> Bridged chain message - let payload = regular_outbound_message_payload(); - - // let's check if estimation matching hardcoded value - assert_eq!( - source::estimate_message_dispatch_and_delivery_fee::( - &payload, - OnThisChainBridge::RELAYER_FEE_PERCENT, - None, - ), - Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), - ); - - // let's check if estimation is less than hardcoded, if dispatch is paid at target chain - let mut payload_with_pay_on_target = regular_outbound_message_payload(); - payload_with_pay_on_target.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; - let fee_at_source = - source::estimate_message_dispatch_and_delivery_fee::( - &payload_with_pay_on_target, - OnThisChainBridge::RELAYER_FEE_PERCENT, - None, - ) - .expect( - "estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message", - ); - assert!( - fee_at_source < EXPECTED_MINIMAL_FEE.into(), - "Computed fee {:?} without prepaid dispatch must be less than the fee with prepaid dispatch {}", - fee_at_source, - EXPECTED_MINIMAL_FEE, - ); - - // and now check that the verifier checks the fee - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ), - Err(source::TOO_LOW_FEE) - ); - assert!(source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ) - .is_ok(),); - } - - #[test] - fn should_disallow_root_calls_from_regular_accounts() { - // payload of the This -> Bridged chain message - let payload = source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![42], - }; - - // and now check that the verifier checks the fee - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ), - Err(source::BAD_ORIGIN) - ); - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::None)), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ), - Err(source::BAD_ORIGIN) - ); - assert!(source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ) - .is_ok(),); - } - - #[test] - fn should_verify_source_and_target_origin_matching() { - // payload of the This -> Bridged chain message - let payload = source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: bp_message_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)), - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![42], - }; - - // and now check that the verifier checks the fee - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ), - Err(source::BAD_ORIGIN) - ); - assert!(source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(1)))), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ) - .is_ok(),); - } - - #[test] - fn message_is_rejected_when_sent_using_disabled_lane() { - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1_000_000), - b"dsbl", - &test_lane_outbound_data(), - ®ular_outbound_message_payload(), - ), - Err(source::MESSAGE_REJECTED_BY_OUTBOUND_LANE) - ); - } - - #[test] - fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() { - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &OutboundLaneData { - latest_received_nonce: 100, - latest_generated_nonce: 100 + MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE + 1, - ..Default::default() - }, - ®ular_outbound_message_payload(), - ), - Err(source::TOO_MANY_PENDING_MESSAGES) - ); - } - #[test] fn verify_chain_message_rejects_message_with_too_small_declared_weight() { assert!(source::verify_chain_message::( @@ -1618,53 +1377,4 @@ mod tests { Err(target::MessageProofError::MessagesCountMismatch), ); } - - #[test] - fn transaction_payment_works_with_zero_multiplier() { - use sp_runtime::traits::Zero; - - assert_eq!( - transaction_payment( - 100, - 10, - FixedU128::zero(), - |weight| weight, - MessageTransaction { size: 50, dispatch_weight: 777 }, - ), - 100 + 50 * 10, - ); - } - - #[test] - fn transaction_payment_works_with_non_zero_multiplier() { - use sp_runtime::traits::One; - - assert_eq!( - transaction_payment( - 100, - 10, - FixedU128::one(), - |weight| weight, - MessageTransaction { size: 50, dispatch_weight: 777 }, - ), - 100 + 50 * 10 + 777, - ); - } - - #[test] - fn conversion_rate_override_works() { - let payload = regular_outbound_message_payload(); - let regular_fee = source::estimate_message_dispatch_and_delivery_fee::( - &payload, - OnThisChainBridge::RELAYER_FEE_PERCENT, - None, - ); - let overrided_fee = source::estimate_message_dispatch_and_delivery_fee::( - &payload, - OnThisChainBridge::RELAYER_FEE_PERCENT, - Some(FixedU128::from_float((BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE * 2) as f64)), - ); - - assert!(regular_fee < overrided_fee); - } } diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs deleted file mode 100644 index b09a88e62..000000000 --- a/bin/runtime-common/src/messages_api.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Helpers for implementing various message-related runtime API mthods. - -use crate::messages::{source::FromThisChainMessagePayload, MessageBridge}; - -use bp_messages::{LaneId, MessageDetails, MessageNonce}; -use codec::Decode; -use sp_std::vec::Vec; - -/// Implementation of the `To*OutboundLaneApi::message_details`. -pub fn outbound_message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, -) -> Vec> -where - Runtime: pallet_bridge_messages::Config, - MessagesPalletInstance: 'static, - BridgeConfig: MessageBridge, -{ - (begin..=end) - .filter_map(|nonce| { - let message_data = - pallet_bridge_messages::Pallet::::outbound_message_data(lane, nonce)?; - let decoded_payload = - FromThisChainMessagePayload::::decode(&mut &message_data.payload[..]).ok()?; - Some(MessageDetails { - nonce, - dispatch_weight: decoded_payload.weight, - size: message_data.payload.len() as _, - delivery_and_dispatch_fee: message_data.fee, - dispatch_fee_payment: decoded_payload.dispatch_fee_payment, - }) - }) - .collect() -} diff --git a/modules/dispatch/Cargo.toml b/modules/dispatch/Cargo.toml index 12655f661..b826272ab 100644 --- a/modules/dispatch/Cargo.toml +++ b/modules/dispatch/Cargo.toml @@ -18,14 +18,14 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [dev-dependencies] -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index d0f061cef..5fa95f20a 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -131,8 +131,8 @@ pub mod pallet { MessageSignatureMismatch(ChainId, BridgeMessageIdOf), /// We have failed to decode Call from the message. MessageCallDecodeFailed(ChainId, BridgeMessageIdOf), - /// The call from the message has been rejected by the call filter. - MessageCallRejected(ChainId, BridgeMessageIdOf), + /// The call from the message has been rejected by the call validator. + MessageCallValidateFailed(ChainId, BridgeMessageIdOf, TransactionValidityError), /// The origin account has failed to pay fee for dispatching the message. MessageDispatchPaymentFailed( ChainId, @@ -298,16 +298,15 @@ impl, I: 'static> MessageDispatch T::IntoDispatchOrigin::into_dispatch_origin(&origin_derived_account, &call); // validate the call - if let Err(_e) = T::CallValidator::call_validate(relayer_account, &dispatch_origin, &call) { + if let Err(e) = T::CallValidator::call_validate(relayer_account, &dispatch_origin, &call) { log::trace!( target: "runtime::bridge-dispatch", - "Message {:?}/{:?}: the call ({:?}) is rejected by filter", + "Message {:?}/{:?}: the call ({:?}) is rejected by the validator", source_chain, id, call, ); - // TODO: https://github.com/paritytech/substrate/pull/11599 - Self::deposit_event(Event::MessageCallRejected(source_chain, id)); + Self::deposit_event(Event::MessageCallValidateFailed(source_chain, id, e)); return dispatch_result; } @@ -386,7 +385,7 @@ impl, I: 'static> MessageDispatch fn extract_actual_weight(result: &DispatchResultWithPostInfo, info: &DispatchInfo) -> Weight { let post_info = match result { - Ok(post_info) => &post_info, + Ok(post_info) => post_info, Err(err) => &err.post_info, }; match post_info.pays_fee { @@ -898,9 +897,10 @@ mod tests { vec![EventRecord { phase: Phase::Initialization, event: Event::Dispatch( - call_dispatch::Event::::MessageCallRejected( + call_dispatch::Event::::MessageCallValidateFailed( SOURCE_CHAIN_ID, - id + id, + TransactionValidityError::Invalid(InvalidTransaction::Call), ) ), topics: vec![], diff --git a/modules/fee-market/Cargo.toml b/modules/fee-market/Cargo.toml index 991045da3..e91276773 100644 --- a/modules/fee-market/Cargo.toml +++ b/modules/fee-market/Cargo.toml @@ -11,32 +11,31 @@ version = "0.1.0" [dependencies] # crates.io -bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # paritytech -frame-benchmarking = { optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-benchmarking = { optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } # darwinia-bridges-substrate bp-messages = { default-features = false, path = "../../primitives/messages" } -bp-runtime = { default-features = false, path = "../../primitives/runtime" } +bp-runtime = { default-features = false, path = "../../primitives/runtime" } pallet-bridge-messages = { default-features = false, path = "../messages" } [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +bitvec = { version = "1" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] std = [ # crates.io - "bitvec/std", "codec/std", "scale-info/std", # paritytech diff --git a/modules/fee-market/README.md b/modules/fee-market/README.md index 180b67b01..f7446a3c8 100644 --- a/modules/fee-market/README.md +++ b/modules/fee-market/README.md @@ -1,54 +1,142 @@ -# Design of Relayer Fee Market +# Design Of Cross-Chain Fee Market ## Requirements -1. Users use native tokens of the source chain as the only method of payment; -2. The estimated fee of the message to be transferred is supported by a pricing system on the source chain which is connected to a Relayer Fee Market; -3. The cost on the target chain is at the expense of the relayer who claims the handling fee on the source chain with the proof of delivery after delivery is completed successfully. To incentivize relayers, the pricing system should ensure the gain is greater than the cost in long term. If an automatic pricing mechanism is infeasible, relayers should be able to give their offers manually and shoulder the cost of offering. The relayers should be punished if they fail to relay the message as expected. -4. Relayers and Users constitute a secondary supply-and-demand market, where prices rise when supply is low and fall when supply is abundant. There are no access restrictions for relayers, and anyone can enter. Relayer should evaluate and quote at their own discretion as an economically rational person. An incomplete list of risks that relayers should take into account is as follows: - 1. Fluctuation in token prices and exchange ratios; - 2. Time delay between quoting and claiming; - 3. Loss of staking funds due to software or network failures +1. Users use native tokens of the source chain as the only method of cross-chain payment. +2. The cross-chain fees paid by users are generated by the fee market system and the final price quoted by the fee market is influenced by all relayers involved in the delivery of messages throughout the market. +3. The cost on the target chain is at the expense of the relayer who claims the handling fee on the source chain with the proof of delivery after delivery is completed successfully. To incentivize relayers, the fee market system should ensure the relayers gain is greater than the cost in long term. If an automatic pricing mechanism is infeasible, relayers should be able to give their offers manually and shoulder the cost of offering. The relayers should be punished if they fail to relay the message as expected. +4. Relayers and Users constitute a secondary supply-and-demand market, where quotes rise when relayers number is low and fall when relayers number is abundant. There are no access restrictions for relayers, and anyone can enter. Relayer should evaluate and quote at their own discretion as an economically rational person. An incomplete list of risks that relayers should take into account is as follows: + * Fluctuation in token prices and exchange ratios; + * Time delay between quoting and claiming; + * Loss of staking funds due to software or network failures; -## Tiered Quotation Market +## Tiered Quotation Mechanism -This approach is suitable for scenarios with lower gas fee on the source chain and shorter finality time. It has better versatility, reliability, and robustness. Such networks include Heco, BSC, Polygon and Darwinia. +> This approach is suitable for scenarios with lower gas fee on the source chain and shorter finality time. It has better versatility, reliability, and robustness. Such networks include Heco, BSC, Polygon and Darwinia. -First, the relayer posts their quotes based on the reference price and the expected profit on the blockchain at any time. An off-chain pricing system maintains the reference price. Each relayer should lock a sufficient default margin on the chain to guarantee the faithful execution of the deal. +First, the relayers must register in the fee market system and post their quotes based on the reference price and the expected profit on the blockchain at any time. An off-chain pricing system maintains the reference price. Each relayer should lock a sufficient default margin on the chain to guarantee the faithful execution of the deal. -In this way, a series of ***Ask*** prices(price meanings fee per message) come into being in the ascending order on the blockchain. When the user initiates a request on the source chain, the lowest n offers **_P1, P2...Pn_** are filtered out and **Pn** is used as the billing price. Those who make these offers are called *Assigned Relayers*. The user can request a cross-chain message delivery after paying **_Pn_**. The reason that we select n relayers in the executed order is that we want to have redundancy for executing the message delivery. P1's relayer is R1, P2's relayer is R2, Pn's relayer is Rn. +In this way, a series of quoted prices (price meanings fee per message) come into being in the ascending order on the blockchain. When the user initiates a cross-chain request on the source chain, the lowest n quoted prices are filtered out and the last one is used as the billing price. Those who make these prices are called *Assigned Relayers*. User can send cross-chain messages after paying billing price on the source chain, then wait for message execution on the target chain. The assigned relayers are responsible for ensuring the success of cross-chain message delivery and need to monitor their running relayer clients closely. If a cross-chain message is not executed in the specified time on the target chain, all assigned relayers will be penalised. The reason that we select n relayers as assigned relayers is that we want to have redundancy for executing the message delivery. Note that if the count of relayers in current market are less than n when some users sends cross-chain message, it means the fee market system fails to provide a price for user sending cross-chain message, and the dispatch call user sent on the source chain will simply fail and exit. -In any time, the message relayer and confirm relayer can be anyone, do not have be the assigned relayer. But in priority time slots, assigned relayer will be rewarded with much more regardless wo relay the message and do the confirmation. -To give them different priority for the specific assigned relayer, each assigned relayer has a time slot. The relayer who is assigned with her own time slot will be rewarded with more percentage, and this reward is for the asked price and the commitment(delivery in time or slash). Relayer with lower price are assigned with earlier time slot. +In any time, the message delivery and confirmation relayer can be anyone, do not have be the assigned relayer. However, there is an additional bonus for being an assigned relayer as a reward for guarding the cross-chain messaging service. In order to better manage the responsibilities of the n assigned relayers, each assigned relayer is given a time slot (from the creation of the cross-chain message), meaning that the assigned relayer is obliged to deliver the cross-chain message in the allocated time slot. If a message is supposed to be delivered to the target chain in one of the assigned relayer's time slots, but it is not, the assigned relayer is considered to have acted badly and will be penalised for locked assets, or even removed from the set of assigned relayers. -For simplicity, if count of relayers in current market are less than MIN_ASSIGNED_RELAYERS_NUMBER(runtime config) when some user is sending bridge message, it means the relayer fee market fails to provide a price for user sending bridge message, and this dispatch call on source chain will simply fail and exit. +## Reward And Slash Rules -### Detailed Steps in Implementation +### Key Parameters -1. Enroll and lock collateral - 1. `enroll_and_lock_collateral` dispatch call - 2. `cancel_enrollment()` dispatch call, remember to check if the relayer is in priority time slots. -2. Ask price - We use simple constant price function for messages currently: fn(message) = const_price * 1 where const_price means fee per message. We might later improve this fn(message) with [relayer defined fee functions](https://github.com/darwinia-network/darwinia-common/issues/813). - 1. Update, Cancel prices storage - 2. If the collateral of any registered relayer is lower than required collateral threshold (e.g. slashed), the enrolment of this relayer will become inactive(will be removed from the ask list, and not able to put new ask). -3. Send message, user pay **_Pn_** for sending a cross-chain message. - 1. Create a new order(with current block number), in the order lifecycle, relayer cannot cancel enrollment and take back collateral. - 2. **_Pn_** is consumed in the module relayer fund account. -4. Message delivery and confirmed by bridger. -5. Reward and Slash Strategy. - 1. If the order is confirmed in Rn's slot, then Rn can claim 60% from the reward Pn, and message relayer can claim 80% * (1 - 60%) from Pn, confirm relayer can claim 20% * (1 - 60%) from Pn, (P3 - Pn) will go to treasury. - 2. If the order is confirmed beyond all assigned relayers slot, and then The reward will be S(t) where S(t) > P3, the part S(t) - P3 comes from funds slashed from R1, R2, R3's collateral. Message relayer can claim 80% from S(t), confirm relayer can claim 20% from S(t). +When calculating rewards and penalties, the following parameters are crucial. - Note: The ratio parameters in the strategy can be defined in runtime, and there might be update to them for refinement after more benchmark and statistics. +- DutyRelayersRewardRatio: `20% by default` +- MessageRelayersRewardRatio: `80% by default` +- ConfirmRelayersRewardRatio: `20% by default` +- AssignedRelayerSlashRatio: `20% by default` +- Slot: `300 blocks for each slot by default.` +### Basic Rules -## Another Proposal B-Oracle + On-chain Automatic Pricing +After a user sends a cross-chain transaction, the fee market system calculates the penalty or reward according to the time the cross-chain transaction is confirmed, with the following rules: -High gas fees in some networks, such as Ethereum, may prevent the relayer from quoting frequently, and the execution cost of message delivery on the target chain is predictable, such as (***Ethereum>Darwinia***). In this scenario, a second-best solution is to query the execution cost by the interface on the target chain, plus the estimated delivery cost. The disadvantage is that it is not adaptable, and it is possible that no relayer is willing to take the order, causing message delivery congestion and stability problems. +- The cross-chain transaction is confirmed before the last block of the n slot. -## Update to Darwinia > Ethereum Bridge: Grandpa Beefy Light Client + Three-tiered Quotation + As long as the order is confirmed before the last block of the nth slot, we consider it to be delivered on time, and the calculation of rewards and penalties varies depending on when the message is confirmed. -For BEEFY, the interaction is a multi-round process in which BridgedChain fee should be paid. The user needs to know in advance how much the handling fee is and whether the amount is sufficient. However, it can not be predicted. We can establish a market which implements a set of ***ask***/***bid*** system. + Suppose the cross-chain message has n slots, the message is confirmed at the m-th slot, and `Pm` denotes the quote price of m-th slot. At this point, the assigned relayers from 0 to m slots will be penalized, and the penalty will be calculated as `AssignedRelayerSlashRatio * collateral`, while the assigned relayers from m to n slots will receive a reward for ensuring the message is completed on time `(DutyRelayersRewardRatio * (fee - Pm)) / (n - m)`. `Pm` plus the penalties for the other assigned relayers mentioned above will be distributed as new rewards to the message delivery relayer and the message confirm relayer, where the message delivery relayer receive the `MessageRelayersRewardRatio` of this reward, the message confirm relayer gets the `ConfirmRelayersRewardRatio` of this reward. The rest of the fee will be given to treasury. -The relayer posts a quote for ***Header Relay*** during a specific period(***ask***) and the user may respond to it (***bid***) if they accept the quoted price. The relayer relays the **header** after the deal is closed. The relayer may lose the staking tokens if they fail to relay the message in time, whatever the reason is. More than one relayer can quote at the same time to compete for users. +- The cross-chain transaction is confirmed after the last block of the n slot. + + We believe that this cross-chain transaction is severely delayed, in which case all assigned relayers will be heavily penalized by deducting the `AssignedRelayerSlashRatio` of the collateral and calculating an additional penalty amount based on the delay time. These penalty amounts, plus the cross-chain fees paid by users, will be distributed as new rewards to the message delivery relayer and the message confirm relayer, where the message delivery relayer receive the `MessageRelayersRewardRatio` of this reward, the message confirm relayer gets the `ConfirmRelayersRewardRatio` of this reward. + + +The following diagram shows how rewards are distributed: + +```sh + + assigned offensive relayers collateral + | |---> messaage delivery relayer + | | + |- slot price + slot offensive slash(may have) = message reward --> | + | | +message fee - |---> message confirm relayer + | ---> treasury + | | + |- message surplus -| + | + ---> slot duty rewards -> assigned duty relayers + +``` + +### An example + +1. Assume that relayers `R1`, `R2`, `R3`, `R4` and `R5` have registered with the fee market and are all running relayer clients capable of delivering messages with quote prices of `P1=10`, `P2=20`, `P3=30`, `P4=4`0 and `P5=50` and are registered with a locked asset of `100`. +2. Assume that the total number of assigned relayers specified by the fee market system is `3` (default). In this case, the fee market will generate a cross-chain fee of `30` (10 < 20 < 30 < 40 < 50) and the set of assigned relayers is `R1, R2, R3`. +3. Assume that the slot value in the fee market runtime is equal to `50` blocks. + +In this case, suppose the source chain receives a cross-chain message at height `100` and the user pays a cross-chain fee of `30`. After the source chain receives the message, the fee market assigns `R1, R2 and R3` as the assigned relayers for the message, respectively, and their corresponding time slots are `(100, 150)`, `(150, 200)`, `(200, 250)` + +After that, all relayers clients will observe the message in the source chain and deliver it to the target chain first. + +The slash, reward analysis is divided into two cases. + + * *the message in time (confirmed before the end of the 3rd assigned relayer's slot)* + + - Confirmed at block `110(the first slot)` + + No assigned relayers will be slashed in this case. + + Reward Summary: + + * To assigned relayers (R1, R2, R3): `(DutyRelayersRewardRatio * (30 - 10)) / 3 = 1` + * To treasury: `30 - 10 - 1 * 3 = 17` + * To message delivery relayer: `10 * MessageRelayersRewardRatio = 8` + * To message confirm relayer: `10 * ConfirmRelayersRewardRatio = 2` + + - Confirmed at block `160(the second slot)` + + Since the message is confirmed at the second slot, the first assigned relayer will be slashed. + + Slash Summary: + + * R1: `100 * AssignedRelayerSlashRatio = 20` + + Reward Summary: + + * To assigned relayers (R2, R3) = `(DutyRelayersRewardRatio * (30 - 20)) / 2 = 1` + * To treasury: `30 - 20 - 1 * 2 = 8` + * To message delivery relayer: `(20 + 20) * MessageRelayersRewardRatio = 32` + * To message confirm relayer: `(20 + 20) * MessageRelayersRewardRatio = 8` + + + - Confirmed at block `210(the third slot)` + + Since the message is confirmed at the third slot, the first two assigned relayer will be slashed. + + Slash Summary: + + * R1: `100 * AssignedRelayerSlashRatio = 20` + * R2: `100 * AssignedRelayerSlashRatio = 20` + + Reward Summary: + + * To assigned relayers (R3) = `(DutyRelayersRewardRatio * (30 - 30)) / 1 = 0` + * To treasury: `30 - 30 - 0 = 0` + * To message delivery relayer: `(10 + 20 * 2) * MessageRelayersRewardRatio = 56` + * To message confirm relayer: `(10 + 20 * 2) * MessageRelayersRewardRatio = 14` + + * *the message times out (confirmed after the end of the 3rd assigned relayer's slot)* + + - Confirmed at block `260(Out of slot)` + + The message is confirmed out of slot 10 blocks, all the assigned relayer will be slashed. + + Slash Summary: + + * R1: `100 * AssignedRelayerSlashRatio + 10 * 2 = 40` + * R2: `100 * AssignedRelayerSlashRatio + 10 * 2 = 40` + * R3: `100 * AssignedRelayerSlashRatio + 10 * 2 = 40` + + Reward Summary: + + * To assigned relayers: `0` + * To treasury: `0` + * To message delivery relayer: `(30 + 40 * 3) * MessageRelayersRewardRatio = 120` + * To message confirm relayer: `(30 + 40 * 3) * MessageRelayersRewardRatio = 30` diff --git a/modules/fee-market/src/lib.rs b/modules/fee-market/src/lib.rs index 1364621d4..e406d0414 100644 --- a/modules/fee-market/src/lib.rs +++ b/modules/fee-market/src/lib.rs @@ -69,6 +69,9 @@ pub mod pallet { #[pallet::constant] type MinimumRelayFee: Get>; /// The collateral relayer need to lock for each order. + /// + /// This also represents the maximum slash value for a single delayed order. + /// Please note that if this value is set to zero the fee market will be suspended. #[pallet::constant] type CollateralPerOrder: Get>; /// The slot times set @@ -77,16 +80,18 @@ pub mod pallet { /// Reward parameters #[pallet::constant] - type AssignedRelayersRewardRatio: Get; + type DutyRelayersRewardRatio: Get; #[pallet::constant] type MessageRelayersRewardRatio: Get; #[pallet::constant] type ConfirmRelayersRewardRatio: Get; - /// The slash rule + /// The slash ratio for assigned relayers. + #[pallet::constant] + type AssignedRelayerSlashRatio: Get; type Slasher: Slasher; - type Currency: LockableCurrency; + type Currency: LockableCurrency; type Event: From> + IsType<::Event>; type WeightInfo: WeightInfo; } @@ -462,11 +467,6 @@ impl, I: 'static> Pallet { Self::assigned_relayers().and_then(|relayers| relayers.last().map(|r| r.fee)) } - /// Get order indexes in the storage - pub fn in_process_orders() -> Vec<(LaneId, MessageNonce)> { - Orders::::iter().map(|(k, _v)| k).collect() - } - /// Get the relayer locked collateral value pub fn relayer_locked_collateral(who: &T::AccountId) -> BalanceOf { RelayersMap::::get(who).map_or(BalanceOf::::zero(), |r| r.collateral) @@ -479,7 +479,8 @@ impl, I: 'static> Pallet { let mut count = 0u32; let mut orders_locked_collateral = BalanceOf::::zero(); for (_, order) in >::iter() { - if order.relayers_slice().iter().any(|r| r.id == *who) && !order.is_confirmed() { + if order.assigned_relayers_slice().iter().any(|r| r.id == *who) && !order.is_confirmed() + { count += 1; orders_locked_collateral = orders_locked_collateral.saturating_add(order.locked_collateral); @@ -505,10 +506,20 @@ impl, I: 'static> Pallet { } fn collateral_to_order_capacity(collateral: BalanceOf) -> u32 { - (collateral / T::CollateralPerOrder::get()).saturated_into::() + let collateral_per_order = T::CollateralPerOrder::get(); + + if collateral_per_order.is_zero() { + 0 + } else { + (collateral / collateral_per_order).saturated_into::() + } } } +/// The assigned relayers slash trait pub trait Slasher, I: 'static> { - fn slash(locked_collateral: BalanceOf, timeout: T::BlockNumber) -> BalanceOf; + fn cal_slash_amount( + collateral_per_order: BalanceOf, + timeout: T::BlockNumber, + ) -> BalanceOf; } diff --git a/modules/fee-market/src/s2s/callbacks.rs b/modules/fee-market/src/s2s/callbacks.rs index 4ba1a470b..98a468d85 100644 --- a/modules/fee-market/src/s2s/callbacks.rs +++ b/modules/fee-market/src/s2s/callbacks.rs @@ -40,8 +40,12 @@ impl, I: 'static> OnMessageAccepted for FeeMarketMessageAcceptedHan assigned_relayers.clone(), T::Slot::get(), ); + // Store the create order >::insert((order.lane, order.message), order.clone()); + // Once order is created, the assigned relayers's order capacity should reduce by one. + // Thus, the whole market needs to re-sort to generate new assigned relayers set. + let _ = Pallet::::update_market(|| Ok(()), None); let ids: Vec = assigned_relayers.iter().map(|r| r.id.clone()).collect(); Pallet::::deposit_event(Event::OrderCreated( @@ -72,6 +76,11 @@ impl, I: 'static> OnDeliveryConfirmed for FeeMarketMessageConfirmed Some(order) => order.set_confirm_time(Some(now)), None => {}, }); + + // Once order is confirmed, the assigned relayers's order capacity should + // increase by one. Thus, the whole market needs to re-sort to generate new + // assigned relayers set. + let _ = Pallet::::update_market(|| Ok(()), None); } } } diff --git a/modules/fee-market/src/s2s/payment.rs b/modules/fee-market/src/s2s/payment.rs index efc375c04..b025c7b2d 100644 --- a/modules/fee-market/src/s2s/payment.rs +++ b/modules/fee-market/src/s2s/payment.rs @@ -26,8 +26,9 @@ use frame_support::{ traits::{Currency as CurrencyT, ExistenceRequirement, Get}, }; use scale_info::TypeInfo; -use sp_runtime::traits::{AccountIdConversion, Saturating, Zero}; +use sp_runtime::traits::{AccountIdConversion, CheckedDiv, Saturating, UniqueSaturatedInto, Zero}; use sp_std::{ + cmp::{max, min}, collections::{btree_map::BTreeMap, vec_deque::VecDeque}, ops::RangeInclusive, }; @@ -90,26 +91,53 @@ where received_range: &RangeInclusive, relayer_fund_account: &T::AccountId, ) { - let RewardsBook { deliver_sum, confirm_sum, assigned_relayers_sum, treasury_sum } = - slash_and_calculate_rewards::( - lane_id, - messages_relayers, - confirmation_relayer.clone(), - received_range, - relayer_fund_account, - ); + let rewards_items = calculate_rewards::( + lane_id, + messages_relayers, + confirmation_relayer.clone(), + received_range, + relayer_fund_account, + ); + + let mut deliver_sum = BTreeMap::>::new(); + let mut confirm_sum = BalanceOf::::zero(); + let mut assigned_relayers_sum = BTreeMap::>::new(); + let mut treasury_sum = BalanceOf::::zero(); + for item in rewards_items { + for (k, v) in item.to_assigned_relayers.iter() { + assigned_relayers_sum + .entry(k.clone()) + .and_modify(|r| *r = r.saturating_add(*v)) + .or_insert(*v); + } + + if let Some(reward) = item.to_treasury { + treasury_sum = treasury_sum.saturating_add(reward); + } + + if let Some((id, reward)) = item.to_message_relayer { + deliver_sum + .entry(id) + .and_modify(|r| *r = r.saturating_add(reward)) + .or_insert(reward); + } + + if let Some((_id, reward)) = item.to_confirm_relayer { + confirm_sum = confirm_sum.saturating_add(reward); + } + } - // Pay confirmation relayer rewards + // Pay rewards to the message confirm relayer do_reward::(relayer_fund_account, confirmation_relayer, confirm_sum); - // Pay messages relayers rewards + // Pay rewards to the messages deliver relayers for (relayer, reward) in deliver_sum { do_reward::(relayer_fund_account, &relayer, reward); } - // Pay assign relayer reward + // Pay rewards to the assigned relayers for (relayer, reward) in assigned_relayers_sum { do_reward::(relayer_fund_account, &relayer, reward); } - // Pay treasury_sum reward + // Pay to treasury do_reward::( relayer_fund_account, &T::TreasuryPalletId::get().into_account_truncating(), @@ -118,90 +146,145 @@ where } } -/// Slash and calculate rewards for messages_relayers, confirmation relayers, treasury_sum, +/// Calculate rewards for messages_relayers, confirmation relayers, treasury_sum, /// assigned_relayers -pub fn slash_and_calculate_rewards( +pub fn calculate_rewards( lane_id: LaneId, messages_relayers: VecDeque>, confirm_relayer: T::AccountId, received_range: &RangeInclusive, relayer_fund_account: &T::AccountId, -) -> RewardsBook +) -> Vec>> where T: frame_system::Config + Config, I: 'static, { - let mut rewards_book = RewardsBook::new(); + let mut rewards_items = Vec::new(); for entry in messages_relayers { - let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); - let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); + let nonce_begin = max(entry.messages.begin, *received_range.start()); + let nonce_end = min(entry.messages.end, *received_range.end()); for message_nonce in nonce_begin..nonce_end + 1 { // The order created when message was accepted, so we can always get the order info. if let Some(order) = >::get(&(lane_id, message_nonce)) { - // The confirm_time of the order is set in the `OnDeliveryConfirmed` callback. And - // the callback function was called as source chain received message delivery proof, - // before the reward payment. - let order_confirm_time = - order.confirm_time.unwrap_or_else(|| frame_system::Pallet::::block_number()); - let message_fee = order.fee(); - let mut reward_item = RewardItem::new(); - let message_reward; - let confirm_reward; - - if let Some((who, base_fee)) = - order.required_delivery_relayer_for_time(order_confirm_time) - { - // message fee - base fee => treasury_sum - reward_item.to_treasury = Some(message_fee.saturating_sub(base_fee)); - - // AssignedRelayersRewardRatio * base fee => slot relayer - let slot_relayer_reward = T::AssignedRelayersRewardRatio::get() * base_fee; - reward_item.to_slot_relayer = Some((who, slot_relayer_reward)); - - let bridger_relayers_reward = base_fee.saturating_sub(slot_relayer_reward); - // MessageRelayersRewardRatio * (1 - AssignedRelayersRewardRatio) * base_fee => - // message relayer - message_reward = T::MessageRelayersRewardRatio::get() * bridger_relayers_reward; - // ConfirmRelayersRewardRatio * (1 - AssignedRelayersRewardRatio) * base_fee => - // confirm relayer - confirm_reward = T::ConfirmRelayersRewardRatio::get() * bridger_relayers_reward; - } else { - // The order delivery is delay, slash occurs. - let mut total_slash = message_fee; - - // calculate slash amount - let mut amount: BalanceOf = T::Slasher::slash( - order.locked_collateral, - order.delivery_delay().unwrap_or_default(), - ); - if let Some(slash_protect) = Pallet::::collateral_slash_protect() { - amount = sp_std::cmp::min(amount, slash_protect); - } - - // Slash order's assigned relayers - let mut assigned_relayers_slash = BalanceOf::::zero(); - for assigned_relayer in order.relayers_slice() { - let report = SlashReport::new(&order, assigned_relayer.id.clone(), amount); - let slashed = do_slash::( - &assigned_relayer.id, - relayer_fund_account, - amount, - report, - ); - assigned_relayers_slash += slashed; - } - total_slash += assigned_relayers_slash; - - // MessageRelayersRewardRatio total slash => message relayer - message_reward = T::MessageRelayersRewardRatio::get() * total_slash; - // ConfirmRelayersRewardRatio total slash => confirm relayer - confirm_reward = T::ConfirmRelayersRewardRatio::get() * total_slash; + + let (message_reward, treasury_reward) = match order.confirmed_info() { + // When the order is confirmed at the first slot, no assigned relayers will be + // not slashed in this case. The total reward to the message deliver relayer and + // message confirm relayer is the confirmed slot price(first slot price), the + // duty relayers would be rewarded with the 20% of the message fee, and all + // the duty relayers share the duty_rewards equally. Finally, the + // surplus of the message fee goes to the treasury. + Some((slot_index, slot_price)) if slot_index == 0 => { + let mut message_surplus = order.fee().saturating_sub(slot_price); + let slot_duty_rewards = T::DutyRelayersRewardRatio::get() * message_surplus; + + // All assigned relayers successfully are on duty in this case, no slash + // happens, just calculate the duty relayers rewards. + let duty_relayers: Vec<_> = + order.assigned_relayers_slice().iter().map(|r| r.id.clone()).collect(); + let average_reward = slot_duty_rewards + .checked_div(&(duty_relayers.len()).unique_saturated_into()) + .unwrap_or_default(); + for id in duty_relayers { + reward_item.to_assigned_relayers.insert(id.clone(), average_reward); + message_surplus = message_surplus.saturating_sub(average_reward); + } + + (slot_price, Some(message_surplus)) + }, + // When the order is confirmed not at the first slot but within the deadline, + // some other assigned relayers will be slashed in this case. The total reward + // to the message deliver relayer and message confirm relayer is the confirmed + // slot price(first slot price) + slot_offensive_slash part, the + // duty relayers would be rewarded with the 20% of the message surplus, and all + // the duty relayers share the duty_rewards equally. Finally, the + // surplus of the message fee goes to the treasury. + Some((slot_index, slot_price)) if slot_index >= 1 => { + let mut message_surplus = order.fee().saturating_sub(slot_price); + let slot_duty_rewards = T::DutyRelayersRewardRatio::get() * message_surplus; + + // Since part of the assigned relayers are on duty, calculate the duty + // relayers slash part first. + let mut offensive_relayers: Vec<_> = + order.assigned_relayers_slice().iter().map(|r| r.id.clone()).collect(); + let duty_relayers = offensive_relayers.split_off(slot_index); + + // Calculate the assigned relayers slash part + let mut slot_offensive_slash = BalanceOf::::zero(); + for r in offensive_relayers { + let amount = slash_assigned_relayer::( + &order, + &r, + relayer_fund_account, + T::AssignedRelayerSlashRatio::get() + * Pallet::::relayer_locked_collateral(&r), + ); + slot_offensive_slash += amount; + } + + // Calculate the duty relayers rewards + let average_reward = slot_duty_rewards + .checked_div(&(duty_relayers.len()).unique_saturated_into()) + .unwrap_or_default(); + for id in duty_relayers { + reward_item.to_assigned_relayers.insert(id.clone(), average_reward); + message_surplus = message_surplus.saturating_sub(average_reward); + } + + (slot_price.saturating_add(slot_offensive_slash), Some(message_surplus)) + }, + // When the order is confirmed delayer, all assigned relayers will be slashed in + // this case. So, no confirmed slot price here. All reward will distribute to + // the message deliver relayer and message confirm relayer. No duty rewards + // and treasury reward. + _ => { + let mut slot_offensive_slash = BalanceOf::::zero(); + for r in order.assigned_relayers_slice() { + // 1. For the fixed part + let mut slash_amount = T::AssignedRelayerSlashRatio::get() + * Pallet::::relayer_locked_collateral(&r.id); + + // 2. For the dynamic part + slash_amount += T::Slasher::cal_slash_amount( + order.locked_collateral, + order.comfirm_delay().unwrap_or_default(), + ); + + // The total_slash_amount can't be greater than the slash_protect. + if let Some(slash_protect) = Pallet::::collateral_slash_protect() + { + // slash_amount = sp_std::cmp::min(slash_amount, slash_protect); + slash_amount = slash_amount.min(slash_protect); + } + + // The total_slash_amount can't be greater than the locked_collateral. + let locked_collateral = + Pallet::::relayer_locked_collateral(&r.id); + slash_amount = sp_std::cmp::min(slash_amount, locked_collateral); + + let amount = slash_assigned_relayer::( + &order, + &r.id, + relayer_fund_account, + slash_amount, + ); + slot_offensive_slash += amount; + } + + (order.fee().saturating_add(slot_offensive_slash), None) + }, + }; + + if let Some(treasury_reward) = treasury_reward { + reward_item.to_treasury = Some(treasury_reward); } - reward_item.to_message_relayer = Some((entry.clone().relayer, message_reward)); - reward_item.to_confirm_relayer = Some((confirm_relayer.clone(), confirm_reward)); + let deliver_rd = T::MessageRelayersRewardRatio::get() * message_reward; + let confirm_rd = T::ConfirmRelayersRewardRatio::get() * message_reward; + reward_item.to_message_relayer = Some((entry.relayer.clone(), deliver_rd)); + reward_item.to_confirm_relayer = Some((confirm_relayer.clone(), confirm_rd)); Pallet::::deposit_event(Event::OrderReward( lane_id, @@ -209,19 +292,23 @@ where reward_item.clone(), )); - rewards_book.add_reward_item(reward_item); + rewards_items.push(reward_item); } } } - rewards_book + rewards_items } -/// Do slash for absent assigned relayers -pub(crate) fn do_slash, I: 'static>( +/// Slash the assigned relayer and emit the slash report. +/// +/// fund_account refers to the user who pays the cross-chain fee to this account when creating an +/// order. The slash part will be transferred to fund_account first, and then distributed to various +/// relayers. +pub(crate) fn slash_assigned_relayer, I: 'static>( + order: &Order>, who: &T::AccountId, fund_account: &T::AccountId, amount: BalanceOf, - report: SlashReport>, ) -> BalanceOf { let locked_collateral = Pallet::::relayer_locked_collateral(who); T::Currency::remove_lock(T::LockId::get(), who); @@ -236,6 +323,7 @@ pub(crate) fn do_slash, I: 'static>( amount, ExistenceRequirement::AllowDeath, ); + let report = SlashReport::new(order, who.clone(), amount); match pay_result { Ok(_) => { crate::Pallet::::update_relayer_after_slash( @@ -282,7 +370,7 @@ pub(crate) fn do_reward, I: 'static>( /// Record the concrete reward distribution of certain order #[derive(Clone, Debug, Encode, Decode, Eq, PartialEq, TypeInfo)] pub struct RewardItem { - pub to_slot_relayer: Option<(AccountId, Balance)>, + pub to_assigned_relayers: BTreeMap, pub to_treasury: Option, pub to_message_relayer: Option<(AccountId, Balance)>, pub to_confirm_relayer: Option<(AccountId, Balance)>, @@ -291,54 +379,10 @@ pub struct RewardItem { impl RewardItem { fn new() -> Self { Self { - to_slot_relayer: None, + to_assigned_relayers: BTreeMap::new(), to_treasury: None, to_message_relayer: None, to_confirm_relayer: None, } } } - -/// Record the calculation rewards result -#[derive(Clone, Debug, Eq, PartialEq, TypeInfo)] -pub struct RewardsBook, I: 'static> { - pub deliver_sum: BTreeMap>, - pub confirm_sum: BalanceOf, - pub assigned_relayers_sum: BTreeMap>, - pub treasury_sum: BalanceOf, -} - -impl, I: 'static> RewardsBook { - fn new() -> Self { - Self { - deliver_sum: BTreeMap::new(), - confirm_sum: BalanceOf::::zero(), - assigned_relayers_sum: BTreeMap::new(), - treasury_sum: BalanceOf::::zero(), - } - } - - fn add_reward_item(&mut self, item: RewardItem>) { - if let Some((id, reward)) = item.to_slot_relayer { - self.assigned_relayers_sum - .entry(id) - .and_modify(|r| *r = r.saturating_add(reward)) - .or_insert(reward); - } - - if let Some(reward) = item.to_treasury { - self.treasury_sum = self.treasury_sum.saturating_add(reward); - } - - if let Some((id, reward)) = item.to_message_relayer { - self.deliver_sum - .entry(id) - .and_modify(|r| *r = r.saturating_add(reward)) - .or_insert(reward); - } - - if let Some((_id, reward)) = item.to_confirm_relayer { - self.confirm_sum = self.confirm_sum.saturating_add(reward); - } - } -} diff --git a/modules/fee-market/src/tests.rs b/modules/fee-market/src/tests.rs index c46d9d4e7..1163fd524 100644 --- a/modules/fee-market/src/tests.rs +++ b/modules/fee-market/src/tests.rs @@ -17,7 +17,10 @@ // along with Darwinia. If not, see . // --- std --- -use std::{collections::VecDeque, ops::RangeInclusive}; +use std::{ + collections::{BTreeMap, VecDeque}, + ops::RangeInclusive, +}; // --- crates.io --- use bitvec::prelude::*; use scale_info::TypeInfo; @@ -51,8 +54,8 @@ use sp_runtime::{ use crate::{ self as darwinia_fee_market, s2s::{ - payment::{slash_and_calculate_rewards, RewardsBook}, - FeeMarketMessageAcceptedHandler, FeeMarketMessageConfirmedHandler, + payment::calculate_rewards, FeeMarketMessageAcceptedHandler, + FeeMarketMessageConfirmedHandler, }, *, }; @@ -284,19 +287,46 @@ impl MessageDeliveryAndDispatchPayment fn pay_relayers_rewards( lane_id: LaneId, - message_relayers: VecDeque>, + messages_relayers: VecDeque>, confirmation_relayer: &AccountId, received_range: &RangeInclusive, relayer_fund_account: &AccountId, ) { - let RewardsBook { deliver_sum, confirm_sum, assigned_relayers_sum, treasury_sum } = - slash_and_calculate_rewards::( - lane_id, - message_relayers, - confirmation_relayer.clone(), - received_range, - relayer_fund_account, - ); + let rewards_items = calculate_rewards::( + lane_id, + messages_relayers, + confirmation_relayer.clone(), + received_range, + relayer_fund_account, + ); + + let mut deliver_sum = BTreeMap::::new(); + let mut confirm_sum = Balance::zero(); + let mut assigned_relayers_sum = BTreeMap::::new(); + let mut treasury_sum = Balance::zero(); + for item in rewards_items { + for (k, v) in item.to_assigned_relayers.iter() { + assigned_relayers_sum + .entry(k.clone()) + .and_modify(|r| *r = r.saturating_add(v.clone())) + .or_insert(*v); + } + + if let Some(reward) = item.to_treasury { + treasury_sum = treasury_sum.saturating_add(reward); + } + + if let Some((id, reward)) = item.to_message_relayer { + deliver_sum + .entry(id) + .and_modify(|r| *r = r.saturating_add(reward)) + .or_insert(reward); + } + + if let Some((_id, reward)) = item.to_confirm_relayer { + confirm_sum = confirm_sum.saturating_add(reward); + } + } let confimation_key = (b":relayer-reward:", confirmation_relayer, confirm_sum).encode(); frame_support::storage::unhashed::put(&confimation_key, &true); @@ -420,28 +450,33 @@ frame_support::parameter_types! { pub const CollateralPerOrder: Balance = 100; pub const Slot: u64 = 50; - pub const AssignedRelayersRewardRatio: Permill = Permill::from_percent(60); + pub const DutyRelayersRewardRatio: Permill = Permill::from_percent(20); pub const MessageRelayersRewardRatio: Permill = Permill::from_percent(80); pub const ConfirmRelayersRewardRatio: Permill = Permill::from_percent(20); + pub const AssignedRelayerSlashRatio: Permill = Permill::from_percent(20); pub const TreasuryPalletAccount: u64 = 666; } pub struct TestSlasher; impl, I: 'static> Slasher for TestSlasher { - fn slash(locked_collateral: BalanceOf, timeout: T::BlockNumber) -> BalanceOf { + fn cal_slash_amount( + collateral_per_order: BalanceOf, + timeout: T::BlockNumber, + ) -> BalanceOf { let slash_each_block = 2; let slash_value = UniqueSaturatedInto::::unique_saturated_into(timeout) .saturating_mul(UniqueSaturatedInto::::unique_saturated_into(slash_each_block)) .unique_saturated_into(); - sp_std::cmp::min(locked_collateral, slash_value) + sp_std::cmp::min(collateral_per_order, slash_value) } } impl Config for Test { - type AssignedRelayersRewardRatio = AssignedRelayersRewardRatio; + type AssignedRelayerSlashRatio = AssignedRelayerSlashRatio; type CollateralPerOrder = CollateralPerOrder; type ConfirmRelayersRewardRatio = ConfirmRelayersRewardRatio; type Currency = Balances; + type DutyRelayersRewardRatio = DutyRelayersRewardRatio; type Event = Event; type LockId = FeeMarketLockId; type MessageRelayersRewardRatio = MessageRelayersRewardRatio; @@ -739,9 +774,9 @@ fn receive_messages_delivery_proof() { #[test] fn test_callback_order_creation() { new_test_ext().execute_with(|| { - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 200, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 210, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(4), 220, None); System::set_block_number(2); let assigned_relayers = FeeMarket::assigned_relayers().unwrap(); @@ -751,7 +786,7 @@ fn test_callback_order_creation() { assert!(FeeMarket::assigned_relayers().is_some()); let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); - let relayers = order.relayers_slice(); + let relayers = order.assigned_relayers_slice(); assert_eq!(relayers[0].id, assigned_relayers.get(0).unwrap().id); assert_eq!(relayers[1].id, assigned_relayers.get(1).unwrap().id); assert_eq!(relayers[2].id, assigned_relayers.get(2).unwrap().id); @@ -770,8 +805,8 @@ fn test_callback_order_creation() { #[test] fn test_callback_no_order_created_when_fee_market_not_ready() { new_test_ext().execute_with(|| { - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 100, None); System::set_block_number(2); assert!(FeeMarket::assigned_relayers().is_none()); @@ -790,9 +825,9 @@ fn test_callback_no_order_created_when_fee_market_not_ready() { fn test_callback_order_confirm() { new_test_ext().execute_with(|| { System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, Some(100)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 110, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(3), 120, None); let market_fee = FeeMarket::market_fee().unwrap(); let (lane, message_nonce) = send_regular_message(market_fee); let order = FeeMarket::order((&lane, &message_nonce)).unwrap(); @@ -808,7 +843,7 @@ fn test_callback_order_confirm() { } #[test] -fn test_payment_cal_reward_normally_single_message() { +fn test_payment_cal_rewards_normally_single_message() { new_test_ext().execute_with(|| { // Send message System::set_block_number(2); @@ -819,7 +854,7 @@ fn test_payment_cal_reward_normally_single_message() { let (lane, message_nonce) = send_regular_message(market_fee); // Receive delivery message proof - System::set_block_number(4); + System::set_block_number(4); // confirmed at block 4, the first slot assert_ok!(Messages::receive_messages_delivery_proof( Origin::signed(5), TestMessagesDeliveryProof(Ok(( @@ -836,32 +871,36 @@ fn test_payment_cal_reward_normally_single_message() { }, )); - // Reward Analysis: assigned_relayers [(1, 30, 2-52),(2, 50, 52-102),(3, 100, 102-152)] - // 1. slot relayer -> id: 1, reward = 60% * 30 = 18 - // 2. message relayer -> id: 100, reward = 40% * 30 * 80% = 9.6 ~ 10 - // 3. confirm relayer -> id: 5, reward = 40% * 30 * 20% = 2.4 ~ 2 - // 4. treasury reward -> reward = 100 - 30 = 70 + // Rewards Analysis: + // 1. The order's assigned_relayers: [(1, 30, 2-52),(2, 50, 52-102),(3, 100, 102-152)] + // 2. The order's fee: 100 + // For message delivery relayer(id=100): 30 * 80% = 24 + // For message confirm relayer(id=5): 30 * 20% = 6 + // For each assigned_relayer(id=1, 2, 3): (100 - 30) * 20% / 3 = 4 + // For treasury: 100 - (24 + 6) - (4 * 3) = 58 let t: AccountId = ::TreasuryPalletId::get().into_account_truncating(); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 70)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 18)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 2)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 10)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 58)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 4)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(2, 4)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(3, 4)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 6)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 24)); System::assert_has_event(Event::FeeMarket(crate::Event::OrderReward( lane, message_nonce, RewardItem { - to_slot_relayer: Some((1, 18)), - to_treasury: Some(70), - to_message_relayer: Some((100, 10)), - to_confirm_relayer: Some((5, 2)), + to_assigned_relayers: BTreeMap::from_iter([(1, 4), (2, 4), (3, 4)]), + to_treasury: Some(58), + to_message_relayer: Some((100, 24)), + to_confirm_relayer: Some((5, 6)), }, ))); }); } #[test] -fn test_payment_cal_reward_normally_multi_message() { +fn test_payment_cal_rewards_normally_multi_message() { new_test_ext().execute_with(|| { System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 300, Some(30)); @@ -875,7 +914,7 @@ fn test_payment_cal_reward_normally_multi_message() { assert_eq!(message_nonce1 + 1, message_nonce2); // Receive delivery message proof - System::set_block_number(4); + System::set_block_number(4); // confirmed at block 4, the first slot assert_ok!(Messages::receive_messages_delivery_proof( Origin::signed(1), TestMessagesDeliveryProof(Ok(( @@ -897,12 +936,128 @@ fn test_payment_cal_reward_normally_multi_message() { }, )); + // Rewards order1 Analysis(The same with order2): + // 1. The order's assigned_relayers: [(5, 30, 2-52),(6, 50, 52-102),(7, 100, 102-152)] + // 2. The order's fee: 100 + // For message delivery relayer(id=100): 30 * 80% = 24 + // For message confirm relayer(id=1): 30 * 20% = 6 + // For each assigned_relayer(id=5, 6, 7): (100 - 30) * 20% / 3 = 4 + // For treasury: 100 - (24 + 6) - (4 * 3) = 58 let t: AccountId = ::TreasuryPalletId::get().into_account_truncating(); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 140)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 4)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 36)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 10)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 10)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 116)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 8)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(6, 8)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(7, 8)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 12)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 24)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 24)); + }); +} + +#[test] +fn test_payment_cal_rewards_when_order_confirmed_in_second_slot() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 300, Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 300, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 300, Some(100)); + + // Send message + let market_fee = FeeMarket::market_fee().unwrap(); + let _ = send_regular_message(market_fee); + + assert_eq!(FeeMarket::relayer_locked_collateral(&5), 300); + assert_eq!(FeeMarket::relayer_locked_collateral(&6), 300); + assert_eq!(FeeMarket::relayer_locked_collateral(&7), 300); + + System::set_block_number(55); // confirmed at block 55, the second slot + assert_ok!(Messages::receive_messages_delivery_proof( + Origin::signed(1), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A),].into_iter().collect(), + ..Default::default() + } + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, + )); + + assert_eq!(FeeMarket::relayer_locked_collateral(&5), 240); + assert_eq!(FeeMarket::relayer_locked_collateral(&6), 300); + assert_eq!(FeeMarket::relayer_locked_collateral(&7), 300); + + // Rewards Analysis: + // 1. The order's assigned_relayers: [(5, 30, 2-52),(6, 50, 52-102),(7, 100, 102-152)] + // 2. The order's fee: 100 + // 3. The slash for relayer(id=5): 300 * 20% = 60 + // For message delivery relayer(id=100): (50 + 60) * 80% = 88 + // For message confirm relayer(id=1): (50 + 60) * 20% = 22 + // For each assigned_relayer(id=6, 7): (100 - 50) * 20% / 2 = 5 + // For treasury: 100 - 50 - (5 * 2) = 40 + let t: AccountId = ::TreasuryPalletId::get().into_account_truncating(); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 40)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(6, 5)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(7, 5)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 22)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 88)); + }); +} + +#[test] +fn test_payment_cal_rewards_when_order_confirmed_in_third_slot() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 300, Some(30)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 300, Some(50)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 300, Some(100)); + + // Send message + let market_fee = FeeMarket::market_fee().unwrap(); + let _ = send_regular_message(market_fee); + + assert_eq!(FeeMarket::relayer_locked_collateral(&5), 300); + assert_eq!(FeeMarket::relayer_locked_collateral(&6), 300); + assert_eq!(FeeMarket::relayer_locked_collateral(&7), 300); + + System::set_block_number(105); // confirmed at block 55, the third slot + assert_ok!(Messages::receive_messages_delivery_proof( + Origin::signed(1), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A),].into_iter().collect(), + ..Default::default() + } + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, + )); + + assert_eq!(FeeMarket::relayer_locked_collateral(&5), 240); + assert_eq!(FeeMarket::relayer_locked_collateral(&6), 240); + assert_eq!(FeeMarket::relayer_locked_collateral(&7), 300); + + // Rewards Analysis: + // 1. The order's assigned_relayers: [(5, 30, 2-52),(6, 50, 52-102),(7, 100, 102-152)] + // 2. The order's fee: 100 + // 3. The slash for relayer(id=5, 6): 300 * 20% = 60 + // For message delivery relayer(id=100): (100 + 60 * 2) * 80% = 176 + // For message confirm relayer(id=1): (100 + 60 * 2) * 20% = 44 + // For each assigned_relayer(id=7): (100 - 100) * 20% = 0 + // For treasury: 100 - 100 - (0 * 2) = 0 + let t: AccountId = ::TreasuryPalletId::get().into_account_truncating(); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 0)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(7, 0)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 44)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 176)); }); } @@ -952,11 +1107,20 @@ fn test_payment_cal_reward_with_duplicated_delivery_proof() { }, )); + // Rewards Analysis: + // 1. The order's assigned_relayers: [(1, 30, 2-52),(2, 50, 52-102),(3, 100, 102-152)] + // 2. The order's fee: 100 + // For message delivery relayer(id=100): 30 * 80% = 24 + // For message confirm relayer(id=5): 30 * 20% = 6 + // For each assigned_relayer(id=1, 2, 3): (100 - 30) * 20% / 3 = 4 + // For treasury: 100 - (24 + 6) - (4 * 3) = 58 let t: AccountId = ::TreasuryPalletId::get().into_account_truncating(); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 70)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 18)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 2)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 10)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(t, 58)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(1, 4)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(2, 4)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(3, 4)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 6)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 24)); }); } @@ -992,11 +1156,11 @@ fn test_payment_with_slash_and_reduce_order_capacity() { assert!(FeeMarket::is_enrolled(&6)); assert!(FeeMarket::is_enrolled(&6)); assert!(FeeMarket::is_enrolled(&6)); - assert_eq!(FeeMarket::relayer_locked_collateral(&6), 300); - assert_eq!(FeeMarket::relayer_locked_collateral(&7), 300); - assert_eq!(FeeMarket::relayer_locked_collateral(&8), 300); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 80)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 320)); + assert_eq!(FeeMarket::relayer_locked_collateral(&6), 220); + assert_eq!(FeeMarket::relayer_locked_collateral(&7), 220); + assert_eq!(FeeMarket::relayer_locked_collateral(&8), 220); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 128)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 512)); }); } @@ -1103,7 +1267,7 @@ fn test_payment_slash_event() { } #[test] -fn test_payment_cal_slash_with_multiple_message() { +fn test_payment_with_multiple_message_out_of_deadline() { new_test_ext().execute_with(|| { System::set_block_number(2); let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 400, Some(300)); @@ -1138,9 +1302,10 @@ fn test_payment_cal_slash_with_multiple_message() { ..Default::default() }, )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 520)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1040)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 1040)); + + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(5, 594)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1232)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 1146)); }); } @@ -1148,9 +1313,9 @@ fn test_payment_cal_slash_with_multiple_message() { fn test_clean_order_state_at_the_end_of_block() { new_test_ext().execute_with(|| { System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 400, Some(300)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 400, Some(500)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(8), 400, Some(1000)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 400, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 400, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(8), 400, None); let market_fee = FeeMarket::market_fee().unwrap(); let (lane1, nonce1) = send_regular_message(market_fee); let (lane2, nonce2) = send_regular_message(market_fee); @@ -1197,8 +1362,8 @@ fn test_clean_order_state_at_the_end_of_block() { #[test] fn test_fee_verification_when_send_message() { new_test_ext().execute_with(|| { - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 100, Some(40)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(1), 100, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(2), 100, None); assert!(FeeMarket::market_fee().is_none()); // Case 1: When fee market are not ready, but somebody send messages @@ -1228,12 +1393,12 @@ fn test_fee_verification_when_send_message() { } #[test] -fn test_relayer_is_occupied() { +fn test_relayer_occupied_result() { new_test_ext().execute_with(|| { System::set_block_number(2); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 300, Some(30)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 300, Some(50)); - let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 300, Some(100)); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 300, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 300, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 300, None); // Send message let market_fee = FeeMarket::market_fee().unwrap(); @@ -1243,9 +1408,59 @@ fn test_relayer_is_occupied() { assert_eq!(FeeMarket::occupied(&5), Some((2, 200))); assert_eq!(FeeMarket::occupied(&6), Some((2, 200))); assert_eq!(FeeMarket::occupied(&7), Some((2, 200))); + assert_eq!(FeeMarket::usable_order_capacity(&5), 1); + assert_eq!(FeeMarket::usable_order_capacity(&6), 1); + assert_eq!(FeeMarket::usable_order_capacity(&7), 1); receive_messages_delivery_proof(); assert_eq!(FeeMarket::occupied(&5), Some((1, 100))); assert_eq!(FeeMarket::occupied(&6), Some((1, 100))); assert_eq!(FeeMarket::occupied(&7), Some((1, 100))); + assert_eq!(FeeMarket::usable_order_capacity(&5), 2); + assert_eq!(FeeMarket::usable_order_capacity(&6), 2); + assert_eq!(FeeMarket::usable_order_capacity(&7), 2); + }); +} + +#[test] +fn test_relayer_update_order_capacity() { + new_test_ext().execute_with(|| { + System::set_block_number(2); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(5), 300, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(6), 300, None); + let _ = FeeMarket::enroll_and_lock_collateral(Origin::signed(7), 300, None); + + let market_fee = FeeMarket::market_fee().unwrap(); + let _ = send_regular_message(market_fee); + let _ = send_regular_message(market_fee); + let _ = send_regular_message(market_fee); + + assert_eq!(FeeMarket::occupied(&5), Some((3, 300))); + assert_eq!(FeeMarket::usable_order_capacity(&5), 0); + assert_eq!(FeeMarket::usable_order_capacity(&6), 0); + assert_eq!(FeeMarket::usable_order_capacity(&7), 0); + assert!(FeeMarket::market_fee().is_none()); + + System::set_block_number(10); + assert_ok!(Messages::receive_messages_delivery_proof( + Origin::signed(5), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![unrewarded_relayer(1, 3, TEST_RELAYER_A),].into_iter().collect(), + ..Default::default() + } + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 3, + ..Default::default() + }, + )); + + assert_eq!(FeeMarket::occupied(&5), None); + assert_eq!(FeeMarket::usable_order_capacity(&5), 3); + assert_eq!(FeeMarket::usable_order_capacity(&6), 3); + assert_eq!(FeeMarket::usable_order_capacity(&7), 3); + assert!(FeeMarket::market_fee().is_some()); }); } diff --git a/modules/fee-market/src/types.rs b/modules/fee-market/src/types.rs index 281b6e250..cdd7aa830 100644 --- a/modules/fee-market/src/types.rs +++ b/modules/fee-market/src/types.rs @@ -77,12 +77,12 @@ pub struct Order { pub sent_time: BlockNumber, pub confirm_time: Option, pub locked_collateral: Balance, - pub relayers: Vec>, + pub assigned_relayers: Vec>, } impl Order where AccountId: Clone, - BlockNumber: Copy + AtLeast32BitUnsigned, + BlockNumber: Copy + AtLeast32BitUnsigned + Default, Balance: Copy + Default, { pub fn new( @@ -90,36 +90,36 @@ where message: MessageNonce, sent_time: BlockNumber, locked_collateral: Balance, - assigned_relayers: Vec>, + relayers: Vec>, slot: BlockNumber, ) -> Self { - let prior_relayers_len = assigned_relayers.len(); - let mut relayers = Vec::with_capacity(prior_relayers_len); + let relayers_len = relayers.len(); + let mut assigned_relayers = Vec::with_capacity(relayers_len); let mut start_time = sent_time; - // PriorRelayer has a duty time zone - for i in 0..prior_relayers_len { - if let Some(r) = assigned_relayers.get(i) { - let p = PriorRelayer::new(r.id.clone(), r.fee, start_time, slot); + // AssignedRelayer has a duty time zone + for i in 0..relayers_len { + if let Some(r) = relayers.get(i) { + let p = AssignedRelayer::new(r.id.clone(), r.fee, start_time, slot); start_time += slot; - relayers.push(p); + assigned_relayers.push(p); } } - Self { lane, message, sent_time, confirm_time: None, locked_collateral, relayers } + Self { lane, message, sent_time, confirm_time: None, locked_collateral, assigned_relayers } } pub fn set_confirm_time(&mut self, confirm_time: Option) { self.confirm_time = confirm_time; } - pub fn relayers_slice(&self) -> &[PriorRelayer] { - self.relayers.as_ref() + pub fn assigned_relayers_slice(&self) -> &[AssignedRelayer] { + self.assigned_relayers.as_ref() } pub fn fee(&self) -> Balance { - self.relayers.iter().last().map(|r| r.fee).unwrap_or_default() + self.assigned_relayers.iter().last().map(|r| r.fee).unwrap_or_default() } pub fn is_confirmed(&self) -> bool { @@ -127,10 +127,10 @@ where } pub fn range_end(&self) -> Option { - self.relayers.iter().last().map(|r| r.valid_range.end) + self.assigned_relayers.iter().last().map(|r| r.valid_range.end) } - pub fn delivery_delay(&self) -> Option { + pub fn comfirm_delay(&self) -> Option { if let (Some(confirm_time), Some(range_end)) = (self.confirm_time, self.range_end()) { if confirm_time > range_end { return Some(confirm_time - range_end); @@ -139,13 +139,14 @@ where None } - pub fn required_delivery_relayer_for_time( - &self, - message_confirm_time: BlockNumber, - ) -> Option<(AccountId, Balance)> { - for prior_relayer in self.relayers.iter() { - if prior_relayer.valid_range.contains(&message_confirm_time) { - return Some((prior_relayer.id.clone(), prior_relayer.fee)); + pub fn confirmed_info(&self) -> Option<(usize, Balance)> { + // The confirm_time of the order is already set in the `OnDeliveryConfirmed` + // callback.And the callback was called as source chain received message + // delivery proof, before the reward payment. + let order_confirmed_time = self.confirm_time.unwrap_or_default(); + for (index, assigned_relayer) in self.assigned_relayers.iter().enumerate() { + if assigned_relayer.valid_range.contains(&order_confirmed_time) { + return Some((index, assigned_relayer.fee)); } } None @@ -156,27 +157,27 @@ where where AccountId: Clone + PartialEq, { - for prior_relayer in self.relayers.iter() { - if prior_relayer.id == id { - return Some(prior_relayer.valid_range.clone()); + for assigned_relayer in self.assigned_relayers.iter() { + if assigned_relayer.id == id { + return Some(assigned_relayer.valid_range.clone()); } } None } } -/// Relayers selected by the fee market. Each prior relayer has a valid slot, if the order can -/// finished in time, will be rewarded with more percentage. PriorRelayer are responsible for the +/// Relayers selected by the fee market. Each assigned relayer has a valid slot, if the order can +/// finished in time, will be rewarded with more percentage. AssignedRelayer are responsible for the /// messages relay in most time. #[derive(Clone, Debug, Default, Encode, Decode, TypeInfo)] -pub struct PriorRelayer { +pub struct AssignedRelayer { pub id: AccountId, pub fee: Balance, pub valid_range: Range, } -impl PriorRelayer +impl AssignedRelayer where - BlockNumber: Copy + AtLeast32BitUnsigned, + BlockNumber: Copy + AtLeast32BitUnsigned + Default, { pub fn new( id: AccountId, @@ -202,7 +203,7 @@ pub struct SlashReport { impl SlashReport where AccountId: Clone, - BlockNumber: Copy + AtLeast32BitUnsigned, + BlockNumber: Copy + AtLeast32BitUnsigned + Default, Balance: Copy + Default, { pub fn new( @@ -215,7 +216,7 @@ where message: order.message, sent_time: order.sent_time, confirm_time: order.confirm_time, - delay_time: order.delivery_delay(), + delay_time: order.comfirm_delay(), account_id, amount, } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 0fbe1fdbb..22a3ff721 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -22,20 +22,20 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } # Optional Benchmarking Dependencies bp-test-utils = { path = "../../primitives/test-utils", default-features = false, optional = true } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false, optional = true } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false, optional = true } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 268ebb725..fa9d4f8d8 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -22,16 +22,16 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [dev-dependencies] -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index b96445ac8..298312c0d 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -761,41 +761,6 @@ pub mod pallet { ) -> Option> { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) } - - /// Get nonce of the latest generated message at given outbound lane. - pub fn outbound_latest_generated_nonce(lane: LaneId) -> MessageNonce { - OutboundLanes::::get(&lane).latest_generated_nonce - } - - /// Get nonce of the latest confirmed message at given outbound lane. - pub fn outbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - OutboundLanes::::get(&lane).latest_received_nonce - } - - /// Get nonce of the latest received message at given inbound lane. - pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).last_delivered_nonce() - } - - /// Get nonce of the latest confirmed message at given inbound lane. - pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).last_confirmed_nonce - } - - /// Get state of unrewarded relayers set. - pub fn inbound_unrewarded_relayers_state( - lane: bp_messages::LaneId, - ) -> bp_messages::UnrewardedRelayersState { - let relayers = InboundLanes::::get(&lane).relayers; - bp_messages::UnrewardedRelayersState { - unrewarded_relayer_entries: relayers.len() as _, - messages_in_oldest_entry: relayers - .front() - .map(|entry| 1 + entry.messages.end - entry.messages.begin) - .unwrap_or(0), - total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), - } - } } } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 7f4b6a992..3b80ac069 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -13,27 +13,29 @@ serde = { version = "1.0.101", optional = true } # Bridge Dependencies +bp-parachains = { path = "../../primitives/parachains", default-features = false } bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-grandpa = { path = "../grandpa", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [dev-dependencies] bp-header-chain = { path = "../../primitives/header-chain" } bp-test-utils = { path = "../../primitives/test-utils" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] std = [ + "bp-parachains/std", "bp-polkadot-core/std", "bp-runtime/std", "codec/std", diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 4d3066fb6..e6d6d76dd 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -23,7 +23,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaId, ParachainHeadsProof}; +use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaId, ParachainHeadsProof}; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; @@ -66,6 +66,12 @@ pub mod pallet { UnknownRelayChainBlock, /// Invalid storage proof has been passed. InvalidStorageProof, + /// Given parachain head is unknown. + UnknownParaHead, + /// The storage proof doesn't contains storage root. So it is invalid for given header. + StorageRootMismatch, + /// Failed to extract state root from given parachain head. + FailedToExtractStateRoot, } #[pallet::config] @@ -185,6 +191,38 @@ pub mod pallet { } impl, I: 'static> Pallet { + /// Get best finalized header of the given parachain. + pub fn best_parachain_head(parachain: ParaId) -> Option { + let best_para_head_hash = BestParaHeads::::get(parachain)?.head_hash; + ImportedParaHeads::::get(parachain, best_para_head_hash) + } + + /// Get parachain head with given hash. + pub fn parachain_head(parachain: ParaId, hash: ParaHash) -> Option { + ImportedParaHeads::::get(parachain, hash) + } + + /// Verify that the passed storage proof is valid, given it is crafted using + /// known finalized header. If the proof is valid, then the `parse` callback + /// is called and the function returns its result. + pub fn parse_finalized_storage_proof( + parachain: ParaId, + hash: ParaHash, + storage_proof: sp_trie::StorageProof, + decode_state_root: impl FnOnce(ParaHead) -> Option, + parse: impl FnOnce(bp_runtime::StorageProofChecker) -> R, + ) -> Result { + let para_head = + Self::parachain_head(parachain, hash).ok_or(Error::::UnknownParaHead)?; + let state_root = + decode_state_root(para_head).ok_or(Error::::FailedToExtractStateRoot)?; + let storage_proof_checker = + bp_runtime::StorageProofChecker::new(state_root, storage_proof) + .map_err(|_| Error::::StorageRootMismatch)?; + + Ok(parse(storage_proof_checker)) + } + /// Read parachain head from storage proof. fn read_parachain_head( storage: &bp_runtime::StorageProofChecker, @@ -289,7 +327,7 @@ pub mod storage_keys { #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, test_relay_header, Origin, TestRuntime}; + use crate::mock::*; use bp_test_utils::{authority_list, make_default_justification}; use frame_support::{assert_noop, assert_ok, traits::OnInitialize}; @@ -329,14 +367,17 @@ mod tests { } fn prepare_parachain_heads_proof( - heads: Vec<(ParaId, ParaHead)>, + heads: Vec<(u32, ParaHead)>, ) -> (RelayBlockHash, ParachainHeadsProof) { let mut root = Default::default(); let mut mdb = MemoryDB::default(); { let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); for (parachain, head) in heads { - let storage_key = storage_keys::parachain_head_key(parachain); + let storage_key = bp_parachains::parachain_head_storage_key_at_source( + PARAS_PALLET_NAME, + ParaId(parachain), + ); trie.insert(&storage_key.0, &head.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in tests"); @@ -384,10 +425,8 @@ mod tests { #[test] fn imports_initial_parachain_heads() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![ - (ParaId(1), head_data(1, 0)), - (ParaId(3), head_data(3, 10)), - ]); + let (state_root, proof) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 0)), (3, head_data(3, 10))]); run_test(|| { initialize(state_root); @@ -428,10 +467,8 @@ mod tests { #[test] fn imports_parachain_heads_is_able_to_progress() { - let (state_root_5, proof_5) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); - let (state_root_10, proof_10) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 10))]); + let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (state_root_10, proof_10) = prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); run_test(|| { // start with relay block #0 and import head#5 of parachain#1 initialize(state_root_5); @@ -477,7 +514,7 @@ mod tests { #[test] fn does_nothing_when_already_imported_this_head_at_previous_relay_header() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 0))]); + let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); run_test(|| { // import head#0 of parachain#1 at relay block#0 initialize(state_root); @@ -494,10 +531,8 @@ mod tests { #[test] fn does_nothing_when_already_imported_head_at_better_relay_header() { - let (state_root_5, proof_5) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); - let (state_root_10, proof_10) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 10))]); + let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (state_root_10, proof_10) = prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); run_test(|| { // start with relay block #0 initialize(state_root_5); @@ -535,8 +570,7 @@ mod tests { // import exactly `HeadsToKeep` headers for i in 0..heads_to_keep { - let (state_root, proof) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, i))]); + let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, i))]); if i == 0 { initialize(state_root); } else { @@ -553,7 +587,7 @@ mod tests { // import next relay chain header and next parachain head let (state_root, proof) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, heads_to_keep))]); + prepare_parachain_heads_proof(vec![(1, head_data(1, heads_to_keep))]); proceed(heads_to_keep, state_root); assert_ok!(import_parachain_1_head(heads_to_keep, state_root, proof)); @@ -570,7 +604,7 @@ mod tests { #[test] fn fails_on_unknown_relay_chain_block() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); + let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); run_test(|| { // start with relay block #0 initialize(state_root); @@ -585,8 +619,7 @@ mod tests { #[test] fn fails_on_invalid_storage_proof() { - let (_state_root, proof) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); + let (_state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); run_test(|| { // start with relay block #0 initialize(Default::default()); diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 141a1e49e..e542f7c6e 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -33,6 +33,8 @@ pub type RelayBlockHeader = type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +pub const PARAS_PALLET_NAME: &str = "Paras"; + construct_runtime! { pub enum TestRuntime where Block = Block, diff --git a/primitives/chain-crab-parachain/Cargo.toml b/primitives/chain-crab-parachain/Cargo.toml index de93ebb09..180eb2763 100644 --- a/primitives/chain-crab-parachain/Cargo.toml +++ b/primitives/chain-crab-parachain/Cargo.toml @@ -12,11 +12,11 @@ bp-darwinia-core = { default-features = false, path = "../darwinia-core" } # paritytech bp-messages = { default-features = false, path = "../messages" } bp-runtime = { default-features = false, path = "../runtime" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/primitives/chain-crab-parachain/src/lib.rs b/primitives/chain-crab-parachain/src/lib.rs index f2c7b2fa0..99cc630fb 100644 --- a/primitives/chain-crab-parachain/src/lib.rs +++ b/primitives/chain-crab-parachain/src/lib.rs @@ -119,4 +119,4 @@ sp_api::decl_runtime_apis! { /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } -} +} \ No newline at end of file diff --git a/primitives/chain-crab/Cargo.toml b/primitives/chain-crab/Cargo.toml index 00b7c9b47..6480c3867 100644 --- a/primitives/chain-crab/Cargo.toml +++ b/primitives/chain-crab/Cargo.toml @@ -12,11 +12,11 @@ bp-darwinia-core = { default-features = false, path = "../darwinia-core" } # paritytech bp-messages = { default-features = false, path = "../messages" } bp-runtime = { default-features = false, path = "../runtime" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/primitives/chain-crab/src/lib.rs b/primitives/chain-crab/src/lib.rs index 1b503cf7a..c575a3964 100644 --- a/primitives/chain-crab/src/lib.rs +++ b/primitives/chain-crab/src/lib.rs @@ -21,19 +21,6 @@ mod copy_paste_from_darwinia { // --- darwinia-network --- use bp_darwinia_core::*; - // --- paritytech --- - use sp_version::RuntimeVersion; - - pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_runtime::create_runtime_str!("Crab"), - impl_name: sp_runtime::create_runtime_str!("Darwinia Crab"), - authoring_version: 0, - spec_version: 12_0_0, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 0, - state_version: 0, - }; pub const EXISTENTIAL_DEPOSIT: Balance = 0; @@ -43,84 +30,5 @@ pub use copy_paste_from_darwinia::*; pub use bp_darwinia_core::*; -// --- paritytech --- -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use frame_support::Parameter; -use sp_std::prelude::*; - /// Crab Chain. pub type Crab = DarwiniaLike; - -/// Name of the With-Crab GRANDPA pallet instance that is deployed at bridged chains. -pub const WITH_CRAB_GRANDPA_PALLET_NAME: &str = "BridgeCrabGrandpa"; -/// Name of the With-Crab messages pallet instance that is deployed at bridged chains. -pub const WITH_CRAB_MESSAGES_PALLET_NAME: &str = "BridgeCrabMessages"; -/// Name of the With-Crab parachains bridge pallet name in the Crab runtime. -pub const BRIDGE_PARAS_PALLET_NAME: &str = "BridgeCrabParachains"; - -/// Name of the `CrabFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_CRAB_HEADER_METHOD: &str = "CrabFinalityApi_best_finalized"; - -/// Name of the `ToCrabOutboundLaneApi::message_details` runtime method. -pub const TO_CRAB_MESSAGE_DETAILS_METHOD: &str = "ToCrabOutboundLaneApi_message_details"; -/// Name of the `ToCrabOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_CRAB_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToCrabOutboundLaneApi_latest_received_nonce"; -/// Name of the `ToCrabOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_CRAB_LATEST_GENERATED_NONCE_METHOD: &str = - "ToCrabOutboundLaneApi_latest_generated_nonce"; - -/// Name of the `FromCrabInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_CRAB_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromCrabInboundLaneApi_latest_received_nonce"; -/// Name of the `FromCrabInboundLaneApi::latest_cnfirmed_nonce` runtime method. -pub const FROM_CRAB_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromCrabInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromCrabInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_CRAB_UNREWARDED_RELAYERS_STATE: &str = - "FromCrabInboundLaneApi_unrewarded_relayers_state"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Crab headers. - /// - /// This API is implemented by runtimes that are bridging with the Crab chain, not the - /// Crab runtime itself. - pub trait CrabFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); - } - - /// Outbound message lane API for messages that are sent to Crab chain. - /// - /// This API is implemented by runtimes that are sending messages to Crab chain, not the - /// Crab runtime itself. - pub trait ToCrabOutboundLaneApi { - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; - } - - /// Inbound message lane API for messages sent by Crab chain. - /// - /// This API is implemented by runtimes that are receiving messages from Crab chain, not the - /// Crab runtime itself. - pub trait FromCrabInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; - /// State of the unrewarded relayers set at given lane. - fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; - } -} diff --git a/primitives/chain-darwinia/Cargo.toml b/primitives/chain-darwinia/Cargo.toml new file mode 100644 index 000000000..4516d02fe --- /dev/null +++ b/primitives/chain-darwinia/Cargo.toml @@ -0,0 +1,34 @@ +[package] +authors = ["Darwinia Network "] +description = "Primitives of Darwinia runtime." +edition = "2021" +license = "GPL-3.0" +name = "bp-darwinia" +version = "0.1.0" + +[dependencies] +# darwinia-network +bp-darwinia-core = { default-features = false, path = "../darwinia-core" } +# paritytech +bp-messages = { default-features = false, path = "../messages" } +bp-runtime = { default-features = false, path = "../runtime" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } + +[features] +default = ["std"] +std = [ + # darwinia-network + "bp-darwinia-core/std", + # paritytech + "bp-messages/std", + "bp-runtime/std", + "frame-support/std", + "sp-api/std", + "sp-runtime/std", + "sp-std/std", + "sp-version/std", +] diff --git a/primitives/chain-darwinia/src/lib.rs b/primitives/chain-darwinia/src/lib.rs new file mode 100644 index 000000000..2ce266556 --- /dev/null +++ b/primitives/chain-darwinia/src/lib.rs @@ -0,0 +1,34 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2022 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Darwinia is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Darwinia. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +mod copy_paste_from_darwinia { + // --- darwinia-network --- + use bp_darwinia_core::*; + + pub const EXISTENTIAL_DEPOSIT: Balance = 100 * MICRO; + + pub const SESSION_LENGTH: BlockNumber = 4 * HOURS; +} +pub use copy_paste_from_darwinia::*; + +pub use bp_darwinia_core::*; + +/// Darwinia Chain. +pub type Darwinia = DarwiniaLike; diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index c70142985..a078da92c 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -11,17 +11,17 @@ smallvec = "1.7" # Bridge Dependencies -bp-messages = { path = "../messages", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-messages = { default-features = false, path = "../messages" } +bp-polkadot-core = { default-features = false, path = "../polkadot-core" } +bp-runtime = { default-features = false, path = "../runtime" } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index d362fd164..e22c7fcea 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -18,60 +18,11 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{LaneId, MessageDetails, MessageNonce}; -use frame_support::weights::{ - WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, -}; -use sp_runtime::FixedU128; -use sp_std::prelude::*; -use sp_version::RuntimeVersion; - pub use bp_polkadot_core::*; /// Kusama Chain pub type Kusama = PolkadotLike; -// NOTE: This needs to be kept up to date with the Kusama runtime found in the Polkadot repo. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("kusama"), - impl_name: sp_version::create_runtime_str!("parity-kusama"), - authoring_version: 2, - spec_version: 9180, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 11, - state_version: 0, -}; - -// NOTE: This needs to be kept up to date with the Kusama runtime found in the Polkadot repo. -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - - fn polynomial() -> WeightToFeeCoefficients { - const CENTS: Balance = 1_000_000_000_000 / 30_000; - // in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - let p = CENTS; - let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); - smallvec::smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - -// We use this to get the account on Kusama (target) which is derived from Polkadot's (source) -// account. -pub fn derive_account_from_polkadot_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::POLKADOT_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - -/// Per-byte fee for Kusama transactions. -pub const TRANSACTION_BYTE_FEE: Balance = 10 * 1_000_000_000_000 / 30_000 / 1_000; - /// Existential deposit on Kusama. pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000; @@ -81,69 +32,3 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000; /// Note that since this is a target sessions may change before/after this time depending on network /// conditions. pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; - -/// Name of the With-Kusama GRANDPA pallet instance that is deployed at bridged chains. -pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; -/// Name of the With-Kusama messages pallet instance that is deployed at bridged chains. -pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; - -/// Name of the transaction payment pallet at the Kusama runtime. -pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; - -/// Name of the DOT->KSM conversion rate stored in the Kusama runtime. -pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = - "PolkadotToKusamaConversionRate"; -/// Name of the Polkadot fee multiplier parameter, stored in the Polkadot runtime. -pub const POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME: &str = "PolkadotFeeMultiplier"; - -/// Name of the `KusamaFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized"; - -/// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToKusamaOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. -pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Kusama headers. - /// - /// This API is implemented by runtimes that are bridging with the Kusama chain, not the - /// Kusama runtime itself. - pub trait KusamaFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); - } - - /// Outbound message lane API for messages that are sent to Kusama chain. - /// - /// This API is implemented by runtimes that are sending messages to Kusama chain, not the - /// Kusama runtime itself. - pub trait ToKusamaOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Kusama from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - kusama_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } -} diff --git a/primitives/chain-pangolin-parachain/Cargo.toml b/primitives/chain-pangolin-parachain/Cargo.toml index 804ea5b04..7db3f05b1 100644 --- a/primitives/chain-pangolin-parachain/Cargo.toml +++ b/primitives/chain-pangolin-parachain/Cargo.toml @@ -12,11 +12,11 @@ bp-darwinia-core = { default-features = false, path = "../darwinia-core" } # paritytech bp-messages = { default-features = false, path = "../messages" } bp-runtime = { default-features = false, path = "../runtime" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/primitives/chain-pangolin-parachain/src/lib.rs b/primitives/chain-pangolin-parachain/src/lib.rs index ec8b61017..b080b71c7 100644 --- a/primitives/chain-pangolin-parachain/src/lib.rs +++ b/primitives/chain-pangolin-parachain/src/lib.rs @@ -88,4 +88,4 @@ sp_api::decl_runtime_apis! { end: MessageNonce, ) -> Vec>; } -} +} \ No newline at end of file diff --git a/primitives/chain-pangolin/Cargo.toml b/primitives/chain-pangolin/Cargo.toml index d67662067..d61199bb7 100644 --- a/primitives/chain-pangolin/Cargo.toml +++ b/primitives/chain-pangolin/Cargo.toml @@ -12,11 +12,11 @@ bp-darwinia-core = { default-features = false, path = "../darwinia-core" } # paritytech bp-messages = { default-features = false, path = "../messages" } bp-runtime = { default-features = false, path = "../runtime" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/primitives/chain-pangolin/src/lib.rs b/primitives/chain-pangolin/src/lib.rs index a1f1b2cd9..4136767da 100644 --- a/primitives/chain-pangolin/src/lib.rs +++ b/primitives/chain-pangolin/src/lib.rs @@ -29,7 +29,7 @@ mod copy_paste_from_darwinia { impl_name: sp_runtime::create_runtime_str!("Pangolin"), authoring_version: 0, #[allow(clippy::inconsistent_digit_grouping)] - spec_version: 2_8_06_0, + spec_version: 2_9_05_0, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, diff --git a/primitives/chain-pangoro/Cargo.toml b/primitives/chain-pangoro/Cargo.toml index eb9156dbd..45e4a67d9 100644 --- a/primitives/chain-pangoro/Cargo.toml +++ b/primitives/chain-pangoro/Cargo.toml @@ -12,11 +12,11 @@ bp-darwinia-core = { default-features = false, path = "../darwinia-core" } # paritytech bp-messages = { default-features = false, path = "../messages" } bp-runtime = { default-features = false, path = "../runtime" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-version = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/primitives/chain-pangoro/src/lib.rs b/primitives/chain-pangoro/src/lib.rs index a14ee3473..140a56876 100644 --- a/primitives/chain-pangoro/src/lib.rs +++ b/primitives/chain-pangoro/src/lib.rs @@ -29,7 +29,7 @@ mod copy_paste_from_darwinia { impl_name: sp_runtime::create_runtime_str!("Pangoro"), authoring_version: 0, #[allow(clippy::inconsistent_digit_grouping)] - spec_version: 2_8_06_0, + spec_version: 2_9_05_0, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 855a3a5cb..c822e727c 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -17,11 +17,11 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [features] default = ["std"] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 7194eb090..bb12047c1 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -18,63 +18,11 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{LaneId, MessageDetails, MessageNonce}; -use frame_support::weights::{ - WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, -}; -use sp_runtime::FixedU128; -use sp_std::prelude::*; -use sp_version::RuntimeVersion; - pub use bp_polkadot_core::*; /// Polkadot Chain pub type Polkadot = PolkadotLike; -// NOTE: This needs to be kept up to date with the Polkadot runtime found in the Polkadot repo. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("polkadot"), - impl_name: sp_version::create_runtime_str!("parity-polkadot"), - authoring_version: 0, - spec_version: 9180, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 12, - state_version: 0, -}; - -// NOTE: This needs to be kept up to date with the Polkadot runtime found in the Polkadot repo. -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - - fn polynomial() -> WeightToFeeCoefficients { - const CENTS: Balance = 10_000_000_000 / 100; - // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - let p = CENTS; - let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); - smallvec::smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - -// We use this to get the account on Polkadot (target) which is derived from Kusama's (source) -// account. -pub fn derive_account_from_kusama_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::KUSAMA_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - -/// Per-byte fee for Polkadot transactions. -pub const TRANSACTION_BYTE_FEE: Balance = 10 * 10_000_000_000 / 100 / 1_000; - -/// Existential deposit on Polkadot. -pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; - /// The target length of a session (how often authorities change) on Polkadot measured in of number /// of blocks. /// @@ -82,68 +30,5 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; -/// Name of the With-Polkadot GRANDPA pallet instance that is deployed at bridged chains. -pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; -/// Name of the With-Polkadot messages pallet instance that is deployed at bridged chains. -pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; - -/// Name of the transaction payment pallet at the Polkadot runtime. -pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; - -/// Name of the KSM->DOT conversion rate parameter, stored in the Polkadot runtime. -pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = - "KusamaToPolkadotConversionRate"; -/// Name of the Kusama fee multiplier parameter, stored in the Polkadot runtime. -pub const KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME: &str = "KusamaFeeMultiplier"; - -/// Name of the `PolkadotFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized"; - -/// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToPolkadotOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. -pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Polkadot headers. - /// - /// This API is implemented by runtimes that are bridging with the Polkadot chain, not the - /// Polkadot runtime itself. - pub trait PolkadotFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); - } - - /// Outbound message lane API for messages that are sent to Polkadot chain. - /// - /// This API is implemented by runtimes that are sending messages to Polkadot chain, not the - /// Polkadot runtime itself. - pub trait ToPolkadotOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Polkadot from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - polkadot_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } -} +/// Existential deposit on Polkadot. +pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index a2097bf2d..f317a11b1 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -16,11 +16,11 @@ bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [features] default = ["std"] diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a4108443b..c75f54d15 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -18,14 +18,6 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{LaneId, MessageDetails, MessageNonce}; -use frame_support::weights::{ - Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, -}; -use sp_runtime::FixedU128; -use sp_std::prelude::*; -use sp_version::RuntimeVersion; - pub use bp_polkadot_core::*; /// Rococo Chain @@ -38,108 +30,5 @@ pub type Rococo = PolkadotLike; /// conditions. pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; -// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("rococo"), - impl_name: sp_version::create_runtime_str!("parity-rococo-v2.0"), - authoring_version: 0, - spec_version: 9180, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 0, - state_version: 0, -}; - -// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - - fn polynomial() -> WeightToFeeCoefficients { - const CENTS: Balance = 1_000_000_000_000 / 100; - let p = CENTS; - let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); - smallvec::smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - -// We use this to get the account on Rococo (target) which is derived from Wococo's (source) -// account. -pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::WOCOCO_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - -/// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains. -pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; -/// Name of the With-Rococo messages pallet instance that is deployed at bridged chains. -pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; - -/// Name of the `RococoFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized"; - -/// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToRococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. -pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; - /// Existential deposit on Rococo. pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 100; - -/// Weight of pay-dispatch-fee operation for inbound messages at Rococo chain. -/// -/// This value corresponds to the result of -/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your -/// chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery -/// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Rococo headers. - /// - /// This API is implemented by runtimes that are bridging with the Rococo chain, not the - /// Rococo runtime itself. - pub trait RococoFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); - } - - /// Outbound message lane API for messages that are sent to Rococo chain. - /// - /// This API is implemented by runtimes that are sending messages to Rococo chain, not the - /// Rococo runtime itself. - pub trait ToRococoOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Rococo from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - rococo_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } -} diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml deleted file mode 100644 index 3f50170bf..000000000 --- a/primitives/chain-wococo/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "bp-wococo" -description = "Primitives of Wococo runtime." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } - -# Bridge Dependencies -bp-messages = { path = "../messages", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-rococo = { path = "../chain-rococo", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } - -# Substrate Based Dependencies -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } - -[features] -default = ["std"] -std = [ - "bp-messages/std", - "bp-polkadot-core/std", - "bp-runtime/std", - "bp-rococo/std", - "parity-scale-codec/std", - "sp-api/std", - "sp-runtime/std", - "sp-std/std", -] diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs deleted file mode 100644 index f39543114..000000000 --- a/primitives/chain-wococo/src/lib.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] - -use bp_messages::{LaneId, MessageDetails, MessageNonce}; -use sp_runtime::FixedU128; -use sp_std::prelude::*; - -pub use bp_polkadot_core::*; -// Rococo runtime = Wococo runtime -pub use bp_rococo::{WeightToFee, EXISTENTIAL_DEPOSIT, PAY_INBOUND_DISPATCH_FEE_WEIGHT, VERSION}; - -/// Wococo Chain -pub type Wococo = PolkadotLike; - -/// The target length of a session (how often authorities change) on Wococo measured in of number -/// of blocks. -/// -/// Note that since this is a target sessions may change before/after this time depending on network -/// conditions. -pub const SESSION_LENGTH: BlockNumber = time_units::MINUTES; - -// We use this to get the account on Wococo (target) which is derived from Rococo's (source) -// account. -pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - -/// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. -pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; -/// Name of the With-Wococo messages pallet instance that is deployed at bridged chains. -pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; - -/// Name of the `WococoFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized"; - -/// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToWococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. -pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Wococo headers. - /// - /// This API is implemented by runtimes that are bridging with the Wococo chain, not the - /// Wococo runtime itself. - pub trait WococoFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); - } - - /// Outbound message lane API for messages that are sent to Wococo chain. - /// - /// This API is implemented by runtimes that are sending messages to Wococo chain, not the - /// Wococo runtime itself. - pub trait ToWococoOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Wococo from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - wococo_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } -} diff --git a/primitives/darwinia-core/Cargo.toml b/primitives/darwinia-core/Cargo.toml index 013583227..a7aa1df25 100644 --- a/primitives/darwinia-core/Cargo.toml +++ b/primitives/darwinia-core/Cargo.toml @@ -13,11 +13,11 @@ scale-info = { version = "2.0.1", default-features = false, features = [ # paritytech bp-messages = { default-features = false, path = "../messages" } bp-runtime = { default-features = false, path = "../runtime" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [features] default = ["std"] diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 1a7fb3599..1fd3e8451 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -18,11 +18,11 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [dev-dependencies] assert_matches = "1.5" diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index 39c388541..c192cc5b3 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -20,7 +20,6 @@ //! Some of tests in this module may partially duplicate tests from `justification.rs`, //! but their purpose is different. -use assert_matches::assert_matches; use bp_header_chain::justification::{verify_justification, Error, GrandpaJustification}; use bp_test_utils::{ header_id, make_justification_for_header, signed_precommit, test_header, Account, @@ -127,14 +126,15 @@ fn same_result_when_precommit_target_has_lower_number_than_commit_target() { Err(Error::PrecommitIsNotCommitDescendant), ); // original implementation returns empty GHOST - assert_matches!( + // https://github.com/paritytech/finality-grandpa/commit/36e409bcb76b41344be5b284732b529cd087432b#diff-b1a35a68f14e696205874893c07fd24fdb88882b47c23cc0e0c80a30c7d53759L496-R521 + assert_eq!( finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), &AncestryChain::new(&justification.votes_ancestries), ) - .map(|result| result.ghost().cloned()), - Ok(None) + .map(|result| result.is_valid()), + Ok(false) ); } @@ -159,14 +159,15 @@ fn same_result_when_precommit_target_is_not_descendant_of_commit_target() { Err(Error::PrecommitIsNotCommitDescendant), ); // original implementation returns empty GHOST - assert_matches!( + // https://github.com/paritytech/finality-grandpa/commit/36e409bcb76b41344be5b284732b529cd087432b#diff-b1a35a68f14e696205874893c07fd24fdb88882b47c23cc0e0c80a30c7d53759L496-R521 + assert_eq!( finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), &AncestryChain::new(&justification.votes_ancestries), ) - .map(|result| result.ghost().cloned()), - Ok(None) + .map(|result| result.is_valid()), + Ok(false) ); } @@ -189,14 +190,15 @@ fn same_result_when_justification_contains_duplicate_vote() { Ok(()), ); // original implementation returns non-empty GHOST - assert_matches!( + // https://github.com/paritytech/finality-grandpa/commit/36e409bcb76b41344be5b284732b529cd087432b#diff-b1a35a68f14e696205874893c07fd24fdb88882b47c23cc0e0c80a30c7d53759L496-R521 + assert_eq!( finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), &AncestryChain::new(&justification.votes_ancestries), ) - .map(|result| result.ghost().cloned()), - Ok(Some(_)) + .map(|result| result.is_valid()), + Ok(false) ); } @@ -223,14 +225,15 @@ fn same_result_when_authority_equivocates_once_in_a_round() { Ok(()), ); // original implementation returns non-empty GHOST - assert_matches!( + // https://github.com/paritytech/finality-grandpa/commit/36e409bcb76b41344be5b284732b529cd087432b#diff-b1a35a68f14e696205874893c07fd24fdb88882b47c23cc0e0c80a30c7d53759L496-R521 + assert_eq!( finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), &AncestryChain::new(&justification.votes_ancestries), ) - .map(|result| result.ghost().cloned()), - Ok(Some(_)) + .map(|result| result.is_valid()), + Ok(false) ); } @@ -267,14 +270,15 @@ fn same_result_when_authority_equivocates_twice_in_a_round() { Ok(()), ); // original implementation returns non-empty GHOST - assert_matches!( + // https://github.com/paritytech/finality-grandpa/commit/36e409bcb76b41344be5b284732b529cd087432b#diff-b1a35a68f14e696205874893c07fd24fdb88882b47c23cc0e0c80a30c7d53759L496-R521 + assert_eq!( finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), &AncestryChain::new(&justification.votes_ancestries), ) - .map(|result| result.ghost().cloned()), - Ok(Some(_)) + .map(|result| result.is_valid()), + Ok(false) ); } @@ -300,13 +304,14 @@ fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_ta Err(Error::TooLowCumulativeWeight), ); // original implementation returns empty GHOST - assert_matches!( + // https://github.com/paritytech/finality-grandpa/commit/36e409bcb76b41344be5b284732b529cd087432b#diff-b1a35a68f14e696205874893c07fd24fdb88882b47c23cc0e0c80a30c7d53759L496-R521 + assert_eq!( finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), &AncestryChain::new(&justification.votes_ancestries), ) - .map(|result| result.ghost().cloned()), - Ok(None) + .map(|result| result.is_valid()), + Ok(false) ); } diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index 40fe12f41..f95b1a0cf 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -13,9 +13,9 @@ scale-info = { version = "2.0.1", default-features = false, features = ["derive" # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [features] default = ["std"] diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index ae9b2be1b..087f49739 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -19,10 +19,10 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [dev-dependencies] hex = "0.4" diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml new file mode 100644 index 000000000..fc05be547 --- /dev/null +++ b/primitives/parachains/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "bp-parachains" +description = "Primitives of parachains module." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +serde = { version = "1.0", optional = true, features = ["derive"] } + +# Bridge dependencies + +bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } + +# Substrate dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-polkadot-core/std", + "bp-runtime/std", + "codec/std", + "frame-support/std", + "scale-info/std", + "serde", + "sp-core/std", +] diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs new file mode 100644 index 000000000..4bcada2da --- /dev/null +++ b/primitives/parachains/src/lib.rs @@ -0,0 +1,86 @@ +// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. + +// Parity Bridges Common is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Bridges Common is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Bridges Common. If not, see . + +//! Primitives of parachains module. + +#![cfg_attr(not(feature = "std"), no_std)] + +use bp_polkadot_core::parachains::ParaId; +// use bp_runtime::{StorageDoubleMapKeyProvider, StorageMapKeyProvider}; +use codec::Encode; +use frame_support::Twox64Concat; +use sp_core::storage::StorageKey; + +// /// Best known parachain head hash. +// #[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] +// pub struct BestParaHeadHash { +// /// Number of relay block where this head has been read. +// /// +// /// Parachain head is opaque to relay chain. So we can't simply decode it as a header of +// /// parachains and call `block_number()` on it. Instead, we're using the fact that parachain +// /// head is always built on top of previous head (because it is blockchain) and relay chain +// /// always imports parachain heads in order. What it means for us is that at any given +// /// **finalized** relay block `B`, head of parachain will be ancestor (or the same) of all +// /// parachain heads available at descendants of `B`. +// pub at_relay_block_number: RelayBlockNumber, +// /// Hash of parachain head. +// pub head_hash: ParaHash, +// } + +// /// Best known parachain head as it is stored in the runtime storage. +// #[derive(Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] +// pub struct ParaInfo { +// /// Best known parachain head hash. +// pub best_head_hash: BestParaHeadHash, +// /// Current ring buffer position for this parachain. +// pub next_imported_hash_position: u32, +// } + +/// Returns runtime storage key of given parachain head at the source chain. +/// +/// The head is stored by the `paras` pallet in the `Heads` map. +pub fn parachain_head_storage_key_at_source( + paras_pallet_name: &str, + para_id: ParaId, +) -> StorageKey { + bp_runtime::storage_map_final_key::(paras_pallet_name, "Heads", ¶_id.encode()) +} + +// /// Can be use to access the runtime storage key of the parachains info at the target chain. +// /// +// /// The info is stored by the `pallet-bridge-parachains` pallet in the `ParasInfo` map. +// pub struct ParasInfoKeyProvider; +// impl StorageMapKeyProvider for ParasInfoKeyProvider { +// const MAP_NAME: &'static str = "ParasInfo"; + +// type Hasher = Blake2_128Concat; +// type Key = ParaId; +// type Value = ParaInfo; +// } + +// /// Can be use to access the runtime storage key of the parachain head at the target chain. +// /// +// /// The head is stored by the `pallet-bridge-parachains` pallet in the `ImportedParaHeads` map. +// pub struct ImportedParaHeadsKeyProvider; +// impl StorageDoubleMapKeyProvider for ImportedParaHeadsKeyProvider { +// const MAP_NAME: &'static str = "ImportedParaHeads"; + +// type Hasher1 = Blake2_128Concat; +// type Key1 = ParaId; +// type Hasher2 = Blake2_128Concat; +// type Key2 = ParaHash; +// type Value = ParaHead; +// } diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 9e2ddf148..a14bf262d 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -19,13 +19,13 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [dev-dependencies] hex = "0.4" diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index c0448a846..3f49bc93d 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -55,6 +55,12 @@ use parity_util_mem::MallocSizeOf; )] pub struct ParaId(pub u32); +impl From for ParaId { + fn from(id: u32) -> Self { + ParaId(id) + } +} + /// Parachain head. /// /// This is an equivalent of the `polkadot_parachain::HeadData`. @@ -78,5 +84,8 @@ impl ParaHead { /// Parachain head hash. pub type ParaHash = crate::Hash; +/// Parachain head hasher. +pub type ParaHasher = crate::Hasher; + /// Raw storage proof of parachain heads, stored in polkadot-like chain runtime. pub type ParachainHeadsProof = Vec>; diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 1a74591f4..b1b03ba5d 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -14,13 +14,13 @@ scale-info = { version = "2.0.1", default-features = false, features = ["derive" # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [dev-dependencies] hex-literal = "0.3" diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 252ecf7c1..c0f089d41 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -75,6 +75,9 @@ pub const PANGOLIN_CHAIN_ID: ChainId = *b"pagl"; /// Bridge-with-PangolinParachain instance id. pub const PANGOLIN_PARACHAIN_CHAIN_ID: ChainId = *b"pglp"; +/// Bridge-with-PangolinParachainAlpha instance id. +pub const PANGOLIN_PARACHAIN_ALPHA_CHAIN_ID: ChainId = *b"pgpa"; + /// Bridge-with-CrabParachain instance id. pub const CRAB_PARACHAIN_CHAIN_ID: ChainId = *b"crap"; diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 55a9d5868..bb3eee8a9 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -10,10 +10,10 @@ bp-header-chain = { path = "../header-chain", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } finality-grandpa = { version = "0.16.0", default-features = false } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26", default-features = false } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27", default-features = false } [features] default = ["std"] diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml deleted file mode 100644 index 82a2dfd7a..000000000 --- a/relays/client-kusama/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "relay-kusama-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } -scale-info = { version = "2.0.1", features = ["derive"] } - -# Bridge dependencies - -bp-header-chain = { path = "../../primitives/header-chain" } -bp-kusama = { path = "../../primitives/chain-kusama" } -bp-message-dispatch = { path = "../../primitives/message-dispatch" } -bp-messages = { path = "../../primitives/messages" } -bp-polkadot = { path = "../../primitives/chain-polkadot" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } -bridge-runtime-common = { path = "../../bin/runtime-common" } -pallet-bridge-dispatch = { path = "../../modules/dispatch" } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs deleted file mode 100644 index 47da76924..000000000 --- a/relays/client-kusama/src/lib.rs +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Types used to connect to the Kusama chain. - -use bp_messages::MessageNonce; -use codec::Encode; -use frame_support::weights::Weight; -use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use std::time::Duration; - -pub mod runtime; - -/// Kusama header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Kusama chain definition -#[derive(Debug, Clone, Copy)] -pub struct Kusama; - -impl ChainBase for Kusama { - type AccountId = bp_kusama::AccountId; - type Balance = bp_kusama::Balance; - type BlockNumber = bp_kusama::BlockNumber; - type Hash = bp_kusama::Hash; - type Hasher = bp_kusama::Hasher; - type Header = bp_kusama::Header; - type Index = bp_kusama::Nonce; - type Signature = bp_kusama::Signature; - - fn max_extrinsic_size() -> u32 { - bp_kusama::Kusama::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_kusama::Kusama::max_extrinsic_weight() - } -} - -impl Chain for Kusama { - type Call = crate::runtime::Call; - type SignedBlock = bp_kusama::SignedBlock; - type WeightToFee = bp_kusama::WeightToFee; - - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - const NAME: &'static str = "Kusama"; - const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE; - const TOKEN_ID: Option<&'static str> = Some("kusama"); -} - -impl ChainWithGrandpa for Kusama { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_kusama::WITH_KUSAMA_GRANDPA_PALLET_NAME; -} - -impl ChainWithMessages for Kusama { - type WeightInfo = (); - - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; -} - -impl ChainWithBalances for Kusama { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - StorageKey(bp_kusama::account_info_storage_key(account_id)) - } -} - -impl TransactionSignScheme for Kusama { - type AccountKeyPair = sp_core::sr25519::Pair; - type Chain = Kusama; - type SignedTransaction = crate::runtime::UncheckedExtrinsic; - - fn sign_transaction(param: SignParam) -> Result { - let raw_payload = SignedPayload::new( - param.unsigned.call.clone(), - bp_kusama::SignedExtensions::new( - param.spec_version, - param.transaction_version, - param.era, - param.genesis_hash, - param.unsigned.nonce, - param.unsigned.tip, - ), - ) - .expect("SignedExtension never fails."); - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(bp_kusama::UncheckedExtrinsic::new_signed( - call, - sp_runtime::MultiAddress::Id(signer.into_account()), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_kusama::AccountId::from(*signer.public().as_array_ref()).into() - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) - } -} - -/// Kusama header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// Kusama signing params. -pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-kusama/src/runtime.rs b/relays/client-kusama/src/runtime.rs deleted file mode 100644 index 485ce1138..000000000 --- a/relays/client-kusama/src/runtime.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Types that are specific to the Kusama runtime. - -use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; -use bp_runtime::Chain; -use codec::{Compact, Decode, Encode}; -use frame_support::weights::Weight; -use scale_info::TypeInfo; -use sp_runtime::FixedU128; - -/// Unchecked Kusama extrinsic. -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Polkadot account ownership digest from Kusama. -/// -/// The byte vector returned by this function should be signed with a Polkadot account private key. -/// This way, the owner of `kusama_account_id` on Kusama proves that the Polkadot account private -/// key is also under his control. -pub fn kusama_to_polkadot_account_ownership_digest( - polkadot_call: &Call, - kusama_account_id: AccountId, - polkadot_spec_version: SpecVersion, -) -> Vec -where - Call: codec::Encode, - AccountId: codec::Encode, - SpecVersion: codec::Encode, -{ - pallet_bridge_dispatch::account_ownership_digest( - polkadot_call, - kusama_account_id, - polkadot_spec_version, - bp_runtime::KUSAMA_CHAIN_ID, - bp_runtime::POLKADOT_CHAIN_ID, - ) -} - -/// Kusama Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Kusama chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Kusama -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/kusama/src/lib.rs) -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// System pallet. - #[codec(index = 0)] - System(SystemCall), - /// Balances pallet. - #[codec(index = 4)] - Balances(BalancesCall), - /// Utility pallet. - #[codec(index = 24)] - Utility(UtilityCall), - /// Polkadot bridge pallet. - #[codec(index = 110)] - BridgePolkadotGrandpa(BridgePolkadotGrandpaCall), - /// Polkadot messages pallet. - #[codec(index = 111)] - BridgePolkadotMessages(BridgePolkadotMessagesCall), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum SystemCall { - #[codec(index = 1)] - remark(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BalancesCall { - #[codec(index = 0)] - transfer(AccountAddress, Compact), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgePolkadotGrandpaCall { - #[codec(index = 0)] - submit_finality_proof( - Box<::Header>, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), - #[codec(index = 3)] - set_operational(bool), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgePolkadotMessagesCall { - #[codec(index = 2)] - update_pallet_parameter(BridgePolkadotMessagesParameter), - #[codec(index = 3)] - send_message( - LaneId, - bp_message_dispatch::MessagePayload< - bp_kusama::AccountId, - bp_polkadot::AccountId, - bp_polkadot::AccountPublic, - Vec, - >, - bp_kusama::Balance, - ), - #[codec(index = 5)] - receive_messages_proof( - bp_polkadot::AccountId, - bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, - u32, - Weight, - ), - #[codec(index = 6)] - receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - bp_polkadot::Hash, - >, - UnrewardedRelayersState, - ), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum UtilityCall { - #[codec(index = 2)] - batch_all(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum BridgePolkadotMessagesParameter { - #[codec(index = 0)] - PolkadotToKusamaConversionRate(FixedU128), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Config = (); - type Info = (); - type Origin = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml deleted file mode 100644 index 016539193..000000000 --- a/relays/client-polkadot/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "relay-polkadot-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } -scale-info = { version = "2.0.1", features = ["derive"] } - -# Bridge dependencies - -bp-header-chain = { path = "../../primitives/header-chain" } -bp-kusama = { path = "../../primitives/chain-kusama" } -bp-message-dispatch = { path = "../../primitives/message-dispatch" } -bp-messages = { path = "../../primitives/messages" } -bp-polkadot = { path = "../../primitives/chain-polkadot" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } -bridge-runtime-common = { path = "../../bin/runtime-common" } -pallet-bridge-dispatch = { path = "../../modules/dispatch" } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs deleted file mode 100644 index b18c5b3bb..000000000 --- a/relays/client-polkadot/src/lib.rs +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Types used to connect to the Polkadot chain. - -use bp_messages::MessageNonce; -use codec::Encode; -use frame_support::weights::Weight; -use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use std::time::Duration; - -pub mod runtime; - -/// Polkadot header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Polkadot chain definition -#[derive(Debug, Clone, Copy)] -pub struct Polkadot; - -impl ChainBase for Polkadot { - type AccountId = bp_polkadot::AccountId; - type Balance = bp_polkadot::Balance; - type BlockNumber = bp_polkadot::BlockNumber; - type Hash = bp_polkadot::Hash; - type Hasher = bp_polkadot::Hasher; - type Header = bp_polkadot::Header; - type Index = bp_polkadot::Nonce; - type Signature = bp_polkadot::Signature; - - fn max_extrinsic_size() -> u32 { - bp_polkadot::Polkadot::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_polkadot::Polkadot::max_extrinsic_weight() - } -} - -impl Chain for Polkadot { - type Call = crate::runtime::Call; - type SignedBlock = bp_polkadot::SignedBlock; - type WeightToFee = bp_polkadot::WeightToFee; - - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - const NAME: &'static str = "Polkadot"; - const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE; - const TOKEN_ID: Option<&'static str> = Some("polkadot"); -} - -impl ChainWithGrandpa for Polkadot { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = - bp_polkadot::WITH_POLKADOT_GRANDPA_PALLET_NAME; -} - -impl ChainWithMessages for Polkadot { - type WeightInfo = (); - - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; -} - -impl ChainWithBalances for Polkadot { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - StorageKey(bp_polkadot::account_info_storage_key(account_id)) - } -} - -impl TransactionSignScheme for Polkadot { - type AccountKeyPair = sp_core::sr25519::Pair; - type Chain = Polkadot; - type SignedTransaction = crate::runtime::UncheckedExtrinsic; - - fn sign_transaction(param: SignParam) -> Result { - let raw_payload = SignedPayload::new( - param.unsigned.call.clone(), - bp_polkadot::SignedExtensions::new( - param.spec_version, - param.transaction_version, - param.era, - param.genesis_hash, - param.unsigned.nonce, - param.unsigned.tip, - ), - ) - .expect("SignedExtension never fails."); - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(bp_polkadot::UncheckedExtrinsic::new_signed( - call, - sp_runtime::MultiAddress::Id(signer.into_account()), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_polkadot::AccountId::from(*signer.public().as_array_ref()).into() - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) - } -} - -/// Polkadot header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// Polkadot signing params. -pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-polkadot/src/runtime.rs b/relays/client-polkadot/src/runtime.rs deleted file mode 100644 index 613f55c21..000000000 --- a/relays/client-polkadot/src/runtime.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Types that are specific to the Polkadot runtime. - -use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; -use bp_runtime::Chain; -use codec::{Compact, Decode, Encode}; -use frame_support::weights::Weight; -use scale_info::TypeInfo; -use sp_runtime::FixedU128; - -/// Unchecked Polkadot extrinsic. -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Kusama account ownership digest from Polkadot. -/// -/// The byte vector returned by this function should be signed with a Kusama account private key. -/// This way, the owner of `kusam_account_id` on Polkadot proves that the Kusama account private key -/// is also under his control. -pub fn polkadot_to_kusama_account_ownership_digest( - kusama_call: &Call, - kusam_account_id: AccountId, - kusama_spec_version: SpecVersion, -) -> Vec -where - Call: codec::Encode, - AccountId: codec::Encode, - SpecVersion: codec::Encode, -{ - pallet_bridge_dispatch::account_ownership_digest( - kusama_call, - kusam_account_id, - kusama_spec_version, - bp_runtime::POLKADOT_CHAIN_ID, - bp_runtime::KUSAMA_CHAIN_ID, - ) -} - -/// Polkadot Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Polkadot chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Polkadot -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: [link](https://github.com/paritytech/kusama/blob/master/runtime/kusam/src/lib.rs) -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// System pallet. - #[codec(index = 0)] - System(SystemCall), - /// Balances pallet. - #[codec(index = 5)] - Balances(BalancesCall), - /// Utility pallet. - #[codec(index = 26)] - Utility(UtilityCall), - /// Kusama bridge pallet. - #[codec(index = 110)] - BridgeKusamaGrandpa(BridgeKusamaGrandpaCall), - /// Kusama messages pallet. - #[codec(index = 111)] - BridgeKusamaMessages(BridgeKusamaMessagesCall), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum SystemCall { - #[codec(index = 1)] - remark(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BalancesCall { - #[codec(index = 0)] - transfer(AccountAddress, Compact), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeKusamaGrandpaCall { - #[codec(index = 0)] - submit_finality_proof( - Box<::Header>, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), - #[codec(index = 3)] - set_operational(bool), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeKusamaMessagesCall { - #[codec(index = 2)] - update_pallet_parameter(BridgeKusamaMessagesParameter), - #[codec(index = 3)] - send_message( - LaneId, - bp_message_dispatch::MessagePayload< - bp_polkadot::AccountId, - bp_kusama::AccountId, - bp_kusama::AccountPublic, - Vec, - >, - bp_polkadot::Balance, - ), - #[codec(index = 5)] - receive_messages_proof( - bp_kusama::AccountId, - bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, - u32, - Weight, - ), - #[codec(index = 6)] - receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - bp_kusama::Hash, - >, - UnrewardedRelayersState, - ), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum UtilityCall { - #[codec(index = 2)] - batch_all(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum BridgeKusamaMessagesParameter { - #[codec(index = 0)] - KusamaToPolkadotConversionRate(FixedU128), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Config = (); - type Info = (); - type Origin = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml deleted file mode 100644 index b5722a860..000000000 --- a/relays/client-rococo/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "relay-rococo-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } -scale-info = { version = "2.0.1", features = ["derive"] } - -# Bridge dependencies - -bridge-runtime-common = { path = "../../bin/runtime-common" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-message-dispatch = { path = "../../primitives/message-dispatch" } -bp-messages = { path = "../../primitives/messages" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rococo = { path = "../../primitives/chain-rococo" } -bp-runtime = { path = "../../primitives/runtime" } -bp-wococo = { path = "../../primitives/chain-wococo" } -pallet-bridge-dispatch = { path = "../../modules/dispatch" } -pallet-bridge-messages = { path = "../../modules/messages" } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs deleted file mode 100644 index 4380621c2..000000000 --- a/relays/client-rococo/src/lib.rs +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Types used to connect to the Rococo-Substrate chain. - -use bp_messages::MessageNonce; -use codec::Encode; -use frame_support::weights::Weight; -use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use std::time::Duration; - -pub mod runtime; - -/// Rococo header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Rococo header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// Rococo chain definition -#[derive(Debug, Clone, Copy)] -pub struct Rococo; - -impl ChainBase for Rococo { - type AccountId = bp_rococo::AccountId; - type Balance = bp_rococo::Balance; - type BlockNumber = bp_rococo::BlockNumber; - type Hash = bp_rococo::Hash; - type Hasher = bp_rococo::Hashing; - type Header = bp_rococo::Header; - type Index = bp_rococo::Nonce; - type Signature = bp_rococo::Signature; - - fn max_extrinsic_size() -> u32 { - bp_rococo::Rococo::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_rococo::Rococo::max_extrinsic_weight() - } -} - -impl Chain for Rococo { - type Call = crate::runtime::Call; - type SignedBlock = bp_rococo::SignedBlock; - type WeightToFee = bp_rococo::WeightToFee; - - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - const NAME: &'static str = "Rococo"; - const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE; - const TOKEN_ID: Option<&'static str> = None; -} - -impl ChainWithGrandpa for Rococo { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_rococo::WITH_ROCOCO_GRANDPA_PALLET_NAME; -} - -impl ChainWithMessages for Rococo { - type WeightInfo = (); - - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; -} - -impl ChainWithBalances for Rococo { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - StorageKey(bp_rococo::account_info_storage_key(account_id)) - } -} - -impl TransactionSignScheme for Rococo { - type AccountKeyPair = sp_core::sr25519::Pair; - type Chain = Rococo; - type SignedTransaction = crate::runtime::UncheckedExtrinsic; - - fn sign_transaction(param: SignParam) -> Result { - let raw_payload = SignedPayload::new( - param.unsigned.call.clone(), - bp_rococo::SignedExtensions::new( - param.spec_version, - param.transaction_version, - param.era, - param.genesis_hash, - param.unsigned.nonce, - param.unsigned.tip, - ), - ) - .expect("SignedExtension never fails."); - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(bp_rococo::UncheckedExtrinsic::new_signed( - call, - sp_runtime::MultiAddress::Id(signer.into_account()), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_rococo::AccountId::from(*signer.public().as_array_ref()).into() - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) - } -} - -/// Rococo signing params. -pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs deleted file mode 100644 index b3fb90fe0..000000000 --- a/relays/client-rococo/src/runtime.rs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Types that are specific to the Rococo runtime. - -use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; -use bp_runtime::Chain; -use codec::{Compact, Decode, Encode}; -use frame_support::weights::Weight; -use scale_info::TypeInfo; - -/// Unchecked Rococo extrinsic. -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Wococo account ownership digest from Rococo. -/// -/// The byte vector returned by this function should be signed with a Wococo account private key. -/// This way, the owner of `rococo_account_id` on Rococo proves that the Wococo account private key -/// is also under his control. -pub fn rococo_to_wococo_account_ownership_digest( - wococo_call: &Call, - rococo_account_id: AccountId, - wococo_spec_version: SpecVersion, -) -> Vec -where - Call: codec::Encode, - AccountId: codec::Encode, - SpecVersion: codec::Encode, -{ - pallet_bridge_dispatch::account_ownership_digest( - wococo_call, - rococo_account_id, - wococo_spec_version, - bp_runtime::ROCOCO_CHAIN_ID, - bp_runtime::WOCOCO_CHAIN_ID, - ) -} - -/// Rococo Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Rococo chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs) -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// System pallet. - #[codec(index = 0)] - System(SystemCall), - /// Balances pallet. - #[codec(index = 4)] - Balances(BalancesCall), - /// Wococo bridge pallet. - #[codec(index = 41)] - BridgeGrandpaWococo(BridgeGrandpaWococoCall), - /// Wococo messages pallet. - #[codec(index = 44)] - BridgeWococoMessages(BridgeWococoMessagesCall), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum SystemCall { - #[codec(index = 1)] - remark(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BalancesCall { - #[codec(index = 0)] - transfer(AccountAddress, Compact), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeGrandpaWococoCall { - #[codec(index = 0)] - submit_finality_proof( - Box<::Header>, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeWococoMessagesCall { - #[codec(index = 3)] - send_message( - LaneId, - bp_message_dispatch::MessagePayload< - bp_rococo::AccountId, - bp_wococo::AccountId, - bp_wococo::AccountPublic, - Vec, - >, - bp_rococo::Balance, - ), - #[codec(index = 5)] - receive_messages_proof( - bp_wococo::AccountId, - bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, - u32, - Weight, - ), - #[codec(index = 6)] - receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - bp_wococo::Hash, - >, - UnrewardedRelayersState, - ), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Config = (); - type Info = (); - type Origin = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml deleted file mode 100644 index b65e13164..000000000 --- a/relays/client-substrate/Cargo.toml +++ /dev/null @@ -1,48 +0,0 @@ -[package] -name = "relay-substrate-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1.40" -codec = { package = "parity-scale-codec", version = "3.0.0" } -jsonrpsee = { version = "0.8", features = ["macros", "ws-client"] } -log = "0.4.11" -num-traits = "0.2" -rand = "0.7" -serde = { version = "1.0" } -tokio = { version = "1.8", features = ["rt-multi-thread"] } -thiserror = "1.0.26" - -# Bridge dependencies - -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-runtime = { path = "../../primitives/runtime" } -pallet-bridge-messages = { path = "../../modules/messages" } -finality-relay = { path = "../finality" } -relay-utils = { path = "../utils" } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } - -#[dev-dependencies] -futures = "0.3.7" diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs deleted file mode 100644 index 57732bbd7..000000000 --- a/relays/client-substrate/src/chain.rs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -use bp_messages::MessageNonce; -use bp_runtime::{Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEraOf}; -use codec::{Codec, Encode}; -use frame_support::weights::{Weight, WeightToFeePolynomial}; -use jsonrpsee::core::{DeserializeOwned, Serialize}; -use num_traits::Zero; -use sc_transaction_pool_api::TransactionStatus; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{ - generic::SignedBlock, - traits::{Block as BlockT, Dispatchable, Member}, - EncodedJustification, -}; -use std::{fmt::Debug, time::Duration}; - -/// Substrate-based chain from minimal relay-client point of view. -pub trait Chain: ChainBase + Clone { - /// Chain name. - const NAME: &'static str; - /// Identifier of the basic token of the chain (if applicable). - /// - /// This identifier is used to fetch token price. In case of testnets, you may either - /// set it to `None`, or associate testnet with one of the existing tokens. - const TOKEN_ID: Option<&'static str>; - /// Name of the runtime API method that is returning best known finalized header number - /// and hash (as tuple). - /// - /// Keep in mind that this method is normally provided by the other chain, which is - /// bridged with this chain. - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str; - - /// Average block interval. - /// - /// How often blocks are produced on that chain. It's suggested to set this value - /// to match the block time of the chain. - const AVERAGE_BLOCK_INTERVAL: Duration; - /// Maximal expected storage proof overhead (in bytes). - const STORAGE_PROOF_OVERHEAD: u32; - /// Maximal size (in bytes) of SCALE-encoded account id on this chain. - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32; - - /// Block type. - type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; - /// The aggregated `Call` type. - type Call: Clone + Codec + Dispatchable + Debug + Send; - - /// Type that is used by the chain, to convert from weight to fee. - type WeightToFee: WeightToFeePolynomial; -} - -/// Substrate-based chain that is using direct GRANDPA finality from minimal relay-client point of -/// view. -/// -/// Keep in mind that parachains are relying on relay chain GRANDPA, so they should not implement -/// this trait. -pub trait ChainWithGrandpa: Chain { - /// Name of the bridge GRANDPA pallet (used in `construct_runtime` macro call) that is deployed - /// at some other chain to bridge with this `ChainWithGrandpa`. - /// - /// We assume that all chains that are bridging with this `ChainWithGrandpa` are using - /// the same name. - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str; -} - -/// Substrate-based chain with messaging support from minimal relay-client point of view. -pub trait ChainWithMessages: Chain { - /// Name of the bridge messages pallet (used in `construct_runtime` macro call) that is deployed - /// at some other chain to bridge with this `ChainWithMessages`. - /// - /// We assume that all chains that are bridging with this `ChainWithMessages` are using - /// the same name. - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str; - - /// Name of the `ToOutboundLaneApi::message_details` runtime API method. - /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; - - /// Additional weight of the dispatch fee payment if dispatch is paid at the target chain - /// and this `ChainWithMessages` is the target chain. - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight; - - /// Maximal number of unrewarded relayers in a single confirmation transaction at this - /// `ChainWithMessages`. - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce; - /// Maximal number of unconfirmed messages in a single confirmation transaction at this - /// `ChainWithMessages`. - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce; - - /// Weights of message pallet calls. - type WeightInfo: pallet_bridge_messages::WeightInfoExt; -} - -/// Call type used by the chain. -pub type CallOf = ::Call; -/// Weight-to-Fee type used by the chain. -pub type WeightToFeeOf = ::WeightToFee; -/// Transaction status of the chain. -pub type TransactionStatusOf = TransactionStatus, HashOf>; - -/// Substrate-based chain with `AccountData` generic argument of `frame_system::AccountInfo` set to -/// the `pallet_balances::AccountData`. -pub trait ChainWithBalances: Chain { - /// Return runtime storage key for getting `frame_system::AccountInfo` of given account. - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey; -} - -/// SCALE-encoded extrinsic. -pub type EncodedExtrinsic = Vec; - -/// Block with justification. -pub trait BlockWithJustification
{ - /// Return block header. - fn header(&self) -> Header; - /// Return encoded block extrinsics. - fn extrinsics(&self) -> Vec; - /// Return block justification, if known. - fn justification(&self) -> Option<&EncodedJustification>; -} - -/// Transaction before it is signed. -#[derive(Clone, Debug, PartialEq)] -pub struct UnsignedTransaction { - /// Runtime call of this transaction. - pub call: EncodedOrDecodedCall, - /// Transaction nonce. - pub nonce: C::Index, - /// Tip included into transaction. - pub tip: C::Balance, -} - -impl UnsignedTransaction { - /// Create new unsigned transaction with given call, nonce and zero tip. - pub fn new(call: EncodedOrDecodedCall, nonce: C::Index) -> Self { - Self { call, nonce, tip: Zero::zero() } - } - - /// Set transaction tip. - pub fn tip(mut self, tip: C::Balance) -> Self { - self.tip = tip; - self - } -} - -/// Account key pair used by transactions signing scheme. -pub type AccountKeyPairOf = ::AccountKeyPair; - -/// Substrate-based chain transactions signing scheme. -pub trait TransactionSignScheme { - /// Chain that this scheme is to be used. - type Chain: Chain; - /// Type of key pairs used to sign transactions. - type AccountKeyPair: Pair; - /// Signed transaction. - type SignedTransaction: Clone + Debug + Codec + Send + 'static; - - /// Create transaction for given runtime call, signed by given account. - fn sign_transaction(param: SignParam) -> Result - where - Self: Sized; - - /// Returns true if transaction is signed. - fn is_signed(tx: &Self::SignedTransaction) -> bool; - - /// Returns true if transaction is signed by given signer. - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool; - - /// Parse signed transaction into its unsigned part. - /// - /// Returns `None` if signed transaction has unsupported format. - fn parse_transaction(tx: Self::SignedTransaction) -> Option>; -} - -/// Sign transaction parameters -pub struct SignParam { - /// Version of the runtime specification. - pub spec_version: u32, - /// Transaction version - pub transaction_version: u32, - /// Hash of the genesis block. - pub genesis_hash: ::Hash, - /// Signer account - pub signer: T::AccountKeyPair, - /// Transaction era used by the chain. - pub era: TransactionEraOf, - /// Transaction before it is signed. - pub unsigned: UnsignedTransaction, -} - -impl BlockWithJustification for SignedBlock { - fn header(&self) -> Block::Header { - self.block.header().clone() - } - - fn extrinsics(&self) -> Vec { - self.block.extrinsics().iter().map(Encode::encode).collect() - } - - fn justification(&self) -> Option<&EncodedJustification> { - self.justifications.as_ref().and_then(|j| j.get(sp_finality_grandpa::GRANDPA_ENGINE_ID)) - } -} diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs deleted file mode 100644 index 8179492cf..000000000 --- a/relays/client-substrate/src/client.rs +++ /dev/null @@ -1,787 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Substrate node client. - -use crate::{ - chain::{Chain, ChainWithBalances, TransactionStatusOf}, - rpc::SubstrateClient, - AccountIdOf, BlockNumberOf, ConnectionParams, Error, HashOf, HeaderIdOf, HeaderOf, IndexOf, - Result, -}; - -use async_std::sync::{Arc, Mutex}; -use async_trait::async_trait; -use codec::{Decode, Encode}; -use frame_system::AccountInfo; -use futures::{SinkExt, StreamExt}; -use jsonrpsee::{ - core::{client::SubscriptionClientT, DeserializeOwned}, - types::params::ParamsSer, - ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}, -}; -use num_traits::{Bounded, CheckedSub, One, Zero}; -use pallet_balances::AccountData; -use pallet_transaction_payment::InclusionFee; -use relay_utils::{relay_loop::RECONNECT_DELAY, HeaderId}; -use sp_core::{ - storage::{StorageData, StorageKey}, - Bytes, Hasher, -}; -use sp_runtime::{ - traits::Header as HeaderT, - transaction_validity::{TransactionSource, TransactionValidity}, -}; -use sp_trie::StorageProof; -use sp_version::RuntimeVersion; -use std::{convert::TryFrom, future::Future}; - -const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; -const SUB_API_TXPOOL_VALIDATE_TRANSACTION: &str = "TaggedTransactionQueue_validate_transaction"; -const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; - -/// Opaque justifications subscription type. -pub struct Subscription(Mutex>>); - -/// Opaque GRANDPA authorities set. -pub type OpaqueGrandpaAuthoritiesSet = Vec; - -/// Chain runtime version in client -#[derive(Clone, Debug)] -pub enum ChainRuntimeVersion { - /// Auto query from chain. - Auto, - /// Custom runtime version, defined by user. - /// the first is `spec_version` - /// the second is `transaction_version` - Custom(u32, u32), -} - -/// Substrate client type. -/// -/// Cloning `Client` is a cheap operation. -pub struct Client { - /// Tokio runtime handle. - tokio: Arc, - /// Client connection params. - params: ConnectionParams, - /// Substrate RPC client. - client: Arc, - /// Genesis block hash. - genesis_hash: HashOf, - /// If several tasks are submitting their transactions simultaneously using - /// `submit_signed_extrinsic` method, they may get the same transaction nonce. So one of - /// transactions will be rejected from the pool. This lock is here to prevent situations like - /// that. - submit_signed_extrinsic_lock: Arc>, - /// Saved chain runtime version - chain_runtime_version: ChainRuntimeVersion, -} - -#[async_trait] -impl relay_utils::relay_loop::Client for Client { - type Error = Error; - - async fn reconnect(&mut self) -> Result<()> { - let (tokio, client) = Self::build_client(self.params.clone()).await?; - self.tokio = tokio; - self.client = client; - Ok(()) - } -} - -impl Clone for Client { - fn clone(&self) -> Self { - Client { - tokio: self.tokio.clone(), - params: self.params.clone(), - client: self.client.clone(), - genesis_hash: self.genesis_hash, - submit_signed_extrinsic_lock: self.submit_signed_extrinsic_lock.clone(), - chain_runtime_version: self.chain_runtime_version.clone(), - } - } -} - -impl std::fmt::Debug for Client { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - fmt.debug_struct("Client").field("genesis_hash", &self.genesis_hash).finish() - } -} - -impl Client { - /// Returns client that is able to call RPCs on Substrate node over websocket connection. - /// - /// This function will keep connecting to given Substrate node until connection is established - /// and is functional. If attempt fail, it will wait for `RECONNECT_DELAY` and retry again. - pub async fn new(params: ConnectionParams) -> Self { - loop { - match Self::try_connect(params.clone()).await { - Ok(client) => return client, - Err(error) => log::error!( - target: "bridge", - "Failed to connect to {} node: {:?}. Going to retry in {}s", - C::NAME, - error, - RECONNECT_DELAY.as_secs(), - ), - } - - async_std::task::sleep(RECONNECT_DELAY).await; - } - } - - /// Try to connect to Substrate node over websocket. Returns Substrate RPC client if connection - /// has been established or error otherwise. - pub async fn try_connect(params: ConnectionParams) -> Result { - let (tokio, client) = Self::build_client(params.clone()).await?; - - let number: C::BlockNumber = Zero::zero(); - let genesis_hash_client = client.clone(); - let genesis_hash = tokio - .spawn(async move { - SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_block_hash(&*genesis_hash_client, Some(number)) - .await - }) - .await??; - - let chain_runtime_version = params.chain_runtime_version.clone(); - Ok(Self { - tokio, - params, - client, - genesis_hash, - submit_signed_extrinsic_lock: Arc::new(Mutex::new(())), - chain_runtime_version, - }) - } - - /// Build client to use in connection. - async fn build_client( - params: ConnectionParams, - ) -> Result<(Arc, Arc)> { - let tokio = tokio::runtime::Runtime::new()?; - let uri = format!( - "{}://{}:{}", - if params.secure { "wss" } else { "ws" }, - params.host, - params.port, - ); - let client = tokio - .spawn(async move { - RpcClientBuilder::default() - .max_notifs_per_subscription(MAX_SUBSCRIPTION_CAPACITY) - .build(&uri) - .await - }) - .await??; - - Ok((Arc::new(tokio), Arc::new(client))) - } -} - -impl Client { - /// Return simple runtime version, only include `spec_version` and `transaction_version`. - pub async fn simple_runtime_version(&self) -> Result<(u32, u32)> { - let (spec_version, transaction_version) = match self.chain_runtime_version { - ChainRuntimeVersion::Auto => { - let runtime_version = self.runtime_version().await?; - (runtime_version.spec_version, runtime_version.transaction_version) - }, - ChainRuntimeVersion::Custom(spec_version, transaction_version) => - (spec_version, transaction_version), - }; - Ok((spec_version, transaction_version)) - } - - /// Returns true if client is connected to at least one peer and is in synced state. - pub async fn ensure_synced(&self) -> Result<()> { - self.jsonrpsee_execute(|client| async move { - let health = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::system_health(&*client) - .await?; - let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0); - if is_synced { - Ok(()) - } else { - Err(Error::ClientNotSynced(health)) - } - }) - .await - } - - /// Return hash of the genesis block. - pub fn genesis_hash(&self) -> &C::Hash { - &self.genesis_hash - } - - /// Return hash of the best finalized block. - pub async fn best_finalized_header_hash(&self) -> Result { - self.jsonrpsee_execute(|client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_finalized_head(&*client) - .await?) - }) - .await - } - - /// Return number of the best finalized block. - pub async fn best_finalized_header_number(&self) -> Result { - Ok(*self.header_by_hash(self.best_finalized_header_hash().await?).await?.number()) - } - - /// Returns the best Substrate header. - pub async fn best_header(&self) -> Result - where - C::Header: DeserializeOwned, - { - self.jsonrpsee_execute(|client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_header(&*client, None) - .await?) - }) - .await - } - - /// Get a Substrate block from its hash. - pub async fn get_block(&self, block_hash: Option) -> Result { - self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_block(&*client, block_hash) - .await?) - }) - .await - } - - /// Get a Substrate header by its hash. - pub async fn header_by_hash(&self, block_hash: C::Hash) -> Result - where - C::Header: DeserializeOwned, - { - self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_header(&*client, Some(block_hash)) - .await?) - }) - .await - } - - /// Get a Substrate block hash by its number. - pub async fn block_hash_by_number(&self, number: C::BlockNumber) -> Result { - self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_block_hash(&*client, Some(number)) - .await?) - }) - .await - } - - /// Get a Substrate header by its number. - pub async fn header_by_number(&self, block_number: C::BlockNumber) -> Result - where - C::Header: DeserializeOwned, - { - let block_hash = Self::block_hash_by_number(self, block_number).await?; - let header_by_hash = Self::header_by_hash(self, block_hash).await?; - Ok(header_by_hash) - } - - /// Return runtime version. - pub async fn runtime_version(&self) -> Result { - self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_runtime_version(&*client) - .await?) - }) - .await - } - - /// Read value from runtime storage. - pub async fn storage_value( - &self, - storage_key: StorageKey, - block_hash: Option, - ) -> Result> { - self.raw_storage_value(storage_key, block_hash) - .await? - .map(|encoded_value| { - T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed) - }) - .transpose() - } - - /// Read raw value from runtime storage. - pub async fn raw_storage_value( - &self, - storage_key: StorageKey, - block_hash: Option, - ) -> Result> { - self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_get_storage(&*client, storage_key, block_hash) - .await?) - }) - .await - } - - /// Return native tokens balance of the account. - pub async fn free_native_balance(&self, account: C::AccountId) -> Result - where - C: ChainWithBalances, - { - self.jsonrpsee_execute(move |client| async move { - let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_get_storage(&*client, storage_key, None) - .await? - .ok_or(Error::AccountDoesNotExist)?; - let decoded_account_data = AccountInfo::>::decode( - &mut &encoded_account_data.0[..], - ) - .map_err(Error::ResponseParseFailed)?; - Ok(decoded_account_data.data.free) - }) - .await - } - - /// Get the nonce of the given Substrate account. - /// - /// Note: It's the caller's responsibility to make sure `account` is a valid SS58 address. - pub async fn next_account_index(&self, account: C::AccountId) -> Result { - self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::system_account_next_index(&*client, account) - .await?) - }) - .await - } - - /// Submit unsigned extrinsic for inclusion in a block. - /// - /// Note: The given transaction needs to be SCALE encoded beforehand. - pub async fn submit_unsigned_extrinsic(&self, transaction: Bytes) -> Result { - self.jsonrpsee_execute(move |client| async move { - let tx_hash = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::author_submit_extrinsic(&*client, transaction) - .await?; - log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); - Ok(tx_hash) - }) - .await - } - - /// Submit an extrinsic signed by given account. - /// - /// All calls of this method are synchronized, so there can't be more than one active - /// `submit_signed_extrinsic()` call. This guarantees that no nonces collision may happen - /// if all client instances are clones of the same initial `Client`. - /// - /// Note: The given transaction needs to be SCALE encoded beforehand. - pub async fn submit_signed_extrinsic( - &self, - extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result + Send + 'static, - ) -> Result { - let _guard = self.submit_signed_extrinsic_lock.lock().await; - let transaction_nonce = self.next_account_index(extrinsic_signer).await?; - let best_header = self.best_header().await?; - - // By using parent of best block here, we are protecing again best-block reorganizations. - // E.g. transaction my have been submitted when the best block was `A[num=100]`. Then it has - // been changed to `B[num=100]`. Hash of `A` has been included into transaction signature - // payload. So when signature will be checked, the check will fail and transaction will be - // dropped from the pool. - let best_header_id = match best_header.number().checked_sub(&One::one()) { - Some(parent_block_number) => HeaderId(parent_block_number, *best_header.parent_hash()), - None => HeaderId(*best_header.number(), best_header.hash()), - }; - - self.jsonrpsee_execute(move |client| async move { - let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let tx_hash = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::author_submit_extrinsic(&*client, extrinsic) - .await?; - log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); - Ok(tx_hash) - }) - .await - } - - /// Does exactly the same as `submit_signed_extrinsic`, but keeps watching for extrinsic status - /// after submission. - pub async fn submit_and_watch_signed_extrinsic( - &self, - extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result + Send + 'static, - ) -> Result>> { - let _guard = self.submit_signed_extrinsic_lock.lock().await; - let transaction_nonce = self.next_account_index(extrinsic_signer).await?; - let best_header = self.best_header().await?; - let best_header_id = HeaderId(*best_header.number(), best_header.hash()); - let subscription = self - .jsonrpsee_execute(move |client| async move { - let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let tx_hash = C::Hasher::hash(&extrinsic.0); - let subscription = client - .subscribe( - "author_submitAndWatchExtrinsic", - Some(ParamsSer::Array(vec![jsonrpsee::core::to_json_value(extrinsic) - .map_err(|e| Error::RpcError(e.into()))?])), - "author_unwatchExtrinsic", - ) - .await?; - log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); - Ok(subscription) - }) - .await?; - let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); - self.tokio.spawn(Subscription::background_worker( - C::NAME.into(), - "extrinsic".into(), - subscription, - sender, - )); - Ok(Subscription(Mutex::new(receiver))) - } - - /// Returns pending extrinsics from transaction pool. - pub async fn pending_extrinsics(&self) -> Result> { - self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::author_pending_extrinsics(&*client) - .await?) - }) - .await - } - - /// Validate transaction at given block state. - pub async fn validate_transaction( - &self, - at_block: C::Hash, - transaction: SignedTransaction, - ) -> Result { - self.jsonrpsee_execute(move |client| async move { - let call = SUB_API_TXPOOL_VALIDATE_TRANSACTION.to_string(); - let data = Bytes((TransactionSource::External, transaction, at_block).encode()); - - let encoded_response = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_call(&*client, call, data, Some(at_block)) - .await?; - let validity = TransactionValidity::decode(&mut &encoded_response.0[..]) - .map_err(Error::ResponseParseFailed)?; - - Ok(validity) - }) - .await - } - - /// Estimate fee that will be spent on given extrinsic. - pub async fn estimate_extrinsic_fee( - &self, - transaction: Bytes, - ) -> Result> { - self.jsonrpsee_execute(move |client| async move { - let fee_details = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::payment_query_fee_details(&*client, transaction, None) - .await?; - let inclusion_fee = fee_details - .inclusion_fee - .map(|inclusion_fee| InclusionFee { - base_fee: C::Balance::try_from(inclusion_fee.base_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - len_fee: C::Balance::try_from(inclusion_fee.len_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - adjusted_weight_fee: C::Balance::try_from( - inclusion_fee.adjusted_weight_fee.into_u256(), - ) - .unwrap_or_else(|_| C::Balance::max_value()), - }) - .unwrap_or_else(|| InclusionFee { - base_fee: Zero::zero(), - len_fee: Zero::zero(), - adjusted_weight_fee: Zero::zero(), - }); - Ok(inclusion_fee) - }) - .await - } - - /// Get the GRANDPA authority set at given block. - pub async fn grandpa_authorities_set( - &self, - block: C::Hash, - ) -> Result { - self.jsonrpsee_execute(move |client| async move { - let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); - let data = Bytes(Vec::new()); - - let encoded_response = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_call(&*client, call, data, Some(block)) - .await?; - let authority_list = encoded_response.0; - - Ok(authority_list) - }) - .await - } - - /// Execute runtime call at given block. - pub async fn state_call( - &self, - method: String, - data: Bytes, - at_block: Option, - ) -> Result { - self.jsonrpsee_execute(move |client| async move { - SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_call(&*client, method, data, at_block) - .await - .map_err(Into::into) - }) - .await - } - - /// Returns storage proof of given storage keys. - pub async fn prove_storage( - &self, - keys: Vec, - at_block: C::Hash, - ) -> Result { - self.jsonrpsee_execute(move |client| async move { - SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_prove_storage(&*client, keys, Some(at_block)) - .await - .map(|proof| { - StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect::>()) - }) - .map_err(Into::into) - }) - .await - } - - /// Return `tokenDecimals` property from the set of chain properties. - pub async fn token_decimals(&self) -> Result> { - self.jsonrpsee_execute(move |client| async move { - let system_properties = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::system_properties(&*client) - .await?; - Ok(system_properties.get("tokenDecimals").and_then(|v| v.as_u64())) - }) - .await - } - - /// Return new justifications stream. - pub async fn subscribe_justifications(&self) -> Result> { - let subscription = self - .jsonrpsee_execute(move |client| async move { - Ok(client - .subscribe( - "grandpa_subscribeJustifications", - None, - "grandpa_unsubscribeJustifications", - ) - .await?) - }) - .await?; - let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); - self.tokio.spawn(Subscription::background_worker( - C::NAME.into(), - "justification".into(), - subscription, - sender, - )); - Ok(Subscription(Mutex::new(receiver))) - } - - /// Execute jsonrpsee future in tokio context. - async fn jsonrpsee_execute(&self, make_jsonrpsee_future: MF) -> Result - where - MF: FnOnce(Arc) -> F + Send + 'static, - F: Future> + Send, - T: Send + 'static, - { - let client = self.client.clone(); - self.tokio.spawn(async move { make_jsonrpsee_future(client).await }).await? - } -} - -impl Subscription { - /// Return next item from the subscription. - pub async fn next(&self) -> Result> { - let mut receiver = self.0.lock().await; - let item = receiver.next().await; - Ok(item.unwrap_or(None)) - } - - /// Background worker that is executed in tokio context as `jsonrpsee` requires. - async fn background_worker( - chain_name: String, - item_type: String, - mut subscription: jsonrpsee::core::client::Subscription, - mut sender: futures::channel::mpsc::Sender>, - ) { - loop { - match subscription.next().await { - Some(Ok(item)) => - if sender.send(Some(item)).await.is_err() { - break; - }, - Some(Err(e)) => { - log::trace!( - target: "bridge", - "{} {} subscription stream has returned '{:?}'. Stream needs to be restarted.", - chain_name, - item_type, - e, - ); - let _ = sender.send(None).await; - break; - }, - None => { - log::trace!( - target: "bridge", - "{} {} subscription stream has returned None. Stream needs to be restarted.", - chain_name, - item_type, - ); - let _ = sender.send(None).await; - break; - }, - } - } - } -} diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs deleted file mode 100644 index e698f2596..000000000 --- a/relays/client-substrate/src/error.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Substrate node RPC errors. - -use jsonrpsee::core::Error as RpcError; -use relay_utils::MaybeConnectionError; -use sc_rpc_api::system::Health; -use sp_runtime::transaction_validity::TransactionValidityError; -use thiserror::Error; - -/// Result type used by Substrate client. -pub type Result = std::result::Result; - -/// Errors that can occur only when interacting with -/// a Substrate node through RPC. -#[derive(Error, Debug)] -pub enum Error { - /// IO error. - #[error("IO error: {0}")] - Io(#[from] std::io::Error), - /// An error that can occur when making a request to - /// an JSON-RPC server. - #[error("RPC error: {0}")] - RpcError(#[from] RpcError), - /// The response from the server could not be SCALE decoded. - #[error("Response parse failed: {0}")] - ResponseParseFailed(#[from] codec::Error), - /// The Substrate bridge pallet has not yet been initialized. - #[error("The Substrate bridge pallet has not been initialized yet.")] - UninitializedBridgePallet, - /// Account does not exist on the chain. - #[error("Account does not exist on the chain.")] - AccountDoesNotExist, - /// Runtime storage is missing mandatory ":code:" entry. - #[error("Mandatory :code: entry is missing from runtime storage.")] - MissingMandatoryCodeEntry, - /// The client we're connected to is not synced, so we can't rely on its state. - #[error("Substrate client is not synced {0}.")] - ClientNotSynced(Health), - /// The bridge pallet is halted and all transactions will be rejected. - #[error("Bridge pallet is halted.")] - BridgePalletIsHalted, - /// An error has happened when we have tried to parse storage proof. - #[error("Error when parsing storage proof: {0:?}.")] - StorageProofError(bp_runtime::StorageProofError), - /// The Substrate transaction is invalid. - #[error("Substrate transaction is invalid: {0:?}")] - TransactionInvalid(#[from] TransactionValidityError), - /// Custom logic error. - #[error("{0}")] - Custom(String), -} - -impl From for Error { - fn from(error: tokio::task::JoinError) -> Self { - Error::Custom(format!("Failed to wait tokio task: {}", error)) - } -} - -impl MaybeConnectionError for Error { - fn is_connection_error(&self) -> bool { - matches!( - *self, - Error::RpcError(RpcError::Transport(_)) - // right now if connection to the ws server is dropped (after it is already established), - // we're getting this error - | Error::RpcError(RpcError::Internal(_)) - | Error::RpcError(RpcError::RestartNeeded(_)) - | Error::ClientNotSynced(_), - ) - } -} diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs deleted file mode 100644 index e1f9b0d31..000000000 --- a/relays/client-substrate/src/guard.rs +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Pallet provides a set of guard functions that are running in background threads -//! and are aborting process if some condition fails. - -use crate::{error::Error, Chain, ChainWithBalances, Client}; - -use async_trait::async_trait; -use num_traits::CheckedSub; -use sp_version::RuntimeVersion; -use std::{ - collections::VecDeque, - fmt::Display, - time::{Duration, Instant}, -}; - -/// Guards environment. -#[async_trait] -pub trait Environment: Send + Sync + 'static { - /// Error type. - type Error: Display + Send + Sync + 'static; - - /// Return current runtime version. - async fn runtime_version(&mut self) -> Result; - /// Return free native balance of the account on the chain. - async fn free_native_balance( - &mut self, - account: C::AccountId, - ) -> Result; - - /// Return current time. - fn now(&self) -> Instant { - Instant::now() - } - - /// Sleep given amount of time. - async fn sleep(&mut self, duration: Duration) { - async_std::task::sleep(duration).await - } - - /// Abort current process. Called when guard condition check fails. - async fn abort(&mut self) { - std::process::abort(); - } -} - -/// Abort when runtime spec version is different from specified. -pub fn abort_on_spec_version_change( - mut env: impl Environment, - expected_spec_version: u32, -) { - async_std::task::spawn(async move { - log::info!( - target: "bridge-guard", - "Starting spec_version guard for {}. Expected spec_version: {}", - C::NAME, - expected_spec_version, - ); - - loop { - let actual_spec_version = env.runtime_version().await; - match actual_spec_version { - Ok(version) if version.spec_version == expected_spec_version => (), - Ok(version) => { - log::error!( - target: "bridge-guard", - "{} runtime spec version has changed from {} to {}. Aborting relay", - C::NAME, - expected_spec_version, - version.spec_version, - ); - - env.abort().await; - }, - Err(error) => log::warn!( - target: "bridge-guard", - "Failed to read {} runtime version: {}. Relay may need to be stopped manually", - C::NAME, - error, - ), - } - - env.sleep(conditions_check_delay::()).await; - } - }); -} - -/// Abort if, during 24 hours, free balance of given account is decreased at least by given value. -/// Other components may increase (or decrease) balance of account and it WILL affect logic of the -/// guard. -pub fn abort_when_account_balance_decreased( - mut env: impl Environment, - account_id: C::AccountId, - maximal_decrease: C::Balance, -) { - const DAY: Duration = Duration::from_secs(60 * 60 * 24); - - async_std::task::spawn(async move { - log::info!( - target: "bridge-guard", - "Starting balance guard for {}/{:?}. Maximal decrease: {:?}", - C::NAME, - account_id, - maximal_decrease, - ); - - let mut balances = VecDeque::new(); - - loop { - let current_time = env.now(); - - // remember balances that are beyound 24h border - let time_border = current_time - DAY; - while balances.front().map(|(time, _)| *time < time_border).unwrap_or(false) { - balances.pop_front(); - } - - // read balance of the account - let current_balance = env.free_native_balance(account_id.clone()).await; - - // remember balance and check difference - match current_balance { - Ok(current_balance) => { - // remember balance - balances.push_back((current_time, current_balance)); - - // check if difference between current and oldest balance is too large - let (oldest_time, oldest_balance) = - balances.front().expect("pushed to queue couple of lines above; qed"); - let balances_difference = oldest_balance.checked_sub(¤t_balance); - if balances_difference > Some(maximal_decrease) { - log::error!( - target: "bridge-guard", - "Balance of {} account {:?} has decreased from {:?} to {:?} in {} minutes. Aborting relay", - C::NAME, - account_id, - oldest_balance, - current_balance, - current_time.duration_since(*oldest_time).as_secs() / 60, - ); - - env.abort().await; - } - }, - Err(error) => { - log::warn!( - target: "bridge-guard", - "Failed to read {} account {:?} balance: {}. Relay may need to be stopped manually", - C::NAME, - account_id, - error, - ); - }, - }; - - env.sleep(conditions_check_delay::()).await; - } - }); -} - -/// Delay between conditions check. -fn conditions_check_delay() -> Duration { - C::AVERAGE_BLOCK_INTERVAL * (10 + rand::random::() % 10) -} - -#[async_trait] -impl Environment for Client { - type Error = Error; - - async fn runtime_version(&mut self) -> Result { - Client::::runtime_version(self).await - } - - async fn free_native_balance( - &mut self, - account: C::AccountId, - ) -> Result { - Client::::free_native_balance(self, account).await - } -} - -#[cfg(test)] -mod tests { - use super::*; - use frame_support::weights::{IdentityFee, Weight}; - use futures::{ - channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, - future::FutureExt, - stream::StreamExt, - SinkExt, - }; - - #[derive(Debug, Clone)] - struct TestChain; - - impl bp_runtime::Chain for TestChain { - type AccountId = u32; - type Balance = u32; - type BlockNumber = u32; - type Hash = sp_core::H256; - type Hasher = sp_runtime::traits::BlakeTwo256; - type Header = sp_runtime::generic::Header; - type Index = u32; - type Signature = sp_runtime::testing::TestSignature; - - fn max_extrinsic_size() -> u32 { - unreachable!() - } - - fn max_extrinsic_weight() -> Weight { - unreachable!() - } - } - - impl Chain for TestChain { - type Call = (); - type SignedBlock = sp_runtime::generic::SignedBlock< - sp_runtime::generic::Block, - >; - type WeightToFee = IdentityFee; - - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1); - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader"; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0; - const NAME: &'static str = "Test"; - const STORAGE_PROOF_OVERHEAD: u32 = 0; - const TOKEN_ID: Option<&'static str> = None; - } - - impl ChainWithBalances for TestChain { - fn account_info_storage_key(_account_id: &u32) -> sp_core::storage::StorageKey { - unreachable!() - } - } - - struct TestEnvironment { - runtime_version_rx: UnboundedReceiver, - free_native_balance_rx: UnboundedReceiver, - slept_tx: UnboundedSender<()>, - aborted_tx: UnboundedSender<()>, - } - - #[async_trait] - impl Environment for TestEnvironment { - type Error = Error; - - async fn runtime_version(&mut self) -> Result { - Ok(self.runtime_version_rx.next().await.unwrap_or_default()) - } - - async fn free_native_balance(&mut self, _account: u32) -> Result { - Ok(self.free_native_balance_rx.next().await.unwrap_or_default()) - } - - async fn sleep(&mut self, _duration: Duration) { - let _ = self.slept_tx.send(()).await; - } - - async fn abort(&mut self) { - let _ = self.aborted_tx.send(()).await; - // simulate process abort :) - async_std::task::sleep(Duration::from_secs(60)).await; - } - } - - #[test] - fn aborts_when_spec_version_is_changed() { - async_std::task::block_on(async { - let ( - (mut runtime_version_tx, runtime_version_rx), - (_free_native_balance_tx, free_native_balance_rx), - (slept_tx, mut slept_rx), - (aborted_tx, mut aborted_rx), - ) = (unbounded(), unbounded(), unbounded(), unbounded()); - abort_on_spec_version_change( - TestEnvironment { - runtime_version_rx, - free_native_balance_rx, - slept_tx, - aborted_tx, - }, - 0, - ); - - // client responds with wrong version - runtime_version_tx - .send(RuntimeVersion { spec_version: 42, ..Default::default() }) - .await - .unwrap(); - - // then the `abort` function is called - aborted_rx.next().await; - // and we do not reach the `sleep` function call - assert!(slept_rx.next().now_or_never().is_none()); - }); - } - - #[test] - fn does_not_aborts_when_spec_version_is_unchanged() { - async_std::task::block_on(async { - let ( - (mut runtime_version_tx, runtime_version_rx), - (_free_native_balance_tx, free_native_balance_rx), - (slept_tx, mut slept_rx), - (aborted_tx, mut aborted_rx), - ) = (unbounded(), unbounded(), unbounded(), unbounded()); - abort_on_spec_version_change( - TestEnvironment { - runtime_version_rx, - free_native_balance_rx, - slept_tx, - aborted_tx, - }, - 42, - ); - - // client responds with the same version - runtime_version_tx - .send(RuntimeVersion { spec_version: 42, ..Default::default() }) - .await - .unwrap(); - - // then the `sleep` function is called - slept_rx.next().await; - // and the `abort` function is not called - assert!(aborted_rx.next().now_or_never().is_none()); - }); - } - - #[test] - fn aborts_when_balance_is_too_low() { - async_std::task::block_on(async { - let ( - (_runtime_version_tx, runtime_version_rx), - (mut free_native_balance_tx, free_native_balance_rx), - (slept_tx, mut slept_rx), - (aborted_tx, mut aborted_rx), - ) = (unbounded(), unbounded(), unbounded(), unbounded()); - abort_when_account_balance_decreased( - TestEnvironment { - runtime_version_rx, - free_native_balance_rx, - slept_tx, - aborted_tx, - }, - 0, - 100, - ); - - // client responds with initial balance - free_native_balance_tx.send(1000).await.unwrap(); - - // then the guard sleeps - slept_rx.next().await; - - // and then client responds with updated balance, which is too low - free_native_balance_tx.send(899).await.unwrap(); - - // then the `abort` function is called - aborted_rx.next().await; - // and we do not reach next `sleep` function call - assert!(slept_rx.next().now_or_never().is_none()); - }); - } - - #[test] - fn does_not_aborts_when_balance_is_enough() { - async_std::task::block_on(async { - let ( - (_runtime_version_tx, runtime_version_rx), - (mut free_native_balance_tx, free_native_balance_rx), - (slept_tx, mut slept_rx), - (aborted_tx, mut aborted_rx), - ) = (unbounded(), unbounded(), unbounded(), unbounded()); - abort_when_account_balance_decreased( - TestEnvironment { - runtime_version_rx, - free_native_balance_rx, - slept_tx, - aborted_tx, - }, - 0, - 100, - ); - - // client responds with initial balance - free_native_balance_tx.send(1000).await.unwrap(); - - // then the guard sleeps - slept_rx.next().await; - - // and then client responds with updated balance, which is enough - free_native_balance_tx.send(950).await.unwrap(); - - // then the `sleep` function is called - slept_rx.next().await; - // and `abort` is not called - assert!(aborted_rx.next().now_or_never().is_none()); - }); - } -} diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs deleted file mode 100644 index b3a7ec414..000000000 --- a/relays/client-substrate/src/lib.rs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Tools to interact with Substrate node using RPC methods. - -#![warn(missing_docs)] - -mod chain; -mod client; -mod error; -mod rpc; -mod sync_header; - -pub mod guard; -pub mod metrics; - -use std::time::Duration; - -pub use crate::{ - chain::{ - AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithGrandpa, ChainWithMessages, SignParam, TransactionSignScheme, TransactionStatusOf, - UnsignedTransaction, WeightToFeeOf, - }, - client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, - error::{Error, Result}, - sync_header::SyncHeader, -}; -pub use bp_runtime::{ - AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, - IndexOf, SignatureOf, TransactionEra, TransactionEraOf, -}; - -/// Header id used by the chain. -pub type HeaderIdOf = relay_utils::HeaderId, BlockNumberOf>; - -/// Substrate-over-websocket connection params. -#[derive(Debug, Clone)] -pub struct ConnectionParams { - /// Websocket server host name. - pub host: String, - /// Websocket server TCP port. - pub port: u16, - /// Use secure websocket connection. - pub secure: bool, - /// Defined chain runtime version - pub chain_runtime_version: ChainRuntimeVersion, -} - -impl Default for ConnectionParams { - fn default() -> Self { - ConnectionParams { - host: "localhost".into(), - port: 9944, - secure: false, - chain_runtime_version: ChainRuntimeVersion::Auto, - } - } -} - -/// Returns stall timeout for relay loop. -/// -/// Relay considers himself stalled if he has submitted transaction to the node, but it has not -/// been mined for this period. -pub fn transaction_stall_timeout( - mortality_period: Option, - average_block_interval: Duration, - default_stall_timeout: Duration, -) -> Duration { - // 1 extra block for transaction to reach the pool && 1 for relayer to awake after it is mined - mortality_period - .map(|mortality_period| average_block_interval.saturating_mul(mortality_period + 1 + 1)) - .unwrap_or(default_stall_timeout) -} - -/// Returns stall timeout for relay loop that submit transactions to two chains. -/// -/// Bidirectional relay may have two active transactions. Even if one of them has been spoiled, we -/// can't just restart the loop - the other transaction may still be alive and we'll be submitting -/// duplicate transaction, which may result in funds loss. So we'll be selecting maximal mortality -/// for choosing loop stall timeout. -pub fn bidirectional_transaction_stall_timeout( - left_mortality_period: Option, - right_mortality_period: Option, - left_average_block_interval: Duration, - right_average_block_interval: Duration, - default_stall_timeout: Duration, -) -> Duration { - std::cmp::max( - transaction_stall_timeout( - left_mortality_period, - left_average_block_interval, - default_stall_timeout, - ), - transaction_stall_timeout( - right_mortality_period, - right_average_block_interval, - default_stall_timeout, - ), - ) -} diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/relays/client-substrate/src/metrics/float_storage_value.rs deleted file mode 100644 index 7b5c56e1e..000000000 --- a/relays/client-substrate/src/metrics/float_storage_value.rs +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -use crate::{chain::Chain, client::Client, Error as SubstrateError}; - -use async_std::sync::{Arc, RwLock}; -use async_trait::async_trait; -use codec::Decode; -use num_traits::One; -use relay_utils::metrics::{ - metric_name, register, F64SharedRef, Gauge, Metric, PrometheusError, Registry, - StandaloneMetric, F64, -}; -use sp_core::storage::{StorageData, StorageKey}; -use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber, FixedU128}; -use std::{marker::PhantomData, time::Duration}; - -/// Storage value update interval (in blocks). -const UPDATE_INTERVAL_IN_BLOCKS: u32 = 5; - -/// Fied-point storage value and the way it is decoded from the raw storage value. -pub trait FloatStorageValue: 'static + Clone + Send + Sync { - /// Type of the value. - type Value: FixedPointNumber; - /// Try to decode value from the raw storage value. - fn decode( - &self, - maybe_raw_value: Option, - ) -> Result, SubstrateError>; -} - -/// Implementation of `FloatStorageValue` that expects encoded `FixedU128` value and returns `1` if -/// value is missing from the storage. -#[derive(Clone, Debug, Default)] -pub struct FixedU128OrOne; - -impl FloatStorageValue for FixedU128OrOne { - type Value = FixedU128; - - fn decode( - &self, - maybe_raw_value: Option, - ) -> Result, SubstrateError> { - maybe_raw_value - .map(|raw_value| { - FixedU128::decode(&mut &raw_value.0[..]) - .map_err(SubstrateError::ResponseParseFailed) - .map(Some) - }) - .unwrap_or_else(|| Ok(Some(FixedU128::one()))) - } -} - -/// Metric that represents fixed-point runtime storage value as float gauge. -#[derive(Clone, Debug)] -pub struct FloatStorageValueMetric { - value_converter: V, - client: Client, - storage_key: StorageKey, - metric: Gauge, - shared_value_ref: F64SharedRef, - _phantom: PhantomData, -} - -impl FloatStorageValueMetric { - /// Create new metric. - pub fn new( - value_converter: V, - client: Client, - storage_key: StorageKey, - name: String, - help: String, - ) -> Result { - let shared_value_ref = Arc::new(RwLock::new(None)); - Ok(FloatStorageValueMetric { - value_converter, - client, - storage_key, - metric: Gauge::new(metric_name(None, &name), help)?, - shared_value_ref, - _phantom: Default::default(), - }) - } - - /// Get shared reference to metric value. - pub fn shared_value_ref(&self) -> F64SharedRef { - self.shared_value_ref.clone() - } -} - -impl Metric for FloatStorageValueMetric { - fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - register(self.metric.clone(), registry).map(drop) - } -} - -#[async_trait] -impl StandaloneMetric for FloatStorageValueMetric { - fn update_interval(&self) -> Duration { - C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS - } - - async fn update(&self) { - let value = self - .client - .raw_storage_value(self.storage_key.clone(), None) - .await - .and_then(|maybe_storage_value| { - self.value_converter.decode(maybe_storage_value).map(|maybe_fixed_point_value| { - maybe_fixed_point_value.map(|fixed_point_value| { - fixed_point_value.into_inner().unique_saturated_into() as f64 - / V::Value::DIV.unique_saturated_into() as f64 - }) - }) - }) - .map_err(|e| e.to_string()); - relay_utils::metrics::set_gauge_value(&self.metric, value.clone()); - *self.shared_value_ref.write().await = value.ok().and_then(|x| x); - } -} diff --git a/relays/client-substrate/src/metrics/mod.rs b/relays/client-substrate/src/metrics/mod.rs deleted file mode 100644 index 3b63099e0..000000000 --- a/relays/client-substrate/src/metrics/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Contains several Substrate-specific metrics that may be exposed by relay. - -pub use float_storage_value::{FixedU128OrOne, FloatStorageValue, FloatStorageValueMetric}; -pub use storage_proof_overhead::StorageProofOverheadMetric; - -mod float_storage_value; -mod storage_proof_overhead; diff --git a/relays/client-substrate/src/metrics/storage_proof_overhead.rs b/relays/client-substrate/src/metrics/storage_proof_overhead.rs deleted file mode 100644 index ec3f7ffa0..000000000 --- a/relays/client-substrate/src/metrics/storage_proof_overhead.rs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -use crate::{chain::Chain, client::Client, error::Error}; - -use async_trait::async_trait; -use relay_utils::metrics::{ - metric_name, register, Gauge, Metric, PrometheusError, Registry, StandaloneMetric, U64, -}; -use sp_core::storage::StorageKey; -use sp_runtime::traits::Header as HeaderT; -use sp_storage::well_known_keys::CODE; -use std::time::Duration; - -/// Storage proof overhead update interval (in blocks). -const UPDATE_INTERVAL_IN_BLOCKS: u32 = 100; - -/// Metric that represents extra size of storage proof as unsigned integer gauge. -/// -/// There's one thing to keep in mind when using this metric: the overhead may be slightly -/// different for other values, but this metric gives a good estimation. -#[derive(Debug)] -pub struct StorageProofOverheadMetric { - client: Client, - metric: Gauge, -} - -impl Clone for StorageProofOverheadMetric { - fn clone(&self) -> Self { - StorageProofOverheadMetric { client: self.client.clone(), metric: self.metric.clone() } - } -} - -impl StorageProofOverheadMetric { - /// Create new metric instance with given name and help. - pub fn new(client: Client, name: String, help: String) -> Result { - Ok(StorageProofOverheadMetric { - client, - metric: Gauge::new(metric_name(None, &name), help)?, - }) - } - - /// Returns approximate storage proof size overhead. - async fn compute_storage_proof_overhead(&self) -> Result { - let best_header_hash = self.client.best_finalized_header_hash().await?; - let best_header = self.client.header_by_hash(best_header_hash).await?; - - let storage_proof = - self.client.prove_storage(vec![StorageKey(CODE.to_vec())], best_header_hash).await?; - let storage_proof_size: usize = storage_proof.clone().iter_nodes().map(|n| n.len()).sum(); - - let storage_value_reader = bp_runtime::StorageProofChecker::::new( - *best_header.state_root(), - storage_proof, - ) - .map_err(Error::StorageProofError)?; - let maybe_encoded_storage_value = - storage_value_reader.read_value(CODE).map_err(Error::StorageProofError)?; - let encoded_storage_value_size = - maybe_encoded_storage_value.ok_or(Error::MissingMandatoryCodeEntry)?.len(); - - Ok(storage_proof_size - encoded_storage_value_size) - } -} - -impl Metric for StorageProofOverheadMetric { - fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - register(self.metric.clone(), registry).map(drop) - } -} - -#[async_trait] -impl StandaloneMetric for StorageProofOverheadMetric { - fn update_interval(&self) -> Duration { - C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS - } - - async fn update(&self) { - relay_utils::metrics::set_gauge_value( - &self.metric, - self.compute_storage_proof_overhead().await.map(|overhead| Some(overhead as u64)), - ); - } -} diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs deleted file mode 100644 index a0172d1e5..000000000 --- a/relays/client-substrate/src/rpc.rs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! The most generic Substrate node RPC interface. - -use jsonrpsee::{core::RpcResult, proc_macros::rpc}; -use pallet_transaction_payment_rpc_runtime_api::FeeDetails; -use sc_rpc_api::{state::ReadProof, system::Health}; -use sp_core::{ - storage::{StorageData, StorageKey}, - Bytes, -}; -use sp_rpc::number::NumberOrHex; -use sp_version::RuntimeVersion; - -#[rpc(client)] -pub(crate) trait Substrate { - #[method(name = "system_health", param_kind = array)] - async fn system_health(&self) -> RpcResult; - #[method(name = "system_properties", param_kind = array)] - async fn system_properties(&self) -> RpcResult; - #[method(name = "chain_getHeader", param_kind = array)] - async fn chain_get_header(&self, block_hash: Option) -> RpcResult
; - #[method(name = "chain_getFinalizedHead", param_kind = array)] - async fn chain_get_finalized_head(&self) -> RpcResult; - #[method(name = "chain_getBlock", param_kind = array)] - async fn chain_get_block(&self, block_hash: Option) -> RpcResult; - #[method(name = "chain_getBlockHash", param_kind = array)] - async fn chain_get_block_hash(&self, block_number: Option) -> RpcResult; - #[method(name = "system_accountNextIndex", param_kind = array)] - async fn system_account_next_index(&self, account_id: AccountId) -> RpcResult; - #[method(name = "author_submitExtrinsic", param_kind = array)] - async fn author_submit_extrinsic(&self, extrinsic: Bytes) -> RpcResult; - #[method(name = "author_pendingExtrinsics", param_kind = array)] - async fn author_pending_extrinsics(&self) -> RpcResult>; - #[method(name = "state_call", param_kind = array)] - async fn state_call( - &self, - method: String, - data: Bytes, - at_block: Option, - ) -> RpcResult; - #[method(name = "state_getStorage", param_kind = array)] - async fn state_get_storage( - &self, - key: StorageKey, - at_block: Option, - ) -> RpcResult>; - #[method(name = "state_getReadProof", param_kind = array)] - async fn state_prove_storage( - &self, - keys: Vec, - hash: Option, - ) -> RpcResult>; - #[method(name = "state_getRuntimeVersion", param_kind = array)] - async fn state_runtime_version(&self) -> RpcResult; - #[method(name = "payment_queryFeeDetails", param_kind = array)] - async fn payment_query_fee_details( - &self, - extrinsic: Bytes, - at_block: Option, - ) -> RpcResult>; -} diff --git a/relays/client-substrate/src/sync_header.rs b/relays/client-substrate/src/sync_header.rs deleted file mode 100644 index e45e6b419..000000000 --- a/relays/client-substrate/src/sync_header.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -use bp_header_chain::find_grandpa_authorities_scheduled_change; -use finality_relay::SourceHeader as FinalitySourceHeader; -use sp_runtime::traits::Header as HeaderT; - -/// Generic wrapper for `sp_runtime::traits::Header` based headers, that -/// implements `finality_relay::SourceHeader` and may be used in headers sync directly. -#[derive(Clone, Debug, PartialEq)] -pub struct SyncHeader
(Header); - -impl
SyncHeader
{ - /// Extracts wrapped header from self. - pub fn into_inner(self) -> Header { - self.0 - } -} - -impl
std::ops::Deref for SyncHeader
{ - type Target = Header; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl
From
for SyncHeader
{ - fn from(header: Header) -> Self { - Self(header) - } -} - -impl FinalitySourceHeader for SyncHeader
{ - fn hash(&self) -> Header::Hash { - self.0.hash() - } - - fn number(&self) -> Header::Number { - *self.0.number() - } - - fn is_mandatory(&self) -> bool { - find_grandpa_authorities_scheduled_change(&self.0).is_some() - } -} diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml deleted file mode 100644 index cc5ae54be..000000000 --- a/relays/finality/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "finality-relay" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -description = "Finality proofs relay" - -[dependencies] -async-std = "1.6.5" -async-trait = "0.1.40" -backoff = "0.2" -bp-header-chain = { path = "../../primitives/header-chain" } -futures = "0.3.5" -log = "0.4.11" -num-traits = "0.2" -relay-utils = { path = "../utils" } - -[dev-dependencies] -parking_lot = "0.11.0" diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs deleted file mode 100644 index c1ba3410d..000000000 --- a/relays/finality/src/finality_loop.rs +++ /dev/null @@ -1,689 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! The loop basically reads all missing headers and their finality proofs from the source client. -//! The proof for the best possible header is then submitted to the target node. The only exception -//! is the mandatory headers, which we always submit to the target node. For such headers, we -//! assume that the persistent proof either exists, or will eventually become available. - -use crate::{ - sync_loop_metrics::SyncLoopMetrics, FinalityProof, FinalitySyncPipeline, SourceHeader, -}; - -use async_trait::async_trait; -use backoff::backoff::Backoff; -use futures::{select, Future, FutureExt, Stream, StreamExt}; -use num_traits::{One, Saturating}; -use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, retry_backoff, FailedClient, - HeaderId, MaybeConnectionError, -}; -use std::{ - pin::Pin, - time::{Duration, Instant}, -}; - -/// Finality proof synchronization loop parameters. -#[derive(Debug, Clone)] -pub struct FinalitySyncParams { - /// Interval at which we check updates on both clients. Normally should be larger than - /// `min(source_block_time, target_block_time)`. - /// - /// This parameter may be used to limit transactions rate. Increase the value && you'll get - /// infrequent updates => sparse headers => potential slow down of bridge applications, but - /// pallet storage won't be super large. Decrease the value to near `source_block_time` and - /// you'll get transaction for (almost) every block of the source chain => all source headers - /// will be known to the target chain => bridge applications will run faster, but pallet - /// storage may explode (but if pruning is there, then it's fine). - pub tick: Duration, - /// Number of finality proofs to keep in internal buffer between loop iterations. - /// - /// While in "major syncing" state, we still read finality proofs from the stream. They're - /// stored in the internal buffer between loop iterations. When we're close to the tip of the - /// chain, we may meet finality delays if headers are not finalized frequently. So instead of - /// waiting for next finality proof to appear in the stream, we may use existing proof from - /// that buffer. - pub recent_finality_proofs_limit: usize, - /// Timeout before we treat our transactions as lost and restart the whole sync process. - pub stall_timeout: Duration, - /// If true, only mandatory headers are relayed. - pub only_mandatory_headers: bool, -} - -/// Source client used in finality synchronization loop. -#[async_trait] -pub trait SourceClient: RelayClient { - /// Stream of new finality proofs. The stream is allowed to miss proofs for some - /// headers, even if those headers are mandatory. - type FinalityProofsStream: Stream + Send; - - /// Get best finalized block number. - async fn best_finalized_block_number(&self) -> Result; - - /// Get canonical header and its finality proof by number. - async fn header_and_finality_proof( - &self, - number: P::Number, - ) -> Result<(P::Header, Option), Self::Error>; - - /// Subscribe to new finality proofs. - async fn finality_proofs(&self) -> Result; -} - -/// Target client used in finality synchronization loop. -#[async_trait] -pub trait TargetClient: RelayClient { - /// Get best finalized source block number. - async fn best_finalized_source_block_id( - &self, - ) -> Result, Self::Error>; - - /// Submit header finality proof. - async fn submit_finality_proof( - &self, - header: P::Header, - proof: P::FinalityProof, - ) -> Result<(), Self::Error>; -} - -/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs -/// sync loop. -pub fn metrics_prefix() -> String { - format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME) -} - -/// Run finality proofs synchronization loop. -pub async fn run( - source_client: impl SourceClient

, - target_client: impl TargetClient

, - sync_params: FinalitySyncParams, - metrics_params: MetricsParams, - exit_signal: impl Future + 'static + Send, -) -> Result<(), relay_utils::Error> { - let exit_signal = exit_signal.shared(); - relay_utils::relay_loop(source_client, target_client) - .with_metrics(metrics_params) - .loop_metric(SyncLoopMetrics::new( - Some(&metrics_prefix::

()), - "source", - "source_at_target", - )?)? - .expose() - .await? - .run(metrics_prefix::

(), move |source_client, target_client, metrics| { - run_until_connection_lost( - source_client, - target_client, - sync_params.clone(), - metrics, - exit_signal.clone(), - ) - }) - .await -} - -/// Unjustified headers container. Ordered by header number. -pub(crate) type UnjustifiedHeaders = Vec; -/// Finality proofs container. Ordered by target header number. -pub(crate) type FinalityProofs

= - Vec<(

::Number,

::FinalityProof)>; -/// Reference to finality proofs container. -pub(crate) type FinalityProofsRef<'a, P> = - &'a [(

::Number,

::FinalityProof)]; - -/// Error that may happen inside finality synchronization loop. -#[derive(Debug)] -pub(crate) enum Error { - /// Source client request has failed with given error. - Source(SourceError), - /// Target client request has failed with given error. - Target(TargetError), - /// Finality proof for mandatory header is missing from the source node. - MissingMandatoryFinalityProof(P::Number), - /// The synchronization has stalled. - Stalled, -} - -impl Error -where - P: FinalitySyncPipeline, - SourceError: MaybeConnectionError, - TargetError: MaybeConnectionError, -{ - fn fail_if_connection_error(&self) -> Result<(), FailedClient> { - match *self { - Error::Source(ref error) if error.is_connection_error() => Err(FailedClient::Source), - Error::Target(ref error) if error.is_connection_error() => Err(FailedClient::Target), - Error::Stalled => Err(FailedClient::Both), - _ => Ok(()), - } - } -} - -/// Information about transaction that we have submitted. -#[derive(Debug, Clone)] -pub(crate) struct Transaction { - /// Time when we have submitted this transaction. - pub time: Instant, - /// The number of the header we have submitted. - pub submitted_header_number: Number, -} - -/// Finality proofs stream that may be restarted. -pub(crate) struct RestartableFinalityProofsStream { - /// Flag that the stream needs to be restarted. - pub(crate) needs_restart: bool, - /// The stream itself. - pub(crate) stream: Pin>, -} - -#[cfg(test)] -impl From for RestartableFinalityProofsStream { - fn from(stream: S) -> Self { - RestartableFinalityProofsStream { needs_restart: false, stream: Box::pin(stream) } - } -} - -/// Finality synchronization loop state. -pub(crate) struct FinalityLoopState<'a, P: FinalitySyncPipeline, FinalityProofsStream> { - /// Synchronization loop progress. - pub(crate) progress: &'a mut (Instant, Option), - /// Finality proofs stream. - pub(crate) finality_proofs_stream: - &'a mut RestartableFinalityProofsStream, - /// Recent finality proofs that we have read from the stream. - pub(crate) recent_finality_proofs: &'a mut FinalityProofs

, - /// Last transaction that we have submitted to the target node. - pub(crate) last_transaction: Option>, -} - -async fn run_until_connection_lost( - source_client: impl SourceClient

, - target_client: impl TargetClient

, - sync_params: FinalitySyncParams, - metrics_sync: Option, - exit_signal: impl Future, -) -> Result<(), FailedClient> { - let restart_finality_proofs_stream = || async { - source_client.finality_proofs().await.map_err(|error| { - log::error!( - target: "bridge", - "Failed to subscribe to {} justifications: {:?}. Going to reconnect", - P::SOURCE_NAME, - error, - ); - - FailedClient::Source - }) - }; - - let exit_signal = exit_signal.fuse(); - futures::pin_mut!(exit_signal); - - let mut finality_proofs_stream = RestartableFinalityProofsStream { - needs_restart: false, - stream: Box::pin(restart_finality_proofs_stream().await?), - }; - let mut recent_finality_proofs = Vec::new(); - - let mut progress = (Instant::now(), None); - let mut retry_backoff = retry_backoff(); - let mut last_transaction = None; - - loop { - // run loop iteration - let iteration_result = run_loop_iteration( - &source_client, - &target_client, - FinalityLoopState { - progress: &mut progress, - finality_proofs_stream: &mut finality_proofs_stream, - recent_finality_proofs: &mut recent_finality_proofs, - last_transaction: last_transaction.clone(), - }, - &sync_params, - &metrics_sync, - ) - .await; - - // deal with errors - let next_tick = match iteration_result { - Ok(updated_last_transaction) => { - last_transaction = updated_last_transaction; - retry_backoff.reset(); - sync_params.tick - }, - Err(error) => { - log::error!(target: "bridge", "Finality sync loop iteration has failed with error: {:?}", error); - error.fail_if_connection_error()?; - retry_backoff.next_backoff().unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY) - }, - }; - if finality_proofs_stream.needs_restart { - log::warn!(target: "bridge", "{} finality proofs stream is being restarted", P::SOURCE_NAME); - - finality_proofs_stream.needs_restart = false; - finality_proofs_stream.stream = Box::pin(restart_finality_proofs_stream().await?); - } - - // wait till exit signal, or new source block - select! { - _ = async_std::task::sleep(next_tick).fuse() => {}, - _ = exit_signal => return Ok(()), - } - } -} - -pub(crate) async fn run_loop_iteration( - source_client: &SC, - target_client: &TC, - state: FinalityLoopState<'_, P, SC::FinalityProofsStream>, - sync_params: &FinalitySyncParams, - metrics_sync: &Option, -) -> Result>, Error> -where - P: FinalitySyncPipeline, - SC: SourceClient

, - TC: TargetClient

, -{ - // read best source headers ids from source and target nodes - let best_number_at_source = - source_client.best_finalized_block_number().await.map_err(Error::Source)?; - let best_id_at_target = - target_client.best_finalized_source_block_id().await.map_err(Error::Target)?; - let best_number_at_target = best_id_at_target.0; - - let different_hash_at_source = - ensure_same_fork::(&best_id_at_target, source_client).await.map_err(Error::Source)?; - let using_same_fork = different_hash_at_source.is_none(); - if let Some(ref different_hash_at_source) = different_hash_at_source { - log::error!( - target: "bridge", - "Source node ({}) and pallet at target node ({}) have different headers at the same height {:?}: \ - at-source {:?} vs at-target {:?}", - P::SOURCE_NAME, - P::TARGET_NAME, - best_number_at_target, - different_hash_at_source, - best_id_at_target.1, - ); - } - - if let Some(ref metrics_sync) = *metrics_sync { - metrics_sync.update_best_block_at_source(best_number_at_source); - metrics_sync.update_best_block_at_target(best_number_at_target); - metrics_sync.update_using_same_fork(using_same_fork); - } - *state.progress = - print_sync_progress::

(*state.progress, best_number_at_source, best_number_at_target); - - // if we have already submitted header, then we just need to wait for it - // if we're waiting too much, then we believe our transaction has been lost and restart sync - if let Some(last_transaction) = state.last_transaction { - if best_number_at_target >= last_transaction.submitted_header_number { - // transaction has been mined && we can continue - } else if last_transaction.time.elapsed() > sync_params.stall_timeout { - log::error!( - target: "bridge", - "Finality synchronization from {} to {} has stalled. Going to restart", - P::SOURCE_NAME, - P::TARGET_NAME, - ); - - return Err(Error::Stalled); - } else { - return Ok(Some(last_transaction)); - } - } - - // submit new header if we have something new - match select_header_to_submit( - source_client, - target_client, - state.finality_proofs_stream, - state.recent_finality_proofs, - best_number_at_source, - best_number_at_target, - sync_params, - ) - .await? - { - Some((header, justification)) => { - let new_transaction = - Transaction { time: Instant::now(), submitted_header_number: header.number() }; - - log::debug!( - target: "bridge", - "Going to submit finality proof of {} header #{:?} to {}", - P::SOURCE_NAME, - new_transaction.submitted_header_number, - P::TARGET_NAME, - ); - - target_client - .submit_finality_proof(header, justification) - .await - .map_err(Error::Target)?; - Ok(Some(new_transaction)) - }, - None => Ok(None), - } -} - -pub(crate) async fn select_header_to_submit( - source_client: &SC, - target_client: &TC, - finality_proofs_stream: &mut RestartableFinalityProofsStream, - recent_finality_proofs: &mut FinalityProofs

, - best_number_at_source: P::Number, - best_number_at_target: P::Number, - sync_params: &FinalitySyncParams, -) -> Result, Error> -where - P: FinalitySyncPipeline, - SC: SourceClient

, - TC: TargetClient

, -{ - // to see that the loop is progressing - log::trace!( - target: "bridge", - "Considering range of headers ({:?}; {:?}]", - best_number_at_target, - best_number_at_source, - ); - - // read missing headers. if we see that the header schedules GRANDPA change, we need to - // submit this header - let selected_finality_proof = read_missing_headers::( - source_client, - target_client, - best_number_at_source, - best_number_at_target, - ) - .await?; - let (mut unjustified_headers, mut selected_finality_proof) = match selected_finality_proof { - SelectedFinalityProof::Mandatory(header, finality_proof) => - return Ok(Some((header, finality_proof))), - _ if sync_params.only_mandatory_headers => { - // we are not reading finality proofs from the stream, so eventually it'll break - // but we don't care about transient proofs at all, so it is acceptable - return Ok(None); - }, - SelectedFinalityProof::Regular(unjustified_headers, header, finality_proof) => - (unjustified_headers, Some((header, finality_proof))), - SelectedFinalityProof::None(unjustified_headers) => (unjustified_headers, None), - }; - - // all headers that are missing from the target client are non-mandatory - // => even if we have already selected some header and its persistent finality proof, - // we may try to select better header by reading non-persistent proofs from the stream - read_finality_proofs_from_stream::(finality_proofs_stream, recent_finality_proofs); - selected_finality_proof = select_better_recent_finality_proof::

( - recent_finality_proofs, - &mut unjustified_headers, - selected_finality_proof, - ); - - // remove obsolete 'recent' finality proofs + keep its size under certain limit - let oldest_finality_proof_to_keep = selected_finality_proof - .as_ref() - .map(|(header, _)| header.number()) - .unwrap_or(best_number_at_target); - prune_recent_finality_proofs::

( - oldest_finality_proof_to_keep, - recent_finality_proofs, - sync_params.recent_finality_proofs_limit, - ); - - Ok(selected_finality_proof) -} - -/// Ensures that both clients are on the same fork. -/// -/// Returns `Some(_)` with header has at the source client if headers are different. -async fn ensure_same_fork>( - best_id_at_target: &HeaderId, - source_client: &SC, -) -> Result, SC::Error> { - let header_at_source = source_client.header_and_finality_proof(best_id_at_target.0).await?.0; - let header_hash_at_source = header_at_source.hash(); - Ok(if best_id_at_target.1 == header_hash_at_source { - None - } else { - Some(header_hash_at_source) - }) -} - -/// Finality proof that has been selected by the `read_missing_headers` function. -pub(crate) enum SelectedFinalityProof { - /// Mandatory header and its proof has been selected. We shall submit proof for this header. - Mandatory(Header, FinalityProof), - /// Regular header and its proof has been selected. We may submit this proof, or proof for - /// some better header. - Regular(UnjustifiedHeaders

, Header, FinalityProof), - /// We haven't found any missing header with persistent proof at the target client. - None(UnjustifiedHeaders
), -} - -/// Read missing headers and their persistent finality proofs from the target client. -/// -/// If we have found some header with known proof, it is returned. -/// Otherwise, `SelectedFinalityProof::None` is returned. -/// -/// Unless we have found mandatory header, all missing headers are collected and returned. -pub(crate) async fn read_missing_headers< - P: FinalitySyncPipeline, - SC: SourceClient

, - TC: TargetClient

, ->( - source_client: &SC, - _target_client: &TC, - best_number_at_source: P::Number, - best_number_at_target: P::Number, -) -> Result, Error> { - let mut unjustified_headers = Vec::new(); - let mut selected_finality_proof = None; - let mut header_number = best_number_at_target + One::one(); - while header_number <= best_number_at_source { - let (header, finality_proof) = - source_client.header_and_finality_proof(header_number).await.map_err(Error::Source)?; - let is_mandatory = header.is_mandatory(); - - match (is_mandatory, finality_proof) { - (true, Some(finality_proof)) => { - log::trace!(target: "bridge", "Header {:?} is mandatory", header_number); - return Ok(SelectedFinalityProof::Mandatory(header, finality_proof)); - }, - (true, None) => return Err(Error::MissingMandatoryFinalityProof(header.number())), - (false, Some(finality_proof)) => { - log::trace!(target: "bridge", "Header {:?} has persistent finality proof", header_number); - unjustified_headers.clear(); - selected_finality_proof = Some((header, finality_proof)); - }, - (false, None) => { - unjustified_headers.push(header); - }, - } - - header_number = header_number + One::one(); - } - - log::trace!( - target: "bridge", - "Read {} {} headers. Selected finality proof for header: {:?}", - best_number_at_source.saturating_sub(best_number_at_target), - P::SOURCE_NAME, - selected_finality_proof.as_ref().map(|(header, _)| header), - ); - - Ok(match selected_finality_proof { - Some((header, proof)) => SelectedFinalityProof::Regular(unjustified_headers, header, proof), - None => SelectedFinalityProof::None(unjustified_headers), - }) -} - -/// Read finality proofs from the stream. -pub(crate) fn read_finality_proofs_from_stream< - P: FinalitySyncPipeline, - FPS: Stream, ->( - finality_proofs_stream: &mut RestartableFinalityProofsStream, - recent_finality_proofs: &mut FinalityProofs

, -) { - let mut proofs_count = 0; - let mut first_header_number = None; - let mut last_header_number = None; - loop { - let next_proof = finality_proofs_stream.stream.next(); - let finality_proof = match next_proof.now_or_never() { - Some(Some(finality_proof)) => finality_proof, - Some(None) => { - finality_proofs_stream.needs_restart = true; - break; - }, - None => break, - }; - - let target_header_number = finality_proof.target_header_number(); - if first_header_number.is_none() { - first_header_number = Some(target_header_number); - } - last_header_number = Some(target_header_number); - proofs_count += 1; - - recent_finality_proofs.push((target_header_number, finality_proof)); - } - - if proofs_count != 0 { - log::trace!( - target: "bridge", - "Read {} finality proofs from {} finality stream for headers in range [{:?}; {:?}]", - proofs_count, - P::SOURCE_NAME, - first_header_number, - last_header_number, - ); - } -} - -/// Try to select better header and its proof, given finality proofs that we -/// have recently read from the stream. -pub(crate) fn select_better_recent_finality_proof( - recent_finality_proofs: FinalityProofsRef

, - unjustified_headers: &mut UnjustifiedHeaders, - selected_finality_proof: Option<(P::Header, P::FinalityProof)>, -) -> Option<(P::Header, P::FinalityProof)> { - if unjustified_headers.is_empty() || recent_finality_proofs.is_empty() { - log::trace!( - target: "bridge", - "Can not improve selected {} finality proof {:?}. No unjustified headers and recent proofs", - P::SOURCE_NAME, - selected_finality_proof.as_ref().map(|(h, _)| h.number()), - ); - return selected_finality_proof; - } - - const NOT_EMPTY_PROOF: &str = "we have checked that the vec is not empty; qed"; - - // we need proofs for headers in range unjustified_range_begin..=unjustified_range_end - let unjustified_range_begin = unjustified_headers.first().expect(NOT_EMPTY_PROOF).number(); - let unjustified_range_end = unjustified_headers.last().expect(NOT_EMPTY_PROOF).number(); - - // we have proofs for headers in range buffered_range_begin..=buffered_range_end - let buffered_range_begin = recent_finality_proofs.first().expect(NOT_EMPTY_PROOF).0; - let buffered_range_end = recent_finality_proofs.last().expect(NOT_EMPTY_PROOF).0; - - // we have two ranges => find intersection - let intersection_begin = std::cmp::max(unjustified_range_begin, buffered_range_begin); - let intersection_end = std::cmp::min(unjustified_range_end, buffered_range_end); - let intersection = intersection_begin..=intersection_end; - - // find last proof from intersection - let selected_finality_proof_index = recent_finality_proofs - .binary_search_by_key(intersection.end(), |(number, _)| *number) - .unwrap_or_else(|index| index.saturating_sub(1)); - let (selected_header_number, finality_proof) = - &recent_finality_proofs[selected_finality_proof_index]; - let has_selected_finality_proof = intersection.contains(selected_header_number); - log::trace!( - target: "bridge", - "Trying to improve selected {} finality proof {:?}. Headers range: [{:?}; {:?}]. Proofs range: [{:?}; {:?}].\ - Trying to improve to: {:?}. Result: {}", - P::SOURCE_NAME, - selected_finality_proof.as_ref().map(|(h, _)| h.number()), - unjustified_range_begin, - unjustified_range_end, - buffered_range_begin, - buffered_range_end, - selected_header_number, - if has_selected_finality_proof { "improved" } else { "not improved" }, - ); - if !has_selected_finality_proof { - return selected_finality_proof; - } - - // now remove all obsolete headers and extract selected header - let selected_header_position = unjustified_headers - .binary_search_by_key(selected_header_number, |header| header.number()) - .expect("unjustified_headers contain all headers from intersection; qed"); - let selected_header = unjustified_headers.swap_remove(selected_header_position); - Some((selected_header, finality_proof.clone())) -} - -pub(crate) fn prune_recent_finality_proofs( - justified_header_number: P::Number, - recent_finality_proofs: &mut FinalityProofs

, - recent_finality_proofs_limit: usize, -) { - let position = recent_finality_proofs - .binary_search_by_key(&justified_header_number, |(header_number, _)| *header_number); - - // remove all obsolete elements - *recent_finality_proofs = recent_finality_proofs - .split_off(position.map(|position| position + 1).unwrap_or_else(|position| position)); - - // now - limit vec by size - let split_index = recent_finality_proofs.len().saturating_sub(recent_finality_proofs_limit); - *recent_finality_proofs = recent_finality_proofs.split_off(split_index); -} - -fn print_sync_progress( - progress_context: (Instant, Option), - best_number_at_source: P::Number, - best_number_at_target: P::Number, -) -> (Instant, Option) { - let (prev_time, prev_best_number_at_target) = progress_context; - let now = Instant::now(); - - let need_update = now - prev_time > Duration::from_secs(10) - || prev_best_number_at_target - .map(|prev_best_number_at_target| { - best_number_at_target.saturating_sub(prev_best_number_at_target) > 10.into() - }) - .unwrap_or(true); - - if !need_update { - return (prev_time, prev_best_number_at_target); - } - - log::info!( - target: "bridge", - "Synced {:?} of {:?} headers", - best_number_at_target, - best_number_at_source, - ); - (now, Some(best_number_at_target)) -} diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs deleted file mode 100644 index 2c2ae2bc4..000000000 --- a/relays/finality/src/finality_loop_tests.rs +++ /dev/null @@ -1,548 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Tests for finality synchronization loop. - -#![cfg(test)] - -use crate::{ - finality_loop::{ - prune_recent_finality_proofs, read_finality_proofs_from_stream, run, run_loop_iteration, - select_better_recent_finality_proof, select_header_to_submit, FinalityLoopState, - FinalityProofs, FinalitySyncParams, RestartableFinalityProofsStream, SourceClient, - TargetClient, - }, - sync_loop_metrics::SyncLoopMetrics, - FinalityProof, FinalitySyncPipeline, SourceHeader, -}; - -use async_trait::async_trait; -use futures::{FutureExt, Stream, StreamExt}; -use parking_lot::Mutex; -use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, HeaderId, MaybeConnectionError, -}; -use std::{ - collections::HashMap, - pin::Pin, - sync::Arc, - time::{Duration, Instant}, -}; - -type IsMandatory = bool; -type TestNumber = u64; -type TestHash = u64; - -#[derive(Debug, Clone)] -enum TestError { - NonConnection, -} - -impl MaybeConnectionError for TestError { - fn is_connection_error(&self) -> bool { - false - } -} - -#[derive(Debug, Clone)] -struct TestFinalitySyncPipeline; - -impl FinalitySyncPipeline for TestFinalitySyncPipeline { - type FinalityProof = TestFinalityProof; - type Hash = TestHash; - type Header = TestSourceHeader; - type Number = TestNumber; - - const SOURCE_NAME: &'static str = "TestSource"; - const TARGET_NAME: &'static str = "TestTarget"; -} - -#[derive(Debug, Clone, PartialEq)] -struct TestSourceHeader(IsMandatory, TestNumber, TestHash); - -impl SourceHeader for TestSourceHeader { - fn hash(&self) -> TestHash { - self.2 - } - - fn number(&self) -> TestNumber { - self.1 - } - - fn is_mandatory(&self) -> bool { - self.0 - } -} - -#[derive(Debug, Clone, PartialEq)] -struct TestFinalityProof(TestNumber); - -impl FinalityProof for TestFinalityProof { - fn target_header_number(&self) -> TestNumber { - self.0 - } -} - -#[derive(Debug, Clone, Default)] -struct ClientsData { - source_best_block_number: TestNumber, - source_headers: HashMap)>, - source_proofs: Vec, - - target_best_block_id: HeaderId, - target_headers: Vec<(TestSourceHeader, TestFinalityProof)>, -} - -#[derive(Clone)] -struct TestSourceClient { - on_method_call: Arc, - data: Arc>, -} - -#[async_trait] -impl RelayClient for TestSourceClient { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - unreachable!() - } -} - -#[async_trait] -impl SourceClient for TestSourceClient { - type FinalityProofsStream = Pin + 'static + Send>>; - - async fn best_finalized_block_number(&self) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); - Ok(data.source_best_block_number) - } - - async fn header_and_finality_proof( - &self, - number: TestNumber, - ) -> Result<(TestSourceHeader, Option), TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); - data.source_headers.get(&number).cloned().ok_or(TestError::NonConnection) - } - - async fn finality_proofs(&self) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); - Ok(futures::stream::iter(data.source_proofs.clone()).boxed()) - } -} - -#[derive(Clone)] -struct TestTargetClient { - on_method_call: Arc, - data: Arc>, -} - -#[async_trait] -impl RelayClient for TestTargetClient { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - unreachable!() - } -} - -#[async_trait] -impl TargetClient for TestTargetClient { - async fn best_finalized_source_block_id( - &self, - ) -> Result, TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); - Ok(data.target_best_block_id) - } - - async fn submit_finality_proof( - &self, - header: TestSourceHeader, - proof: TestFinalityProof, - ) -> Result<(), TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); - data.target_best_block_id = HeaderId(header.number(), header.hash()); - data.target_headers.push((header, proof)); - Ok(()) - } -} - -fn prepare_test_clients( - exit_sender: futures::channel::mpsc::UnboundedSender<()>, - state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, - source_headers: HashMap)>, -) -> (TestSourceClient, TestTargetClient) { - let internal_state_function: Arc = - Arc::new(move |data| { - if state_function(data) { - exit_sender.unbounded_send(()).unwrap(); - } - }); - let clients_data = Arc::new(Mutex::new(ClientsData { - source_best_block_number: 10, - source_headers, - source_proofs: vec![TestFinalityProof(12), TestFinalityProof(14)], - - target_best_block_id: HeaderId(5, 5), - target_headers: vec![], - })); - ( - TestSourceClient { - on_method_call: internal_state_function.clone(), - data: clients_data.clone(), - }, - TestTargetClient { on_method_call: internal_state_function, data: clients_data }, - ) -} - -fn test_sync_params() -> FinalitySyncParams { - FinalitySyncParams { - tick: Duration::from_secs(0), - recent_finality_proofs_limit: 1024, - stall_timeout: Duration::from_secs(1), - only_mandatory_headers: false, - } -} - -fn run_sync_loop( - state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, -) -> ClientsData { - let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); - let (source_client, target_client) = prepare_test_clients( - exit_sender, - state_function, - vec![ - (5, (TestSourceHeader(false, 5, 5), None)), - (6, (TestSourceHeader(false, 6, 6), None)), - (7, (TestSourceHeader(false, 7, 7), Some(TestFinalityProof(7)))), - (8, (TestSourceHeader(true, 8, 8), Some(TestFinalityProof(8)))), - (9, (TestSourceHeader(false, 9, 9), Some(TestFinalityProof(9)))), - (10, (TestSourceHeader(false, 10, 10), None)), - ] - .into_iter() - .collect(), - ); - let sync_params = test_sync_params(); - - let clients_data = source_client.data.clone(); - let _ = async_std::task::block_on(run( - source_client, - target_client, - sync_params, - MetricsParams::disabled(), - exit_receiver.into_future().map(|(_, _)| ()), - )); - - let clients_data = clients_data.lock().clone(); - clients_data -} - -#[test] -fn finality_sync_loop_works() { - let client_data = run_sync_loop(|data| { - // header#7 has persistent finality proof, but it isn't mandatory => it isn't submitted, - // because header#8 has persistent finality proof && it is mandatory => it is submitted - // header#9 has persistent finality proof, but it isn't mandatory => it is submitted, - // because there are no more persistent finality proofs - // - // once this ^^^ is done, we generate more blocks && read proof for blocks 12 and 14 from - // the stream - if data.target_best_block_id.0 == 9 { - data.source_best_block_number = 14; - data.source_headers.insert(11, (TestSourceHeader(false, 11, 11), None)); - data.source_headers - .insert(12, (TestSourceHeader(false, 12, 12), Some(TestFinalityProof(12)))); - data.source_headers.insert(13, (TestSourceHeader(false, 13, 13), None)); - data.source_headers - .insert(14, (TestSourceHeader(false, 14, 14), Some(TestFinalityProof(14)))); - } - // once this ^^^ is done, we generate more blocks && read persistent proof for block 16 - if data.target_best_block_id.0 == 14 { - data.source_best_block_number = 17; - data.source_headers.insert(15, (TestSourceHeader(false, 15, 15), None)); - data.source_headers - .insert(16, (TestSourceHeader(false, 16, 16), Some(TestFinalityProof(16)))); - data.source_headers.insert(17, (TestSourceHeader(false, 17, 17), None)); - } - - data.target_best_block_id.0 == 16 - }); - - assert_eq!( - client_data.target_headers, - vec![ - // before adding 11..14: finality proof for mandatory header#8 - (TestSourceHeader(true, 8, 8), TestFinalityProof(8)), - // before adding 11..14: persistent finality proof for non-mandatory header#9 - (TestSourceHeader(false, 9, 9), TestFinalityProof(9)), - // after adding 11..14: ephemeral finality proof for non-mandatory header#14 - (TestSourceHeader(false, 14, 14), TestFinalityProof(14)), - // after adding 15..17: persistent finality proof for non-mandatory header#16 - (TestSourceHeader(false, 16, 16), TestFinalityProof(16)), - ], - ); -} - -fn run_only_mandatory_headers_mode_test( - only_mandatory_headers: bool, - has_mandatory_headers: bool, -) -> Option<(TestSourceHeader, TestFinalityProof)> { - let (exit_sender, _) = futures::channel::mpsc::unbounded(); - let (source_client, target_client) = prepare_test_clients( - exit_sender, - |_| false, - vec![ - (6, (TestSourceHeader(false, 6, 6), Some(TestFinalityProof(6)))), - (7, (TestSourceHeader(false, 7, 7), Some(TestFinalityProof(7)))), - (8, (TestSourceHeader(has_mandatory_headers, 8, 8), Some(TestFinalityProof(8)))), - (9, (TestSourceHeader(false, 9, 9), Some(TestFinalityProof(9)))), - (10, (TestSourceHeader(false, 10, 10), Some(TestFinalityProof(10)))), - ] - .into_iter() - .collect(), - ); - async_std::task::block_on(select_header_to_submit( - &source_client, - &target_client, - &mut RestartableFinalityProofsStream::from(futures::stream::empty().boxed()), - &mut vec![], - 10, - 5, - &FinalitySyncParams { - tick: Duration::from_secs(0), - recent_finality_proofs_limit: 0, - stall_timeout: Duration::from_secs(0), - only_mandatory_headers, - }, - )) - .unwrap() -} - -#[test] -fn select_header_to_submit_skips_non_mandatory_headers_when_only_mandatory_headers_are_required() { - assert_eq!(run_only_mandatory_headers_mode_test(true, false), None); - assert_eq!( - run_only_mandatory_headers_mode_test(false, false), - Some((TestSourceHeader(false, 10, 10), TestFinalityProof(10))), - ); -} - -#[test] -fn select_header_to_submit_selects_mandatory_headers_when_only_mandatory_headers_are_required() { - assert_eq!( - run_only_mandatory_headers_mode_test(true, true), - Some((TestSourceHeader(true, 8, 8), TestFinalityProof(8))), - ); - assert_eq!( - run_only_mandatory_headers_mode_test(false, true), - Some((TestSourceHeader(true, 8, 8), TestFinalityProof(8))), - ); -} - -#[test] -fn select_better_recent_finality_proof_works() { - // if there are no unjustified headers, nothing is changed - assert_eq!( - select_better_recent_finality_proof::( - &[(5, TestFinalityProof(5))], - &mut vec![], - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ); - - // if there are no recent finality proofs, nothing is changed - assert_eq!( - select_better_recent_finality_proof::( - &[], - &mut vec![TestSourceHeader(false, 5, 5)], - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ); - - // if there's no intersection between recent finality proofs and unjustified headers, nothing is - // changed - let mut unjustified_headers = - vec![TestSourceHeader(false, 9, 9), TestSourceHeader(false, 10, 10)]; - assert_eq!( - select_better_recent_finality_proof::( - &[(1, TestFinalityProof(1)), (4, TestFinalityProof(4))], - &mut unjustified_headers, - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ); - - // if there's intersection between recent finality proofs and unjustified headers, but there are - // no proofs in this intersection, nothing is changed - let mut unjustified_headers = vec![ - TestSourceHeader(false, 8, 8), - TestSourceHeader(false, 9, 9), - TestSourceHeader(false, 10, 10), - ]; - assert_eq!( - select_better_recent_finality_proof::( - &[(7, TestFinalityProof(7)), (11, TestFinalityProof(11))], - &mut unjustified_headers, - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ); - assert_eq!( - unjustified_headers, - vec![ - TestSourceHeader(false, 8, 8), - TestSourceHeader(false, 9, 9), - TestSourceHeader(false, 10, 10) - ] - ); - - // if there's intersection between recent finality proofs and unjustified headers and there's - // a proof in this intersection: - // - this better (last from intersection) proof is selected; - // - 'obsolete' unjustified headers are pruned. - let mut unjustified_headers = vec![ - TestSourceHeader(false, 8, 8), - TestSourceHeader(false, 9, 9), - TestSourceHeader(false, 10, 10), - ]; - assert_eq!( - select_better_recent_finality_proof::( - &[(7, TestFinalityProof(7)), (9, TestFinalityProof(9))], - &mut unjustified_headers, - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 9, 9), TestFinalityProof(9))), - ); -} - -#[test] -fn read_finality_proofs_from_stream_works() { - // when stream is currently empty, nothing is changed - let mut recent_finality_proofs = vec![(1, TestFinalityProof(1))]; - let mut stream = futures::stream::pending().into(); - read_finality_proofs_from_stream::( - &mut stream, - &mut recent_finality_proofs, - ); - assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1))]); - assert!(!stream.needs_restart); - - // when stream has entry with target, it is added to the recent proofs container - let mut stream = - futures::stream::iter(vec![TestFinalityProof(4)]).chain(futures::stream::pending()).into(); - read_finality_proofs_from_stream::( - &mut stream, - &mut recent_finality_proofs, - ); - assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))]); - assert!(!stream.needs_restart); - - // when stream has ended, we'll need to restart it - let mut stream = futures::stream::empty().into(); - read_finality_proofs_from_stream::( - &mut stream, - &mut recent_finality_proofs, - ); - assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))]); - assert!(stream.needs_restart); -} - -#[test] -fn prune_recent_finality_proofs_works() { - let original_recent_finality_proofs: FinalityProofs = vec![ - (10, TestFinalityProof(10)), - (13, TestFinalityProof(13)), - (15, TestFinalityProof(15)), - (17, TestFinalityProof(17)), - (19, TestFinalityProof(19)), - ] - .into_iter() - .collect(); - - // when there's proof for justified header in the vec - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(10, &mut recent_finality_proofs, 1024); - assert_eq!(&original_recent_finality_proofs[1..], recent_finality_proofs,); - - // when there are no proof for justified header in the vec - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(11, &mut recent_finality_proofs, 1024); - assert_eq!(&original_recent_finality_proofs[1..], recent_finality_proofs,); - - // when there are too many entries after initial prune && they also need to be pruned - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(10, &mut recent_finality_proofs, 2); - assert_eq!(&original_recent_finality_proofs[3..], recent_finality_proofs,); - - // when last entry is pruned - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(19, &mut recent_finality_proofs, 2); - assert_eq!(&original_recent_finality_proofs[5..], recent_finality_proofs,); - - // when post-last entry is pruned - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(20, &mut recent_finality_proofs, 2); - assert_eq!(&original_recent_finality_proofs[5..], recent_finality_proofs,); -} - -#[test] -fn different_forks_at_source_and_at_target_are_detected() { - let (exit_sender, _exit_receiver) = futures::channel::mpsc::unbounded(); - let (source_client, target_client) = prepare_test_clients( - exit_sender, - |_| false, - vec![ - (5, (TestSourceHeader(false, 5, 42), None)), - (6, (TestSourceHeader(false, 6, 6), None)), - (7, (TestSourceHeader(false, 7, 7), None)), - (8, (TestSourceHeader(false, 8, 8), None)), - (9, (TestSourceHeader(false, 9, 9), None)), - (10, (TestSourceHeader(false, 10, 10), None)), - ] - .into_iter() - .collect(), - ); - - let mut progress = (Instant::now(), None); - let mut finality_proofs_stream = RestartableFinalityProofsStream { - needs_restart: false, - stream: Box::pin(futures::stream::iter(vec![]).boxed()), - }; - let mut recent_finality_proofs = Vec::new(); - let metrics_sync = SyncLoopMetrics::new(None, "source", "target").unwrap(); - async_std::task::block_on(run_loop_iteration::( - &source_client, - &target_client, - FinalityLoopState { - progress: &mut progress, - finality_proofs_stream: &mut finality_proofs_stream, - recent_finality_proofs: &mut recent_finality_proofs, - last_transaction: None, - }, - &test_sync_params(), - &Some(metrics_sync.clone()), - )) - .unwrap(); - - assert!(!metrics_sync.is_using_same_fork()); -} diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs deleted file mode 100644 index 49be64ff7..000000000 --- a/relays/finality/src/lib.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! This crate has single entrypoint to run synchronization loop that is built around finality -//! proofs, as opposed to headers synchronization loop, which is built around headers. The headers -//! are still submitted to the target node, but are treated as auxiliary data as we are not trying -//! to submit all source headers to the target node. - -pub use crate::{ - finality_loop::{metrics_prefix, run, FinalitySyncParams, SourceClient, TargetClient}, - sync_loop_metrics::SyncLoopMetrics, -}; - -use bp_header_chain::FinalityProof; -use std::fmt::Debug; - -mod finality_loop; -mod finality_loop_tests; -mod sync_loop_metrics; - -/// Finality proofs synchronization pipeline. -pub trait FinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { - /// Name of the finality proofs source. - const SOURCE_NAME: &'static str; - /// Name of the finality proofs target. - const TARGET_NAME: &'static str; - - /// Headers we're syncing are identified by this hash. - type Hash: Eq + Clone + Copy + Send + Sync + Debug; - /// Headers we're syncing are identified by this number. - type Number: relay_utils::BlockNumberBase; - /// Type of header that we're syncing. - type Header: SourceHeader; - /// Finality proof type. - type FinalityProof: FinalityProof; -} - -/// Header that we're receiving from source node. -pub trait SourceHeader: Clone + Debug + PartialEq + Send + Sync { - /// Returns hash of header. - fn hash(&self) -> Hash; - /// Returns number of header. - fn number(&self) -> Number; - /// Returns true if this header needs to be submitted to target node. - fn is_mandatory(&self) -> bool; -} diff --git a/relays/finality/src/sync_loop_metrics.rs b/relays/finality/src/sync_loop_metrics.rs deleted file mode 100644 index a003a47d8..000000000 --- a/relays/finality/src/sync_loop_metrics.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Metrics for headers synchronization relay loop. - -use relay_utils::metrics::{metric_name, register, IntGauge, Metric, PrometheusError, Registry}; - -/// Headers sync metrics. -#[derive(Clone)] -pub struct SyncLoopMetrics { - /// Best syncing header at the source. - best_source_block_number: IntGauge, - /// Best syncing header at the target. - best_target_block_number: IntGauge, - /// Flag that has `0` value when best source headers at the source node and at-target-chain - /// are matching and `1` otherwise. - using_different_forks: IntGauge, -} - -impl SyncLoopMetrics { - /// Create and register headers loop metrics. - pub fn new( - prefix: Option<&str>, - at_source_chain_label: &str, - at_target_chain_label: &str, - ) -> Result { - Ok(SyncLoopMetrics { - best_source_block_number: IntGauge::new( - metric_name(prefix, &format!("best_{}_block_number", at_source_chain_label)), - format!("Best block number at the {}", at_source_chain_label), - )?, - best_target_block_number: IntGauge::new( - metric_name(prefix, &format!("best_{}_block_number", at_target_chain_label)), - format!("Best block number at the {}", at_target_chain_label), - )?, - using_different_forks: IntGauge::new( - metric_name(prefix, &format!("is_{}_and_{}_using_different_forks", at_source_chain_label, at_target_chain_label)), - "Whether the best finalized source block at target node is different (value 1) from the \ - corresponding block at the source node", - )?, - }) - } - - /// Returns current value of the using-same-fork flag. - #[cfg(test)] - pub(crate) fn is_using_same_fork(&self) -> bool { - self.using_different_forks.get() == 0 - } - - /// Update best block number at source. - pub fn update_best_block_at_source>(&self, source_best_number: Number) { - self.best_source_block_number.set(source_best_number.into()); - } - - /// Update best block number at target. - pub fn update_best_block_at_target>(&self, target_best_number: Number) { - self.best_target_block_number.set(target_best_number.into()); - } - - /// Update using-same-fork flag. - pub fn update_using_same_fork(&self, using_same_fork: bool) { - self.using_different_forks.set(if using_same_fork { 0 } else { 1 }) - } -} - -impl Metric for SyncLoopMetrics { - fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - register(self.best_source_block_number.clone(), registry)?; - register(self.best_target_block_number.clone(), registry)?; - register(self.using_different_forks.clone(), registry)?; - Ok(()) - } -} diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml deleted file mode 100644 index b2845afc2..000000000 --- a/relays/messages/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "messages-relay" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1.40" -futures = "0.3.5" -hex = "0.4" -log = "0.4.11" -num-traits = "0.2" -parking_lot = "0.11.0" - -# Bridge Dependencies - -bp-messages = { path = "../../primitives/messages" } -bp-runtime = { path = "../../primitives/runtime" } -finality-relay = { path = "../finality" } -relay-utils = { path = "../utils" } - -sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } diff --git a/relays/messages/src/lib.rs b/relays/messages/src/lib.rs deleted file mode 100644 index c9e460300..000000000 --- a/relays/messages/src/lib.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Relaying [`pallet-bridge-messages`](../pallet_bridge_messages/index.html) application specific -//! data. Message lane allows sending arbitrary messages between bridged chains. This -//! module provides entrypoint that starts reading messages from given message lane -//! of source chain and submits proof-of-message-at-source-chain transactions to the -//! target chain. Additionally, proofs-of-messages-delivery are sent back from the -//! target chain to the source chain. - -// required for futures::select! -#![recursion_limit = "1024"] -#![warn(missing_docs)] - -mod metrics; - -pub mod message_lane; -pub mod message_lane_loop; -pub mod relay_strategy; - -mod message_race_delivery; -mod message_race_loop; -mod message_race_receiving; -mod message_race_strategy; diff --git a/relays/messages/src/message_lane.rs b/relays/messages/src/message_lane.rs deleted file mode 100644 index 5c9728ad9..000000000 --- a/relays/messages/src/message_lane.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! One-way message lane types. Within single one-way lane we have three 'races' where we try to: -//! -//! 1) relay new messages from source to target node; -//! 2) relay proof-of-delivery from target to source node. - -use num_traits::{SaturatingAdd, Zero}; -use relay_utils::{BlockNumberBase, HeaderId}; -use sp_arithmetic::traits::AtLeast32BitUnsigned; -use std::{fmt::Debug, ops::Sub}; - -/// One-way message lane. -pub trait MessageLane: 'static + Clone + Send + Sync { - /// Name of the messages source. - const SOURCE_NAME: &'static str; - /// Name of the messages target. - const TARGET_NAME: &'static str; - - /// Messages proof. - type MessagesProof: Clone + Debug + Send + Sync; - /// Messages receiving proof. - type MessagesReceivingProof: Clone + Debug + Send + Sync; - - /// The type of the source chain token balance, that is used to: - /// - /// 1) pay transaction fees; - /// 2) pay message delivery and dispatch fee; - /// 3) pay relayer rewards. - type SourceChainBalance: AtLeast32BitUnsigned - + Clone - + Copy - + Debug - + PartialOrd - + Sub - + SaturatingAdd - + Zero - + Send - + Sync; - /// Number of the source header. - type SourceHeaderNumber: BlockNumberBase; - /// Hash of the source header. - type SourceHeaderHash: Clone + Debug + Default + PartialEq + Send + Sync; - - /// Number of the target header. - type TargetHeaderNumber: BlockNumberBase; - /// Hash of the target header. - type TargetHeaderHash: Clone + Debug + Default + PartialEq + Send + Sync; -} - -/// Source header id within given one-way message lane. -pub type SourceHeaderIdOf

= - HeaderId<

::SourceHeaderHash,

::SourceHeaderNumber>; - -/// Target header id within given one-way message lane. -pub type TargetHeaderIdOf

= - HeaderId<

::TargetHeaderHash,

::TargetHeaderNumber>; diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs deleted file mode 100644 index 5764be3fb..000000000 --- a/relays/messages/src/message_lane_loop.rs +++ /dev/null @@ -1,966 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Message delivery loop. Designed to work with messages pallet. -//! -//! Single relay instance delivers messages of single lane in single direction. -//! To serve two-way lane, you would need two instances of relay. -//! To serve N two-way lanes, you would need N*2 instances of relay. -//! -//! Please keep in mind that the best header in this file is actually best -//! finalized header. I.e. when talking about headers in lane context, we -//! only care about finalized headers. - -use std::{collections::BTreeMap, fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; - -use async_trait::async_trait; -use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; - -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; -use bp_runtime::messages::DispatchFeePayment; -use relay_utils::{ - interval, metrics::MetricsParams, process_future_result, relay_loop::Client as RelayClient, - retry_backoff, FailedClient, -}; - -use crate::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - message_race_delivery::run as run_message_delivery_race, - message_race_receiving::run as run_message_receiving_race, - metrics::MessageLaneLoopMetrics, - relay_strategy::RelayStrategy, -}; - -/// Message lane loop configuration params. -#[derive(Debug, Clone)] -pub struct Params { - /// Id of lane this loop is servicing. - pub lane: LaneId, - /// Interval at which we ask target node about its updates. - pub source_tick: Duration, - /// Interval at which we ask target node about its updates. - pub target_tick: Duration, - /// Delay between moments when connection error happens and our reconnect attempt. - pub reconnect_delay: Duration, - /// The loop will auto-restart if there has been no updates during this period. - pub stall_timeout: Duration, - /// Message delivery race parameters. - pub delivery_params: MessageDeliveryParams, -} - -/// Relayer operating mode. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum RelayerMode { - /// The relayer doesn't care about rewards. - Altruistic, - /// The relayer will deliver all messages and confirmations as long as he's not losing any - /// funds. - Rational, -} - -/// Message delivery race parameters. -#[derive(Debug, Clone)] -pub struct MessageDeliveryParams { - /// Maximal number of unconfirmed relayer entries at the inbound lane. If there's that number - /// of entries in the `InboundLaneData::relayers` set, all new messages will be rejected until - /// reward payment will be proved (by including outbound lane state to the message delivery - /// transaction). - pub max_unrewarded_relayer_entries_at_target: MessageNonce, - /// Message delivery race will stop delivering messages if there are - /// `max_unconfirmed_nonces_at_target` unconfirmed nonces on the target node. The race would - /// continue once they're confirmed by the receiving race. - pub max_unconfirmed_nonces_at_target: MessageNonce, - /// Maximal number of relayed messages in single delivery transaction. - pub max_messages_in_single_batch: MessageNonce, - /// Maximal cumulative dispatch weight of relayed messages in single delivery transaction. - pub max_messages_weight_in_single_batch: Weight, - /// Maximal cumulative size of relayed messages in single delivery transaction. - pub max_messages_size_in_single_batch: u32, - /// Relay strategy - pub relay_strategy: Strategy, -} - -/// Message details. -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct MessageDetails { - /// Message dispatch weight. - pub dispatch_weight: Weight, - /// Message size (number of bytes in encoded payload). - pub size: u32, - /// The relayer reward paid in the source chain tokens. - pub reward: SourceChainBalance, - /// Where the fee for dispatching message is paid? - pub dispatch_fee_payment: DispatchFeePayment, -} - -/// Messages details map. -pub type MessageDetailsMap = - BTreeMap>; - -/// Message delivery race proof parameters. -#[derive(Debug, PartialEq)] -pub struct MessageProofParameters { - /// Include outbound lane state proof? - pub outbound_state_proof_required: bool, - /// Cumulative dispatch weight of messages that we're building proof for. - pub dispatch_weight: Weight, -} - -/// Source client trait. -#[async_trait] -pub trait SourceClient: RelayClient { - /// Returns state of the client. - async fn state(&self) -> Result, Self::Error>; - - /// Get nonce of instance of latest generated message. - async fn latest_generated_nonce( - &self, - id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error>; - - /// Get nonce of the latest message, which receiving has been confirmed by the target chain. - async fn latest_confirmed_received_nonce( - &self, - id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error>; - - /// Returns mapping of message nonces, generated on this client, to their weights. - /// - /// Some messages may be missing from returned map, if corresponding messages were pruned at - /// the source chain. - async fn generated_message_details( - &self, - id: SourceHeaderIdOf

, - nonces: RangeInclusive, - ) -> Result, Self::Error>; - - /// Prove messages in inclusive range [begin; end]. - async fn prove_messages( - &self, - id: SourceHeaderIdOf

, - nonces: RangeInclusive, - proof_parameters: MessageProofParameters, - ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error>; - - /// Submit messages receiving proof. - async fn submit_messages_receiving_proof( - &self, - generated_at_block: TargetHeaderIdOf

, - proof: P::MessagesReceivingProof, - ) -> Result<(), Self::Error>; - - /// We need given finalized target header on source to continue synchronization. - async fn require_target_header_on_source(&self, id: TargetHeaderIdOf

); - - /// Estimate cost of single message confirmation transaction in source chain tokens. - async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance; -} - -/// Target client trait. -#[async_trait] -pub trait TargetClient: RelayClient { - /// Returns state of the client. - async fn state(&self) -> Result, Self::Error>; - - /// Get nonce of latest received message. - async fn latest_received_nonce( - &self, - id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error>; - - /// Get nonce of the latest confirmed message. - async fn latest_confirmed_received_nonce( - &self, - id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error>; - - /// Get state of unrewarded relayers set at the inbound lane. - async fn unrewarded_relayers_state( - &self, - id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, UnrewardedRelayersState), Self::Error>; - - /// Prove messages receiving at given block. - async fn prove_messages_receiving( - &self, - id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), Self::Error>; - - /// Submit messages proof. - async fn submit_messages_proof( - &self, - generated_at_header: SourceHeaderIdOf

, - nonces: RangeInclusive, - proof: P::MessagesProof, - ) -> Result, Self::Error>; - - /// We need given finalized source header on target to continue synchronization. - async fn require_source_header_on_target(&self, id: SourceHeaderIdOf

); - - /// Estimate cost of messages delivery transaction in source chain tokens. - /// - /// Please keep in mind that the returned cost must be converted to the source chain - /// tokens, even though the transaction fee will be paid in the target chain tokens. - async fn estimate_delivery_transaction_in_source_tokens( - &self, - nonces: RangeInclusive, - total_prepaid_nonces: MessageNonce, - total_dispatch_weight: Weight, - total_size: u32, - ) -> Result; -} - -/// State of the client. -#[derive(Clone, Debug, Default, PartialEq)] -pub struct ClientState { - /// The best header id of this chain. - pub best_self: SelfHeaderId, - /// Best finalized header id of this chain. - pub best_finalized_self: SelfHeaderId, - /// Best finalized header id of the peer chain read at the best block of this chain (at - /// `best_finalized_self`). - pub best_finalized_peer_at_best_self: PeerHeaderId, - /// Header id of the peer chain with the number, matching the - /// `best_finalized_peer_at_best_self`. - pub actual_best_finalized_peer_at_best_self: PeerHeaderId, -} - -/// State of source client in one-way message lane. -pub type SourceClientState

= ClientState, TargetHeaderIdOf

>; - -/// State of target client in one-way message lane. -pub type TargetClientState

= ClientState, SourceHeaderIdOf

>; - -/// Both clients state. -#[derive(Debug, Default)] -pub struct ClientsState { - /// Source client state. - pub source: Option>, - /// Target client state. - pub target: Option>, -} - -/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs -/// sync loop. -pub fn metrics_prefix(lane: &LaneId) -> String { - format!("{}_to_{}_MessageLane_{}", P::SOURCE_NAME, P::TARGET_NAME, hex::encode(lane)) -} - -/// Run message lane service loop. -pub async fn run( - params: Params, - source_client: impl SourceClient

, - target_client: impl TargetClient

, - metrics_params: MetricsParams, - exit_signal: impl Future + Send + 'static, -) -> Result<(), relay_utils::Error> { - let exit_signal = exit_signal.shared(); - relay_utils::relay_loop(source_client, target_client) - .reconnect_delay(params.reconnect_delay) - .with_metrics(metrics_params) - .loop_metric(MessageLaneLoopMetrics::new(Some(&metrics_prefix::

(¶ms.lane)))?)? - .expose() - .await? - .run(metrics_prefix::

(¶ms.lane), move |source_client, target_client, metrics| { - run_until_connection_lost( - params.clone(), - source_client, - target_client, - metrics, - exit_signal.clone(), - ) - }) - .await -} - -/// Run one-way message delivery loop until connection with target or source node is lost, or exit -/// signal is received. -async fn run_until_connection_lost< - P: MessageLane, - Strategy: RelayStrategy, - SC: SourceClient

, - TC: TargetClient

, ->( - params: Params, - source_client: SC, - target_client: TC, - metrics_msg: Option, - exit_signal: impl Future, -) -> Result<(), FailedClient> { - let mut source_retry_backoff = retry_backoff(); - let mut source_client_is_online = false; - let mut source_state_required = true; - let source_state = source_client.state().fuse(); - let source_go_offline_future = futures::future::Fuse::terminated(); - let source_tick_stream = interval(params.source_tick).fuse(); - - let mut target_retry_backoff = retry_backoff(); - let mut target_client_is_online = false; - let mut target_state_required = true; - let target_state = target_client.state().fuse(); - let target_go_offline_future = futures::future::Fuse::terminated(); - let target_tick_stream = interval(params.target_tick).fuse(); - - let ( - (delivery_source_state_sender, delivery_source_state_receiver), - (delivery_target_state_sender, delivery_target_state_receiver), - ) = (unbounded(), unbounded()); - let delivery_race_loop = run_message_delivery_race( - source_client.clone(), - delivery_source_state_receiver, - target_client.clone(), - delivery_target_state_receiver, - params.stall_timeout, - metrics_msg.clone(), - params.delivery_params, - ) - .fuse(); - - let ( - (receiving_source_state_sender, receiving_source_state_receiver), - (receiving_target_state_sender, receiving_target_state_receiver), - ) = (unbounded(), unbounded()); - let receiving_race_loop = run_message_receiving_race( - source_client.clone(), - receiving_source_state_receiver, - target_client.clone(), - receiving_target_state_receiver, - params.stall_timeout, - metrics_msg.clone(), - ) - .fuse(); - - let exit_signal = exit_signal.fuse(); - - futures::pin_mut!( - source_state, - source_go_offline_future, - source_tick_stream, - target_state, - target_go_offline_future, - target_tick_stream, - delivery_race_loop, - receiving_race_loop, - exit_signal - ); - - loop { - futures::select! { - new_source_state = source_state => { - source_state_required = false; - - source_client_is_online = process_future_result( - new_source_state, - &mut source_retry_backoff, - |new_source_state| { - log::debug!( - target: "bridge", - "Received state from {} node: {:?}", - P::SOURCE_NAME, - new_source_state, - ); - let _ = delivery_source_state_sender.unbounded_send(new_source_state.clone()); - let _ = receiving_source_state_sender.unbounded_send(new_source_state.clone()); - - if let Some(metrics_msg) = metrics_msg.as_ref() { - metrics_msg.update_source_state::

(new_source_state); - } - }, - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving state from {} node", P::SOURCE_NAME), - ).fail_if_connection_error(FailedClient::Source)?; - }, - _ = source_go_offline_future => { - source_client_is_online = true; - }, - _ = source_tick_stream.next() => { - source_state_required = true; - }, - new_target_state = target_state => { - target_state_required = false; - - target_client_is_online = process_future_result( - new_target_state, - &mut target_retry_backoff, - |new_target_state| { - log::debug!( - target: "bridge", - "Received state from {} node: {:?}", - P::TARGET_NAME, - new_target_state, - ); - let _ = delivery_target_state_sender.unbounded_send(new_target_state.clone()); - let _ = receiving_target_state_sender.unbounded_send(new_target_state.clone()); - - if let Some(metrics_msg) = metrics_msg.as_ref() { - metrics_msg.update_target_state::

(new_target_state); - } - }, - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving state from {} node", P::TARGET_NAME), - ).fail_if_connection_error(FailedClient::Target)?; - }, - _ = target_go_offline_future => { - target_client_is_online = true; - }, - _ = target_tick_stream.next() => { - target_state_required = true; - }, - - delivery_error = delivery_race_loop => { - match delivery_error { - Ok(_) => unreachable!("only ends with error; qed"), - Err(err) => return Err(err), - } - }, - receiving_error = receiving_race_loop => { - match receiving_error { - Ok(_) => unreachable!("only ends with error; qed"), - Err(err) => return Err(err), - } - }, - - () = exit_signal => { - return Ok(()); - } - } - - if source_client_is_online && source_state_required { - log::debug!(target: "bridge", "Asking {} node about its state", P::SOURCE_NAME); - source_state.set(source_client.state().fuse()); - source_client_is_online = false; - } - - if target_client_is_online && target_state_required { - log::debug!(target: "bridge", "Asking {} node about its state", P::TARGET_NAME); - target_state.set(target_client.state().fuse()); - target_client_is_online = false; - } - } -} - -#[cfg(test)] -pub(crate) mod tests { - use std::sync::Arc; - - use futures::stream::StreamExt; - use parking_lot::Mutex; - - use relay_utils::{HeaderId, MaybeConnectionError}; - - use crate::relay_strategy::AltruisticStrategy; - - use super::*; - - pub fn header_id(number: TestSourceHeaderNumber) -> TestSourceHeaderId { - HeaderId(number, number) - } - - pub const CONFIRMATION_TRANSACTION_COST: TestSourceChainBalance = 1; - pub const BASE_MESSAGE_DELIVERY_TRANSACTION_COST: TestSourceChainBalance = 1; - - pub type TestSourceChainBalance = u64; - pub type TestSourceHeaderId = HeaderId; - pub type TestTargetHeaderId = HeaderId; - - pub type TestMessagesProof = (RangeInclusive, Option); - pub type TestMessagesReceivingProof = MessageNonce; - - pub type TestSourceHeaderNumber = u64; - pub type TestSourceHeaderHash = u64; - - pub type TestTargetHeaderNumber = u64; - pub type TestTargetHeaderHash = u64; - - #[derive(Debug)] - pub struct TestError; - - impl MaybeConnectionError for TestError { - fn is_connection_error(&self) -> bool { - true - } - } - - #[derive(Clone)] - pub struct TestMessageLane; - - impl MessageLane for TestMessageLane { - type MessagesProof = TestMessagesProof; - type MessagesReceivingProof = TestMessagesReceivingProof; - type SourceChainBalance = TestSourceChainBalance; - type SourceHeaderHash = TestSourceHeaderHash; - type SourceHeaderNumber = TestSourceHeaderNumber; - type TargetHeaderHash = TestTargetHeaderHash; - type TargetHeaderNumber = TestTargetHeaderNumber; - - const SOURCE_NAME: &'static str = "TestSource"; - const TARGET_NAME: &'static str = "TestTarget"; - } - - #[derive(Debug, Default, Clone)] - pub struct TestClientData { - is_source_fails: bool, - is_source_reconnected: bool, - source_state: SourceClientState, - source_latest_generated_nonce: MessageNonce, - source_latest_confirmed_received_nonce: MessageNonce, - submitted_messages_receiving_proofs: Vec, - is_target_fails: bool, - is_target_reconnected: bool, - target_state: SourceClientState, - target_latest_received_nonce: MessageNonce, - target_latest_confirmed_received_nonce: MessageNonce, - submitted_messages_proofs: Vec, - target_to_source_header_required: Option, - target_to_source_header_requirements: Vec, - source_to_target_header_required: Option, - source_to_target_header_requirements: Vec, - } - - #[derive(Clone)] - pub struct TestSourceClient { - data: Arc>, - tick: Arc, - } - - impl Default for TestSourceClient { - fn default() -> Self { - TestSourceClient { - data: Arc::new(Mutex::new(TestClientData::default())), - tick: Arc::new(|_| {}), - } - } - } - - #[async_trait] - impl RelayClient for TestSourceClient { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - data.is_source_reconnected = true; - } - Ok(()) - } - } - - #[async_trait] - impl SourceClient for TestSourceClient { - async fn state(&self) -> Result, TestError> { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - if data.is_source_fails { - return Err(TestError); - } - Ok(data.source_state.clone()) - } - - async fn latest_generated_nonce( - &self, - id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), TestError> { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - if data.is_source_fails { - return Err(TestError); - } - Ok((id, data.source_latest_generated_nonce)) - } - - async fn latest_confirmed_received_nonce( - &self, - id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), TestError> { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - Ok((id, data.source_latest_confirmed_received_nonce)) - } - - async fn generated_message_details( - &self, - _id: SourceHeaderIdOf, - nonces: RangeInclusive, - ) -> Result, TestError> { - Ok(nonces - .map(|nonce| { - ( - nonce, - MessageDetails { - dispatch_weight: 1, - size: 1, - reward: 1, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - }, - ) - }) - .collect()) - } - - async fn prove_messages( - &self, - id: SourceHeaderIdOf, - nonces: RangeInclusive, - proof_parameters: MessageProofParameters, - ) -> Result< - (SourceHeaderIdOf, RangeInclusive, TestMessagesProof), - TestError, - > { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - Ok(( - id, - nonces.clone(), - ( - nonces, - if proof_parameters.outbound_state_proof_required { - Some(data.source_latest_confirmed_received_nonce) - } else { - None - }, - ), - )) - } - - async fn submit_messages_receiving_proof( - &self, - _generated_at_block: TargetHeaderIdOf, - proof: TestMessagesReceivingProof, - ) -> Result<(), TestError> { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - data.source_state.best_self = - HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1); - data.source_state.best_finalized_self = data.source_state.best_self; - data.submitted_messages_receiving_proofs.push(proof); - data.source_latest_confirmed_received_nonce = proof; - Ok(()) - } - - async fn require_target_header_on_source(&self, id: TargetHeaderIdOf) { - let mut data = self.data.lock(); - data.target_to_source_header_required = Some(id); - data.target_to_source_header_requirements.push(id); - (self.tick)(&mut *data); - } - - async fn estimate_confirmation_transaction(&self) -> TestSourceChainBalance { - CONFIRMATION_TRANSACTION_COST - } - } - - #[derive(Clone)] - pub struct TestTargetClient { - data: Arc>, - tick: Arc, - } - - impl Default for TestTargetClient { - fn default() -> Self { - TestTargetClient { - data: Arc::new(Mutex::new(TestClientData::default())), - tick: Arc::new(|_| {}), - } - } - } - - #[async_trait] - impl RelayClient for TestTargetClient { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - data.is_target_reconnected = true; - } - Ok(()) - } - } - - #[async_trait] - impl TargetClient for TestTargetClient { - async fn state(&self) -> Result, TestError> { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - if data.is_target_fails { - return Err(TestError); - } - Ok(data.target_state.clone()) - } - - async fn latest_received_nonce( - &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), TestError> { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - if data.is_target_fails { - return Err(TestError); - } - Ok((id, data.target_latest_received_nonce)) - } - - async fn unrewarded_relayers_state( - &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, UnrewardedRelayersState), TestError> { - Ok(( - id, - UnrewardedRelayersState { - unrewarded_relayer_entries: 0, - messages_in_oldest_entry: 0, - total_messages: 0, - }, - )) - } - - async fn latest_confirmed_received_nonce( - &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), TestError> { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - if data.is_target_fails { - return Err(TestError); - } - Ok((id, data.target_latest_confirmed_received_nonce)) - } - - async fn prove_messages_receiving( - &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, TestMessagesReceivingProof), TestError> { - Ok((id, self.data.lock().target_latest_received_nonce)) - } - - async fn submit_messages_proof( - &self, - _generated_at_header: SourceHeaderIdOf, - nonces: RangeInclusive, - proof: TestMessagesProof, - ) -> Result, TestError> { - let mut data = self.data.lock(); - (self.tick)(&mut *data); - if data.is_target_fails { - return Err(TestError); - } - data.target_state.best_self = - HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); - data.target_state.best_finalized_self = data.target_state.best_self; - data.target_latest_received_nonce = *proof.0.end(); - if let Some(target_latest_confirmed_received_nonce) = proof.1 { - data.target_latest_confirmed_received_nonce = - target_latest_confirmed_received_nonce; - } - data.submitted_messages_proofs.push(proof); - Ok(nonces) - } - - async fn require_source_header_on_target(&self, id: SourceHeaderIdOf) { - let mut data = self.data.lock(); - data.source_to_target_header_required = Some(id); - data.source_to_target_header_requirements.push(id); - (self.tick)(&mut *data); - } - - async fn estimate_delivery_transaction_in_source_tokens( - &self, - nonces: RangeInclusive, - _total_prepaid_nonces: MessageNonce, - total_dispatch_weight: Weight, - total_size: u32, - ) -> Result { - Ok(BASE_MESSAGE_DELIVERY_TRANSACTION_COST * (nonces.end() - nonces.start() + 1) - + total_dispatch_weight - + total_size as TestSourceChainBalance) - } - } - - fn run_loop_test( - data: TestClientData, - source_tick: Arc, - target_tick: Arc, - exit_signal: impl Future + 'static + Send, - ) -> TestClientData { - async_std::task::block_on(async { - let data = Arc::new(Mutex::new(data)); - - let source_client = TestSourceClient { data: data.clone(), tick: source_tick }; - let target_client = TestTargetClient { data: data.clone(), tick: target_tick }; - let _ = run( - Params { - lane: [0, 0, 0, 0], - source_tick: Duration::from_millis(100), - target_tick: Duration::from_millis(100), - reconnect_delay: Duration::from_millis(0), - stall_timeout: Duration::from_millis(60 * 1000), - delivery_params: MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: 4, - max_unconfirmed_nonces_at_target: 4, - max_messages_in_single_batch: 4, - max_messages_weight_in_single_batch: 4, - max_messages_size_in_single_batch: 4, - relay_strategy: AltruisticStrategy, - }, - }, - source_client, - target_client, - MetricsParams::disabled(), - exit_signal, - ) - .await; - let result = data.lock().clone(); - result - }) - } - - #[test] - fn message_lane_loop_is_able_to_recover_from_connection_errors() { - // with this configuration, source client will return Err, making source client - // reconnect. Then the target client will fail with Err + reconnect. Then we finally - // able to deliver messages. - let (exit_sender, exit_receiver) = unbounded(); - let result = run_loop_test( - TestClientData { - is_source_fails: true, - source_state: ClientState { - best_self: HeaderId(0, 0), - best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), - }, - source_latest_generated_nonce: 1, - target_state: ClientState { - best_self: HeaderId(0, 0), - best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), - }, - target_latest_received_nonce: 0, - ..Default::default() - }, - Arc::new(|data: &mut TestClientData| { - if data.is_source_reconnected { - data.is_source_fails = false; - data.is_target_fails = true; - } - }), - Arc::new(move |data: &mut TestClientData| { - if data.is_target_reconnected { - data.is_target_fails = false; - } - if data.target_state.best_finalized_peer_at_best_self.0 < 10 { - data.target_state.best_finalized_peer_at_best_self = HeaderId( - data.target_state.best_finalized_peer_at_best_self.0 + 1, - data.target_state.best_finalized_peer_at_best_self.0 + 1, - ); - } - if !data.submitted_messages_proofs.is_empty() { - exit_sender.unbounded_send(()).unwrap(); - } - }), - exit_receiver.into_future().map(|(_, _)| ()), - ); - - assert_eq!(result.submitted_messages_proofs, vec![(1..=1, None)],); - } - - #[test] - fn message_lane_loop_works() { - let (exit_sender, exit_receiver) = unbounded(); - let result = run_loop_test( - TestClientData { - source_state: ClientState { - best_self: HeaderId(10, 10), - best_finalized_self: HeaderId(10, 10), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), - }, - source_latest_generated_nonce: 10, - target_state: ClientState { - best_self: HeaderId(0, 0), - best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), - }, - target_latest_received_nonce: 0, - ..Default::default() - }, - Arc::new(|data: &mut TestClientData| { - // blocks are produced on every tick - data.source_state.best_self = - HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1); - data.source_state.best_finalized_self = data.source_state.best_self; - // headers relay must only be started when we need new target headers at source node - if data.target_to_source_header_required.is_some() { - assert!( - data.source_state.best_finalized_peer_at_best_self.0 - < data.target_state.best_self.0 - ); - data.target_to_source_header_required = None; - } - // syncing target headers -> source chain - if let Some(last_requirement) = data.target_to_source_header_requirements.last() { - if *last_requirement != data.source_state.best_finalized_peer_at_best_self { - data.source_state.best_finalized_peer_at_best_self = *last_requirement; - } - } - }), - Arc::new(move |data: &mut TestClientData| { - // blocks are produced on every tick - data.target_state.best_self = - HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); - data.target_state.best_finalized_self = data.target_state.best_self; - // headers relay must only be started when we need new source headers at target node - if data.source_to_target_header_required.is_some() { - assert!( - data.target_state.best_finalized_peer_at_best_self.0 - < data.source_state.best_self.0 - ); - data.source_to_target_header_required = None; - } - // syncing source headers -> target chain - if let Some(last_requirement) = data.source_to_target_header_requirements.last() { - if *last_requirement != data.target_state.best_finalized_peer_at_best_self { - data.target_state.best_finalized_peer_at_best_self = *last_requirement; - } - } - // if source has received all messages receiving confirmations => stop - if data.source_latest_confirmed_received_nonce == 10 { - exit_sender.unbounded_send(()).unwrap(); - } - }), - exit_receiver.into_future().map(|(_, _)| ()), - ); - - // there are no strict restrictions on when reward confirmation should come - // (because `max_unconfirmed_nonces_at_target` is `100` in tests and this confirmation - // depends on the state of both clients) - // => we do not check it here - assert_eq!(result.submitted_messages_proofs[0].0, 1..=4); - assert_eq!(result.submitted_messages_proofs[1].0, 5..=8); - assert_eq!(result.submitted_messages_proofs[2].0, 9..=10); - assert!(!result.submitted_messages_receiving_proofs.is_empty()); - - // check that we have at least once required new source->target or target->source headers - assert!(!result.target_to_source_header_requirements.is_empty()); - assert!(!result.source_to_target_header_requirements.is_empty()); - } -} diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs deleted file mode 100644 index 896e37075..000000000 --- a/relays/messages/src/message_race_delivery.rs +++ /dev/null @@ -1,1071 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -//! Message delivery race delivers proof-of-messages from "lane.source" to "lane.target". - -use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; - -use async_trait::async_trait; -use futures::stream::FusedStream; - -use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight}; -use relay_utils::FailedClient; - -use crate::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - message_lane_loop::{ - MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, - SourceClient as MessageLaneSourceClient, SourceClientState, - TargetClient as MessageLaneTargetClient, TargetClientState, - }, - message_race_loop::{ - MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces, - TargetClient, TargetClientNonces, - }, - message_race_strategy::BasicStrategy, - metrics::MessageLaneLoopMetrics, - relay_strategy::{EnforcementStrategy, RelayMessagesBatchReference, RelayStrategy}, -}; - -/// Run message delivery race. -pub async fn run( - source_client: impl MessageLaneSourceClient

, - source_state_updates: impl FusedStream>, - target_client: impl MessageLaneTargetClient

, - target_state_updates: impl FusedStream>, - stall_timeout: Duration, - metrics_msg: Option, - params: MessageDeliveryParams, -) -> Result<(), FailedClient> { - crate::message_race_loop::run( - MessageDeliveryRaceSource { - client: source_client.clone(), - metrics_msg: metrics_msg.clone(), - _phantom: Default::default(), - }, - source_state_updates, - MessageDeliveryRaceTarget { - client: target_client.clone(), - metrics_msg, - _phantom: Default::default(), - }, - target_state_updates, - stall_timeout, - MessageDeliveryStrategy:: { - lane_source_client: source_client, - lane_target_client: target_client, - max_unrewarded_relayer_entries_at_target: params - .max_unrewarded_relayer_entries_at_target, - max_unconfirmed_nonces_at_target: params.max_unconfirmed_nonces_at_target, - max_messages_in_single_batch: params.max_messages_in_single_batch, - max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, - max_messages_size_in_single_batch: params.max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - latest_confirmed_nonces_at_source: VecDeque::new(), - target_nonces: None, - strategy: BasicStrategy::new(), - }, - ) - .await -} - -/// Message delivery race. -struct MessageDeliveryRace

(std::marker::PhantomData

); - -impl MessageRace for MessageDeliveryRace

{ - type MessageNonce = MessageNonce; - type Proof = P::MessagesProof; - type SourceHeaderId = SourceHeaderIdOf

; - type TargetHeaderId = TargetHeaderIdOf

; - - fn source_name() -> String { - format!("{}::MessagesDelivery", P::SOURCE_NAME) - } - - fn target_name() -> String { - format!("{}::MessagesDelivery", P::TARGET_NAME) - } -} - -/// Message delivery race source, which is a source of the lane. -struct MessageDeliveryRaceSource { - client: C, - metrics_msg: Option, - _phantom: PhantomData

, -} - -#[async_trait] -impl SourceClient> for MessageDeliveryRaceSource -where - P: MessageLane, - C: MessageLaneSourceClient

, -{ - type Error = C::Error; - type NoncesRange = MessageDetailsMap; - type ProofParameters = MessageProofParameters; - - async fn nonces( - &self, - at_block: SourceHeaderIdOf

, - prev_latest_nonce: MessageNonce, - ) -> Result<(SourceHeaderIdOf

, SourceClientNonces), Self::Error> { - let (at_block, latest_generated_nonce) = - self.client.latest_generated_nonce(at_block).await?; - let (at_block, latest_confirmed_nonce) = - self.client.latest_confirmed_received_nonce(at_block).await?; - - if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_source_latest_generated_nonce::

(latest_generated_nonce); - metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); - } - - let new_nonces = if latest_generated_nonce > prev_latest_nonce { - self.client - .generated_message_details( - at_block.clone(), - prev_latest_nonce + 1..=latest_generated_nonce, - ) - .await? - } else { - MessageDetailsMap::new() - }; - - Ok(( - at_block, - SourceClientNonces { new_nonces, confirmed_nonce: Some(latest_confirmed_nonce) }, - )) - } - - async fn generate_proof( - &self, - at_block: SourceHeaderIdOf

, - nonces: RangeInclusive, - proof_parameters: Self::ProofParameters, - ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> - { - self.client.prove_messages(at_block, nonces, proof_parameters).await - } -} - -/// Message delivery race target, which is a target of the lane. -struct MessageDeliveryRaceTarget { - client: C, - metrics_msg: Option, - _phantom: PhantomData

, -} - -#[async_trait] -impl TargetClient> for MessageDeliveryRaceTarget -where - P: MessageLane, - C: MessageLaneTargetClient

, -{ - type Error = C::Error; - type TargetNoncesData = DeliveryRaceTargetNoncesData; - - async fn require_source_header(&self, id: SourceHeaderIdOf

) { - self.client.require_source_header_on_target(id).await - } - - async fn nonces( - &self, - at_block: TargetHeaderIdOf

, - update_metrics: bool, - ) -> Result<(TargetHeaderIdOf

, TargetClientNonces), Self::Error> - { - let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; - let (at_block, latest_confirmed_nonce) = - self.client.latest_confirmed_received_nonce(at_block).await?; - let (at_block, unrewarded_relayers) = - self.client.unrewarded_relayers_state(at_block).await?; - - if update_metrics { - if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); - metrics_msg.update_target_latest_confirmed_nonce::

(latest_confirmed_nonce); - } - } - - Ok(( - at_block, - TargetClientNonces { - latest_nonce: latest_received_nonce, - nonces_data: DeliveryRaceTargetNoncesData { - confirmed_nonce: latest_confirmed_nonce, - unrewarded_relayers, - }, - }, - )) - } - - async fn submit_proof( - &self, - generated_at_block: SourceHeaderIdOf

, - nonces: RangeInclusive, - proof: P::MessagesProof, - ) -> Result, Self::Error> { - self.client.submit_messages_proof(generated_at_block, nonces, proof).await - } -} - -/// Additional nonces data from the target client used by message delivery race. -#[derive(Debug, Clone)] -struct DeliveryRaceTargetNoncesData { - /// The latest nonce that we know: (1) has been delivered to us (2) has been confirmed - /// back to the source node (by confirmations race) and (3) relayer has received - /// reward for (and this has been confirmed by the message delivery race). - confirmed_nonce: MessageNonce, - /// State of the unrewarded relayers set at the target node. - unrewarded_relayers: UnrewardedRelayersState, -} - -/// Messages delivery strategy. -struct MessageDeliveryStrategy { - /// The client that is connected to the message lane source node. - lane_source_client: SC, - /// The client that is connected to the message lane target node. - lane_target_client: TC, - /// Maximal unrewarded relayer entries at target client. - max_unrewarded_relayer_entries_at_target: MessageNonce, - /// Maximal unconfirmed nonces at target client. - max_unconfirmed_nonces_at_target: MessageNonce, - /// Maximal number of messages in the single delivery transaction. - max_messages_in_single_batch: MessageNonce, - /// Maximal cumulative messages weight in the single delivery transaction. - max_messages_weight_in_single_batch: Weight, - /// Maximal messages size in the single delivery transaction. - max_messages_size_in_single_batch: u32, - /// Relayer operating mode. - relay_strategy: Strategy, - /// Latest confirmed nonces at the source client + the header id where we have first met this - /// nonce. - latest_confirmed_nonces_at_source: VecDeque<(SourceHeaderIdOf

, MessageNonce)>, - /// Target nonces from the source client. - target_nonces: Option>, - /// Basic delivery strategy. - strategy: MessageDeliveryStrategyBase

, -} - -type MessageDeliveryStrategyBase

= BasicStrategy< -

::SourceHeaderNumber, -

::SourceHeaderHash, -

::TargetHeaderNumber, -

::TargetHeaderHash, - MessageDetailsMap<

::SourceChainBalance>, -

::MessagesProof, ->; - -impl std::fmt::Debug - for MessageDeliveryStrategy -{ - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - fmt.debug_struct("MessageDeliveryStrategy") - .field( - "max_unrewarded_relayer_entries_at_target", - &self.max_unrewarded_relayer_entries_at_target, - ) - .field("max_unconfirmed_nonces_at_target", &self.max_unconfirmed_nonces_at_target) - .field("max_messages_in_single_batch", &self.max_messages_in_single_batch) - .field("max_messages_weight_in_single_batch", &self.max_messages_weight_in_single_batch) - .field("max_messages_size_in_single_batch", &self.max_messages_size_in_single_batch) - .field("latest_confirmed_nonces_at_source", &self.latest_confirmed_nonces_at_source) - .field("target_nonces", &self.target_nonces) - .field("strategy", &self.strategy) - .finish() - } -} - -impl MessageDeliveryStrategy { - /// Returns total weight of all undelivered messages. - fn total_queued_dispatch_weight(&self) -> Weight { - self.strategy - .source_queue() - .iter() - .flat_map(|(_, range)| range.values().map(|details| details.dispatch_weight)) - .fold(0, |total, weight| total.saturating_add(weight)) - } -} - -#[async_trait] -impl - RaceStrategy, TargetHeaderIdOf

, P::MessagesProof> - for MessageDeliveryStrategy -where - P: MessageLane, - SC: MessageLaneSourceClient

, - TC: MessageLaneTargetClient

, -{ - type ProofParameters = MessageProofParameters; - type SourceNoncesRange = MessageDetailsMap; - type TargetNoncesData = DeliveryRaceTargetNoncesData; - - fn is_empty(&self) -> bool { - self.strategy.is_empty() - } - - fn required_source_header_at_target( - &self, - current_best: &SourceHeaderIdOf

, - ) -> Option> { - let header_required_for_messages_delivery = - self.strategy.required_source_header_at_target(current_best); - let header_required_for_reward_confirmations_delivery = - self.latest_confirmed_nonces_at_source.back().map(|(id, _)| id.clone()); - match ( - header_required_for_messages_delivery, - header_required_for_reward_confirmations_delivery, - ) { - (Some(id1), Some(id2)) => Some(if id1.0 > id2.0 { id1 } else { id2 }), - (a, b) => a.or(b), - } - } - - fn best_at_source(&self) -> Option { - self.strategy.best_at_source() - } - - fn best_at_target(&self) -> Option { - self.strategy.best_at_target() - } - - fn source_nonces_updated( - &mut self, - at_block: SourceHeaderIdOf

, - nonces: SourceClientNonces, - ) { - if let Some(confirmed_nonce) = nonces.confirmed_nonce { - let is_confirmed_nonce_updated = self - .latest_confirmed_nonces_at_source - .back() - .map(|(_, prev_nonce)| *prev_nonce != confirmed_nonce) - .unwrap_or(true); - if is_confirmed_nonce_updated { - self.latest_confirmed_nonces_at_source - .push_back((at_block.clone(), confirmed_nonce)); - } - } - self.strategy.source_nonces_updated(at_block, nonces) - } - - fn best_target_nonces_updated( - &mut self, - nonces: TargetClientNonces, - race_state: &mut RaceState, TargetHeaderIdOf

, P::MessagesProof>, - ) { - // best target nonces must always be ge than finalized target nonces - let mut target_nonces = self.target_nonces.take().unwrap_or_else(|| nonces.clone()); - target_nonces.nonces_data = nonces.nonces_data.clone(); - target_nonces.latest_nonce = std::cmp::max(target_nonces.latest_nonce, nonces.latest_nonce); - self.target_nonces = Some(target_nonces); - - self.strategy.best_target_nonces_updated( - TargetClientNonces { latest_nonce: nonces.latest_nonce, nonces_data: () }, - race_state, - ) - } - - fn finalized_target_nonces_updated( - &mut self, - nonces: TargetClientNonces, - race_state: &mut RaceState, TargetHeaderIdOf

, P::MessagesProof>, - ) { - if let Some(ref best_finalized_source_header_id_at_best_target) = - race_state.best_finalized_source_header_id_at_best_target - { - let oldest_header_number_to_keep = best_finalized_source_header_id_at_best_target.0; - while self - .latest_confirmed_nonces_at_source - .front() - .map(|(id, _)| id.0 < oldest_header_number_to_keep) - .unwrap_or(false) - { - self.latest_confirmed_nonces_at_source.pop_front(); - } - } - - if let Some(ref mut target_nonces) = self.target_nonces { - target_nonces.latest_nonce = - std::cmp::max(target_nonces.latest_nonce, nonces.latest_nonce); - } - - self.strategy.finalized_target_nonces_updated( - TargetClientNonces { latest_nonce: nonces.latest_nonce, nonces_data: () }, - race_state, - ) - } - - async fn select_nonces_to_deliver( - &mut self, - race_state: RaceState, TargetHeaderIdOf

, P::MessagesProof>, - ) -> Option<(RangeInclusive, Self::ProofParameters)> { - let best_finalized_source_header_id_at_best_target = - race_state.best_finalized_source_header_id_at_best_target.clone()?; - let latest_confirmed_nonce_at_source = self - .latest_confirmed_nonces_at_source - .iter() - .take_while(|(id, _)| id.0 <= best_finalized_source_header_id_at_best_target.0) - .last() - .map(|(_, nonce)| *nonce)?; - let target_nonces = self.target_nonces.as_ref()?; - - // There's additional condition in the message delivery race: target would reject messages - // if there are too much unconfirmed messages at the inbound lane. - - // The receiving race is responsible to deliver confirmations back to the source chain. So - // if there's a lot of unconfirmed messages, let's wait until it'll be able to do its job. - let latest_received_nonce_at_target = target_nonces.latest_nonce; - let confirmations_missing = - latest_received_nonce_at_target.checked_sub(latest_confirmed_nonce_at_source); - match confirmations_missing { - Some(confirmations_missing) - if confirmations_missing >= self.max_unconfirmed_nonces_at_target => - { - log::debug!( - target: "bridge", - "Cannot deliver any more messages from {} to {}. Too many unconfirmed nonces \ - at target: target.latest_received={:?}, source.latest_confirmed={:?}, max={:?}", - MessageDeliveryRace::

::source_name(), - MessageDeliveryRace::

::target_name(), - latest_received_nonce_at_target, - latest_confirmed_nonce_at_source, - self.max_unconfirmed_nonces_at_target, - ); - - return None; - }, - _ => (), - } - - // Ok - we may have new nonces to deliver. But target may still reject new messages, because - // we haven't notified it that (some) messages have been confirmed. So we may want to - // include updated `source.latest_confirmed` in the proof. - // - // Important note: we're including outbound state lane proof whenever there are unconfirmed - // nonces on the target chain. Other strategy is to include it only if it's absolutely - // necessary. - let latest_confirmed_nonce_at_target = target_nonces.nonces_data.confirmed_nonce; - let outbound_state_proof_required = - latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source; - - // The target node would also reject messages if there are too many entries in the - // "unrewarded relayers" set. If we are unable to prove new rewards to the target node, then - // we should wait for confirmations race. - let unrewarded_relayer_entries_limit_reached = - target_nonces.nonces_data.unrewarded_relayers.unrewarded_relayer_entries - >= self.max_unrewarded_relayer_entries_at_target; - if unrewarded_relayer_entries_limit_reached { - // so there are already too many unrewarded relayer entries in the set - // - // => check if we can prove enough rewards. If not, we should wait for more rewards to - // be paid - let number_of_rewards_being_proved = - latest_confirmed_nonce_at_source.saturating_sub(latest_confirmed_nonce_at_target); - let enough_rewards_being_proved = number_of_rewards_being_proved - >= target_nonces.nonces_data.unrewarded_relayers.messages_in_oldest_entry; - if !enough_rewards_being_proved { - return None; - } - } - - // If we're here, then the confirmations race did its job && sending side now knows that - // messages have been delivered. Now let's select nonces that we want to deliver. - // - // We may deliver at most: - // - // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - - // latest_confirmed_nonce_at_target) - // - // messages in the batch. But since we're including outbound state proof in the batch, then - // it may be increased to: - // - // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - - // latest_confirmed_nonce_at_source) - let future_confirmed_nonce_at_target = if outbound_state_proof_required { - latest_confirmed_nonce_at_source - } else { - latest_confirmed_nonce_at_target - }; - let max_nonces = latest_received_nonce_at_target - .checked_sub(future_confirmed_nonce_at_target) - .and_then(|diff| self.max_unconfirmed_nonces_at_target.checked_sub(diff)) - .unwrap_or_default(); - let max_nonces = std::cmp::min(max_nonces, self.max_messages_in_single_batch); - let max_messages_weight_in_single_batch = self.max_messages_weight_in_single_batch; - let max_messages_size_in_single_batch = self.max_messages_size_in_single_batch; - let lane_source_client = self.lane_source_client.clone(); - let lane_target_client = self.lane_target_client.clone(); - - let maximal_source_queue_index = - self.strategy.maximal_available_source_queue_index(race_state)?; - let previous_total_dispatch_weight = self.total_queued_dispatch_weight(); - let source_queue = self.strategy.source_queue(); - - let reference = RelayMessagesBatchReference { - max_messages_in_this_batch: max_nonces, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - lane_source_client: lane_source_client.clone(), - lane_target_client: lane_target_client.clone(), - nonces_queue: source_queue.clone(), - nonces_queue_range: 0..maximal_source_queue_index + 1, - }; - - let mut strategy = EnforcementStrategy::new(self.relay_strategy.clone()); - let range_end = strategy.decide(reference).await?; - - let range_begin = source_queue[0].1.begin(); - let selected_nonces = range_begin..=range_end; - self.strategy.remove_le_nonces_from_source_queue(range_end); - - let new_total_dispatch_weight = self.total_queued_dispatch_weight(); - let dispatch_weight = previous_total_dispatch_weight - new_total_dispatch_weight; - - Some(( - selected_nonces, - MessageProofParameters { outbound_state_proof_required, dispatch_weight }, - )) - } -} - -impl NoncesRange for MessageDetailsMap { - fn begin(&self) -> MessageNonce { - self.keys().next().cloned().unwrap_or_default() - } - - fn end(&self) -> MessageNonce { - self.keys().next_back().cloned().unwrap_or_default() - } - - fn greater_than(mut self, nonce: MessageNonce) -> Option { - let gte = self.split_off(&(nonce + 1)); - if gte.is_empty() { - None - } else { - Some(gte) - } - } -} - -#[cfg(test)] -mod tests { - use bp_runtime::messages::DispatchFeePayment; - - use crate::{ - message_lane_loop::{ - tests::{ - header_id, TestMessageLane, TestMessagesProof, TestSourceChainBalance, - TestSourceClient, TestSourceHeaderId, TestTargetClient, TestTargetHeaderId, - BASE_MESSAGE_DELIVERY_TRANSACTION_COST, CONFIRMATION_TRANSACTION_COST, - }, - MessageDetails, RelayerMode, - }, - relay_strategy::MixStrategy, - }; - - use super::*; - - const DEFAULT_DISPATCH_WEIGHT: Weight = 1; - const DEFAULT_SIZE: u32 = 1; - const DEFAULT_REWARD: TestSourceChainBalance = CONFIRMATION_TRANSACTION_COST - + BASE_MESSAGE_DELIVERY_TRANSACTION_COST - + DEFAULT_DISPATCH_WEIGHT - + (DEFAULT_SIZE as TestSourceChainBalance); - - type TestRaceState = RaceState; - type TestStrategy = - MessageDeliveryStrategy; - - fn source_nonces( - new_nonces: RangeInclusive, - confirmed_nonce: MessageNonce, - reward: TestSourceChainBalance, - dispatch_fee_payment: DispatchFeePayment, - ) -> SourceClientNonces> { - SourceClientNonces { - new_nonces: new_nonces - .into_iter() - .map(|nonce| { - ( - nonce, - MessageDetails { - dispatch_weight: DEFAULT_DISPATCH_WEIGHT, - size: DEFAULT_SIZE, - reward, - dispatch_fee_payment, - }, - ) - }) - .into_iter() - .collect(), - confirmed_nonce: Some(confirmed_nonce), - } - } - - fn prepare_strategy() -> (TestRaceState, TestStrategy) { - let mut race_state = RaceState { - best_finalized_source_header_id_at_source: Some(header_id(1)), - best_finalized_source_header_id_at_best_target: Some(header_id(1)), - best_target_header_id: Some(header_id(1)), - best_finalized_target_header_id: Some(header_id(1)), - nonces_to_submit: None, - nonces_submitted: None, - }; - - let mut race_strategy = TestStrategy { - max_unrewarded_relayer_entries_at_target: 4, - max_unconfirmed_nonces_at_target: 4, - max_messages_in_single_batch: 4, - max_messages_weight_in_single_batch: 4, - max_messages_size_in_single_batch: 4, - latest_confirmed_nonces_at_source: vec![(header_id(1), 19)].into_iter().collect(), - lane_source_client: TestSourceClient::default(), - lane_target_client: TestTargetClient::default(), - target_nonces: Some(TargetClientNonces { - latest_nonce: 19, - nonces_data: DeliveryRaceTargetNoncesData { - confirmed_nonce: 19, - unrewarded_relayers: UnrewardedRelayersState { - unrewarded_relayer_entries: 0, - messages_in_oldest_entry: 0, - total_messages: 0, - }, - }, - }), - strategy: BasicStrategy::new(), - relay_strategy: MixStrategy::new(RelayerMode::Altruistic), - }; - - race_strategy.strategy.source_nonces_updated( - header_id(1), - source_nonces(20..=23, 19, DEFAULT_REWARD, DispatchFeePayment::AtSourceChain), - ); - - let target_nonces = TargetClientNonces { latest_nonce: 19, nonces_data: () }; - race_strategy.strategy.best_target_nonces_updated(target_nonces.clone(), &mut race_state); - race_strategy.strategy.finalized_target_nonces_updated(target_nonces, &mut race_state); - - (race_state, race_strategy) - } - - fn proof_parameters(state_required: bool, weight: Weight) -> MessageProofParameters { - MessageProofParameters { - outbound_state_proof_required: state_required, - dispatch_weight: weight, - } - } - - #[test] - fn weights_map_works_as_nonces_range() { - fn build_map( - range: RangeInclusive, - ) -> MessageDetailsMap { - range - .map(|idx| { - ( - idx, - MessageDetails { - dispatch_weight: idx, - size: idx as _, - reward: idx as _, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - }, - ) - }) - .collect() - } - - let map = build_map(20..=30); - - assert_eq!(map.begin(), 20); - assert_eq!(map.end(), 30); - assert_eq!(map.clone().greater_than(10), Some(build_map(20..=30))); - assert_eq!(map.clone().greater_than(19), Some(build_map(20..=30))); - assert_eq!(map.clone().greater_than(20), Some(build_map(21..=30))); - assert_eq!(map.clone().greater_than(25), Some(build_map(26..=30))); - assert_eq!(map.clone().greater_than(29), Some(build_map(30..=30))); - assert_eq!(map.greater_than(30), None); - } - - #[async_std::test] - async fn message_delivery_strategy_selects_messages_to_deliver() { - let (state, mut strategy) = prepare_strategy(); - - // both sides are ready to relay new messages - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=23), proof_parameters(false, 4))) - ); - } - - #[async_std::test] - async fn message_delivery_strategy_selects_nothing_if_too_many_confirmations_missing() { - let (state, mut strategy) = prepare_strategy(); - - // if there are already `max_unconfirmed_nonces_at_target` messages on target, - // we need to wait until confirmations will be delivered by receiving race - strategy.latest_confirmed_nonces_at_source = vec![( - header_id(1), - strategy.target_nonces.as_ref().unwrap().latest_nonce - - strategy.max_unconfirmed_nonces_at_target, - )] - .into_iter() - .collect(); - assert_eq!(strategy.select_nonces_to_deliver(state).await, None); - } - - #[async_std::test] - async fn message_delivery_strategy_includes_outbound_state_proof_when_new_nonces_are_available() - { - let (state, mut strategy) = prepare_strategy(); - - // if there are new confirmed nonces on source, we want to relay this information - // to target to prune rewards queue - let prev_confirmed_nonce_at_source = - strategy.latest_confirmed_nonces_at_source.back().unwrap().1; - strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = - prev_confirmed_nonce_at_source - 1; - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=23), proof_parameters(true, 4))) - ); - } - - #[async_std::test] - async fn message_delivery_strategy_selects_nothing_if_there_are_too_many_unrewarded_relayers() { - let (state, mut strategy) = prepare_strategy(); - - // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, - // we need to wait until rewards will be paid - { - let mut unrewarded_relayers = - &mut strategy.target_nonces.as_mut().unwrap().nonces_data.unrewarded_relayers; - unrewarded_relayers.unrewarded_relayer_entries = - strategy.max_unrewarded_relayer_entries_at_target; - unrewarded_relayers.messages_in_oldest_entry = 4; - } - assert_eq!(strategy.select_nonces_to_deliver(state).await, None); - } - - #[async_std::test] - async fn message_delivery_strategy_selects_nothing_if_proved_rewards_is_not_enough_to_remove_oldest_unrewarded_entry( - ) { - let (state, mut strategy) = prepare_strategy(); - - // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, - // we need to prove at least `messages_in_oldest_entry` rewards - let prev_confirmed_nonce_at_source = - strategy.latest_confirmed_nonces_at_source.back().unwrap().1; - { - let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; - nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; - let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers; - unrewarded_relayers.unrewarded_relayer_entries = - strategy.max_unrewarded_relayer_entries_at_target; - unrewarded_relayers.messages_in_oldest_entry = 4; - } - assert_eq!(strategy.select_nonces_to_deliver(state).await, None); - } - - #[async_std::test] - async fn message_delivery_strategy_includes_outbound_state_proof_if_proved_rewards_is_enough() { - let (state, mut strategy) = prepare_strategy(); - - // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, - // we need to prove at least `messages_in_oldest_entry` rewards - let prev_confirmed_nonce_at_source = - strategy.latest_confirmed_nonces_at_source.back().unwrap().1; - { - let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; - nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 3; - let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers; - unrewarded_relayers.unrewarded_relayer_entries = - strategy.max_unrewarded_relayer_entries_at_target; - unrewarded_relayers.messages_in_oldest_entry = 3; - } - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=23), proof_parameters(true, 4))) - ); - } - - #[async_std::test] - async fn message_delivery_strategy_limits_batch_by_messages_weight() { - let (state, mut strategy) = prepare_strategy(); - - // not all queued messages may fit in the batch, because batch has max weight - strategy.max_messages_weight_in_single_batch = 3; - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=22), proof_parameters(false, 3))) - ); - } - - #[async_std::test] - async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_weight( - ) { - let (state, mut strategy) = prepare_strategy(); - - // first message doesn't fit in the batch, because it has weight (10) that overflows max - // weight (4) - strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().dispatch_weight = 10; - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=20), proof_parameters(false, 10))) - ); - } - - #[async_std::test] - async fn message_delivery_strategy_limits_batch_by_messages_size() { - let (state, mut strategy) = prepare_strategy(); - - // not all queued messages may fit in the batch, because batch has max weight - strategy.max_messages_size_in_single_batch = 3; - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=22), proof_parameters(false, 3))) - ); - } - - #[async_std::test] - async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_size( - ) { - let (state, mut strategy) = prepare_strategy(); - - // first message doesn't fit in the batch, because it has weight (10) that overflows max - // weight (4) - strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().size = 10; - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=20), proof_parameters(false, 1))) - ); - } - - #[async_std::test] - async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_is_upper_limit() { - let (state, mut strategy) = prepare_strategy(); - - // not all queued messages may fit in the batch, because batch has max number of messages - // limit - strategy.max_messages_in_single_batch = 3; - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=22), proof_parameters(false, 3))) - ); - } - - #[async_std::test] - async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_are_unconfirmed_nonces( - ) { - let (state, mut strategy) = prepare_strategy(); - - // 1 delivery confirmation from target to source is still missing, so we may only - // relay 3 new messages - let prev_confirmed_nonce_at_source = - strategy.latest_confirmed_nonces_at_source.back().unwrap().1; - strategy.latest_confirmed_nonces_at_source = - vec![(header_id(1), prev_confirmed_nonce_at_source - 1)].into_iter().collect(); - strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = - prev_confirmed_nonce_at_source - 1; - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=22), proof_parameters(false, 3))) - ); - } - - #[async_std::test] - async fn message_delivery_strategy_waits_for_confirmed_nonce_header_to_appear_on_target() { - // 1 delivery confirmation from target to source is still missing, so we may deliver - // reward confirmation with our message delivery transaction. But the problem is that - // the reward has been paid at header 2 && this header is still unknown to target node. - // - // => so we can't deliver more than 3 messages - let (mut state, mut strategy) = prepare_strategy(); - let prev_confirmed_nonce_at_source = - strategy.latest_confirmed_nonces_at_source.back().unwrap().1; - strategy.latest_confirmed_nonces_at_source = vec![ - (header_id(1), prev_confirmed_nonce_at_source - 1), - (header_id(2), prev_confirmed_nonce_at_source), - ] - .into_iter() - .collect(); - strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = - prev_confirmed_nonce_at_source - 1; - state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=22), proof_parameters(false, 3))) - ); - - // the same situation, but the header 2 is known to the target node, so we may deliver - // reward confirmation - let (mut state, mut strategy) = prepare_strategy(); - let prev_confirmed_nonce_at_source = - strategy.latest_confirmed_nonces_at_source.back().unwrap().1; - strategy.latest_confirmed_nonces_at_source = vec![ - (header_id(1), prev_confirmed_nonce_at_source - 1), - (header_id(2), prev_confirmed_nonce_at_source), - ] - .into_iter() - .collect(); - strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = - prev_confirmed_nonce_at_source - 1; - state.best_finalized_source_header_id_at_source = Some(header_id(2)); - state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=23), proof_parameters(true, 4))) - ); - } - - #[async_std::test] - async fn source_header_is_required_when_confirmations_are_required() { - // let's prepare situation when: - // - all messages [20; 23] have been generated at source block#1; - let (mut state, mut strategy) = prepare_strategy(); - // - // - messages [20; 21] have been delivered, but messages [11; 20] can't be delivered because - // of unrewarded relayers vector capacity; - strategy.max_unconfirmed_nonces_at_target = 2; - assert_eq!( - strategy.select_nonces_to_deliver(state.clone()).await, - Some(((20..=21), proof_parameters(false, 2))) - ); - strategy.finalized_target_nonces_updated( - TargetClientNonces { - latest_nonce: 21, - nonces_data: DeliveryRaceTargetNoncesData { - confirmed_nonce: 19, - unrewarded_relayers: UnrewardedRelayersState { - unrewarded_relayer_entries: 2, - messages_in_oldest_entry: 2, - total_messages: 2, - }, - }, - }, - &mut state, - ); - assert_eq!(strategy.select_nonces_to_deliver(state).await, None); - // - // - messages [1; 10] receiving confirmation has been delivered at source block#2; - strategy.source_nonces_updated( - header_id(2), - SourceClientNonces { new_nonces: MessageDetailsMap::new(), confirmed_nonce: Some(21) }, - ); - // - // - so now we'll need to relay source block#11 to be able to accept messages [11; 20]. - assert_eq!(strategy.required_source_header_at_target(&header_id(1)), Some(header_id(2))); - } - - #[async_std::test] - async fn rational_relayer_is_delivering_messages_if_cost_is_equal_to_reward() { - let (state, mut strategy) = prepare_strategy(); - strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); - - // so now we have: - // - 20..=23 with reward = cost - // => strategy shall select all 20..=23 - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=23), proof_parameters(false, 4))) - ); - } - - #[async_std::test] - async fn rational_relayer_is_not_delivering_messages_if_cost_is_larger_than_reward() { - let (mut state, mut strategy) = prepare_strategy(); - let nonces = source_nonces( - 24..=25, - 19, - DEFAULT_REWARD - BASE_MESSAGE_DELIVERY_TRANSACTION_COST, - DispatchFeePayment::AtSourceChain, - ); - strategy.strategy.source_nonces_updated(header_id(2), nonces); - state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); - - // so now we have: - // - 20..=23 with reward = cost - // - 24..=25 with reward less than cost - // => strategy shall only select 20..=23 - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=23), proof_parameters(false, 4))) - ); - } - - #[async_std::test] - async fn rational_relayer_is_delivering_unpaid_messages() { - async fn test_with_dispatch_fee_payment( - dispatch_fee_payment: DispatchFeePayment, - ) -> Option<(RangeInclusive, MessageProofParameters)> { - let (mut state, mut strategy) = prepare_strategy(); - let nonces = source_nonces( - 24..=24, - 19, - DEFAULT_REWARD - DEFAULT_DISPATCH_WEIGHT, - dispatch_fee_payment, - ); - strategy.strategy.source_nonces_updated(header_id(2), nonces); - state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - strategy.max_unrewarded_relayer_entries_at_target = 100; - strategy.max_unconfirmed_nonces_at_target = 100; - strategy.max_messages_in_single_batch = 100; - strategy.max_messages_weight_in_single_batch = 100; - strategy.max_messages_size_in_single_batch = 100; - strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); - - // so now we have: - // - 20..=23 with reward = cost - // - 24..=24 with reward less than cost, but we're deducting `DEFAULT_DISPATCH_WEIGHT` - // from the cost, so it should be fine; - // => when MSG#24 fee is paid at the target chain, strategy shall select all 20..=24 - // => when MSG#25 fee is paid at the source chain, strategy shall only select 20..=23 - strategy.select_nonces_to_deliver(state).await - } - - assert_eq!( - test_with_dispatch_fee_payment(DispatchFeePayment::AtTargetChain).await, - Some(((20..=24), proof_parameters(false, 5))) - ); - assert_eq!( - test_with_dispatch_fee_payment(DispatchFeePayment::AtSourceChain).await, - Some(((20..=23), proof_parameters(false, 4))) - ); - } - - #[async_std::test] - async fn relayer_uses_flattened_view_of_the_source_queue_to_select_nonces() { - // Real scenario that has happened on test deployments: - // 1) relayer witnessed M1 at block 1 => it has separate entry in the `source_queue` - // 2) relayer witnessed M2 at block 2 => it has separate entry in the `source_queue` - // 3) if block 2 is known to the target node, then both M1 and M2 are selected for single - // delivery, even though weight(M1+M2) > larger than largest allowed weight - // - // This was happening because selector (`select_nonces_for_delivery_transaction`) has been - // called for every `source_queue` entry separately without preserving any context. - let (mut state, mut strategy) = prepare_strategy(); - let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD, DispatchFeePayment::AtSourceChain); - strategy.strategy.source_nonces_updated(header_id(2), nonces); - strategy.max_unrewarded_relayer_entries_at_target = 100; - strategy.max_unconfirmed_nonces_at_target = 100; - strategy.max_messages_in_single_batch = 5; - strategy.max_messages_weight_in_single_batch = 100; - strategy.max_messages_size_in_single_batch = 100; - state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=24), proof_parameters(false, 5))) - ); - } -} diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs deleted file mode 100644 index 314008daa..000000000 --- a/relays/messages/src/message_race_loop.rs +++ /dev/null @@ -1,631 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -//! Loop that is serving single race within message lane. This could be -//! message delivery race, receiving confirmations race or processing -//! confirmations race. -//! -//! The idea of the race is simple - we have `nonce`-s on source and target -//! nodes. We're trying to prove that the source node has this nonce (and -//! associated data - like messages, lane state, etc) to the target node by -//! generating and submitting proof. - -use crate::message_lane_loop::ClientState; - -use async_trait::async_trait; -use bp_messages::MessageNonce; -use futures::{ - future::FutureExt, - stream::{FusedStream, StreamExt}, -}; -use relay_utils::{process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; -use std::{ - fmt::Debug, - ops::RangeInclusive, - time::{Duration, Instant}, -}; - -/// One of races within lane. -pub trait MessageRace { - /// Header id of the race source. - type SourceHeaderId: Debug + Clone + PartialEq; - /// Header id of the race source. - type TargetHeaderId: Debug + Clone + PartialEq; - - /// Message nonce used in the race. - type MessageNonce: Debug + Clone; - /// Proof that is generated and delivered in this race. - type Proof: Debug + Clone; - - /// Name of the race source. - fn source_name() -> String; - /// Name of the race target. - fn target_name() -> String; -} - -/// State of race source client. -type SourceClientState

= - ClientState<

::SourceHeaderId,

::TargetHeaderId>; - -/// State of race target client. -type TargetClientState

= - ClientState<

::TargetHeaderId,

::SourceHeaderId>; - -/// Inclusive nonces range. -pub trait NoncesRange: Debug + Sized { - /// Get begin of the range. - fn begin(&self) -> MessageNonce; - /// Get end of the range. - fn end(&self) -> MessageNonce; - /// Returns new range with current range nonces that are greater than the passed `nonce`. - /// If there are no such nonces, `None` is returned. - fn greater_than(self, nonce: MessageNonce) -> Option; -} - -/// Nonces on the race source client. -#[derive(Debug, Clone)] -pub struct SourceClientNonces { - /// New nonces range known to the client. `New` here means all nonces generated after - /// `prev_latest_nonce` passed to the `SourceClient::nonces` method. - pub new_nonces: NoncesRange, - /// The latest nonce that is confirmed to the bridged client. This nonce only makes - /// sense in some races. In other races it is `None`. - pub confirmed_nonce: Option, -} - -/// Nonces on the race target client. -#[derive(Debug, Clone)] -pub struct TargetClientNonces { - /// The latest nonce that is known to the target client. - pub latest_nonce: MessageNonce, - /// Additional data from target node that may be used by the race. - pub nonces_data: TargetNoncesData, -} - -/// One of message lane clients, which is source client for the race. -#[async_trait] -pub trait SourceClient { - /// Type of error these clients returns. - type Error: std::fmt::Debug + MaybeConnectionError; - /// Type of nonces range returned by the source client. - type NoncesRange: NoncesRange; - /// Additional proof parameters required to generate proof. - type ProofParameters; - - /// Return nonces that are known to the source client. - async fn nonces( - &self, - at_block: P::SourceHeaderId, - prev_latest_nonce: MessageNonce, - ) -> Result<(P::SourceHeaderId, SourceClientNonces), Self::Error>; - /// Generate proof for delivering to the target client. - async fn generate_proof( - &self, - at_block: P::SourceHeaderId, - nonces: RangeInclusive, - proof_parameters: Self::ProofParameters, - ) -> Result<(P::SourceHeaderId, RangeInclusive, P::Proof), Self::Error>; -} - -/// One of message lane clients, which is target client for the race. -#[async_trait] -pub trait TargetClient { - /// Type of error these clients returns. - type Error: std::fmt::Debug + MaybeConnectionError; - /// Type of the additional data from the target client, used by the race. - type TargetNoncesData: std::fmt::Debug; - - /// Ask headers relay to relay finalized headers up to (and including) given header - /// from race source to race target. - async fn require_source_header(&self, id: P::SourceHeaderId); - - /// Return nonces that are known to the target client. - async fn nonces( - &self, - at_block: P::TargetHeaderId, - update_metrics: bool, - ) -> Result<(P::TargetHeaderId, TargetClientNonces), Self::Error>; - /// Submit proof to the target client. - async fn submit_proof( - &self, - generated_at_block: P::SourceHeaderId, - nonces: RangeInclusive, - proof: P::Proof, - ) -> Result, Self::Error>; -} - -/// Race strategy. -#[async_trait] -pub trait RaceStrategy: Debug { - /// Type of nonces range expected from the source client. - type SourceNoncesRange: NoncesRange; - /// Additional proof parameters required to generate proof. - type ProofParameters; - /// Additional data expected from the target client. - type TargetNoncesData; - - /// Should return true if nothing has to be synced. - fn is_empty(&self) -> bool; - /// Return id of source header that is required to be on target to continue synchronization. - fn required_source_header_at_target( - &self, - current_best: &SourceHeaderId, - ) -> Option; - /// Return the best nonce at source node. - /// - /// `Some` is returned only if we are sure that the value is greater or equal - /// than the result of `best_at_target`. - fn best_at_source(&self) -> Option; - /// Return the best nonce at target node. - /// - /// May return `None` if value is yet unknown. - fn best_at_target(&self) -> Option; - - /// Called when nonces are updated at source node of the race. - fn source_nonces_updated( - &mut self, - at_block: SourceHeaderId, - nonces: SourceClientNonces, - ); - /// Called when best nonces are updated at target node of the race. - fn best_target_nonces_updated( - &mut self, - nonces: TargetClientNonces, - race_state: &mut RaceState, - ); - /// Called when finalized nonces are updated at target node of the race. - fn finalized_target_nonces_updated( - &mut self, - nonces: TargetClientNonces, - race_state: &mut RaceState, - ); - /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated - /// data) from source to target node. - /// Additionally, parameters required to generate proof are returned. - async fn select_nonces_to_deliver( - &mut self, - race_state: RaceState, - ) -> Option<(RangeInclusive, Self::ProofParameters)>; -} - -/// State of the race. -#[derive(Debug, Clone)] -pub struct RaceState { - /// Best finalized source header id at the source client. - pub best_finalized_source_header_id_at_source: Option, - /// Best finalized source header id at the best block on the target - /// client (at the `best_finalized_source_header_id_at_best_target`). - pub best_finalized_source_header_id_at_best_target: Option, - /// The best header id at the target client. - pub best_target_header_id: Option, - /// Best finalized header id at the target client. - pub best_finalized_target_header_id: Option, - /// Range of nonces that we have selected to submit. - pub nonces_to_submit: Option<(SourceHeaderId, RangeInclusive, Proof)>, - /// Range of nonces that is currently submitted. - pub nonces_submitted: Option>, -} - -/// Run race loop until connection with target or source node is lost. -pub async fn run, TC: TargetClient

>( - race_source: SC, - race_source_updated: impl FusedStream>, - race_target: TC, - race_target_updated: impl FusedStream>, - stall_timeout: Duration, - mut strategy: impl RaceStrategy< - P::SourceHeaderId, - P::TargetHeaderId, - P::Proof, - SourceNoncesRange = SC::NoncesRange, - ProofParameters = SC::ProofParameters, - TargetNoncesData = TC::TargetNoncesData, - >, -) -> Result<(), FailedClient> { - let mut progress_context = Instant::now(); - let mut race_state = RaceState::default(); - let mut stall_countdown = Instant::now(); - - let mut source_retry_backoff = retry_backoff(); - let mut source_client_is_online = true; - let mut source_nonces_required = false; - let source_nonces = futures::future::Fuse::terminated(); - let source_generate_proof = futures::future::Fuse::terminated(); - let source_go_offline_future = futures::future::Fuse::terminated(); - - let mut target_retry_backoff = retry_backoff(); - let mut target_client_is_online = true; - let mut target_best_nonces_required = false; - let mut target_finalized_nonces_required = false; - let target_best_nonces = futures::future::Fuse::terminated(); - let target_finalized_nonces = futures::future::Fuse::terminated(); - let target_submit_proof = futures::future::Fuse::terminated(); - let target_go_offline_future = futures::future::Fuse::terminated(); - - futures::pin_mut!( - race_source_updated, - source_nonces, - source_generate_proof, - source_go_offline_future, - race_target_updated, - target_best_nonces, - target_finalized_nonces, - target_submit_proof, - target_go_offline_future, - ); - - loop { - futures::select! { - // when headers ids are updated - source_state = race_source_updated.next() => { - if let Some(source_state) = source_state { - let is_source_state_updated = race_state.best_finalized_source_header_id_at_source.as_ref() - != Some(&source_state.best_finalized_self); - if is_source_state_updated { - source_nonces_required = true; - race_state.best_finalized_source_header_id_at_source = Some(source_state.best_finalized_self); - } - } - }, - target_state = race_target_updated.next() => { - if let Some(target_state) = target_state { - let is_target_best_state_updated = race_state.best_target_header_id.as_ref() - != Some(&target_state.best_self); - - if is_target_best_state_updated { - target_best_nonces_required = true; - race_state.best_target_header_id = Some(target_state.best_self); - race_state.best_finalized_source_header_id_at_best_target - = Some(target_state.best_finalized_peer_at_best_self); - } - - let is_target_finalized_state_updated = race_state.best_finalized_target_header_id.as_ref() - != Some(&target_state.best_finalized_self); - if is_target_finalized_state_updated { - target_finalized_nonces_required = true; - race_state.best_finalized_target_header_id = Some(target_state.best_finalized_self); - } - } - }, - - // when nonces are updated - nonces = source_nonces => { - source_nonces_required = false; - - source_client_is_online = process_future_result( - nonces, - &mut source_retry_backoff, - |(at_block, nonces)| { - log::debug!( - target: "bridge", - "Received nonces from {}: {:?}", - P::source_name(), - nonces, - ); - - strategy.source_nonces_updated(at_block, nonces); - }, - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving nonces from {}", P::source_name()), - ).fail_if_connection_error(FailedClient::Source)?; - - // ask for more headers if we have nonces to deliver and required headers are missing - let required_source_header_id = race_state - .best_finalized_source_header_id_at_best_target - .as_ref() - .and_then(|best|strategy.required_source_header_at_target(best)); - if let Some(required_source_header_id) = required_source_header_id { - race_target.require_source_header(required_source_header_id).await; - } - }, - nonces = target_best_nonces => { - target_best_nonces_required = false; - - target_client_is_online = process_future_result( - nonces, - &mut target_retry_backoff, - |(_, nonces)| { - log::debug!( - target: "bridge", - "Received best nonces from {}: {:?}", - P::target_name(), - nonces, - ); - - let prev_best_at_target = strategy.best_at_target(); - strategy.best_target_nonces_updated(nonces, &mut race_state); - if strategy.best_at_target() != prev_best_at_target { - stall_countdown = Instant::now(); - } - }, - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving best nonces from {}", P::target_name()), - ).fail_if_connection_error(FailedClient::Target)?; - }, - nonces = target_finalized_nonces => { - target_finalized_nonces_required = false; - - target_client_is_online = process_future_result( - nonces, - &mut target_retry_backoff, - |(_, nonces)| { - log::debug!( - target: "bridge", - "Received finalized nonces from {}: {:?}", - P::target_name(), - nonces, - ); - - strategy.finalized_target_nonces_updated(nonces, &mut race_state); - }, - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving finalized nonces from {}", P::target_name()), - ).fail_if_connection_error(FailedClient::Target)?; - }, - - // proof generation and submission - proof = source_generate_proof => { - source_client_is_online = process_future_result( - proof, - &mut source_retry_backoff, - |(at_block, nonces_range, proof)| { - log::debug!( - target: "bridge", - "Received proof for nonces in range {:?} from {}", - nonces_range, - P::source_name(), - ); - - race_state.nonces_to_submit = Some((at_block, nonces_range, proof)); - }, - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error generating proof at {}", P::source_name()), - ).fail_if_connection_error(FailedClient::Source)?; - }, - proof_submit_result = target_submit_proof => { - target_client_is_online = process_future_result( - proof_submit_result, - &mut target_retry_backoff, - |nonces_range| { - log::debug!( - target: "bridge", - "Successfully submitted proof of nonces {:?} to {}", - nonces_range, - P::target_name(), - ); - - race_state.nonces_to_submit = None; - race_state.nonces_submitted = Some(nonces_range); - stall_countdown = Instant::now(); - }, - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error submitting proof {}", P::target_name()), - ).fail_if_connection_error(FailedClient::Target)?; - }, - - // when we're ready to retry request - _ = source_go_offline_future => { - source_client_is_online = true; - }, - _ = target_go_offline_future => { - target_client_is_online = true; - }, - } - - progress_context = print_race_progress::(progress_context, &strategy); - - if stall_countdown.elapsed() > stall_timeout { - log::warn!( - target: "bridge", - "{} -> {} race has stalled. State: {:?}. Strategy: {:?}", - P::source_name(), - P::target_name(), - race_state, - strategy, - ); - - return Err(FailedClient::Both); - } else if race_state.nonces_to_submit.is_none() - && race_state.nonces_submitted.is_none() - && strategy.is_empty() - { - stall_countdown = Instant::now(); - } - - if source_client_is_online { - source_client_is_online = false; - - let nonces_to_deliver = - select_nonces_to_deliver(race_state.clone(), &mut strategy).await; - let best_at_source = strategy.best_at_source(); - - if let Some((at_block, nonces_range, proof_parameters)) = nonces_to_deliver { - log::debug!( - target: "bridge", - "Asking {} to prove nonces in range {:?} at block {:?}", - P::source_name(), - nonces_range, - at_block, - ); - source_generate_proof.set( - race_source.generate_proof(at_block, nonces_range, proof_parameters).fuse(), - ); - } else if source_nonces_required && best_at_source.is_some() { - log::debug!(target: "bridge", "Asking {} about message nonces", P::source_name()); - let at_block = race_state - .best_finalized_source_header_id_at_source - .as_ref() - .expect( - "source_nonces_required is only true when\ - best_finalized_source_header_id_at_source is Some; qed", - ) - .clone(); - source_nonces.set( - race_source - .nonces(at_block, best_at_source.expect("guaranteed by if condition; qed")) - .fuse(), - ); - } else { - source_client_is_online = true; - } - } - - if target_client_is_online { - target_client_is_online = false; - - if let Some((at_block, nonces_range, proof)) = race_state.nonces_to_submit.as_ref() { - log::debug!( - target: "bridge", - "Going to submit proof of messages in range {:?} to {} node", - nonces_range, - P::target_name(), - ); - target_submit_proof.set( - race_target - .submit_proof(at_block.clone(), nonces_range.clone(), proof.clone()) - .fuse(), - ); - } else if target_best_nonces_required { - log::debug!(target: "bridge", "Asking {} about best message nonces", P::target_name()); - let at_block = race_state - .best_target_header_id - .as_ref() - .expect("target_best_nonces_required is only true when best_target_header_id is Some; qed") - .clone(); - target_best_nonces.set(race_target.nonces(at_block, false).fuse()); - } else if target_finalized_nonces_required { - log::debug!(target: "bridge", "Asking {} about finalized message nonces", P::target_name()); - let at_block = race_state - .best_finalized_target_header_id - .as_ref() - .expect( - "target_finalized_nonces_required is only true when\ - best_finalized_target_header_id is Some; qed", - ) - .clone(); - target_finalized_nonces.set(race_target.nonces(at_block, true).fuse()); - } else { - target_client_is_online = true; - } - } - } -} - -impl Default - for RaceState -{ - fn default() -> Self { - RaceState { - best_finalized_source_header_id_at_source: None, - best_finalized_source_header_id_at_best_target: None, - best_target_header_id: None, - best_finalized_target_header_id: None, - nonces_to_submit: None, - nonces_submitted: None, - } - } -} - -/// Print race progress. -fn print_race_progress(prev_time: Instant, strategy: &S) -> Instant -where - P: MessageRace, - S: RaceStrategy, -{ - let now_time = Instant::now(); - - let need_update = now_time.saturating_duration_since(prev_time) > Duration::from_secs(10); - if !need_update { - return prev_time; - } - - let now_best_nonce_at_source = strategy.best_at_source(); - let now_best_nonce_at_target = strategy.best_at_target(); - log::info!( - target: "bridge", - "Synced {:?} of {:?} nonces in {} -> {} race", - now_best_nonce_at_target, - now_best_nonce_at_source, - P::source_name(), - P::target_name(), - ); - now_time -} - -async fn select_nonces_to_deliver( - race_state: RaceState, - strategy: &mut Strategy, -) -> Option<(SourceHeaderId, RangeInclusive, Strategy::ProofParameters)> -where - SourceHeaderId: Clone, - Strategy: RaceStrategy, -{ - let best_finalized_source_header_id_at_best_target = - race_state.best_finalized_source_header_id_at_best_target.clone()?; - strategy.select_nonces_to_deliver(race_state).await.map(|(nonces_range, proof_parameters)| { - (best_finalized_source_header_id_at_best_target, nonces_range, proof_parameters) - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::message_race_strategy::BasicStrategy; - use relay_utils::HeaderId; - - #[async_std::test] - async fn proof_is_generated_at_best_block_known_to_target_node() { - const GENERATED_AT: u64 = 6; - const BEST_AT_SOURCE: u64 = 10; - const BEST_AT_TARGET: u64 = 8; - - // target node only knows about source' BEST_AT_TARGET block - // source node has BEST_AT_SOURCE > BEST_AT_TARGET block - let mut race_state = RaceState::<_, _, ()> { - best_finalized_source_header_id_at_source: Some(HeaderId( - BEST_AT_SOURCE, - BEST_AT_SOURCE, - )), - best_finalized_source_header_id_at_best_target: Some(HeaderId( - BEST_AT_TARGET, - BEST_AT_TARGET, - )), - best_target_header_id: Some(HeaderId(0, 0)), - best_finalized_target_header_id: Some(HeaderId(0, 0)), - nonces_to_submit: None, - nonces_submitted: None, - }; - - // we have some nonces to deliver and they're generated at GENERATED_AT < BEST_AT_SOURCE - let mut strategy = BasicStrategy::new(); - strategy.source_nonces_updated( - HeaderId(GENERATED_AT, GENERATED_AT), - SourceClientNonces { new_nonces: 0..=10, confirmed_nonce: None }, - ); - strategy.best_target_nonces_updated( - TargetClientNonces { latest_nonce: 5u64, nonces_data: () }, - &mut race_state, - ); - - // the proof will be generated on source, but using BEST_AT_TARGET block - assert_eq!( - select_nonces_to_deliver(race_state, &mut strategy).await, - Some((HeaderId(BEST_AT_TARGET, BEST_AT_TARGET), 6..=10, (),)) - ); - } -} diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs deleted file mode 100644 index a23add589..000000000 --- a/relays/messages/src/message_race_receiving.rs +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -//! Message receiving race delivers proof-of-messages-delivery from "lane.target" to "lane.source". - -use crate::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - message_lane_loop::{ - SourceClient as MessageLaneSourceClient, SourceClientState, - TargetClient as MessageLaneTargetClient, TargetClientState, - }, - message_race_loop::{ - MessageRace, NoncesRange, SourceClient, SourceClientNonces, TargetClient, - TargetClientNonces, - }, - message_race_strategy::BasicStrategy, - metrics::MessageLaneLoopMetrics, -}; - -use async_trait::async_trait; -use bp_messages::MessageNonce; -use futures::stream::FusedStream; -use relay_utils::FailedClient; -use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; - -/// Message receiving confirmations delivery strategy. -type ReceivingConfirmationsBasicStrategy

= BasicStrategy< -

::TargetHeaderNumber, -

::TargetHeaderHash, -

::SourceHeaderNumber, -

::SourceHeaderHash, - RangeInclusive, -

::MessagesReceivingProof, ->; - -/// Run receiving confirmations race. -pub async fn run( - source_client: impl MessageLaneSourceClient

, - source_state_updates: impl FusedStream>, - target_client: impl MessageLaneTargetClient

, - target_state_updates: impl FusedStream>, - stall_timeout: Duration, - metrics_msg: Option, -) -> Result<(), FailedClient> { - crate::message_race_loop::run( - ReceivingConfirmationsRaceSource { - client: target_client, - metrics_msg: metrics_msg.clone(), - _phantom: Default::default(), - }, - target_state_updates, - ReceivingConfirmationsRaceTarget { - client: source_client, - metrics_msg, - _phantom: Default::default(), - }, - source_state_updates, - stall_timeout, - ReceivingConfirmationsBasicStrategy::

::new(), - ) - .await -} - -/// Messages receiving confirmations race. -struct ReceivingConfirmationsRace

(std::marker::PhantomData

); - -impl MessageRace for ReceivingConfirmationsRace

{ - type MessageNonce = MessageNonce; - type Proof = P::MessagesReceivingProof; - type SourceHeaderId = TargetHeaderIdOf

; - type TargetHeaderId = SourceHeaderIdOf

; - - fn source_name() -> String { - format!("{}::ReceivingConfirmationsDelivery", P::TARGET_NAME) - } - - fn target_name() -> String { - format!("{}::ReceivingConfirmationsDelivery", P::SOURCE_NAME) - } -} - -/// Message receiving confirmations race source, which is a target of the lane. -struct ReceivingConfirmationsRaceSource { - client: C, - metrics_msg: Option, - _phantom: PhantomData

, -} - -#[async_trait] -impl SourceClient> for ReceivingConfirmationsRaceSource -where - P: MessageLane, - C: MessageLaneTargetClient

, -{ - type Error = C::Error; - type NoncesRange = RangeInclusive; - type ProofParameters = (); - - async fn nonces( - &self, - at_block: TargetHeaderIdOf

, - prev_latest_nonce: MessageNonce, - ) -> Result<(TargetHeaderIdOf

, SourceClientNonces), Self::Error> { - let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; - if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); - } - Ok(( - at_block, - SourceClientNonces { - new_nonces: prev_latest_nonce + 1..=latest_received_nonce, - confirmed_nonce: None, - }, - )) - } - - #[allow(clippy::unit_arg)] - async fn generate_proof( - &self, - at_block: TargetHeaderIdOf

, - nonces: RangeInclusive, - _proof_parameters: Self::ProofParameters, - ) -> Result< - (TargetHeaderIdOf

, RangeInclusive, P::MessagesReceivingProof), - Self::Error, - > { - self.client - .prove_messages_receiving(at_block) - .await - .map(|(at_block, proof)| (at_block, nonces, proof)) - } -} - -/// Message receiving confirmations race target, which is a source of the lane. -struct ReceivingConfirmationsRaceTarget { - client: C, - metrics_msg: Option, - _phantom: PhantomData

, -} - -#[async_trait] -impl TargetClient> for ReceivingConfirmationsRaceTarget -where - P: MessageLane, - C: MessageLaneSourceClient

, -{ - type Error = C::Error; - type TargetNoncesData = (); - - async fn require_source_header(&self, id: TargetHeaderIdOf

) { - self.client.require_target_header_on_source(id).await - } - - async fn nonces( - &self, - at_block: SourceHeaderIdOf

, - update_metrics: bool, - ) -> Result<(SourceHeaderIdOf

, TargetClientNonces<()>), Self::Error> { - let (at_block, latest_confirmed_nonce) = - self.client.latest_confirmed_received_nonce(at_block).await?; - if update_metrics { - if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); - } - } - Ok((at_block, TargetClientNonces { latest_nonce: latest_confirmed_nonce, nonces_data: () })) - } - - async fn submit_proof( - &self, - generated_at_block: TargetHeaderIdOf

, - nonces: RangeInclusive, - proof: P::MessagesReceivingProof, - ) -> Result, Self::Error> { - self.client.submit_messages_receiving_proof(generated_at_block, proof).await?; - Ok(nonces) - } -} - -impl NoncesRange for RangeInclusive { - fn begin(&self) -> MessageNonce { - *RangeInclusive::::start(self) - } - - fn end(&self) -> MessageNonce { - *RangeInclusive::::end(self) - } - - fn greater_than(self, nonce: MessageNonce) -> Option { - let next_nonce = nonce + 1; - let end = *self.end(); - if next_nonce > end { - None - } else { - Some(std::cmp::max(self.begin(), next_nonce)..=end) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn range_inclusive_works_as_nonces_range() { - let range = 20..=30; - - assert_eq!(NoncesRange::begin(&range), 20); - assert_eq!(NoncesRange::end(&range), 30); - assert_eq!(range.clone().greater_than(10), Some(20..=30)); - assert_eq!(range.clone().greater_than(19), Some(20..=30)); - assert_eq!(range.clone().greater_than(20), Some(21..=30)); - assert_eq!(range.clone().greater_than(25), Some(26..=30)); - assert_eq!(range.clone().greater_than(29), Some(30..=30)); - assert_eq!(range.greater_than(30), None); - } -} diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs deleted file mode 100644 index b660c5f11..000000000 --- a/relays/messages/src/message_race_strategy.rs +++ /dev/null @@ -1,517 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -//! Basic delivery strategy. The strategy selects nonces if: -//! -//! 1) there are more nonces on the source side than on the target side; -//! 2) new nonces may be proved to target node (i.e. they have appeared at the -//! block, which is known to the target node). - -use crate::message_race_loop::{ - NoncesRange, RaceState, RaceStrategy, SourceClientNonces, TargetClientNonces, -}; - -use async_trait::async_trait; -use bp_messages::MessageNonce; -use relay_utils::HeaderId; -use std::{collections::VecDeque, fmt::Debug, marker::PhantomData, ops::RangeInclusive}; - -/// Queue of nonces known to the source node. -pub type SourceRangesQueue = - VecDeque<(HeaderId, SourceNoncesRange)>; - -/// Nonces delivery strategy. -#[derive(Debug)] -pub struct BasicStrategy< - SourceHeaderNumber, - SourceHeaderHash, - TargetHeaderNumber, - TargetHeaderHash, - SourceNoncesRange, - Proof, -> { - /// All queued nonces. - source_queue: SourceRangesQueue, - /// The best nonce known to target node (at its best block). `None` if it has not been received - /// yet. - best_target_nonce: Option, - /// Unused generic types dump. - _phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>, -} - -impl< - SourceHeaderNumber, - SourceHeaderHash, - TargetHeaderNumber, - TargetHeaderHash, - SourceNoncesRange, - Proof, - > - BasicStrategy< - SourceHeaderNumber, - SourceHeaderHash, - TargetHeaderNumber, - TargetHeaderHash, - SourceNoncesRange, - Proof, - > where - SourceHeaderHash: Clone, - SourceHeaderNumber: Clone + Ord, - SourceNoncesRange: NoncesRange, -{ - /// Create new delivery strategy. - pub fn new() -> Self { - BasicStrategy { - source_queue: VecDeque::new(), - best_target_nonce: None, - _phantom: Default::default(), - } - } - - /// Reference to source queue. - pub(crate) fn source_queue( - &self, - ) -> &VecDeque<(HeaderId, SourceNoncesRange)> { - &self.source_queue - } - - /// Mutable reference to source queue to use in tests. - #[cfg(test)] - pub(crate) fn source_queue_mut( - &mut self, - ) -> &mut VecDeque<(HeaderId, SourceNoncesRange)> { - &mut self.source_queue - } - - /// Returns index of the latest source queue entry, that may be delivered to the target node. - /// - /// Returns `None` if no entries may be delivered. All entries before and including the - /// `Some(_)` index are guaranteed to be witnessed at source blocks that are known to be - /// finalized at the target node. - pub fn maximal_available_source_queue_index( - &self, - race_state: RaceState< - HeaderId, - HeaderId, - Proof, - >, - ) -> Option { - // if we do not know best nonce at target node, we can't select anything - let _ = self.best_target_nonce?; - - // if we have already selected nonces that we want to submit, do nothing - if race_state.nonces_to_submit.is_some() { - return None; - } - - // if we already submitted some nonces, do nothing - if race_state.nonces_submitted.is_some() { - return None; - } - - // 1) we want to deliver all nonces, starting from `target_nonce + 1` - // 2) we can't deliver new nonce until header, that has emitted this nonce, is finalized - // by target client - // 3) selector is used for more complicated logic - // - // => let's first select range of entries inside deque that are already finalized at - // the target client and pass this range to the selector - let best_header_at_target = race_state.best_finalized_source_header_id_at_best_target?; - self.source_queue - .iter() - .enumerate() - .take_while(|(_, (queued_at, _))| queued_at.0 <= best_header_at_target.0) - .map(|(index, _)| index) - .last() - } - - /// Remove all nonces that are less than or equal to given nonce from the source queue. - pub fn remove_le_nonces_from_source_queue(&mut self, nonce: MessageNonce) { - while let Some((queued_at, queued_range)) = self.source_queue.pop_front() { - if let Some(range_to_requeue) = queued_range.greater_than(nonce) { - self.source_queue.push_front((queued_at, range_to_requeue)); - break; - } - } - } -} - -#[async_trait] -impl< - SourceHeaderNumber, - SourceHeaderHash, - TargetHeaderNumber, - TargetHeaderHash, - SourceNoncesRange, - Proof, - > - RaceStrategy< - HeaderId, - HeaderId, - Proof, - > - for BasicStrategy< - SourceHeaderNumber, - SourceHeaderHash, - TargetHeaderNumber, - TargetHeaderHash, - SourceNoncesRange, - Proof, - > where - SourceHeaderHash: Clone + Debug + Send, - SourceHeaderNumber: Clone + Ord + Debug + Send, - SourceNoncesRange: NoncesRange + Debug + Send, - TargetHeaderHash: Debug + Send, - TargetHeaderNumber: Debug + Send, - Proof: Debug + Send, -{ - type ProofParameters = (); - type SourceNoncesRange = SourceNoncesRange; - type TargetNoncesData = (); - - fn is_empty(&self) -> bool { - self.source_queue.is_empty() - } - - fn required_source_header_at_target( - &self, - current_best: &HeaderId, - ) -> Option> { - self.source_queue - .back() - .and_then(|(h, _)| if h.0 > current_best.0 { Some(h.clone()) } else { None }) - } - - fn best_at_source(&self) -> Option { - let best_in_queue = self.source_queue.back().map(|(_, range)| range.end()); - match (best_in_queue, self.best_target_nonce) { - (Some(best_in_queue), Some(best_target_nonce)) if best_in_queue > best_target_nonce => - Some(best_in_queue), - (_, Some(best_target_nonce)) => Some(best_target_nonce), - (_, None) => None, - } - } - - fn best_at_target(&self) -> Option { - self.best_target_nonce - } - - fn source_nonces_updated( - &mut self, - at_block: HeaderId, - nonces: SourceClientNonces, - ) { - let best_in_queue = self - .source_queue - .back() - .map(|(_, range)| range.end()) - .or(self.best_target_nonce) - .unwrap_or_default(); - self.source_queue.extend( - nonces - .new_nonces - .greater_than(best_in_queue) - .into_iter() - .map(move |range| (at_block.clone(), range)), - ) - } - - fn best_target_nonces_updated( - &mut self, - nonces: TargetClientNonces<()>, - race_state: &mut RaceState< - HeaderId, - HeaderId, - Proof, - >, - ) { - let nonce = nonces.latest_nonce; - - if let Some(best_target_nonce) = self.best_target_nonce { - if nonce < best_target_nonce { - return; - } - } - - while let Some(true) = self.source_queue.front().map(|(_, range)| range.begin() <= nonce) { - let maybe_subrange = self.source_queue.pop_front().and_then(|(at_block, range)| { - range.greater_than(nonce).map(|subrange| (at_block, subrange)) - }); - if let Some((at_block, subrange)) = maybe_subrange { - self.source_queue.push_front((at_block, subrange)); - break; - } - } - - let need_to_select_new_nonces = race_state - .nonces_to_submit - .as_ref() - .map(|(_, nonces, _)| *nonces.end() <= nonce) - .unwrap_or(false); - if need_to_select_new_nonces { - race_state.nonces_to_submit = None; - } - - let need_new_nonces_to_submit = race_state - .nonces_submitted - .as_ref() - .map(|nonces| *nonces.end() <= nonce) - .unwrap_or(false); - if need_new_nonces_to_submit { - race_state.nonces_submitted = None; - } - - self.best_target_nonce = - Some(std::cmp::max(self.best_target_nonce.unwrap_or(nonces.latest_nonce), nonce)); - } - - fn finalized_target_nonces_updated( - &mut self, - nonces: TargetClientNonces<()>, - _race_state: &mut RaceState< - HeaderId, - HeaderId, - Proof, - >, - ) { - self.best_target_nonce = Some(std::cmp::max( - self.best_target_nonce.unwrap_or(nonces.latest_nonce), - nonces.latest_nonce, - )); - } - - async fn select_nonces_to_deliver( - &mut self, - race_state: RaceState< - HeaderId, - HeaderId, - Proof, - >, - ) -> Option<(RangeInclusive, Self::ProofParameters)> { - let maximal_source_queue_index = self.maximal_available_source_queue_index(race_state)?; - let range_begin = self.source_queue[0].1.begin(); - let range_end = self.source_queue[maximal_source_queue_index].1.end(); - self.remove_le_nonces_from_source_queue(range_end); - Some((range_begin..=range_end, ())) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - message_lane::MessageLane, - message_lane_loop::tests::{ - header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderHash, - TestSourceHeaderNumber, - }, - }; - - type SourceNoncesRange = RangeInclusive; - - type BasicStrategy

= super::BasicStrategy< -

::SourceHeaderNumber, -

::SourceHeaderHash, -

::TargetHeaderNumber, -

::TargetHeaderHash, - SourceNoncesRange, -

::MessagesProof, - >; - - fn source_nonces(new_nonces: SourceNoncesRange) -> SourceClientNonces { - SourceClientNonces { new_nonces, confirmed_nonce: None } - } - - fn target_nonces(latest_nonce: MessageNonce) -> TargetClientNonces<()> { - TargetClientNonces { latest_nonce, nonces_data: () } - } - - #[test] - fn strategy_is_empty_works() { - let mut strategy = BasicStrategy::::new(); - assert!(strategy.is_empty()); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=1)); - assert!(!strategy.is_empty()); - } - - #[test] - fn best_at_source_is_never_lower_than_target_nonce() { - let mut strategy = BasicStrategy::::new(); - assert_eq!(strategy.best_at_source(), None); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); - assert_eq!(strategy.best_at_source(), None); - strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); - assert_eq!(strategy.source_queue, vec![]); - assert_eq!(strategy.best_at_source(), Some(10)); - } - - #[test] - fn source_nonce_is_never_lower_than_known_target_nonce() { - let mut strategy = BasicStrategy::::new(); - strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); - assert_eq!(strategy.source_queue, vec![]); - } - - #[test] - fn source_nonce_is_never_lower_than_latest_known_source_nonce() { - let mut strategy = BasicStrategy::::new(); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); - strategy.source_nonces_updated(header_id(2), source_nonces(1..=3)); - strategy.source_nonces_updated(header_id(2), source_nonces(1..=5)); - assert_eq!(strategy.source_queue, vec![(header_id(1), 1..=5)]); - } - - #[test] - fn target_nonce_is_never_lower_than_latest_known_target_nonce() { - let mut strategy = BasicStrategy::::new(); - assert_eq!(strategy.best_target_nonce, None); - strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); - assert_eq!(strategy.best_target_nonce, Some(10)); - strategy.best_target_nonces_updated(target_nonces(5), &mut Default::default()); - assert_eq!(strategy.best_target_nonce, Some(10)); - } - - #[test] - fn updated_target_nonce_removes_queued_entries() { - let mut strategy = BasicStrategy::::new(); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); - strategy.source_nonces_updated(header_id(2), source_nonces(6..=10)); - strategy.source_nonces_updated(header_id(3), source_nonces(11..=15)); - strategy.source_nonces_updated(header_id(4), source_nonces(16..=20)); - strategy.best_target_nonces_updated(target_nonces(15), &mut Default::default()); - assert_eq!(strategy.source_queue, vec![(header_id(4), 16..=20)]); - strategy.best_target_nonces_updated(target_nonces(17), &mut Default::default()); - assert_eq!(strategy.source_queue, vec![(header_id(4), 18..=20)]); - } - - #[test] - fn selected_nonces_are_dropped_on_target_nonce_update() { - let mut state = RaceState::default(); - let mut strategy = BasicStrategy::::new(); - state.nonces_to_submit = Some((header_id(1), 5..=10, (5..=10, None))); - strategy.best_target_nonces_updated(target_nonces(7), &mut state); - assert!(state.nonces_to_submit.is_some()); - strategy.best_target_nonces_updated(target_nonces(10), &mut state); - assert!(state.nonces_to_submit.is_none()); - } - - #[test] - fn submitted_nonces_are_dropped_on_target_nonce_update() { - let mut state = RaceState::default(); - let mut strategy = BasicStrategy::::new(); - state.nonces_submitted = Some(5..=10); - strategy.best_target_nonces_updated(target_nonces(7), &mut state); - assert!(state.nonces_submitted.is_some()); - strategy.best_target_nonces_updated(target_nonces(10), &mut state); - assert!(state.nonces_submitted.is_none()); - } - - #[async_std::test] - async fn nothing_is_selected_if_something_is_already_selected() { - let mut state = RaceState::default(); - let mut strategy = BasicStrategy::::new(); - state.nonces_to_submit = Some((header_id(1), 1..=10, (1..=10, None))); - strategy.best_target_nonces_updated(target_nonces(0), &mut state); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); - assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - } - - #[async_std::test] - async fn nothing_is_selected_if_something_is_already_submitted() { - let mut state = RaceState::default(); - let mut strategy = BasicStrategy::::new(); - state.nonces_submitted = Some(1..=10); - strategy.best_target_nonces_updated(target_nonces(0), &mut state); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); - assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - } - - #[async_std::test] - async fn select_nonces_to_deliver_works() { - let mut state = RaceState::<_, _, TestMessagesProof>::default(); - let mut strategy = BasicStrategy::::new(); - strategy.best_target_nonces_updated(target_nonces(0), &mut state); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=1)); - strategy.source_nonces_updated(header_id(2), source_nonces(2..=2)); - strategy.source_nonces_updated(header_id(3), source_nonces(3..=6)); - strategy.source_nonces_updated(header_id(5), source_nonces(7..=8)); - - state.best_finalized_source_header_id_at_best_target = Some(header_id(4)); - assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, Some((1..=6, ()))); - strategy.best_target_nonces_updated(target_nonces(6), &mut state); - assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - - state.best_finalized_source_header_id_at_best_target = Some(header_id(5)); - assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, Some((7..=8, ()))); - strategy.best_target_nonces_updated(target_nonces(8), &mut state); - assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - } - - #[test] - fn maximal_available_source_queue_index_works() { - let mut state = RaceState::<_, _, TestMessagesProof>::default(); - let mut strategy = BasicStrategy::::new(); - strategy.best_target_nonces_updated(target_nonces(0), &mut state); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=3)); - strategy.source_nonces_updated(header_id(2), source_nonces(4..=6)); - strategy.source_nonces_updated(header_id(3), source_nonces(7..=9)); - - state.best_finalized_source_header_id_at_best_target = Some(header_id(0)); - assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), None); - - state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); - assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(0)); - - state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(1)); - - state.best_finalized_source_header_id_at_best_target = Some(header_id(3)); - assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(2)); - - state.best_finalized_source_header_id_at_best_target = Some(header_id(4)); - assert_eq!(strategy.maximal_available_source_queue_index(state), Some(2)); - } - - #[test] - fn remove_le_nonces_from_source_queue_works() { - let mut state = RaceState::<_, _, TestMessagesProof>::default(); - let mut strategy = BasicStrategy::::new(); - strategy.best_target_nonces_updated(target_nonces(0), &mut state); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=3)); - strategy.source_nonces_updated(header_id(2), source_nonces(4..=6)); - strategy.source_nonces_updated(header_id(3), source_nonces(7..=9)); - - fn source_queue_nonces( - source_queue: &SourceRangesQueue< - TestSourceHeaderHash, - TestSourceHeaderNumber, - SourceNoncesRange, - >, - ) -> Vec { - source_queue.iter().flat_map(|(_, range)| range.clone()).collect() - } - - strategy.remove_le_nonces_from_source_queue(1); - assert_eq!(source_queue_nonces(&strategy.source_queue), vec![2, 3, 4, 5, 6, 7, 8, 9],); - - strategy.remove_le_nonces_from_source_queue(5); - assert_eq!(source_queue_nonces(&strategy.source_queue), vec![6, 7, 8, 9],); - - strategy.remove_le_nonces_from_source_queue(9); - assert_eq!(source_queue_nonces(&strategy.source_queue), Vec::::new(),); - - strategy.remove_le_nonces_from_source_queue(100); - assert_eq!(source_queue_nonces(&strategy.source_queue), Vec::::new(),); - } -} diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs deleted file mode 100644 index db300b477..000000000 --- a/relays/messages/src/metrics.rs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Metrics for message lane relay loop. - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{SourceClientState, TargetClientState}, -}; - -use bp_messages::MessageNonce; -use finality_relay::SyncLoopMetrics; -use relay_utils::metrics::{ - metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, -}; - -/// Message lane relay metrics. -/// -/// Cloning only clones references. -#[derive(Clone)] -pub struct MessageLaneLoopMetrics { - /// Best finalized block numbers - "source", "source_at_target", "target_at_source". - source_to_target_finality_metrics: SyncLoopMetrics, - /// Best finalized block numbers - "source", "target", "source_at_target", "target_at_source". - target_to_source_finality_metrics: SyncLoopMetrics, - /// Lane state nonces: "source_latest_generated", "source_latest_confirmed", - /// "target_latest_received", "target_latest_confirmed". - lane_state_nonces: GaugeVec, -} - -impl MessageLaneLoopMetrics { - /// Create and register messages loop metrics. - pub fn new(prefix: Option<&str>) -> Result { - Ok(MessageLaneLoopMetrics { - source_to_target_finality_metrics: SyncLoopMetrics::new( - prefix, - "source", - "source_at_target", - )?, - target_to_source_finality_metrics: SyncLoopMetrics::new( - prefix, - "target", - "target_at_source", - )?, - lane_state_nonces: GaugeVec::new( - Opts::new(metric_name(prefix, "lane_state_nonces"), "Nonces of the lane state"), - &["type"], - )?, - }) - } - - /// Update source client state metrics. - pub fn update_source_state(&self, source_client_state: SourceClientState

) { - self.source_to_target_finality_metrics - .update_best_block_at_source(source_client_state.best_self.0.into()); - self.target_to_source_finality_metrics.update_best_block_at_target( - source_client_state.best_finalized_peer_at_best_self.0.into(), - ); - self.target_to_source_finality_metrics.update_using_same_fork( - source_client_state.best_finalized_peer_at_best_self.1 - == source_client_state.actual_best_finalized_peer_at_best_self.1, - ); - } - - /// Update target client state metrics. - pub fn update_target_state(&self, target_client_state: TargetClientState

) { - self.target_to_source_finality_metrics - .update_best_block_at_source(target_client_state.best_self.0.into()); - self.source_to_target_finality_metrics.update_best_block_at_target( - target_client_state.best_finalized_peer_at_best_self.0.into(), - ); - self.source_to_target_finality_metrics.update_using_same_fork( - target_client_state.best_finalized_peer_at_best_self.1 - == target_client_state.actual_best_finalized_peer_at_best_self.1, - ); - } - - /// Update latest generated nonce at source. - pub fn update_source_latest_generated_nonce( - &self, - source_latest_generated_nonce: MessageNonce, - ) { - self.lane_state_nonces - .with_label_values(&["source_latest_generated"]) - .set(source_latest_generated_nonce); - } - - /// Update the latest confirmed nonce at source. - pub fn update_source_latest_confirmed_nonce( - &self, - source_latest_confirmed_nonce: MessageNonce, - ) { - self.lane_state_nonces - .with_label_values(&["source_latest_confirmed"]) - .set(source_latest_confirmed_nonce); - } - - /// Update the latest received nonce at target. - pub fn update_target_latest_received_nonce( - &self, - target_latest_generated_nonce: MessageNonce, - ) { - self.lane_state_nonces - .with_label_values(&["target_latest_received"]) - .set(target_latest_generated_nonce); - } - - /// Update the latest confirmed nonce at target. - pub fn update_target_latest_confirmed_nonce( - &self, - target_latest_confirmed_nonce: MessageNonce, - ) { - self.lane_state_nonces - .with_label_values(&["target_latest_confirmed"]) - .set(target_latest_confirmed_nonce); - } -} - -impl Metric for MessageLaneLoopMetrics { - fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - self.source_to_target_finality_metrics.register(registry)?; - self.target_to_source_finality_metrics.register(registry)?; - register(self.lane_state_nonces.clone(), registry)?; - Ok(()) - } -} diff --git a/relays/messages/src/relay_strategy/altruistic_strategy.rs b/relays/messages/src/relay_strategy/altruistic_strategy.rs deleted file mode 100644 index d6fec7f12..000000000 --- a/relays/messages/src/relay_strategy/altruistic_strategy.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Altruistic relay strategy - -use async_trait::async_trait; - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{ - SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient, - }, - relay_strategy::{RelayReference, RelayStrategy}, -}; - -/// The relayer doesn't care about rewards. -#[derive(Clone)] -pub struct AltruisticStrategy; - -#[async_trait] -impl RelayStrategy for AltruisticStrategy { - async fn decide< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &mut self, - _reference: &mut RelayReference, - ) -> bool { - true - } -} diff --git a/relays/messages/src/relay_strategy/enforcement_strategy.rs b/relays/messages/src/relay_strategy/enforcement_strategy.rs deleted file mode 100644 index def6665be..000000000 --- a/relays/messages/src/relay_strategy/enforcement_strategy.rs +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! enforcement strategy - -use num_traits::Zero; - -use bp_messages::{MessageNonce, Weight}; -use bp_runtime::messages::DispatchFeePayment; - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{ - MessageDetails, SourceClient as MessageLaneSourceClient, - TargetClient as MessageLaneTargetClient, - }, - message_race_loop::NoncesRange, - relay_strategy::{RelayMessagesBatchReference, RelayReference, RelayStrategy}, -}; - -/// Do hard check and run soft check strategy -#[derive(Clone)] -pub struct EnforcementStrategy { - strategy: Strategy, -} - -impl EnforcementStrategy { - pub fn new(strategy: Strategy) -> Self { - Self { strategy } - } -} - -impl EnforcementStrategy { - pub async fn decide< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &mut self, - reference: RelayMessagesBatchReference, - ) -> Option { - let mut hard_selected_count = 0; - let mut soft_selected_count = 0; - - let mut selected_weight: Weight = 0; - let mut selected_count: MessageNonce = 0; - - let hard_selected_begin_nonce = - reference.nonces_queue[reference.nonces_queue_range.start].1.begin(); - - // relay reference - let mut relay_reference = RelayReference { - lane_source_client: reference.lane_source_client.clone(), - lane_target_client: reference.lane_target_client.clone(), - - selected_reward: P::SourceChainBalance::zero(), - selected_cost: P::SourceChainBalance::zero(), - selected_size: 0, - - total_reward: P::SourceChainBalance::zero(), - total_confirmations_cost: P::SourceChainBalance::zero(), - total_cost: P::SourceChainBalance::zero(), - - hard_selected_begin_nonce, - selected_prepaid_nonces: 0, - selected_unpaid_weight: 0, - - index: 0, - nonce: 0, - details: MessageDetails { - dispatch_weight: 0, - size: 0, - reward: P::SourceChainBalance::zero(), - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - }, - }; - - let all_ready_nonces = reference - .nonces_queue - .range(reference.nonces_queue_range.clone()) - .flat_map(|(_, ready_nonces)| ready_nonces.iter()) - .enumerate(); - for (index, (nonce, details)) in all_ready_nonces { - relay_reference.index = index; - relay_reference.nonce = *nonce; - relay_reference.details = *details; - - // Since we (hopefully) have some reserves in `max_messages_weight_in_single_batch` - // and `max_messages_size_in_single_batch`, we may still try to submit transaction - // with single message if message overflows these limits. The worst case would be if - // transaction will be rejected by the target runtime, but at least we have tried. - - // limit messages in the batch by weight - let new_selected_weight = match selected_weight.checked_add(details.dispatch_weight) { - Some(new_selected_weight) - if new_selected_weight <= reference.max_messages_weight_in_single_batch => - new_selected_weight, - new_selected_weight if selected_count == 0 => { - log::warn!( - target: "bridge", - "Going to submit message delivery transaction with declared dispatch \ - weight {:?} that overflows maximal configured weight {}", - new_selected_weight, - reference.max_messages_weight_in_single_batch, - ); - new_selected_weight.unwrap_or(Weight::MAX) - }, - _ => break, - }; - - // limit messages in the batch by size - let new_selected_size = match relay_reference.selected_size.checked_add(details.size) { - Some(new_selected_size) - if new_selected_size <= reference.max_messages_size_in_single_batch => - new_selected_size, - new_selected_size if selected_count == 0 => { - log::warn!( - target: "bridge", - "Going to submit message delivery transaction with message \ - size {:?} that overflows maximal configured size {}", - new_selected_size, - reference.max_messages_size_in_single_batch, - ); - new_selected_size.unwrap_or(u32::MAX) - }, - _ => break, - }; - - // limit number of messages in the batch - let new_selected_count = selected_count + 1; - if new_selected_count > reference.max_messages_in_this_batch { - break; - } - relay_reference.selected_size = new_selected_size; - - // If dispatch fee has been paid at the source chain, it means that it is **relayer** - // who's paying for dispatch at the target chain AND reward must cover this dispatch - // fee. - // - // If dispatch fee is paid at the target chain, it means that it'll be withdrawn from - // the dispatch origin account AND reward is not covering this fee. - // - // So in the latter case we're not adding the dispatch weight to the delivery - // transaction weight. - let mut new_selected_prepaid_nonces = relay_reference.selected_prepaid_nonces; - let new_selected_unpaid_weight = match details.dispatch_fee_payment { - DispatchFeePayment::AtSourceChain => { - new_selected_prepaid_nonces += 1; - relay_reference.selected_unpaid_weight.saturating_add(details.dispatch_weight) - }, - DispatchFeePayment::AtTargetChain => relay_reference.selected_unpaid_weight, - }; - relay_reference.selected_prepaid_nonces = new_selected_prepaid_nonces; - relay_reference.selected_unpaid_weight = new_selected_unpaid_weight; - - // now the message has passed all 'strong' checks, and we CAN deliver it. But do we WANT - // to deliver it? It depends on the relayer strategy. - if self.strategy.decide(&mut relay_reference).await { - soft_selected_count = index + 1; - } - - hard_selected_count = index + 1; - selected_weight = new_selected_weight; - selected_count = new_selected_count; - } - - if hard_selected_count != soft_selected_count { - let hard_selected_end_nonce = - hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; - let soft_selected_begin_nonce = hard_selected_begin_nonce; - let soft_selected_end_nonce = - soft_selected_begin_nonce + soft_selected_count as MessageNonce - 1; - log::warn!( - target: "bridge", - "Relayer may deliver nonces [{:?}; {:?}], but because of its strategy it has selected \ - nonces [{:?}; {:?}].", - hard_selected_begin_nonce, - hard_selected_end_nonce, - soft_selected_begin_nonce, - soft_selected_end_nonce, - ); - - hard_selected_count = soft_selected_count; - } - - if hard_selected_count != 0 { - if relay_reference.selected_reward != P::SourceChainBalance::zero() - && relay_reference.selected_cost != P::SourceChainBalance::zero() - { - log::trace!( - target: "bridge", - "Expected reward from delivering nonces [{:?}; {:?}] is: {:?} - {:?} = {:?}", - hard_selected_begin_nonce, - hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1, - &relay_reference.selected_reward, - &relay_reference.selected_cost, - relay_reference.selected_reward - relay_reference.selected_cost, - ); - } - - Some(hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1) - } else { - None - } - } -} diff --git a/relays/messages/src/relay_strategy/mix_strategy.rs b/relays/messages/src/relay_strategy/mix_strategy.rs deleted file mode 100644 index 4ac7fe1d0..000000000 --- a/relays/messages/src/relay_strategy/mix_strategy.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Adapter for using `enum RelayerMode` in a context which requires `RelayStrategy`. - -use async_trait::async_trait; - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{ - RelayerMode, SourceClient as MessageLaneSourceClient, - TargetClient as MessageLaneTargetClient, - }, - relay_strategy::{AltruisticStrategy, RationalStrategy, RelayReference, RelayStrategy}, -}; - -/// `RelayerMode` adapter. -#[derive(Clone)] -pub struct MixStrategy { - relayer_mode: RelayerMode, -} - -impl MixStrategy { - /// Create mix strategy instance - pub fn new(relayer_mode: RelayerMode) -> Self { - Self { relayer_mode } - } -} - -#[async_trait] -impl RelayStrategy for MixStrategy { - async fn decide< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &mut self, - reference: &mut RelayReference, - ) -> bool { - match self.relayer_mode { - RelayerMode::Altruistic => AltruisticStrategy.decide(reference).await, - RelayerMode::Rational => RationalStrategy.decide(reference).await, - } - } -} diff --git a/relays/messages/src/relay_strategy/mod.rs b/relays/messages/src/relay_strategy/mod.rs deleted file mode 100644 index d902bd93e..000000000 --- a/relays/messages/src/relay_strategy/mod.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Relayer strategy - -use std::ops::Range; - -use async_trait::async_trait; - -use bp_messages::{MessageNonce, Weight}; - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{ - MessageDetails, MessageDetailsMap, SourceClient as MessageLaneSourceClient, - TargetClient as MessageLaneTargetClient, - }, - message_race_strategy::SourceRangesQueue, -}; - -pub(crate) use self::enforcement_strategy::*; -pub use self::{altruistic_strategy::*, mix_strategy::*, rational_strategy::*}; - -mod altruistic_strategy; -mod enforcement_strategy; -mod mix_strategy; -mod rational_strategy; - -/// Relayer strategy trait -#[async_trait] -pub trait RelayStrategy: 'static + Clone + Send + Sync { - /// The relayer decide how to process nonce by reference. - /// From given set of source nonces, that are ready to be delivered, select nonces - /// to fit into single delivery transaction. - /// - /// The function returns last nonce that must be delivered to the target chain. - async fn decide< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &mut self, - reference: &mut RelayReference, - ) -> bool; -} - -/// Reference data for participating in relay -pub struct RelayReference< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, -> { - /// The client that is connected to the message lane source node. - pub lane_source_client: SourceClient, - /// The client that is connected to the message lane target node. - pub lane_target_client: TargetClient, - /// Current block reward summary - pub selected_reward: P::SourceChainBalance, - /// Current block cost summary - pub selected_cost: P::SourceChainBalance, - /// Messages size summary - pub selected_size: u32, - - /// Current block reward summary - pub total_reward: P::SourceChainBalance, - /// All confirmations cost - pub total_confirmations_cost: P::SourceChainBalance, - /// Current block cost summary - pub total_cost: P::SourceChainBalance, - - /// Hard check begin nonce - pub hard_selected_begin_nonce: MessageNonce, - /// Count prepaid nonces - pub selected_prepaid_nonces: MessageNonce, - /// Unpaid nonces weight summary - pub selected_unpaid_weight: Weight, - - /// Index by all ready nonces - pub index: usize, - /// Current nonce - pub nonce: MessageNonce, - /// Current nonce details - pub details: MessageDetails, -} - -/// Relay reference data -pub struct RelayMessagesBatchReference< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, -> { - /// Maximal number of relayed messages in single delivery transaction. - pub max_messages_in_this_batch: MessageNonce, - /// Maximal cumulative dispatch weight of relayed messages in single delivery transaction. - pub max_messages_weight_in_single_batch: Weight, - /// Maximal cumulative size of relayed messages in single delivery transaction. - pub max_messages_size_in_single_batch: u32, - /// The client that is connected to the message lane source node. - pub lane_source_client: SourceClient, - /// The client that is connected to the message lane target node. - pub lane_target_client: TargetClient, - /// Source queue. - pub nonces_queue: SourceRangesQueue< - P::SourceHeaderHash, - P::SourceHeaderNumber, - MessageDetailsMap, - >, - /// Source queue range - pub nonces_queue_range: Range, -} diff --git a/relays/messages/src/relay_strategy/rational_strategy.rs b/relays/messages/src/relay_strategy/rational_strategy.rs deleted file mode 100644 index ea4f39d0a..000000000 --- a/relays/messages/src/relay_strategy/rational_strategy.rs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Rational relay strategy - -use async_trait::async_trait; -use num_traits::SaturatingAdd; - -use bp_messages::MessageNonce; - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{ - SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient, - }, - relay_strategy::{RelayReference, RelayStrategy}, -}; - -/// The relayer will deliver all messages and confirmations as long as he's not losing any -/// funds. -#[derive(Clone)] -pub struct RationalStrategy; - -#[async_trait] -impl RelayStrategy for RationalStrategy { - async fn decide< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &mut self, - reference: &mut RelayReference, - ) -> bool { - // technically, multiple confirmations will be delivered in a single transaction, - // meaning less loses for relayer. But here we don't know the final relayer yet, so - // we're adding a separate transaction for every message. Normally, this cost is covered - // by the message sender. Probably reconsider this? - let confirmation_transaction_cost = - reference.lane_source_client.estimate_confirmation_transaction().await; - - let delivery_transaction_cost = match reference - .lane_target_client - .estimate_delivery_transaction_in_source_tokens( - reference.hard_selected_begin_nonce - ..=(reference.hard_selected_begin_nonce + reference.index as MessageNonce), - reference.selected_prepaid_nonces, - reference.selected_unpaid_weight, - reference.selected_size as u32, - ) - .await - { - Ok(v) => v, - Err(err) => { - log::debug!( - target: "bridge", - "Failed to estimate delivery transaction cost: {:?}. No nonces selected for delivery", - err, - ); - return false; - }, - }; - - // if it is the first message that makes reward less than cost, let's log it - // if this message makes batch profitable again, let's log it - let is_total_reward_less_than_cost = reference.total_reward < reference.total_cost; - let prev_total_cost = reference.total_cost; - let prev_total_reward = reference.total_reward; - reference.total_confirmations_cost = - reference.total_confirmations_cost.saturating_add(&confirmation_transaction_cost); - reference.total_reward = reference.total_reward.saturating_add(&reference.details.reward); - reference.total_cost = - reference.total_confirmations_cost.saturating_add(&delivery_transaction_cost); - if !is_total_reward_less_than_cost && reference.total_reward < reference.total_cost { - log::debug!( - target: "bridge", - "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it larger than \ - total reward {:?}->{:?}", - reference.nonce, - reference.details.reward, - prev_total_cost, - reference.total_cost, - prev_total_reward, - reference.total_reward, - ); - } else if is_total_reward_less_than_cost && reference.total_reward >= reference.total_cost { - log::debug!( - target: "bridge", - "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it less than or \ - equal to the total reward {:?}->{:?} (again)", - reference.nonce, - reference.details.reward, - prev_total_cost, - reference.total_cost, - prev_total_reward, - reference.total_reward, - ); - } - - // Rational relayer never want to lose his funds - if reference.total_reward >= reference.total_cost { - reference.selected_reward = reference.total_reward; - reference.selected_cost = reference.total_cost; - return true; - } - - false - } -} diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml deleted file mode 100644 index e6c8a4751..000000000 --- a/relays/utils/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "relay-utils" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -ansi_term = "0.12" -anyhow = "1.0" -async-std = "1.6.5" -async-trait = "0.1.40" -backoff = "0.2" -isahc = "1.2" -env_logger = "0.8.2" -futures = "0.3.5" -jsonpath_lib = "0.2" -log = "0.4.11" -num-traits = "0.2" -serde_json = "1.0" -sysinfo = "0.15" -time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.8", features = ["rt"] } -thiserror = "1.0.26" - -# Bridge dependencies - -bp-runtime = { path = "../../primitives/runtime" } - -# Substrate dependencies - -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.26" } diff --git a/relays/utils/src/error.rs b/relays/utils/src/error.rs deleted file mode 100644 index 26f1d0cac..000000000 --- a/relays/utils/src/error.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -use std::net::AddrParseError; -use thiserror::Error; - -/// Result type used by relay utilities. -pub type Result = std::result::Result; - -/// Relay utilities errors. -#[derive(Error, Debug)] -pub enum Error { - /// Failed to request a float value from HTTP service. - #[error("Failed to fetch token price from remote server: {0}")] - FetchTokenPrice(#[source] anyhow::Error), - /// Failed to parse the response from HTTP service. - #[error("Failed to parse HTTP service response: {0:?}. Response: {1:?}")] - ParseHttp(serde_json::Error, String), - /// Failed to select response value from the Json response. - #[error("Failed to select value from response: {0:?}. Response: {1:?}")] - SelectResponseValue(jsonpath_lib::JsonPathError, String), - /// Failed to parse float value from the selected value. - #[error( - "Failed to parse float value {0:?} from response. It is assumed to be positive and normal" - )] - ParseFloat(f64), - /// Couldn't found value in the JSON response. - #[error("Missing required value from response: {0:?}")] - MissingResponseValue(String), - /// Invalid host address was used for exposing Prometheus metrics. - #[error("Invalid host {0} is used to expose Prometheus metrics: {1}")] - ExposingMetricsInvalidHost(String, AddrParseError), - /// Prometheus error. - #[error("{0}")] - Prometheus(#[from] substrate_prometheus_endpoint::prometheus::Error), -} diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs deleted file mode 100644 index ad69a766e..000000000 --- a/relays/utils/src/initialize.rs +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Relayer initialization functions. - -use std::{cell::RefCell, fmt::Display, io::Write}; - -async_std::task_local! { - pub(crate) static LOOP_NAME: RefCell = RefCell::new(String::default()); -} - -/// Initialize relay environment. -pub fn initialize_relay() { - initialize_logger(true); -} - -/// Initialize Relay logger instance. -pub fn initialize_logger(with_timestamp: bool) { - let format = time::format_description::parse( - "[year]-[month]-[day] \ - [hour repr:24]:[minute]:[second] [offset_hour sign:mandatory]", - ) - .expect("static format string is valid"); - - let mut builder = env_logger::Builder::new(); - builder.filter_level(log::LevelFilter::Warn); - builder.filter_module("bridge", log::LevelFilter::Info); - builder.parse_default_env(); - if with_timestamp { - builder.format(move |buf, record| { - let timestamp = time::OffsetDateTime::now_local() - .unwrap_or_else(|_| time::OffsetDateTime::now_utc()); - let timestamp = timestamp.format(&format).unwrap_or_else(|_| timestamp.to_string()); - - let log_level = color_level(record.level()); - let log_target = color_target(record.target()); - let timestamp = if cfg!(windows) { - Either::Left(timestamp) - } else { - Either::Right(ansi_term::Colour::Fixed(8).bold().paint(timestamp)) - }; - - writeln!( - buf, - "{}{} {} {} {}", - loop_name_prefix(), - timestamp, - log_level, - log_target, - record.args(), - ) - }); - } else { - builder.format(move |buf, record| { - let log_level = color_level(record.level()); - let log_target = color_target(record.target()); - - writeln!(buf, "{}{} {} {}", loop_name_prefix(), log_level, log_target, record.args(),) - }); - } - - builder.init(); -} - -/// Initialize relay loop. Must only be called once per every loop task. -pub(crate) fn initialize_loop(loop_name: String) { - LOOP_NAME.with(|g_loop_name| *g_loop_name.borrow_mut() = loop_name); -} - -/// Returns loop name prefix to use in logs. The prefix is initialized with the `initialize_loop` -/// call. -fn loop_name_prefix() -> String { - // try_with to avoid panic outside of async-std task context - LOOP_NAME - .try_with(|loop_name| { - // using borrow is ok here, because loop is only initialized once (=> borrow_mut will - // only be called once) - let loop_name = loop_name.borrow(); - if loop_name.is_empty() { - String::new() - } else { - format!("[{}] ", loop_name) - } - }) - .unwrap_or_else(|_| String::new()) -} - -enum Either { - Left(A), - Right(B), -} -impl Display for Either { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - Self::Left(a) => write!(fmt, "{}", a), - Self::Right(b) => write!(fmt, "{}", b), - } - } -} - -fn color_target(target: &str) -> impl Display + '_ { - if cfg!(windows) { - Either::Left(target) - } else { - Either::Right(ansi_term::Colour::Fixed(8).paint(target)) - } -} - -fn color_level(level: log::Level) -> impl Display { - if cfg!(windows) { - Either::Left(level) - } else { - let s = level.to_string(); - use ansi_term::Colour as Color; - Either::Right(match level { - log::Level::Error => Color::Fixed(9).bold().paint(s), - log::Level::Warn => Color::Fixed(11).bold().paint(s), - log::Level::Info => Color::Fixed(10).paint(s), - log::Level::Debug => Color::Fixed(14).paint(s), - log::Level::Trace => Color::Fixed(12).paint(s), - }) - } -} diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs deleted file mode 100644 index a335be791..000000000 --- a/relays/utils/src/lib.rs +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Utilities used by different relays. - -pub use bp_runtime::HeaderId; -pub use error::Error; -pub use relay_loop::{relay_loop, relay_metrics}; - -use backoff::{backoff::Backoff, ExponentialBackoff}; -use futures::future::FutureExt; -use std::time::Duration; -use thiserror::Error; - -/// Max delay after connection-unrelated error happened before we'll try the -/// same request again. -pub const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); -/// Delay after connection-related error happened before we'll try -/// reconnection again. -pub const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); - -pub mod error; -pub mod initialize; -pub mod metrics; -pub mod relay_loop; - -/// Block number traits shared by all chains that relay is able to serve. -pub trait BlockNumberBase: - 'static - + From - + Into - + Ord - + Clone - + Copy - + Default - + Send - + Sync - + std::fmt::Debug - + std::fmt::Display - + std::hash::Hash - + std::ops::Add - + std::ops::Sub - + num_traits::CheckedSub - + num_traits::Saturating - + num_traits::Zero - + num_traits::One -{ -} - -impl BlockNumberBase for T where - T: 'static - + From - + Into - + Ord - + Clone - + Copy - + Default - + Send - + Sync - + std::fmt::Debug - + std::fmt::Display - + std::hash::Hash - + std::ops::Add - + std::ops::Sub - + num_traits::CheckedSub - + num_traits::Saturating - + num_traits::Zero - + num_traits::One -{ -} - -/// Macro that returns (client, Err(error)) tuple from function if result is Err(error). -#[macro_export] -macro_rules! bail_on_error { - ($result: expr) => { - match $result { - (client, Ok(result)) => (client, result), - (client, Err(error)) => return (client, Err(error)), - } - }; -} - -/// Macro that returns (client, Err(error)) tuple from function if result is Err(error). -#[macro_export] -macro_rules! bail_on_arg_error { - ($result: expr, $client: ident) => { - match $result { - Ok(result) => result, - Err(error) => return ($client, Err(error)), - } - }; -} - -/// Error type that can signal connection errors. -pub trait MaybeConnectionError { - /// Returns true if error (maybe) represents connection error. - fn is_connection_error(&self) -> bool; -} - -/// Stringified error that may be either connection-related or not. -#[derive(Error, Debug)] -pub enum StringifiedMaybeConnectionError { - /// The error is connection-related error. - #[error("{0}")] - Connection(String), - /// The error is connection-unrelated error. - #[error("{0}")] - NonConnection(String), -} - -impl StringifiedMaybeConnectionError { - /// Create new stringified connection error. - pub fn new(is_connection_error: bool, error: String) -> Self { - if is_connection_error { - StringifiedMaybeConnectionError::Connection(error) - } else { - StringifiedMaybeConnectionError::NonConnection(error) - } - } -} - -impl MaybeConnectionError for StringifiedMaybeConnectionError { - fn is_connection_error(&self) -> bool { - match *self { - StringifiedMaybeConnectionError::Connection(_) => true, - StringifiedMaybeConnectionError::NonConnection(_) => false, - } - } -} - -/// Exponential backoff for connection-unrelated errors retries. -pub fn retry_backoff() -> ExponentialBackoff { - ExponentialBackoff { - // we do not want relayer to stop - max_elapsed_time: None, - max_interval: MAX_BACKOFF_INTERVAL, - ..Default::default() - } -} - -/// Compact format of IDs vector. -pub fn format_ids(mut ids: impl ExactSizeIterator) -> String { - const NTH_PROOF: &str = "we have checked len; qed"; - match ids.len() { - 0 => "".into(), - 1 => format!("{:?}", ids.next().expect(NTH_PROOF)), - 2 => { - let id0 = ids.next().expect(NTH_PROOF); - let id1 = ids.next().expect(NTH_PROOF); - format!("[{:?}, {:?}]", id0, id1) - }, - len => { - let id0 = ids.next().expect(NTH_PROOF); - let id_last = ids.last().expect(NTH_PROOF); - format!("{}:[{:?} ... {:?}]", len, id0, id_last) - }, - } -} - -/// Stream that emits item every `timeout_ms` milliseconds. -pub fn interval(timeout: Duration) -> impl futures::Stream { - futures::stream::unfold((), move |_| async move { - async_std::task::sleep(timeout).await; - Some(((), ())) - }) -} - -/// Which client has caused error. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum FailedClient { - /// It is the source client who has caused error. - Source, - /// It is the target client who has caused error. - Target, - /// Both clients are failing, or we just encountered some other error that - /// should be treated like that. - Both, -} - -/// Future process result. -#[derive(Debug, Clone, Copy)] -pub enum ProcessFutureResult { - /// Future has been processed successfully. - Success, - /// Future has failed with non-connection error. - Failed, - /// Future has failed with connection error. - ConnectionFailed, -} - -impl ProcessFutureResult { - /// Returns true if result is Success. - pub fn is_ok(self) -> bool { - match self { - ProcessFutureResult::Success => true, - ProcessFutureResult::Failed | ProcessFutureResult::ConnectionFailed => false, - } - } - - /// Returns Ok(true) if future has succeeded. - /// Returns Ok(false) if future has failed with non-connection error. - /// Returns Err if future is `ConnectionFailed`. - pub fn fail_if_connection_error( - self, - failed_client: FailedClient, - ) -> Result { - match self { - ProcessFutureResult::Success => Ok(true), - ProcessFutureResult::Failed => Ok(false), - ProcessFutureResult::ConnectionFailed => Err(failed_client), - } - } -} - -/// Process result of the future from a client. -pub fn process_future_result( - result: Result, - retry_backoff: &mut ExponentialBackoff, - on_success: impl FnOnce(TResult), - go_offline_future: &mut std::pin::Pin<&mut futures::future::Fuse>, - go_offline: impl FnOnce(Duration) -> TGoOfflineFuture, - error_pattern: impl FnOnce() -> String, -) -> ProcessFutureResult -where - TError: std::fmt::Debug + MaybeConnectionError, - TGoOfflineFuture: FutureExt, -{ - match result { - Ok(result) => { - on_success(result); - retry_backoff.reset(); - ProcessFutureResult::Success - }, - Err(error) if error.is_connection_error() => { - log::error!( - target: "bridge", - "{}: {:?}. Going to restart", - error_pattern(), - error, - ); - - retry_backoff.reset(); - go_offline_future.set(go_offline(CONNECTION_ERROR_DELAY).fuse()); - ProcessFutureResult::ConnectionFailed - }, - Err(error) => { - let retry_delay = retry_backoff.next_backoff().unwrap_or(CONNECTION_ERROR_DELAY); - log::error!( - target: "bridge", - "{}: {:?}. Retrying in {}", - error_pattern(), - error, - retry_delay.as_secs_f64(), - ); - - go_offline_future.set(go_offline(retry_delay).fuse()); - ProcessFutureResult::Failed - }, - } -} diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs deleted file mode 100644 index 084f72e79..000000000 --- a/relays/utils/src/metrics.rs +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -pub use float_json_value::FloatJsonValueMetric; -pub use global::GlobalMetrics; -pub use substrate_prometheus_endpoint::{ - prometheus::core::{Atomic, Collector}, - register, Counter, CounterVec, Gauge, GaugeVec, Opts, PrometheusError, Registry, F64, I64, U64, -}; - -use async_std::sync::{Arc, RwLock}; -use async_trait::async_trait; -use std::{fmt::Debug, time::Duration}; - -mod float_json_value; -mod global; - -/// Shared reference to `f64` value that is updated by the metric. -pub type F64SharedRef = Arc>>; -/// Int gauge metric type. -pub type IntGauge = Gauge; - -/// Unparsed address that needs to be used to expose Prometheus metrics. -#[derive(Debug, Clone)] -pub struct MetricsAddress { - /// Serve HTTP requests at given host. - pub host: String, - /// Serve HTTP requests at given port. - pub port: u16, -} - -/// Prometheus endpoint MetricsParams. -#[derive(Debug, Clone)] -pub struct MetricsParams { - /// Interface and TCP port to be used when exposing Prometheus metrics. - pub address: Option, - /// Metrics registry. May be `Some(_)` if several components share the same endpoint. - pub registry: Registry, -} - -/// Metric API. -pub trait Metric: Clone + Send + Sync + 'static { - fn register(&self, registry: &Registry) -> Result<(), PrometheusError>; -} - -/// Standalone metric API. -/// -/// Metrics of this kind know how to update themselves, so we may just spawn and forget the -/// asynchronous self-update task. -#[async_trait] -pub trait StandaloneMetric: Metric { - /// Update metric values. - async fn update(&self); - - /// Metrics update interval. - fn update_interval(&self) -> Duration; - - /// Register and spawn metric. Metric is only spawned if it is registered for the first time. - fn register_and_spawn(self, registry: &Registry) -> Result<(), PrometheusError> { - match self.register(registry) { - Ok(()) => { - self.spawn(); - Ok(()) - }, - Err(PrometheusError::AlreadyReg) => Ok(()), - Err(e) => Err(e), - } - } - - /// Spawn the self update task that will keep update metric value at given intervals. - fn spawn(self) { - async_std::task::spawn(async move { - let update_interval = self.update_interval(); - loop { - self.update().await; - async_std::task::sleep(update_interval).await; - } - }); - } -} - -impl Default for MetricsAddress { - fn default() -> Self { - MetricsAddress { host: "127.0.0.1".into(), port: 9616 } - } -} - -impl MetricsParams { - /// Creates metrics params so that metrics are not exposed. - pub fn disabled() -> Self { - MetricsParams { address: None, registry: Registry::new() } - } - - /// Do not expose metrics. - pub fn disable(mut self) -> Self { - self.address = None; - self - } -} - -impl From> for MetricsParams { - fn from(address: Option) -> Self { - MetricsParams { address, registry: Registry::new() } - } -} - -/// Returns metric name optionally prefixed with given prefix. -pub fn metric_name(prefix: Option<&str>, name: &str) -> String { - if let Some(prefix) = prefix { - format!("{}_{}", prefix, name) - } else { - name.into() - } -} - -/// Set value of gauge metric. -/// -/// If value is `Ok(None)` or `Err(_)`, metric would have default value. -pub fn set_gauge_value, E: Debug>( - gauge: &Gauge, - value: Result, E>, -) { - gauge.set(match value { - Ok(Some(value)) => { - log::trace!( - target: "bridge-metrics", - "Updated value of metric '{:?}': {:?}", - gauge.desc().first().map(|d| &d.fq_name), - value, - ); - value - }, - Ok(None) => { - log::warn!( - target: "bridge-metrics", - "Failed to update metric '{:?}': value is empty", - gauge.desc().first().map(|d| &d.fq_name), - ); - Default::default() - }, - Err(error) => { - log::warn!( - target: "bridge-metrics", - "Failed to update metric '{:?}': {:?}", - gauge.desc().first().map(|d| &d.fq_name), - error, - ); - Default::default() - }, - }) -} diff --git a/relays/utils/src/metrics/float_json_value.rs b/relays/utils/src/metrics/float_json_value.rs deleted file mode 100644 index 569acc429..000000000 --- a/relays/utils/src/metrics/float_json_value.rs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -use crate::{ - error::{self, Error}, - metrics::{ - metric_name, register, F64SharedRef, Gauge, Metric, PrometheusError, Registry, - StandaloneMetric, F64, - }, -}; - -use async_std::sync::{Arc, RwLock}; -use async_trait::async_trait; -use std::time::Duration; - -/// Value update interval. -const UPDATE_INTERVAL: Duration = Duration::from_secs(60); - -/// Metric that represents float value received from HTTP service as float gauge. -/// -/// The float value returned by the service is assumed to be normal (`f64::is_normal` -/// should return `true`) and strictly positive. -#[derive(Debug, Clone)] -pub struct FloatJsonValueMetric { - url: String, - json_path: String, - metric: Gauge, - shared_value_ref: F64SharedRef, -} - -impl FloatJsonValueMetric { - /// Create new metric instance with given name and help. - pub fn new( - url: String, - json_path: String, - name: String, - help: String, - ) -> Result { - let shared_value_ref = Arc::new(RwLock::new(None)); - Ok(FloatJsonValueMetric { - url, - json_path, - metric: Gauge::new(metric_name(None, &name), help)?, - shared_value_ref, - }) - } - - /// Get shared reference to metric value. - pub fn shared_value_ref(&self) -> F64SharedRef { - self.shared_value_ref.clone() - } - - /// Request value from HTTP service. - async fn request_value(&self) -> anyhow::Result { - use isahc::{AsyncReadResponseExt, HttpClient, Request}; - - let request = Request::get(&self.url).header("Accept", "application/json").body(())?; - let raw_response = HttpClient::new()?.send_async(request).await?.text().await?; - Ok(raw_response) - } - - /// Read value from HTTP service. - async fn read_value(&self) -> error::Result { - let raw_response = self.request_value().await.map_err(Error::FetchTokenPrice)?; - parse_service_response(&self.json_path, &raw_response) - } -} - -impl Metric for FloatJsonValueMetric { - fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - register(self.metric.clone(), registry).map(drop) - } -} - -#[async_trait] -impl StandaloneMetric for FloatJsonValueMetric { - fn update_interval(&self) -> Duration { - UPDATE_INTERVAL - } - - async fn update(&self) { - let value = self.read_value().await; - let maybe_ok = value.as_ref().ok().copied(); - crate::metrics::set_gauge_value(&self.metric, value.map(Some)); - *self.shared_value_ref.write().await = maybe_ok; - } -} - -/// Parse HTTP service response. -fn parse_service_response(json_path: &str, response: &str) -> error::Result { - let json = - serde_json::from_str(response).map_err(|err| Error::ParseHttp(err, response.to_owned()))?; - - let mut selector = jsonpath_lib::selector(&json); - let maybe_selected_value = - selector(json_path).map_err(|err| Error::SelectResponseValue(err, response.to_owned()))?; - let selected_value = maybe_selected_value - .first() - .and_then(|v| v.as_f64()) - .ok_or_else(|| Error::MissingResponseValue(response.to_owned()))?; - if !selected_value.is_normal() || selected_value < 0.0 { - return Err(Error::ParseFloat(selected_value)); - } - - Ok(selected_value) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parse_service_response_works() { - assert_eq!( - parse_service_response("$.kusama.usd", r#"{"kusama":{"usd":433.05}}"#).map_err(drop), - Ok(433.05), - ); - } - - #[test] - fn parse_service_response_rejects_negative_numbers() { - assert!(parse_service_response("$.kusama.usd", r#"{"kusama":{"usd":-433.05}}"#).is_err()); - } - - #[test] - fn parse_service_response_rejects_zero_numbers() { - assert!(parse_service_response("$.kusama.usd", r#"{"kusama":{"usd":0.0}}"#).is_err()); - } - - #[test] - fn parse_service_response_rejects_nan() { - assert!(parse_service_response("$.kusama.usd", r#"{"kusama":{"usd":NaN}}"#).is_err()); - } -} diff --git a/relays/utils/src/metrics/global.rs b/relays/utils/src/metrics/global.rs deleted file mode 100644 index df90a2c48..000000000 --- a/relays/utils/src/metrics/global.rs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Global system-wide Prometheus metrics exposed by relays. - -use crate::metrics::{ - metric_name, register, Gauge, GaugeVec, Metric, Opts, PrometheusError, Registry, - StandaloneMetric, F64, U64, -}; - -use async_std::sync::{Arc, Mutex}; -use async_trait::async_trait; -use std::time::Duration; -use sysinfo::{ProcessExt, RefreshKind, System, SystemExt}; - -/// Global metrics update interval. -const UPDATE_INTERVAL: Duration = Duration::from_secs(10); - -/// Global Prometheus metrics. -#[derive(Debug, Clone)] -pub struct GlobalMetrics { - system: Arc>, - system_average_load: GaugeVec, - process_cpu_usage_percentage: Gauge, - process_memory_usage_bytes: Gauge, -} - -impl GlobalMetrics { - /// Create and register global metrics. - pub fn new() -> Result { - Ok(GlobalMetrics { - system: Arc::new(Mutex::new(System::new_with_specifics(RefreshKind::everything()))), - system_average_load: GaugeVec::new( - Opts::new(metric_name(None, "system_average_load"), "System load average"), - &["over"], - )?, - process_cpu_usage_percentage: Gauge::new( - metric_name(None, "process_cpu_usage_percentage"), - "Process CPU usage", - )?, - process_memory_usage_bytes: Gauge::new( - metric_name(None, "process_memory_usage_bytes"), - "Process memory (resident set size) usage", - )?, - }) - } -} - -impl Metric for GlobalMetrics { - fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - register(self.system_average_load.clone(), registry)?; - register(self.process_cpu_usage_percentage.clone(), registry)?; - register(self.process_memory_usage_bytes.clone(), registry)?; - Ok(()) - } -} - -#[async_trait] -impl StandaloneMetric for GlobalMetrics { - async fn update(&self) { - // update system-wide metrics - let mut system = self.system.lock().await; - let load = system.get_load_average(); - self.system_average_load.with_label_values(&["1min"]).set(load.one); - self.system_average_load.with_label_values(&["5min"]).set(load.five); - self.system_average_load.with_label_values(&["15min"]).set(load.fifteen); - - // update process-related metrics - let pid = sysinfo::get_current_pid().expect( - "only fails where pid is unavailable (os=unknown || arch=wasm32);\ - relay is not supposed to run in such MetricsParamss;\ - qed", - ); - let is_process_refreshed = system.refresh_process(pid); - match (is_process_refreshed, system.get_process(pid)) { - (true, Some(process_info)) => { - let cpu_usage = process_info.cpu_usage() as f64; - let memory_usage = process_info.memory() * 1024; - log::trace!( - target: "bridge-metrics", - "Refreshed process metrics: CPU={}, memory={}", - cpu_usage, - memory_usage, - ); - - self.process_cpu_usage_percentage.set(if cpu_usage.is_finite() { - cpu_usage - } else { - 0f64 - }); - self.process_memory_usage_bytes.set(memory_usage); - }, - _ => { - log::warn!( - target: "bridge-metrics", - "Failed to refresh process information. Metrics may show obsolete values", - ); - }, - } - } - - fn update_interval(&self) -> Duration { - UPDATE_INTERVAL - } -} diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs deleted file mode 100644 index bf2ea2e45..000000000 --- a/relays/utils/src/relay_loop.rs +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -use crate::{ - error::Error, - metrics::{Metric, MetricsAddress, MetricsParams}, - FailedClient, MaybeConnectionError, -}; - -use async_trait::async_trait; -use std::{fmt::Debug, future::Future, net::SocketAddr, time::Duration}; -use substrate_prometheus_endpoint::{init_prometheus, Registry}; - -/// Default pause between reconnect attempts. -pub const RECONNECT_DELAY: Duration = Duration::from_secs(10); - -/// Basic blockchain client from relay perspective. -#[async_trait] -pub trait Client: 'static + Clone + Send + Sync { - /// Type of error these clients returns. - type Error: 'static + Debug + MaybeConnectionError + Send + Sync; - - /// Try to reconnect to source node. - async fn reconnect(&mut self) -> Result<(), Self::Error>; -} - -#[async_trait] -impl Client for () { - type Error = crate::StringifiedMaybeConnectionError; - - async fn reconnect(&mut self) -> Result<(), Self::Error> { - Ok(()) - } -} - -/// Returns generic loop that may be customized and started. -pub fn relay_loop(source_client: SC, target_client: TC) -> Loop { - Loop { reconnect_delay: RECONNECT_DELAY, source_client, target_client, loop_metric: None } -} - -/// Returns generic relay loop metrics that may be customized and used in one or several relay -/// loops. -pub fn relay_metrics(params: MetricsParams) -> LoopMetrics<(), (), ()> { - LoopMetrics { - relay_loop: Loop { - reconnect_delay: RECONNECT_DELAY, - source_client: (), - target_client: (), - loop_metric: None, - }, - address: params.address, - registry: params.registry, - loop_metric: None, - } -} - -/// Generic relay loop. -pub struct Loop { - reconnect_delay: Duration, - source_client: SC, - target_client: TC, - loop_metric: Option, -} - -/// Relay loop metrics builder. -pub struct LoopMetrics { - relay_loop: Loop, - address: Option, - registry: Registry, - loop_metric: Option, -} - -impl Loop { - /// Customize delay between reconnect attempts. - pub fn reconnect_delay(mut self, reconnect_delay: Duration) -> Self { - self.reconnect_delay = reconnect_delay; - self - } - - /// Start building loop metrics using given prefix. - pub fn with_metrics(self, params: MetricsParams) -> LoopMetrics { - LoopMetrics { - relay_loop: Loop { - reconnect_delay: self.reconnect_delay, - source_client: self.source_client, - target_client: self.target_client, - loop_metric: None, - }, - address: params.address, - registry: params.registry, - loop_metric: None, - } - } - - /// Run relay loop. - /// - /// This function represents an outer loop, which in turn calls provided `run_loop` function to - /// do actual job. When `run_loop` returns, this outer loop reconnects to failed client (source, - /// target or both) and calls `run_loop` again. - pub async fn run(mut self, loop_name: String, run_loop: R) -> Result<(), Error> - where - R: 'static + Send + Fn(SC, TC, Option) -> F, - F: 'static + Send + Future>, - SC: 'static + Client, - TC: 'static + Client, - LM: 'static + Send + Clone, - { - let run_loop_task = async move { - crate::initialize::initialize_loop(loop_name); - - loop { - let loop_metric = self.loop_metric.clone(); - let future_result = - run_loop(self.source_client.clone(), self.target_client.clone(), loop_metric); - let result = future_result.await; - - match result { - Ok(()) => break, - Err(failed_client) => - reconnect_failed_client( - failed_client, - self.reconnect_delay, - &mut self.source_client, - &mut self.target_client, - ) - .await, - } - - log::debug!(target: "bridge", "Restarting relay loop"); - } - - Ok(()) - }; - - async_std::task::spawn(run_loop_task).await - } -} - -impl LoopMetrics { - /// Add relay loop metrics. - /// - /// Loop metrics will be passed to the loop callback. - pub fn loop_metric( - self, - metric: NewLM, - ) -> Result, Error> { - metric.register(&self.registry)?; - - Ok(LoopMetrics { - relay_loop: self.relay_loop, - address: self.address, - registry: self.registry, - loop_metric: Some(metric), - }) - } - - /// Convert into `MetricsParams` structure so that metrics registry may be extended later. - pub fn into_params(self) -> MetricsParams { - MetricsParams { address: self.address, registry: self.registry } - } - - /// Expose metrics using address passed at creation. - /// - /// If passed `address` is `None`, metrics are not exposed. - pub async fn expose(self) -> Result, Error> { - if let Some(address) = self.address { - let socket_addr = SocketAddr::new( - address - .host - .parse() - .map_err(|err| Error::ExposingMetricsInvalidHost(address.host.clone(), err))?, - address.port, - ); - - let registry = self.registry; - async_std::task::spawn(async move { - let runtime = - match tokio::runtime::Builder::new_current_thread().enable_all().build() { - Ok(runtime) => runtime, - Err(err) => { - log::trace!( - target: "bridge-metrics", - "Failed to create tokio runtime. Prometheus meterics are not available: {:?}", - err, - ); - return; - }, - }; - - let _ = runtime.block_on(async move { - log::trace!( - target: "bridge-metrics", - "Starting prometheus endpoint at: {:?}", - socket_addr, - ); - let result = init_prometheus(socket_addr, registry).await; - log::trace!( - target: "bridge-metrics", - "Prometheus endpoint has exited with result: {:?}", - result, - ); - }); - }); - } - - Ok(Loop { - reconnect_delay: self.relay_loop.reconnect_delay, - source_client: self.relay_loop.source_client, - target_client: self.relay_loop.target_client, - loop_metric: self.loop_metric, - }) - } -} - -/// Deal with the client who has returned connection error. -pub async fn reconnect_failed_client( - failed_client: FailedClient, - reconnect_delay: Duration, - source_client: &mut impl Client, - target_client: &mut impl Client, -) { - loop { - async_std::task::sleep(reconnect_delay).await; - if failed_client == FailedClient::Both || failed_client == FailedClient::Source { - match source_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to source client. Going to retry in {}s: {:?}", - reconnect_delay.as_secs(), - error, - ); - continue; - }, - } - } - if failed_client == FailedClient::Both || failed_client == FailedClient::Target { - match target_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to target client. Going to retry in {}s: {:?}", - reconnect_delay.as_secs(), - error, - ); - continue; - }, - } - } - - break; - } -}